Пример #1
0
        // Disposer
        public override void Dispose()
        {
            // Not already disposed?
            if (!IsDisposed)
            {
                // Clean up
                sides   = null;
                floor   = null;
                ceiling = null;

                // Dispose base
                base.Dispose();
            }
        }
Пример #2
0
        //mxd
        protected void AlignTextureToClosestLine(bool alignx, bool aligny)
        {
            if (!(mode.HighlightedObject is BaseVisualSector))
            {
                return;
            }

            // Do we need to align this? (and also grab texture scale while we are at it)
            float scaleX, scaleY;
            bool  isFloor = (geometrytype == VisualGeometryType.FLOOR);

            if (mode.HighlightedTarget is VisualFloor)
            {
                VisualFloor target = (VisualFloor)mode.HighlightedTarget;

                // Check texture
                if (target.Sector.Sector.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture))
                {
                    return;
                }

                scaleX = target.Sector.Sector.Fields.GetValue("xscalefloor", 1.0f);
                scaleY = target.Sector.Sector.Fields.GetValue("yscalefloor", 1.0f);
            }
            else
            {
                VisualCeiling target = (VisualCeiling)mode.HighlightedTarget;

                // Check texture
                if (target.Sector.Sector.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture))
                {
                    return;
                }

                scaleX = target.Sector.Sector.Fields.GetValue("xscaleceiling", 1.0f);
                scaleY = target.Sector.Sector.Fields.GetValue("yscaleceiling", 1.0f);
            }

            //find a linedef to align to
            Vector2D hitpos = mode.GetHitPosition();

            if (!hitpos.IsFinite())
            {
                return;
            }

            //align to line of highlighted sector, which is closest to hitpos
            Sector         highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector;
            List <Linedef> lines             = new List <Linedef>();

            foreach (Sidedef side in highlightedSector.Sidedefs)
            {
                lines.Add(side.Line);
            }

            Linedef targetLine = MapSet.NearestLinedef(lines, hitpos);

            if (targetLine == null)
            {
                return;
            }

            bool isFront = targetLine.SideOfLine(hitpos) > 0;

            Sector.Sector.Fields.BeforeFieldsChange();

            //find an angle to rotate texture
            float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1);

            if (!isFront)
            {
                sourceAngle = General.ClampAngle(sourceAngle + 180);
            }

            //update angle
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f);

            //set scale
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f);
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f);

            //update offset
            float    distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position);
            float    distToEnd   = Vector2D.Distance(hitpos, targetLine.End.Position);
            Vector2D offset      = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle));

            if (alignx)
            {
                if (Texture != null && Texture.IsImageLoaded)
                {
                    offset.x %= Texture.Width / scaleX;
                }
                UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f);
            }

            if (aligny)
            {
                if (Texture != null && Texture.IsImageLoaded)
                {
                    offset.y %= Texture.Height / scaleY;
                }
                UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f);
            }

            //update geometry
            Sector.UpdateSectorGeometry(false);
        }
        //mxd
        protected void AlignTextureToClosestLine(bool alignx, bool aligny)
        {
            if (!(mode.HighlightedObject is BaseVisualSector))
            {
                return;
            }

            // Do we need to align this? (and also grab texture scale while we are at it)
            float scaleX, scaleY;
            bool  isFloor = (geometrytype == VisualGeometryType.FLOOR);

            if (mode.HighlightedTarget is VisualFloor)
            {
                Sector      target;
                VisualFloor vf = (VisualFloor)mode.HighlightedTarget;

                // Use the control sector if the floor belongs to a 3D floor
                if (vf.ExtraFloor == null)
                {
                    target = vf.Sector.Sector;
                }
                else
                {
                    target = vf.GetControlSector();
                }

                // Check texture
                if (target.FloorTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture))
                {
                    return;
                }

                scaleX = target.Fields.GetValue("xscalefloor", 1.0f);
                scaleY = target.Fields.GetValue("yscalefloor", 1.0f);
            }
            else
            {
                Sector        target;
                VisualCeiling vc = (VisualCeiling)mode.HighlightedTarget;

                // Use the control sector if the ceiling belongs to a 3D floor
                if (vc.ExtraFloor == null)
                {
                    target = vc.Sector.Sector;
                }
                else
                {
                    target = vc.GetControlSector();
                }

                // Check texture
                if (target.CeilTexture != (isFloor ? Sector.Sector.FloorTexture : Sector.Sector.CeilTexture))
                {
                    return;
                }

                scaleX = target.Fields.GetValue("xscaleceiling", 1.0f);
                scaleY = target.Fields.GetValue("yscaleceiling", 1.0f);
            }

            //find a linedef to align to
            Vector2D hitpos = mode.GetHitPosition();

            if (!hitpos.IsFinite())
            {
                return;
            }

            //align to line of highlighted sector, which is closest to hitpos
            Sector         highlightedSector = ((BaseVisualSector)mode.HighlightedObject).Sector;
            List <Linedef> lines             = new List <Linedef>();

            foreach (Sidedef side in highlightedSector.Sidedefs)
            {
                lines.Add(side.Line);
            }

            Linedef targetLine = MapSet.NearestLinedef(lines, hitpos);

            if (targetLine == null)
            {
                return;
            }

            bool isFront = targetLine.SideOfLine(hitpos) > 0;

            Sector.Sector.Fields.BeforeFieldsChange();

            //find an angle to rotate texture
            float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(targetLine.Angle) + 90 : -Angle2D.RadToDeg(targetLine.Angle) - 90), 1);

            if (!isFront)
            {
                sourceAngle = General.ClampAngle(sourceAngle + 180);
            }

            //update angle
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "rotationfloor" : "rotationceiling"), sourceAngle, 0f);

            // Scale texture if it's a slope and the appropriate option is set
            if (level.plane.Normal.z != 1.0f && BuilderPlug.Me.ScaleTexturesOnSlopes != 2)
            {
                Vector2D basescale = new Vector2D(1.0f, 1.0f);

                // User wants to use the current scale as a base?
                if (BuilderPlug.Me.ScaleTexturesOnSlopes == 1)
                {
                    basescale.x = scaleX;
                    basescale.y = scaleY;
                }

                // Create a unit vector of the direction of the target line in 3D space
                Vector3D targetlinevector = new Line3D(new Vector3D(targetLine.Start.Position, level.plane.GetZ(targetLine.Start.Position)), new Vector3D(targetLine.End.Position, level.plane.GetZ(targetLine.End.Position))).GetDelta().GetNormal();

                // Get a perpendicular vector of the target line in 3D space. This is used to get the slope angle relative to the target line
                Vector3D targetlineperpendicular = Vector3D.CrossProduct(targetlinevector, level.plane.Normal);

                if (alignx)
                {
                    scaleX = Math.Abs(basescale.x * (1.0f / (float)Math.Cos(targetlinevector.GetAngleZ())));
                }

                if (aligny)
                {
                    scaleY = Math.Abs(basescale.y * (1.0f / (float)Math.Cos(targetlineperpendicular.GetAngleZ())));
                }
            }

            //set scale
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xscalefloor" : "xscaleceiling"), scaleX, 1.0f);
            UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "yscalefloor" : "yscaleceiling"), scaleY, 1.0f);

            //update offset
            float    distToStart = Vector2D.Distance(hitpos, targetLine.Start.Position);
            float    distToEnd   = Vector2D.Distance(hitpos, targetLine.End.Position);
            Vector2D offset      = (distToStart < distToEnd ? targetLine.Start.Position : targetLine.End.Position).GetRotated(Angle2D.DegToRad(sourceAngle));

            if (alignx)
            {
                if (Texture != null && Texture.IsImageLoaded)
                {
                    offset.x %= Texture.Width / scaleX;
                }
                UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "xpanningfloor" : "xpanningceiling"), (float)Math.Round(-offset.x), 0f);
            }

            if (aligny)
            {
                if (Texture != null && Texture.IsImageLoaded)
                {
                    offset.y %= Texture.Height / scaleY;
                }
                UniFields.SetFloat(Sector.Sector.Fields, (isFloor ? "ypanningfloor" : "ypanningceiling"), (float)Math.Round(offset.y), 0f);
            }

            //update geometry
            Sector.UpdateSectorGeometry(false);
        }
Пример #4
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;
        }
Пример #5
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;
        }