Beispiel #1
0
        // This sets the Lower Unpegged flag
        public virtual void ApplyLowerUnpegged(bool set)
        {
            if (!set)
            {
                // Remove flag
                mode.CreateUndo("Remove lower-unpegged setting");
                mode.SetActionResult("Removed lower-unpegged setting.");
                this.Sidedef.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, false);
            }
            else
            {
                // Add flag
                mode.CreateUndo("Set lower-unpegged setting");
                mode.SetActionResult("Set lower-unpegged setting.");
                this.Sidedef.Line.SetFlag(General.Map.Config.LowerUnpeggedFlag, true);
            }

            // Update sidedef geometry
            VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);

            parts.SetupAllParts();

            // Update other sidedef geometry
            if (Sidedef.Other != null)
            {
                BaseVisualSector othersector = (BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector);
                parts = othersector.GetSidedefParts(Sidedef.Other);
                parts.SetupAllParts();
            }
        }
Beispiel #2
0
        // Flood-fill textures
        public virtual void OnTextureFloodfill()
        {
            if (BuilderPlug.Me.CopiedTexture != null)
            {
                string oldtexture     = GetTextureName();
                long   oldtexturelong = Lump.MakeLongName(oldtexture);
                string newtexture     = BuilderPlug.Me.CopiedTexture;
                if (newtexture != oldtexture)
                {
                    mode.CreateUndo("Flood-fill textures with " + newtexture);
                    mode.SetActionResult("Flood-filled textures with " + newtexture + ".");

                    mode.Renderer.SetCrosshairBusy(true);
                    General.Interface.RedrawDisplay();

                    // Get the texture
                    ImageData newtextureimage = General.Map.Data.GetTextureImage(newtexture);
                    if (newtextureimage != null)
                    {
                        if (mode.IsSingleSelection)
                        {
                            // Clear all marks, this will align everything it can
                            General.Map.Map.ClearMarkedSidedefs(false);
                        }
                        else
                        {
                            // Limit the alignment to selection only
                            General.Map.Map.ClearMarkedSidedefs(true);
                            List <Sidedef> sides = mode.GetSelectedSidedefs();
                            foreach (Sidedef sd in sides)
                            {
                                sd.Marked = false;
                            }
                        }

                        // Do the alignment
                        Tools.FloodfillTextures(this.Sidedef, oldtexturelong, newtextureimage, false);

                        // Get the changed sidedefs
                        List <Sidedef> changes = General.Map.Map.GetMarkedSidedefs(true);
                        foreach (Sidedef sd in changes)
                        {
                            // Update the parts for this sidedef!
                            if (mode.VisualSectorExists(sd.Sector))
                            {
                                BaseVisualSector   vs    = (mode.GetVisualSector(sd.Sector) as BaseVisualSector);
                                VisualSidedefParts parts = vs.GetSidedefParts(sd);
                                parts.SetupAllParts();
                            }
                        }

                        General.Map.Data.UpdateUsedTextures();
                        mode.Renderer.SetCrosshairBusy(false);
                        mode.ShowTargetInfo();
                    }
                }
            }
        }
Beispiel #3
0
        // Paste texture offsets
        public virtual void OnPasteTextureOffsets()
        {
            mode.CreateUndo("Paste texture offsets");
            Sidedef.OffsetX = BuilderPlug.Me.CopiedOffsets.X;
            Sidedef.OffsetY = BuilderPlug.Me.CopiedOffsets.Y;
            mode.SetActionResult("Pasted texture offsets " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + ".");

            // Update sidedef geometry
            VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);

            parts.SetupAllParts();
        }
Beispiel #4
0
        //mxd. This checks if any of the sidedef texture match the given textures
        public static bool SidedefTextureMatch(BaseVisualMode mode, Sidedef sd, HashSet <long> texturelongnames)
        {
            if (!mode.VisualSectorExists(sd.Sector))
            {
                return(false);
            }
            VisualSidedefParts parts = ((BaseVisualSector)mode.GetVisualSector(sd.Sector)).GetSidedefParts(sd);

            return((texturelongnames.Contains(sd.LongHighTexture) && (parts.upper != null && parts.upper.Triangles > 0)) ||
                   (texturelongnames.Contains(sd.LongLowTexture) && (parts.lower != null && parts.lower.Triangles > 0)) ||
                   (texturelongnames.Contains(sd.LongMiddleTexture) &&
                    ((parts.middledouble != null && parts.middledouble.Triangles > 0) || (parts.middlesingle != null && parts.middlesingle.Triangles > 0))));
        }
Beispiel #5
0
        // Reset texture offsets
        public virtual void OnResetTextureOffset()
        {
            mode.CreateUndo("Reset texture offsets");
            mode.SetActionResult("Texture offsets reset.");

            // Apply offsets
            Sidedef.OffsetX = 0;
            Sidedef.OffsetY = 0;

            // Update sidedef geometry
            VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);

            parts.SetupAllParts();
        }
Beispiel #6
0
        //mxd
        protected override void UpdateSkyRenderFlag()
        {
            bool isrenderedassky = renderassky;

            renderassky = (level.sector.FloorTexture == General.Map.Config.SkyFlatName || level.sector.LongFloorTexture == MapSet.EmptyLongName);
            if (isrenderedassky != renderassky && Sector.Sides != null)
            {
                // Middle geometry may need updating...
                foreach (Sidedef side in level.sector.Sidedefs)
                {
                    VisualSidedefParts parts = Sector.GetSidedefParts(side);
                    if (parts.middlesingle != null)
                    {
                        parts.middlesingle.UpdateSkyRenderFlag();
                    }
                }
            }
        }
Beispiel #7
0
        // Texture offset change
        public virtual void OnChangeTextureOffset(int horizontal, int vertical)
        {
            if ((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
            {
                undoticket = mode.CreateUndo("Change texture offsets");
            }

            // Apply offsets
            Sidedef.OffsetX -= horizontal;
            Sidedef.OffsetY -= vertical;

            mode.SetActionResult("Changed texture offsets to " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + ".");

            // Update sidedef geometry
            VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);

            parts.SetupAllParts();
        }
Beispiel #8
0
        // Auto-align texture X offsets
        public virtual void OnTextureAlign(bool alignx, bool aligny)
        {
            mode.CreateUndo("Auto-align textures");
            mode.SetActionResult("Auto-aligned textures.");

            // Make sure the texture is loaded (we need the texture size)
            if (!base.Texture.IsImageLoaded)
            {
                base.Texture.LoadImage();
            }

            if (mode.IsSingleSelection)
            {
                // Clear all marks, this will align everything it can
                General.Map.Map.ClearMarkedSidedefs(false);
            }
            else
            {
                // Limit the alignment to selection only
                General.Map.Map.ClearMarkedSidedefs(true);
                List <Sidedef> sides = mode.GetSelectedSidedefs();
                foreach (Sidedef sd in sides)
                {
                    sd.Marked = false;
                }
            }

            // Do the alignment
            Tools.AutoAlignTextures(this.Sidedef, base.Texture, alignx, aligny, false);

            // Get the changed sidedefs
            List <Sidedef> changes = General.Map.Map.GetMarkedSidedefs(true);

            foreach (Sidedef sd in changes)
            {
                // Update the parts for this sidedef!
                if (mode.VisualSectorExists(sd.Sector))
                {
                    BaseVisualSector   vs    = (mode.GetVisualSector(sd.Sector) as BaseVisualSector);
                    VisualSidedefParts parts = vs.GetSidedefParts(sd);
                    parts.SetupAllParts();
                }
            }
        }
Beispiel #9
0
        //mxd
        protected override void UpdateSkyRenderFlag()
        {
            bool isrenderedassky = renderassky;

            renderassky = (level.sector.CeilTexture == General.Map.Config.SkyFlatName);
            if (isrenderedassky != renderassky && Sector.Sides != null)
            {
                // Upper/middle geometry may need updating...
                foreach (Sidedef side in level.sector.Sidedefs)
                {
                    VisualSidedefParts parts = Sector.GetSidedefParts(side);
                    if (parts.upper != null)
                    {
                        parts.upper.UpdateSkyRenderFlag();
                    }
                    else if (parts.middlesingle != null)
                    {
                        parts.middlesingle.UpdateSkyRenderFlag();
                    }

                    // On the other side as well...
                    if (side.Other != null && side.Other.Sector != null &&
                        side.Other.Sector.CeilTexture == General.Map.Config.SkyFlatName)
                    {
                        BaseVisualSector other = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
                        if (other != null && other.Sides != null)
                        {
                            parts = other.GetSidedefParts(side.Other);
                            if (parts.upper != null)
                            {
                                parts.upper.UpdateSkyRenderFlag();
                            }
                        }
                    }
                }
            }
        }
Beispiel #10
0
        // This performs texture floodfill along all walls that match with the same texture
        // NOTE: This method uses the sidedefs marking to indicate which sides have been filled
        // When resetsidemarks is set to true, all sidedefs will first be marked false (not aligned).
        // Setting resetsidemarks to false is usefull to fill only within a specific selection
        // (set the marked property to true for the sidedefs outside the selection)
        public static void FloodfillTextures(BaseVisualMode mode, Sidedef start, HashSet <long> originaltextures, string filltexture, bool resetsidemarks)
        {
            Stack <Tools.SidedefFillJob> todo = new Stack <Tools.SidedefFillJob>(50);

            // Mark all sidedefs false (they will be marked true when the texture is aligned)
            if (resetsidemarks)
            {
                General.Map.Map.ClearMarkedSidedefs(false);
            }

            // Begin with first sidedef
            if (SidedefTextureMatch(mode, start, originaltextures))
            {
                todo.Push(new Tools.SidedefFillJob {
                    sidedef = start, forward = true
                });
            }

            // Continue until nothing more to align
            while (todo.Count > 0)
            {
                // Get the align job to do
                Tools.SidedefFillJob j = todo.Pop();

                //mxd. Get visual parts
                if (mode.VisualSectorExists(j.sidedef.Sector))
                {
                    VisualSidedefParts parts = ((BaseVisualSector)mode.GetVisualSector(j.sidedef.Sector)).GetSidedefParts(j.sidedef);

                    // Apply texturing
                    if ((parts.upper != null && parts.upper.Triangles > 0) && originaltextures.Contains(j.sidedef.LongHighTexture))
                    {
                        j.sidedef.SetTextureHigh(filltexture);
                    }
                    if (((parts.middledouble != null && parts.middledouble.Triangles > 0) || (parts.middlesingle != null && parts.middlesingle.Triangles > 0)) && originaltextures.Contains(j.sidedef.LongMiddleTexture))
                    {
                        j.sidedef.SetTextureMid(filltexture);
                    }
                    if ((parts.lower != null && parts.lower.Triangles > 0) && originaltextures.Contains(j.sidedef.LongLowTexture))
                    {
                        j.sidedef.SetTextureLow(filltexture);
                    }
                }

                j.sidedef.Marked = true;

                if (j.forward)
                {
                    // Add sidedefs forward (connected to the right vertex)
                    Vertex v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
                    AddSidedefsForFloodfill(mode, todo, v, true, originaltextures);

                    // Add sidedefs backward (connected to the left vertex)
                    v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
                    AddSidedefsForFloodfill(mode, todo, v, false, originaltextures);
                }
                else
                {
                    // Add sidedefs backward (connected to the left vertex)
                    Vertex v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
                    AddSidedefsForFloodfill(mode, todo, v, false, originaltextures);

                    // Add sidedefs forward (connected to the right vertex)
                    v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
                    AddSidedefsForFloodfill(mode, todo, v, true, originaltextures);
                }
            }
        }
Beispiel #11
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;             //mxd

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationceiling", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningceiling", 0.0f),
                                           s.Fields.GetValue("ypanningceiling", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscaleceiling", 1.0f),
                                          s.Fields.GetValue("yscaleceiling", 1.0f));

            //Load ceiling texture
            if (s.LongCeilTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongCeilTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }
            else
            {
                // Use missing texture
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = 0;
            }

            // Determine texture scale
            if (base.Texture.IsImageLoaded)
            {
                texscale = new Vector2D(1.0f / base.Texture.ScaledWidth, 1.0f / base.Texture.ScaledHeight);
            }
            else
            {
                texscale = new Vector2D(1.0f / 64.0f, 1.0f / 64.0f);
            }

            // Determine brightness
            byte alpha = (byte)General.Clamp(level.alpha, 0, 255);
            int  color = PixelColor.FromInt(level.color).WithAlpha(alpha).ToInt();
            int  targetbrightness;

            if (extrafloor != null && !extrafloor.VavoomType && !level.disablelighting)
            {
                //mxd. Top extrafloor level should calculate fogdensity from the brightness of the level above it
                if (!innerside)
                {
                    targetbrightness = 0;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count - 1; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
                            break;
                        }
                    }
                }
                //mxd. Inner extrafloor ceilings must be colored using control sector's color and brightness
                else
                {
                    targetbrightness = level.brightnessbelow;
                    SectorData sd = mode.GetSectorData(this.Sector.Sector);
                    for (int i = 0; i < sd.LightLevels.Count; i++)
                    {
                        if (sd.LightLevels[i] == level)
                        {
                            if (i > 0)
                            {
                                color = PixelColor.FromInt(sd.LightLevels[i - 1].color).WithAlpha(alpha).ToInt();
                            }
                            break;
                        }
                    }
                }
            }
            else
            {
                targetbrightness = level.brightnessbelow;
            }

            //mxd. Determine fog density
            fogfactor = CalculateFogFactor(targetbrightness);

            // Make vertices
            ReadOnlyCollection <Vector2D> triverts = Sector.Sector.Triangles.Vertices;

            WorldVertex[] verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                verts[i].c = color;                 //mxd

                // Vertex coordinates
                verts[i].x = triverts[i].x;
                verts[i].y = triverts[i].y;
                verts[i].z = level.plane.GetZ(triverts[i]);

                // Texture coordinates
                Vector2D pos = triverts[i];
                pos        = pos.GetRotated(rotate);
                pos.y      = -pos.y;
                pos        = (pos + offset) * scale * texscale;
                verts[i].u = pos.x;
                verts[i].v = pos.y;
            }

            // The sector triangulation created clockwise triangles that
            // are right up for the floor. For the ceiling we must flip
            // the triangles upside down.
            if (extrafloor == null || extrafloor.VavoomType || innerside)
            {
                SwapTriangleVertices(verts);
            }

            // Determine render pass
            if (extrafloor != null)
            {
                if (extrafloor.Sloped3dFloor)                //mxd
                {
                    this.RenderPass = RenderPass.Mask;
                }
                else if (extrafloor.RenderAdditive)                //mxd
                {
                    this.RenderPass = RenderPass.Additive;
                }
                else if (level.alpha < 255)
                {
                    this.RenderPass = RenderPass.Alpha;
                }
                else
                {
                    this.RenderPass = RenderPass.Mask;
                }
            }
            else
            {
                this.RenderPass = RenderPass.Solid;
            }

            //mxd. Update sky render flag
            bool isrenderedassky = renderassky;

            renderassky = (level.sector.CeilTexture == General.Map.Config.SkyFlatName);
            if (isrenderedassky != renderassky && Sector.Sides != null)
            {
                // Upper sidedef geometry may need updating...
                foreach (Sidedef side in level.sector.Sidedefs)
                {
                    VisualSidedefParts parts = Sector.GetSidedefParts(side);

                    // Upper side can exist in either our, or the neightbouring sector, right?
                    if (parts.upper != null && parts.upper.Triangles > 0)
                    {
                        parts.upper.UpdateSkyRenderFlag();
                    }
                    else if (side.Other != null && side.Other.Sector != null && side.Other.Sector.CeilTexture == General.Map.Config.SkyFlatName)
                    {
                        // Update upper side of the neightbouring sector
                        BaseVisualSector other = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
                        if (other != null && other.Sides != null)
                        {
                            parts = other.GetSidedefParts(side.Other);
                            if (parts.upper != null && parts.upper.Triangles > 0)
                            {
                                parts.upper.UpdateSkyRenderFlag();
                            }
                        }
                    }
                }
            }

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
Beispiel #12
0
        // This (re)builds the visual sector, calculating all geometry from scratch
        public void Rebuild()
        {
            // Forget old geometry
            base.ClearGeometry();

            // Get sector data
            SectorData data = GetSectorData();

            if (!data.Updated)
            {
                data.Update();
            }

            // Create floor
            floor = (floor ?? new VisualFloor(mode, this));
            if (floor.Setup(data.Floor, null))
            {
                AddGeometry(floor);
            }

            // Create ceiling
            ceiling = (ceiling ?? new VisualCeiling(mode, this));
            if (ceiling.Setup(data.Ceiling, null))
            {
                AddGeometry(ceiling);
            }

            // Create 3D floors
            for (int i = 0; i < data.ExtraFloors.Count; i++)
            {
                Effect3DFloor ef              = data.ExtraFloors[i];
                bool          floorRequired   = ef.VavoomType;      //mxd
                bool          ceilingRequired = ef.VavoomType;      //mxd

                if (ef.VavoomType || !ef.IgnoreBottomHeight)
                {
                    //mxd. check if 3d floor is between real floor and ceiling
                    if (!ef.VavoomType)
                    {
                        if (ef.Ceiling.plane.GetInverted().Normal != floor.Level.plane.Normal ||
                            ef.Ceiling.plane.Normal != ceiling.Level.plane.Normal)
                        {
                            //mxd. check if at least one vertex of 3d floor is between floor and ceiling
                            floorRequired = Check3dFloorPlane(floor.Vertices, ceiling.Vertices, ef.Ceiling.plane);
                        }
                        //if floor, ceiling and 3d floor are not sloped, compare offsets
                        else if (-floor.Level.plane.Offset < ef.Ceiling.plane.Offset &&
                                 ceiling.Level.plane.Offset > ef.Ceiling.plane.Offset)
                        {
                            floorRequired = true;
                        }
                    }

                    //mxd. Create a floor
                    if (floorRequired && ef.Ceiling.sector.IsDisposed == false)
                    {
                        VisualFloor vf = (i < extrafloors.Count) ? extrafloors[i] : new VisualFloor(mode, this);
                        if (vf.Setup(ef.Ceiling, ef))
                        {
                            base.AddGeometry(vf);

                            //mxd. add backside as well
                            if (!ef.VavoomType && ef.RenderInside)
                            {
                                VisualFloor vfb = (i < extrabackfloors.Count) ? extrabackfloors[i] : new VisualFloor(mode, this);
                                if (vfb.Setup(ef.Ceiling, ef, true))
                                {
                                    base.AddGeometry(vfb);
                                }
                                if (i >= extrabackfloors.Count)
                                {
                                    extrabackfloors.Add(vfb);
                                }
                            }
                        }
                        if (i >= extrafloors.Count)
                        {
                            extrafloors.Add(vf);
                        }
                    }
                }

                //mxd. check if 3d ceiling is between real floor and ceiling
                if (!ef.VavoomType)
                {
                    if (ef.Floor.plane.GetInverted().Normal != ceiling.Level.plane.Normal ||
                        ef.Floor.plane.Normal != floor.Level.plane.Normal)
                    {
                        //mxd. check if at least one vertex of 3d ceiling is between floor and ceiling
                        ceilingRequired = Check3dFloorPlane(floor.Vertices, ceiling.Vertices, ef.Floor.plane);
                    }
                    //if floor, ceiling and 3d ceiling are not sloped, compare offsets
                    else if (ceiling.Level.plane.Offset > -ef.Floor.plane.Offset &&
                             floor.Level.plane.Offset > ef.Floor.plane.Offset)
                    {
                        ceilingRequired = true;
                    }
                }

                //mxd. Create a ceiling
                if (ceilingRequired && ef.Floor.sector.IsDisposed == false)
                {
                    VisualCeiling vc = (i < extraceilings.Count) ? extraceilings[i] : new VisualCeiling(mode, this);
                    if (vc.Setup(ef.Floor, ef))
                    {
                        base.AddGeometry(vc);

                        //mxd. add backside as well
                        if (!ef.VavoomType && (ef.RenderInside || ef.IgnoreBottomHeight))
                        {
                            VisualCeiling vcb = (i < extrabackceilings.Count) ? extrabackceilings[i] : new VisualCeiling(mode, this);
                            if (vcb.Setup(ef.Floor, ef, true))
                            {
                                base.AddGeometry(vcb);
                            }
                            if (i >= extrabackceilings.Count)
                            {
                                extrabackceilings.Add(vcb);
                            }
                        }
                    }
                    if (i >= extraceilings.Count)
                    {
                        extraceilings.Add(vc);
                    }
                }
            }

            // Go for all sidedefs
            Dictionary <Sidedef, VisualSidedefParts> oldsides = sides ?? new Dictionary <Sidedef, VisualSidedefParts>(1);

            sides = new Dictionary <Sidedef, VisualSidedefParts>(base.Sector.Sidedefs.Count);
            foreach (Sidedef sd in base.Sector.Sidedefs)
            {
                // VisualSidedef already exists?
                VisualSidedefParts parts = oldsides.ContainsKey(sd) ? oldsides[sd] : new VisualSidedefParts();

                // Doublesided or singlesided?
                if (sd.Other != null && sd.Line.IsFlagSet(General.Map.Config.DoubleSidedFlag))
                {
                    // Create upper part
                    VisualUpper vu = parts.upper ?? new VisualUpper(mode, this, sd);
                    if (vu.Setup())
                    {
                        base.AddGeometry(vu);
                    }

                    // Create lower part
                    VisualLower vl = parts.lower ?? new VisualLower(mode, this, sd);
                    if (vl.Setup())
                    {
                        base.AddGeometry(vl);
                    }

                    // Create middle part
                    VisualMiddleDouble vm = parts.middledouble ?? new VisualMiddleDouble(mode, this, sd);
                    if (vm.Setup())
                    {
                        base.AddGeometry(vm);
                    }

                    //mxd. Create fog boundary
                    VisualFogBoundary vb = parts.fogboundary ?? new VisualFogBoundary(mode, this, sd);
                    if (vb.Setup())
                    {
                        vm.FogFactor = 0;                         // Avoid double-fogging the middle part
                        base.AddGeometry(vb);
                    }

                    // Create 3D wall parts
                    SectorData osd = mode.GetSectorData(sd.Other.Sector);
                    if (!osd.Updated)
                    {
                        osd.Update();
                    }
                    List <VisualMiddle3D> middles = parts.middle3d ?? new List <VisualMiddle3D>(osd.ExtraFloors.Count);
                    for (int i = 0; i < osd.ExtraFloors.Count; i++)
                    {
                        Effect3DFloor ef = osd.ExtraFloors[i];
                        if (!ef.VavoomType && ef.IgnoreBottomHeight)
                        {
                            continue;                                                                 //mxd
                        }
                        VisualMiddle3D vm3 = (i < middles.Count) ? middles[i] : new VisualMiddle3D(mode, this, sd);
                        if (vm3.Setup(ef))
                        {
                            base.AddGeometry(vm3);
                        }
                        if (i >= middles.Count)
                        {
                            middles.Add(vm3);
                        }
                    }

                    //mxd. Create backsides
                    List <VisualMiddleBack> middlebacks = new List <VisualMiddleBack>();
                    for (int i = 0; i < data.ExtraFloors.Count; i++)
                    {
                        Effect3DFloor ef = data.ExtraFloors[i];

                        if (!ef.VavoomType && ef.RenderInside && !ef.IgnoreBottomHeight)
                        {
                            VisualMiddleBack vms = new VisualMiddleBack(mode, this, sd);
                            if (vms.Setup(ef))
                            {
                                base.AddGeometry(vms);
                            }
                            middlebacks.Add(vms);
                        }
                    }

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vu, vl, vm, vb, middles, middlebacks));
                }
                else
                {
                    // Create middle part
                    VisualMiddleSingle vm = parts.middlesingle ?? new VisualMiddleSingle(mode, this, sd);
                    if (vm.Setup())
                    {
                        base.AddGeometry(vm);
                    }

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vm));
                }
            }

            // Done
            changed = false;
        }
        // This usually happens when geometry is changed by undo, redo, cut or paste actions
        // and uses the marks to check what needs to be reloaded.
        protected override void ResourcesReloadedPartial()
        {
            bool sectorsmarked = false;

            if (General.Map.UndoRedo.GeometryChanged)
            {
                // Let the core do this (it will just dispose the sectors that were changed)
                base.ResourcesReloadedPartial();
            }
            else
            {
                // Neighbour sectors must be updated as well
                foreach (Sector s in General.Map.Map.Sectors)
                {
                    if (s.Marked)
                    {
                        sectorsmarked = true;
                        foreach (Sidedef sd in s.Sidedefs)
                        {
                            sd.Marked = true;
                            if (sd.Other != null)
                            {
                                sd.Other.Marked = true;
                            }
                        }
                    }
                }

                // Go for all sidedefs to update
                foreach (Sidedef sd in General.Map.Map.Sidedefs)
                {
                    if (sd.Marked && VisualSectorExists(sd.Sector))
                    {
                        BaseVisualSector   vs    = (BaseVisualSector)GetVisualSector(sd.Sector);
                        VisualSidedefParts parts = vs.GetSidedefParts(sd);
                        parts.SetupAllParts();
                    }
                }

                // Go for all sectors to update
                foreach (Sector s in General.Map.Map.Sectors)
                {
                    if (s.Marked && VisualSectorExists(s))
                    {
                        BaseVisualSector vs = (BaseVisualSector)GetVisualSector(s);
                        vs.Floor.Setup();
                        vs.Ceiling.Setup();
                    }
                }

                if (!sectorsmarked)
                {
                    // No sectors or geometry changed. So we only have
                    // to update things when they have changed.
                    foreach (KeyValuePair <Thing, VisualThing> vt in allthings)
                    {
                        if (vt.Key.Marked)
                        {
                            (vt.Value as BaseVisualThing).Rebuild();
                        }
                    }
                }
                else
                {
                    // Things depend on the sector they are in and because we can't
                    // easily determine which ones changed, we dispose all things
                    foreach (KeyValuePair <Thing, VisualThing> vt in allthings)
                    {
                        vt.Value.Dispose();
                    }

                    // Apply new lists
                    allthings = new Dictionary <Thing, VisualThing>(allthings.Count);
                }

                // Clear visibility collections
                visiblesectors.Clear();
                visibleblocks.Clear();
                visiblegeometry.Clear();
                visiblethings.Clear();

                // Make new blockmap
                if (sectorsmarked || General.Map.UndoRedo.PopulationChanged)
                {
                    FillBlockMap();
                }

                // Visibility culling (this re-creates the needed resources)
                DoCulling();
            }

            // Determine what we're aiming at now
            PickTarget();
        }
Beispiel #14
0
        // This (re)builds the visual sector, calculating all geometry from scratch
        public void Rebuild()
        {
            // Forget old geometry
            base.ClearGeometry();

            // Create floor
            if (floor == null)
            {
                floor = new VisualFloor(mode, this);
            }
            floor.Setup();
            base.AddGeometry(floor);

            // Create ceiling
            if (ceiling == null)
            {
                ceiling = new VisualCeiling(mode, this);
            }
            ceiling.Setup();
            base.AddGeometry(ceiling);

            // Go for all sidedefs
            Dictionary <Sidedef, VisualSidedefParts> oldsides = sides ?? new Dictionary <Sidedef, VisualSidedefParts>(1);

            sides = new Dictionary <Sidedef, VisualSidedefParts>(base.Sector.Sidedefs.Count);
            foreach (Sidedef sd in base.Sector.Sidedefs)
            {
                // VisualSidedef already exists?
                VisualSidedefParts parts = oldsides.ContainsKey(sd) ? oldsides[sd] : new VisualSidedefParts();

                // Doublesided or singlesided?
                if (sd.Other != null)
                {
                    // Create upper part
                    VisualUpper vu = parts.upper ?? new VisualUpper(mode, this, sd);
                    vu.Setup();
                    base.AddGeometry(vu);

                    // Create lower part
                    VisualLower vl = parts.lower ?? new VisualLower(mode, this, sd);
                    vl.Setup();
                    base.AddGeometry(vl);

                    // Create middle part
                    VisualMiddleDouble vm = parts.middledouble ?? new VisualMiddleDouble(mode, this, sd);
                    vm.Setup();
                    base.AddGeometry(vm);

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vu, vl, vm));
                }
                else
                {
                    // Create middle part
                    VisualMiddleSingle vm = parts.middlesingle ?? new VisualMiddleSingle(mode, this, sd);
                    vm.Setup();
                    base.AddGeometry(vm);

                    // Store
                    sides.Add(sd, new VisualSidedefParts(vm));
                }
            }

            // Done
            changed = false;
        }