override protected void SetupInterface()
        {
            maxsubdivisions        = 512;
            minsubdivisions        = 3;
            minpointscount         = 3;
            alwaysrendershapehints = true;

            // Load stored settings
            subdivisions = General.Clamp(General.Settings.ReadPluginSetting("drawellipsemode.subdivisions", 8), minsubdivisions, maxsubdivisions);
            bevelwidth   = General.Settings.ReadPluginSetting("drawellipsemode.bevelwidth", 0);
            int angledeg = General.Settings.ReadPluginSetting("drawellipsemode.angle", 0);

            angle             = Angle2D.DegToRad(angledeg);
            currentbevelwidth = bevelwidth;

            //Add options docker
            panel = new DrawEllipseOptionsPanel();
            panel.MaxSubdivisions             = maxsubdivisions;
            panel.MinSubdivisions             = minsubdivisions;
            panel.MinSpikiness                = (int)General.Map.FormatInterface.MinCoordinate;
            panel.MaxSpikiness                = (int)General.Map.FormatInterface.MaxCoordinate;
            panel.Spikiness                   = bevelwidth;
            panel.Angle                       = angledeg;
            panel.Subdivisions                = subdivisions;
            panel.OnValueChanged             += OptionsPanelOnValueChanged;
            panel.OnContinuousDrawingChanged += OnContinuousDrawingChanged;
            panel.OnShowGuidelinesChanged    += OnShowGuidelinesChanged;

            // Needs to be set after adding the OnContinuousDrawingChanged event...
            panel.ContinuousDrawing = General.Settings.ReadPluginSetting("drawellipsemode.continuousdrawing", false);
            panel.ShowGuidelines    = General.Settings.ReadPluginSetting("drawellipsemode.showguidelines", false);
        }
 private void OptionsPanelOnValueChanged(object sender, EventArgs eventArgs)
 {
     bevelwidth   = panel.Spikiness;
     subdivisions = Math.Min(maxsubdivisions, panel.Subdivisions);
     angle        = Angle2D.DegToRad(panel.Angle);
     Update();
 }
示例#3
0
        //mxd
        public void SetPitch(int newpitch)
        {
            BeforePropsChange();

            pitch = General.ClampAngle(newpitch);

            switch (rendermode)
            {
            case ThingRenderMode.MODEL:
                double    pmult = General.Map.Config.BuggyModelDefPitch ? 1 : -1;
                ModelData md    = General.Map.Data.ModeldefEntries[type];
                if (md.InheritActorPitch || md.UseActorPitch)
                {
                    pitchrad = Angle2D.DegToRad(pmult * (md.InheritActorPitch ? -pitch : pitch));
                }
                else
                {
                    pitchrad = 0;
                }
                break;

            case ThingRenderMode.FLATSPRITE:
                pitchrad = Angle2D.DegToRad(pitch);
                break;

            default:
                pitchrad = 0;
                break;
            }

            if (type != General.Map.Config.Start3DModeThingType)
            {
                General.Map.IsChanged = true;
            }
        }
		//mxd
		public override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			closestline = MapSet.NearestLinedef(selectedlines, mousedownmappos);

			// Special cases...
			int distance;
			if(panel.FixedCurve)
			{
				if(panel.Angle > 0)
				{
					// Calculate diameter for current angle...
					double ma = Angle2D.DegToRad(panel.Angle);
					double d = (closestline.Length / Math.Tan(ma / 2f)) / 2;
					double D = d / Math.Cos(ma / 2f);
					distance = (int)Math.Round(D - d) * Math.Sign(panel.Distance);
				}
				else
				{
					distance = 0; // Special cases...
				}
			}
			else
			{
				distance = panel.Distance;
			}

			// Store offset between intial mouse position and curve top
			Vector2D perpendicular = closestline.Line.GetPerpendicular().GetNormal();
			if(distance != 0) perpendicular *= distance; // Special cases...
			Vector2D curvetop = closestline.GetCenterPoint() - perpendicular;
			mousedownoffset = mousedownmappos - curvetop;
		}
        //mxd. merged from GZDoomEditing plugin
        // This applies the given values on the vertices
        private static void SetupSurfaceVertices(FlatVertex[] vertices, Sector s, ImageData img, Vector2D offset,
                                                 Vector2D scale, double rotate, int color, int light, bool absolute)
        {
            // Prepare for math!
            rotate = Angle2D.DegToRad(rotate);
            Vector2D texscale = new Vector2D(1.0f / img.ScaledWidth, 1.0f / img.ScaledHeight);

            if (!absolute)
            {
                light = s.Brightness + light;
            }
            PixelColor lightcolor = PixelColor.FromInt(color);
            PixelColor brightness = PixelColor.FromInt(General.Map.Renderer2D.CalculateBrightness(light));
            PixelColor finalcolor = PixelColor.Modulate(lightcolor, brightness);

            color = finalcolor.WithAlpha(255).ToInt();

            // Do the math for all vertices
            for (int i = 0; i < vertices.Length; i++)
            {
                Vector2D pos = new Vector2D(vertices[i].x, vertices[i].y);
                pos           = pos.GetRotated(rotate);
                pos.y         = -pos.y;
                pos           = (pos + offset) * scale * texscale;
                vertices[i].u = (float)pos.x;
                vertices[i].v = (float)pos.y;
                vertices[i].c = color;
            }
        }
示例#6
0
 private void absrot_Validated(object sender, EventArgs e)
 {
     if(userinput)
     {
         float rad = Angle2D.DegToRad(absrot.GetResultFloat(this.absrotate));
         mode.SetAbsRotation(rad);
     }
 }
        // This performs an accurate test for object picking
        public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray)
        {
            u_ray = pickrayu;

            // Check on which side of the nearest sidedef we are
            Sidedef sd   = MapSet.NearestSidedef(Sector.Sector.Sidedefs, pickintersect);
            float   side = sd.Line.SideOfLine(pickintersect);

            //mxd. Alpha based picking. Used only on extrafloors with transparent or masked textures
            if ((side <= 0.0f && sd.IsFront) || (side > 0.0f && !sd.IsFront))
            {
                if (!BuilderPlug.Me.AlphaBasedTextureHighlighting || !Texture.IsImageLoaded || extrafloor == null || RenderPass == RenderPass.Solid || (!Texture.IsTranslucent && !Texture.IsMasked))
                {
                    return(true);
                }

                // Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead
                Bitmap image = Texture.GetBitmap();

                lock (image)
                {
                    // Fetch ZDoom fields
                    float    rotate   = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationfloor", 0.0f));
                    Vector2D offset   = new Vector2D(level.sector.Fields.GetValue("xpanningfloor", 0.0f), level.sector.Fields.GetValue("ypanningfloor", 0.0f));
                    Vector2D scale    = new Vector2D(level.sector.Fields.GetValue("xscalefloor", 1.0f), level.sector.Fields.GetValue("yscalefloor", 1.0f));
                    Vector2D texscale = new Vector2D(1.0f / Texture.ScaledWidth, 1.0f / Texture.ScaledHeight);

                    // Texture coordinates
                    Vector2D o = pickintersect;
                    o   = o.GetRotated(rotate);
                    o.y = -o.y;
                    o   = (o + offset) * scale * texscale;
                    o.x = (o.x * image.Width) % image.Width;
                    o.y = (o.y * image.Height) % image.Height;

                    // Make sure coordinates are inside of texture dimensions...
                    if (o.x < 0)
                    {
                        o.x += image.Width;
                    }
                    if (o.y < 0)
                    {
                        o.y += image.Height;
                    }

                    // Make final texture coordinates...
                    int ox = General.Clamp((int)Math.Floor(o.x), 0, image.Width - 1);
                    int oy = General.Clamp((int)Math.Floor(o.y), 0, image.Height - 1);

                    // Check pixel alpha
                    return(image.GetPixel(ox, oy).A > 0);
                }
            }

            return(false);
        }
示例#8
0
        //mxd. This checks if the thing has model override and whether pitch/roll values should be used
        internal void UpdateCache()
        {
            if (General.Map.Data == null)
            {
                return;
            }

            // Check if the thing has model override
            if (General.Map.Data.ModeldefEntries.ContainsKey(type))
            {
                ModelData md = General.Map.Data.ModeldefEntries[type];
                if ((md.LoadState == ModelLoadState.None && General.Map.Data.ProcessModel(type)) || md.LoadState != ModelLoadState.None)
                {
                    rendermode = (General.Map.Data.ModeldefEntries[type].IsVoxel ? ThingRenderMode.VOXEL : ThingRenderMode.MODEL);
                }
            }
            else // reset rendermode if we SUDDENLY became a sprite out of a model. otherwise it crashes violently.
            {
                ThingTypeInfo ti = General.Map.Data.GetThingInfo(Type);
                rendermode = (ti != null) ? ti.RenderMode : ThingRenderMode.NORMAL;
            }

            // Update radian versions of pitch and roll
            switch (rendermode)
            {
            case ThingRenderMode.MODEL:
                float     pmult = General.Map.Config.BuggyModelDefPitch ? 1 : -1;
                ModelData md    = General.Map.Data.ModeldefEntries[type];
                rollrad  = (md.UseActorRoll ? Angle2D.DegToRad(roll) : 0);
                pitchrad = ((md.InheritActorPitch || md.UseActorPitch) ? Angle2D.DegToRad(pmult * (md.InheritActorPitch ? -pitch : pitch)) : 0);
                break;

            case ThingRenderMode.FLATSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = Angle2D.DegToRad(pitch);
                break;

            case ThingRenderMode.WALLSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = 0;
                break;

            case ThingRenderMode.NORMAL:
                rollrad  = (rollsprite ? Angle2D.DegToRad(roll) : 0);
                pitchrad = 0;
                break;

            case ThingRenderMode.VOXEL:
                rollrad  = 0;
                pitchrad = 0;
                break;

            default: throw new NotImplementedException("Unknown ThingRenderMode");
            }
        }
        //mxd
        private void ChangeAngle(int increment)
        {
            PreAction(UndoGroup.AngleChange);
            float incrementrad = Angle2D.DegToRad(increment);
            List <IVisualEventReceiver> objs = GetSelectedObjects(true, false, true);

            foreach (IVisualEventReceiver i in objs)
            {
                i.OnChangeTargetAngle(incrementrad);
            }
            PostAction();
        }
示例#10
0
        //mxd
        public void SetRoll(int newroll)
        {
            BeforePropsChange();

            roll    = General.ClampAngle(newroll);
            rollrad = ((rollsprite || (rendermode == ThingRenderMode.MODEL && General.Map.Data.ModeldefEntries[type].UseActorRoll))
                                ? Angle2D.DegToRad(roll) : 0);

            if (type != General.Map.Config.Start3DModeThingType)
            {
                General.Map.IsChanged = true;
            }
        }
示例#11
0
        //mxd. This checks if the thing has model override and whether pitch/roll values should be used
        internal void UpdateCache()
        {
            if (General.Map.Data == null)
            {
                return;
            }

            // Check if the thing has model override
            if (General.Map.Data.ModeldefEntries.ContainsKey(type))
            {
                ModelData md = General.Map.Data.ModeldefEntries[type];
                if ((md.LoadState == ModelLoadState.None && General.Map.Data.ProcessModel(type)) || md.LoadState != ModelLoadState.None)
                {
                    rendermode = (General.Map.Data.ModeldefEntries[type].IsVoxel ? ThingRenderMode.VOXEL : ThingRenderMode.MODEL);
                }
            }

            // Update radian versions of pitch and roll
            switch (rendermode)
            {
            case ThingRenderMode.MODEL:
                ModelData md = General.Map.Data.ModeldefEntries[type];
                rollrad  = (md.UseActorRoll ? Angle2D.DegToRad(roll) : 0);
                pitchrad = ((md.InheritActorPitch || md.UseActorPitch) ? Angle2D.DegToRad(md.InheritActorPitch ? -pitch : pitch) : 0);
                break;

            case ThingRenderMode.FLATSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = Angle2D.DegToRad(pitch);
                break;

            case ThingRenderMode.WALLSPRITE:
                rollrad  = Angle2D.DegToRad(roll);
                pitchrad = 0;
                break;

            case ThingRenderMode.NORMAL:
                rollrad  = (rollsprite ? Angle2D.DegToRad(roll) : 0);
                pitchrad = 0;
                break;

            case ThingRenderMode.VOXEL:
                rollrad  = 0;
                pitchrad = 0;
                break;

            default: throw new NotImplementedException("Unknown ThingRenderMode");
            }
        }
示例#12
0
        // Constructor
        internal Renderer3D(D3DDevice graphics) : base(graphics)
        {
            // Initialize
            CreateProjection();
            CreateMatrices2D();
            SetupThingCage();
            SetupTextures();
            renderthingcages = true;
            showselection    = true;
            showhighlight    = true;

            // Dummy frustum
            frustum = new ProjectedFrustum2D(new Vector2D(), 0.0f, 0.0f, PROJ_NEAR_PLANE,
                                             General.Settings.ViewDistance, Angle2D.DegToRad(General.Settings.VisualFOV));
        }
示例#13
0
        // This creates matrices for a camera view
        public void PositionAndLookAt(Vector3D pos, Vector3D lookat)
        {
            // Calculate delta vector
            cameraposition = pos;
            Vector3D delta   = lookat - pos;
            float    anglexy = delta.GetAngleXY();
            float    anglez  = delta.GetAngleZ();

            // Create frustum
            frustum = new ProjectedFrustum2D(pos, anglexy, anglez, PROJ_NEAR_PLANE,
                                             General.Settings.ViewDistance, Angle2D.DegToRad(General.Settings.VisualFOV));

            // Make the view matrix
            view3d = Matrix.LookAtRH(D3DDevice.V3(pos), D3DDevice.V3(lookat), new Vector3(0f, 0f, 1f));

            // Make the billboard matrix
            billboard = Matrix.RotationZ(anglexy + Angle2D.PI);
        }
示例#14
0
        // This creates the projection
        internal void CreateProjection()
        {
            // Calculate aspect
            float aspect = (float)General.Map.Graphics.RenderTarget.ClientSize.Width /
                           (float)General.Map.Graphics.RenderTarget.ClientSize.Height;

            // The DirectX PerspectiveFovRH matrix method calculates the scaling in X and Y as follows:
            // yscale = 1 / tan(fovY / 2)
            // xscale = yscale / aspect
            // The fov specified in the method is the FOV over Y, but we want the user to specify the FOV
            // over X, so calculate what it would be over Y first;
            float fov         = Angle2D.DegToRad((float)General.Settings.VisualFOV);
            float reversefov  = 1.0f / (float)Math.Tan(fov / 2.0f);
            float reversefovy = reversefov * aspect;
            float fovy        = (float)Math.Atan(1.0f / reversefovy) * 2.0f;

            // Make the projection matrix
            projection = Matrix.PerspectiveFovRH(fovy, aspect, PROJ_NEAR_PLANE, General.Settings.ViewDistance);

            // Apply matrices
            ApplyMatrices3D();
        }
        /*public DrawEllipseMode()
         * {
         *      autoclosedrawing = false;
         * }*/

        #endregion

        #region ================== Settings panel

        override protected void SetupInterface()
        {
            maxsubdivisions        = 512;
            minsubdivisions        = 3;
            minpointscount         = 3;
            alwaysrendershapehints = true;

            // Load stored settings
            subdivisions = General.Clamp(General.Settings.ReadPluginSetting("drawellipsemode.subdivisions", 8), minsubdivisions, maxsubdivisions);
            int angledeg = General.Settings.ReadPluginSetting("drawellipsemode.angle", 0);

            angle = Angle2D.DegToRad(angledeg);
            //currentbevelwidth = bevelwidth;

            //Add options docker
            panel = new DrawEllipseOptionsPanel();
            panel.MaxSubdivisions = maxsubdivisions;
            panel.MinSubdivisions = minsubdivisions;
            panel.Angle           = angledeg;
            panel.Subdivisions    = subdivisions;
            panel.OnValueChanged += OptionsPanelOnValueChanged;
        }
示例#16
0
        /// <summary>
        /// Updates the arch with the values currently entered in the dialog
        /// </summary>
        private void UpdateArch()
        {
            double t = theta.GetResultFloat(originaltheta);
            double o = offset.GetResultFloat(originaloffset);
            double s = scale.GetResultFloat(originalscale * 100.0) / 100.0;

            // Flip the scale if "down" is checked
            if (!up.Checked)
            {
                s *= -1.0;
            }

            slopearcher.Theta        = Angle2D.DegToRad(t);
            slopearcher.OffsetAngle  = Angle2D.DegToRad(o);
            slopearcher.Scale        = s;
            slopearcher.HeightOffset = heightoffset.GetResultFloat(originalheightoffset);

            slopearcher.ApplySlope();

            // BaseVisualMode added a event handler to the dialog, so BaseVisualMode will update the geometry when we tell it to
            UpdateChangedObjects?.Invoke(this, EventArgs.Empty);
        }
示例#17
0
        // Redraw the control
        private void AngleControl_Paint(object sender, PaintEventArgs e)
        {
            float rad = Angle2D.DegToRad((float)angle);

            e.Graphics.PixelOffsetMode   = PixelOffsetMode.HighQuality;
            e.Graphics.InterpolationMode = InterpolationMode.High;
            e.Graphics.SmoothingMode     = SmoothingMode.HighQuality;
            e.Graphics.Clear(this.BackColor);
            Pen    linepen     = new Pen(SystemColors.ControlText, LINE_THICKNESS);
            PointF start       = new PointF((float)this.Size.Width * 0.5f, (float)this.Size.Height * 0.5f);
            float  line_length = (float)this.Size.Width * 0.26f;

            if ((rad >= 0) && (rad < 360))
            {
                PointF end = new PointF(start.X + (float)Math.Sin(rad + Angle2D.PIHALF) * line_length,
                                        start.Y + (float)Math.Cos(rad + Angle2D.PIHALF) * line_length);
                e.Graphics.DrawLine(linepen, start, end);
            }
            else
            {
                e.Graphics.DrawLine(linepen, start, start);
            }
        }
示例#18
0
        // This makes sure we are updated with the source linedef information
        public override void Update()
        {
            ThingData td = data.Mode.GetThingData(thing);
            Thing     t  = thing;

            // Floor slope thing
            if (t.Type == 9502)
            {
                t.DetermineSector(data.Mode.BlockMap);
                if (t.Sector != null)
                {
                    //mxd. Vertex zheight overrides this effect
                    if (General.Map.UDMF && t.Sector.Sidedefs.Count == 3)
                    {
                        foreach (Sidedef side in t.Sector.Sidedefs)
                        {
                            if (!double.IsNaN(side.Line.Start.ZFloor) || !double.IsNaN(side.Line.End.ZFloor))
                            {
                                return;
                            }
                        }
                    }

                    double   angle         = Angle2D.DoomToReal((int)Angle2D.RadToDeg(t.Angle));
                    double   vangle        = Angle2D.DegToRad(General.Clamp(t.Args[0], 0, 180));            //mxd. Don't underestimate user stupidity (or curiosity)!
                    Vector2D point         = new Vector2D(t.Position.x + Math.Cos(angle) * Math.Sin(vangle), t.Position.y + Math.Sin(angle) * Math.Sin(vangle));
                    Vector2D perpendicular = new Line2D(t.Position, point).GetPerpendicular();

                    Vector3D v1 = new Vector3D(t.Position.x, t.Position.y, t.Position.z + t.Sector.FloorHeight);

                    Vector3D v2 = new Vector3D(
                        point.x + perpendicular.x,
                        point.y + perpendicular.y,
                        t.Position.z + t.Sector.FloorHeight + Math.Cos(vangle)
                        );

                    Vector3D v3 = new Vector3D(
                        point.x - perpendicular.x,
                        point.y - perpendicular.y,
                        t.Position.z + t.Sector.FloorHeight + Math.Cos(vangle)
                        );

                    SectorData sd = data.Mode.GetSectorData(t.Sector);
                    sd.AddUpdateSector(data.Sector, true);
                    if (!sd.Updated)
                    {
                        sd.Update();
                    }
                    td.AddUpdateSector(t.Sector, true);
                    sd.Floor.plane = new Plane(v1, v2, v3, true);
                }
            }
            // Ceiling slope thing
            else if (t.Type == 9503)
            {
                t.DetermineSector(data.Mode.BlockMap);
                if (t.Sector != null)
                {
                    //mxd. Vertex zheight overrides this effect
                    if (General.Map.UDMF && t.Sector.Sidedefs.Count == 3)
                    {
                        foreach (Sidedef side in t.Sector.Sidedefs)
                        {
                            if (!double.IsNaN(side.Line.Start.ZCeiling) || !double.IsNaN(side.Line.End.ZCeiling))
                            {
                                return;
                            }
                        }
                    }

                    double   angle         = Angle2D.DoomToReal((int)Angle2D.RadToDeg(t.Angle));
                    double   vangle        = Angle2D.DegToRad(General.Clamp(t.Args[0], 0, 180));            //mxd. Don't underestimate user stupidity (or curiosity)!
                    Vector2D point         = new Vector2D(t.Position.x + Math.Cos(angle) * Math.Sin(vangle), t.Position.y + Math.Sin(angle) * Math.Sin(vangle));
                    Vector2D perpendicular = new Line2D(t.Position, point).GetPerpendicular();

                    Vector3D v1 = new Vector3D(t.Position.x, t.Position.y, t.Position.z + t.Sector.CeilHeight);

                    Vector3D v2 = new Vector3D(
                        point.x + perpendicular.x,
                        point.y + perpendicular.y,
                        t.Position.z + t.Sector.CeilHeight + Math.Cos(vangle)
                        );

                    Vector3D v3 = new Vector3D(
                        point.x - perpendicular.x,
                        point.y - perpendicular.y,
                        t.Position.z + t.Sector.CeilHeight + Math.Cos(vangle)
                        );

                    SectorData sd = data.Mode.GetSectorData(t.Sector);
                    sd.AddUpdateSector(data.Sector, true);
                    if (!sd.Updated)
                    {
                        sd.Update();
                    }
                    td.AddUpdateSector(t.Sector, true);
                    sd.Ceiling.plane = new Plane(v1, v2, v3, false);
                }
            }
        }
示例#19
0
        //mxd
        public bool Setup(SectorLevel level, Effect3DFloor extrafloor, bool innerside)
        {
            Sector   s = level.sector;
            Vector2D texscale;

            this.innerside = innerside;

            base.Setup(level, extrafloor);

            // Fetch ZDoom fields
            float    rotate = Angle2D.DegToRad(s.Fields.GetValue("rotationfloor", 0.0f));
            Vector2D offset = new Vector2D(s.Fields.GetValue("xpanningfloor", 0.0f),
                                           s.Fields.GetValue("ypanningfloor", 0.0f));
            Vector2D scale = new Vector2D(s.Fields.GetValue("xscalefloor", 1.0f),
                                          s.Fields.GetValue("yscalefloor", 1.0f));

            //Load floor texture
            if (s.LongFloorTexture != MapSet.EmptyLongName)
            {
                base.Texture = General.Map.Data.GetFlatImage(s.LongFloorTexture);
                if (base.Texture == null || base.Texture is UnknownImage)
                {
                    base.Texture         = General.Map.Data.UnknownTexture3D;
                    setuponloadedtexture = s.LongFloorTexture;
                }
                else if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongFloorTexture;
                }
            }
            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
            int color = PixelColor.FromInt(level.color).WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

            //mxd. Top extrafloor level should calculate fogdensity
            //from the brightness of the level above it
            int targetbrightness;

            if (extrafloor != null && extrafloor.VavoomType && !level.disablelighting)
            {
                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;
                    }
                }
            }
            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
            UpdateSkyRenderFlag();

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
        /// <summary>
        /// Exports the sectors to images
        /// </summary>
        public void Export()
        {
            Bitmap   texturebitmap   = null;
            Bitmap   brightmapbitmap = null;
            Graphics gbrightmap      = null;
            Graphics gtexture        = null;
            Vector2D offset;
            Vector2D size;

            GetSizeAndOffset(out size, out offset);

            // Normal texture
            texturebitmap = new Bitmap((int)size.x, (int)size.y, settings.PixelFormat);
            gtexture      = Graphics.FromImage(texturebitmap);
            gtexture.Clear(Color.Black);             // If we don't clear to black we'll see seams where the sectors touch, due to the AA
            gtexture.InterpolationMode  = InterpolationMode.HighQualityBilinear;
            gtexture.CompositingQuality = CompositingQuality.HighQuality;
            gtexture.PixelOffsetMode    = PixelOffsetMode.HighQuality;
            gtexture.SmoothingMode      = SmoothingMode.AntiAlias;        // Without AA the sector edges will be quite rough

            // Brightmap
            if (settings.Brightmap)
            {
                brightmapbitmap = new Bitmap((int)size.x, (int)size.y, settings.PixelFormat);
                gbrightmap      = Graphics.FromImage(brightmapbitmap);
                gbrightmap.Clear(Color.Black);                 // If we don't clear to black we'll see seams where the sectors touch, due to the AA
                gbrightmap.InterpolationMode  = InterpolationMode.HighQualityBilinear;
                gbrightmap.CompositingQuality = CompositingQuality.HighQuality;
                gbrightmap.PixelOffsetMode    = PixelOffsetMode.HighQuality;
                gbrightmap.SmoothingMode      = SmoothingMode.AntiAlias;            // Without AA the sector edges will be quite rough
            }

            foreach (Sector s in sectors)
            {
                GraphicsPath p        = new GraphicsPath();
                float        rotation = (float)s.Fields.GetValue("rotationfloor", 0.0);

                // If a sector is rotated any offset is on the rotated axes. But we need to offset by
                // map coordinates. We'll use this vector to compute that offset
                Vector2D rotationvector = Vector2D.FromAngle(Angle2D.DegToRad(rotation) + Angle2D.PIHALF);

                // Sectors are triangulated, so draw every triangle
                for (int i = 0; i < s.Triangles.Vertices.Count / 3; i++)
                {
                    // The GDI image has the 0/0 coordinate in the top left, so invert the y component
                    Vector2D v1 = s.Triangles.Vertices[i * 3] - offset; v1.y *= -1.0;
                    Vector2D v2 = s.Triangles.Vertices[i * 3 + 1] - offset; v2.y *= -1.0;
                    Vector2D v3 = s.Triangles.Vertices[i * 3 + 2] - offset; v3.y *= -1.0;

                    p.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
                    p.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
                    p.CloseFigure();
                }

                Bitmap brushtexture;

                if (settings.Floor)
                {
                    brushtexture = General.Map.Data.GetFlatImage(s.FloorTexture).ExportBitmap();
                }
                else
                {
                    brushtexture = General.Map.Data.GetFlatImage(s.CeilTexture).ExportBitmap();
                }

                if (!settings.Fullbright)
                {
                    brushtexture = AdjustBrightness(brushtexture, s.Brightness > 0 ? s.Brightness / 255.0f : 0.0f);
                }

                Vector2D textureoffset = new Vector2D();
                textureoffset.x = s.Fields.GetValue("xpanningfloor", 0.0);
                textureoffset.y = s.Fields.GetValue("ypanningfloor", 0.0);

                // Create the transformation matrix
                Matrix matrix = new Matrix();
                matrix.Rotate(rotation);
                matrix.Translate((float)(-offset.x * rotationvector.x), (float)(offset.x * rotationvector.y)); // Left/right offset from the map origin
                matrix.Translate((float)(offset.y * rotationvector.y), (float)(offset.y * rotationvector.x));  // Up/down offset from the map origin
                matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y);                            // Texture offset

                // Create the texture brush and apply the matrix
                TextureBrush tbrush = new TextureBrush(brushtexture);
                tbrush.Transform = matrix;

                // Draw the islands of the sector
                gtexture.FillPath(tbrush, p);

                // Create the brightmap based on the sector brightness
                if (settings.Brightmap)
                {
                    SolidBrush sbrush = new SolidBrush(Color.FromArgb(255, s.Brightness, s.Brightness, s.Brightness));
                    gbrightmap.FillPath(sbrush, p);
                }
            }

            // Finally save the image(s)
            if (settings.Tiles)
            {
                SaveImageAsTiles(texturebitmap);

                if (settings.Brightmap)
                {
                    SaveImageAsTiles(brightmapbitmap, "_brightmap");
                }
            }
            else
            {
                texturebitmap.Save(Path.Combine(settings.Path, settings.Name) + settings.Extension, settings.ImageFormat);

                if (settings.Brightmap)
                {
                    brightmapbitmap.Save(Path.Combine(settings.Path, settings.Name) + "_brightmap" + settings.Extension, settings.ImageFormat);
                }
            }
        }
示例#21
0
        /// <summary>
        /// This loads all nodes structures data from the lumps
        /// </summary>
        private bool LoadClassicStructures()
        {
            // Load the nodes structure
            MemoryStream nodesstream = General.Map.GetLumpData("NODES");
            int          numnodes    = (int)nodesstream.Length / 28;

            //mxd. Boilerplate!
            if (numnodes < 1)
            {
                // Cancel mode
                MessageBox.Show("The map has only one subsector. Please add more sectors, then try running this mode again.", "THY NODETH ARETH BROKH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                General.Editing.CancelMode();
                return(false);
            }

            BinaryReader nodesreader = new BinaryReader(nodesstream);

            nodes = new Node[numnodes];
            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i].linestart.x = nodesreader.ReadInt16();
                nodes[i].linestart.y = nodesreader.ReadInt16();
                nodes[i].linedelta.x = nodesreader.ReadInt16();
                nodes[i].linedelta.y = nodesreader.ReadInt16();
                float top   = nodesreader.ReadInt16();
                float bot   = nodesreader.ReadInt16();
                float left  = nodesreader.ReadInt16();
                float right = nodesreader.ReadInt16();
                nodes[i].rightbox = new RectangleF(left, top, (right - left), (bot - top));
                top              = nodesreader.ReadInt16();
                bot              = nodesreader.ReadInt16();
                left             = nodesreader.ReadInt16();
                right            = nodesreader.ReadInt16();
                nodes[i].leftbox = new RectangleF(left, top, (right - left), (bot - top));
                int rightindex = nodesreader.ReadInt16();
                int leftindex  = nodesreader.ReadInt16();
                nodes[i].rightchild     = rightindex & 0x7FFF;
                nodes[i].leftchild      = leftindex & 0x7FFF;
                nodes[i].rightsubsector = (rightindex & 0x8000) != 0;
                nodes[i].leftsubsector  = (leftindex & 0x8000) != 0;
            }
            nodesreader.Close();

            // Add additional properties to nodes
            nodes[nodes.Length - 1].parent = -1;
            SetupNodes();             //mxd

            // Load the segs structure
            MemoryStream segsstream = General.Map.GetLumpData("SEGS");
            BinaryReader segsreader = new BinaryReader(segsstream);
            int          numsegs    = (int)segsstream.Length / 12;

            //mxd. Boilerplate!
            if (numsegs < 1)
            {
                // Cancel mode
                MessageBox.Show("The map has empty SEGS lump. Please rebuild the nodes, then try running this mode again.", "THY SEGS HATH SINNETH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                General.Editing.CancelMode();
                return(false);
            }

            //mxd. ZDoom SEGS overflow error
            if (numsegs >= ushort.MaxValue)
            {
                // Cancel mode
                MessageBox.Show("The map has too many SEGS (" + numsegs + "/" + ushort.MaxValue + ").\nIt won't load in Vanilla-style source ports\nand may not load in some enhanced source ports.", "THY SEGS ARETH WAAAY TOO PHAT!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                General.Editing.CancelMode();
                return(false);
            }
            //mxd. Vanilla SEGS overflow warning
            else if (numsegs >= short.MaxValue)
            {
                MessageBox.Show("The map has too many SEGS (" + numsegs + "/" + short.MaxValue + ").\nIt won't load in Vanilla-style source ports.", "THY SEGS ARETH TOO PHAT!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            segs = new Seg[numsegs];
            for (int i = 0; i < segs.Length; i++)
            {
                segs[i].startvertex = segsreader.ReadUInt16();
                segs[i].endvertex   = segsreader.ReadUInt16();
                segs[i].angle       = Angle2D.DegToRad(General.ClampAngle(segsreader.ReadInt16() / 182 + 90));           //mxd 182 == 65536 / 360;
                segs[i].lineindex   = segsreader.ReadUInt16();
                segs[i].leftside    = segsreader.ReadInt16() != 0;
                segs[i].offset      = segsreader.ReadInt16();
            }
            segsreader.Close();

            // Load the vertexes structure
            MemoryStream vertsstream = General.Map.GetLumpData("VERTEXES");
            BinaryReader vertsreader = new BinaryReader(vertsstream);
            int          numverts    = (int)vertsstream.Length / 4;

            //mxd. Boilerplate!
            if (numverts < 1)
            {
                // Cancel mode
                MessageBox.Show("The map has empty VERTEXES lump. Please rebuild the nodes, then try running this mode again.", "THY VERTEXES ARETH FOUL!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                General.Editing.CancelMode();
                return(false);
            }

            verts = new Vector2D[numverts];
            for (int i = 0; i < verts.Length; i++)
            {
                verts[i].x = vertsreader.ReadInt16();
                verts[i].y = vertsreader.ReadInt16();
            }
            vertsreader.Close();

            // Load the subsectors structure
            MemoryStream ssecstream = General.Map.GetLumpData("SSECTORS");
            BinaryReader ssecreader = new BinaryReader(ssecstream);
            int          numssec    = (int)ssecstream.Length / 4;

            //mxd. Boilerplate!
            if (numssec < 1)
            {
                // Cancel mode
                MessageBox.Show("The map has empty SSECTORS lump. Please rebuild the nodes, then try running this mode again.", "THY SSECTORS ARETH HERETYSH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                General.Editing.CancelMode();
                return(false);
            }

            ssectors = new Subsector[numssec];
            for (int i = 0; i < ssectors.Length; i++)
            {
                ssectors[i].numsegs  = ssecreader.ReadUInt16();                //TECH: these are short in Doom, ushort in ZDoom/PRBoom+
                ssectors[i].firstseg = ssecreader.ReadUInt16();
            }
            ssecreader.Close();

            // Link all segs to their subsectors
            for (int i = 0; i < ssectors.Length; i++)
            {
                int lastseg = ssectors[i].firstseg + ssectors[i].numsegs - 1;
                for (int sg = ssectors[i].firstseg; sg <= lastseg; sg++)
                {
                    segs[sg].ssector = i;
                }
            }

            return(true);
        }
        // This returns the aligned and snapped draw position
        public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, bool snaptocardinal, bool usefourcardinaldirections, IRenderer2D renderer, List <DrawnVertex> points)
        {
            DrawnVertex p = new DrawnVertex();

            p.stitch       = true;                                 //mxd. Setting these to false seems to be a good way to create invalid geometry...
            p.stitchline   = true;                                 //mxd
            snaptocardinal = (snaptocardinal && points.Count > 0); //mxd. Don't snap to cardinal when there are no points

            //mxd. If snap to cardinal directions is enabled and we have points, modify mouse position
            Vector2D vm, gridoffset;

            if (snaptocardinal)
            {
                Vector2D offset = mousemappos - points[points.Count - 1].pos;

                float angle;
                if (usefourcardinaldirections)
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()))) / 90 * 90 + 45);
                }
                else
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 22)) / 45 * 45);
                }

                offset = new Vector2D(0, -offset.GetLength()).GetRotated(angle);
                vm     = points[points.Count - 1].pos + offset;

                //mxd. We need to be snapped relative to initial position
                Vector2D prev = points[points.Count - 1].pos;
                gridoffset = prev - General.Map.Grid.SnappedToGrid(prev);
            }
            else
            {
                vm         = mousemappos;
                gridoffset = new Vector2D();
            }

            float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

            // Snap to nearest?
            if (snaptonearest)
            {
                // Go for all drawn points
                foreach (DrawnVertex v in points)
                {
                    if (Vector2D.DistanceSq(vm, v.pos) < (vrange * vrange))
                    {
                        p.pos = v.pos;
                        return(p);
                    }
                }

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(vm, vrange);
                if (nv != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D ourline = new Line2D(points[points.Count - 1].pos, vm);
                        if (Math.Round(ourline.GetSideOfLine(nv.Position), 1) == 0)
                        {
                            p.pos = nv.Position;
                            return(p);
                        }
                    }
                    else
                    {
                        p.pos = nv.Position;
                        return(p);
                    }
                }

                // Try the nearest linedef. mxd. We'll need much bigger stitch distance when snapping to cardinal directions
                Linedef nl = General.Map.Map.NearestLinedefRange(vm, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D   ourline      = new Line2D(points[points.Count - 1].pos, vm);
                        Line2D   nearestline  = new Line2D(nl.Start.Position, nl.End.Position);
                        Vector2D intersection = Line2D.GetIntersectionPoint(nearestline, ourline, false);
                        if (!float.IsNaN(intersection.x))
                        {
                            // Intersection is on nearestline?
                            float u = Line2D.GetNearestOnLine(nearestline.v1, nearestline.v2, intersection);

                            if (u < 0f || u > 1f)
                            {
                            }
                            else
                            {
                                p.pos = new Vector2D((float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals),
                                                     (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals));
                                return(p);
                            }
                        }
                    }
                    // Snap to grid?
                    else if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections(General.Map.Grid.GridRotate,
                                                                         General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY);

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = vm - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            p.pos = found_coord;
                            return(p);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        p.pos = nl.NearestOnLine(vm);
                        return(p);
                    }
                }
            }
            else
            {
                // Always snap to the first drawn vertex so that the user can finish a complete sector without stitching
                if (points.Count > 0)
                {
                    if (Vector2D.DistanceSq(vm, points[0].pos) < (vrange * vrange))
                    {
                        p.pos = points[0].pos;
                        return(p);
                    }
                }
            }

            // if the mouse cursor is outside the map bondaries check if the line between the last set point and the
            // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection
            if (points.Count > 0 &&
                (mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary ||
                 mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary))
            {
                Line2D        dline             = new Line2D(mousemappos, points[points.Count - 1].pos);
                bool          foundintersection = false;
                float         u      = 0.0f;
                List <Line2D> blines = new List <Line2D>();

                // lines for left, top, right and bottom boundaries
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary));

                // check for intersections with boundaries
                for (int i = 0; i < blines.Count; i++)
                {
                    if (!foundintersection)
                    {
                        // only check for intersection if the last set point is not on the
                        // line we are checking against
                        if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f)
                        {
                            foundintersection = blines[i].GetIntersection(dline, out u);
                        }
                    }
                }

                // if there was no intersection set the position to the last set point
                if (!foundintersection)
                {
                    vm = points[points.Count - 1].pos;
                }
                else
                {
                    vm = dline.GetCoordinatesAt(u);
                }
            }

            // Snap to grid?
            if (snaptogrid)
            {
                // Aligned to grid
                p.pos = General.Map.Grid.SnappedToGrid(vm - gridoffset) + gridoffset;

                // special handling
                if (p.pos.x > General.Map.Config.RightBoundary)
                {
                    p.pos.x = General.Map.Config.RightBoundary;
                }
                if (p.pos.y < General.Map.Config.BottomBoundary)
                {
                    p.pos.y = General.Map.Config.BottomBoundary;
                }

                return(p);
            }
            else
            {
                // Normal position
                p.pos.x = (float)Math.Round(vm.x);                 //mxd
                p.pos.y = (float)Math.Round(vm.y);                 //mxd

                return(p);
            }
        }
示例#23
0
        // This builds the geometry. Returns false when no geometry created.
        public override bool Setup(SectorLevel level, Effect3DFloor extrafloor)
        {
            WorldVertex[] verts;
            Sector        s = level.sector;
            Vector2D      texscale;

            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 floor texture
            base.Texture = General.Map.Data.GetFlatImage(s.LongCeilTexture);
            if (base.Texture == null)
            {
                base.Texture         = General.Map.Data.MissingTexture3D;
                setuponloadedtexture = s.LongCeilTexture;
            }
            else
            {
                if (!base.Texture.IsImageLoaded)
                {
                    setuponloadedtexture = s.LongCeilTexture;
                }
            }

            // 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);
            }

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

            verts = new WorldVertex[triverts.Count];
            for (int i = 0; i < triverts.Count; i++)
            {
                // Color shading
                PixelColor c = PixelColor.FromInt(level.color);
                verts[i].c = c.WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();

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

                // 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)
            {
                SwapTriangleVertices(verts);
            }

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

            // Apply vertices
            base.SetVertices(verts);
            return(verts.Length > 0);
        }
 private void DecreaseAngle()
 {
     panel.Angle = General.ClampAngle(panel.Angle - 5);
     angle       = Angle2D.DegToRad(panel.Angle);
     Update();
 }
        // Apply clicked
        private void apply_Click(object sender, EventArgs e)
        {
            //mxd. Make Undo
            MakeUndo();

            List <string> defaultflags = new List <string>();

            // Verify the tag
            if (General.Map.FormatInterface.HasThingTag)  //mxd
            {
                tagSelector.ValidateTag();                //mxd
                if (((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag)))
                {
                    General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
                    return;
                }
            }

            // Verify the type
            if (!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)))
            {
                General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
                return;
            }

            // Verify the action
            if (General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction)))
            {
                General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK);
                return;
            }

            // Go for all the things
            int offset = 0;             //mxd

            foreach (Thing t in things)
            {
                // Coordination
                //mxd. Randomize rotations?
                if (cbrandomangle.Checked)
                {
                    int newangle = General.Random(0, 359);
                    if (General.Map.Config.DoomThingRotationAngles)
                    {
                        newangle = newangle / 45 * 45;
                    }
                    t.Rotate(newangle);
                }
                if (cbrandompitch.Checked)
                {
                    t.SetPitch(General.Random(0, 359));
                }
                if (cbrandomroll.Checked)
                {
                    t.SetRoll(General.Random(0, 359));
                }

                //mxd. Check position
                double px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
                double py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary);
                if (t.Position.x != px || t.Position.y != py)
                {
                    t.Move(new Vector2D(px, py));
                }

                // Action/tags
                t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag);                 //mxd
                if (!action.Empty)
                {
                    t.Action = action.Value;
                }

                //mxd. Apply args
                argscontrol.Apply(t, offset);

                //mxd. Custom fields
                fieldslist.Apply(t.Fields);
                if (!string.IsNullOrEmpty(conversationID.Text))
                {
                    UniFields.SetInteger(t.Fields, "conversation", conversationID.GetResult(t.Fields.GetValue("conversation", 0)), 0);
                }
                if (!string.IsNullOrEmpty(floatbobphase.Text))
                {
                    UniFields.SetInteger(t.Fields, "floatbobphase", General.Clamp(floatbobphase.GetResult(t.Fields.GetValue("floatbobphase", -1)), -1, 63), -1);
                }
                if (!string.IsNullOrEmpty(gravity.Text))
                {
                    UniFields.SetFloat(t.Fields, "gravity", gravity.GetResultFloat(t.Fields.GetValue("gravity", 1.0)), 1.0);
                }
                if (!string.IsNullOrEmpty(health.Text))
                {
                    UniFields.SetInteger(t.Fields, "health", health.GetResult(t.Fields.GetValue("health", 1)), 1);
                }
                if (!string.IsNullOrEmpty(score.Text))
                {
                    UniFields.SetInteger(t.Fields, "score", score.GetResult(t.Fields.GetValue("score", 0)), 0);
                }

                //mxd. User vars. Should be called after fieldslist.Apply()
                ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
                if (ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0)
                {
                    fieldslist.ApplyUserVars(ti.Actor.UserVars, t.Fields);
                }

                color.ApplyTo(t.Fields, t.Fields.GetValue("fillcolor", 0));

                //mxd. Comments
                commenteditor.Apply(t.Fields);

                // Update settings
                t.UpdateConfiguration();

                //mxd. Increase offset...
                offset++;
            }

            // Set as defaults
            foreach (CheckBox c in flags.Checkboxes)
            {
                if (c.CheckState == CheckState.Checked)
                {
                    defaultflags.Add(c.Tag.ToString());
                }
            }
            General.Settings.DefaultThingType  = thingtype.GetResult(General.Settings.DefaultThingType);
            General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
            General.Settings.SetDefaultThingFlags(defaultflags);

            // Done
            General.Map.IsChanged = true;
            if (OnValuesChanged != null)
            {
                OnValuesChanged(this, EventArgs.Empty);                                     //mxd
            }
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        // Apply clicked
        private void apply_Click(object sender, EventArgs e)
        {
            MakeUndo();

            List <string> defaultflags = new List <string>();

            // Verify the tag
            if (General.Map.FormatInterface.HasThingTag)  //mxd
            {
                tagSelector.ValidateTag();                //mxd
                if (((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag)))
                {
                    General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
                    return;
                }
            }

            // Verify the type
            if (!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)))
            {
                General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
                return;
            }

            // Verify the action
            if (General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction)))
            {
                General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK);
                return;
            }

            // Go for all the things
            int offset = 0;             //mxd

            foreach (Thing t in things)
            {
                // Coordination
                if (cbRandomAngle.Checked)                //mxd
                {
                    int newangle = General.Random(0, 359);
                    if (General.Map.Config.DoomThingRotationAngles)
                    {
                        newangle = newangle / 45 * 45;
                    }
                    t.Rotate(newangle);
                }

                //mxd. Check position
                float px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
                float py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary);
                if (t.Position.x != px || t.Position.y != py)
                {
                    t.Move(new Vector2D(px, py));
                }

                // Apply all flags
                foreach (CheckBox c in flags.Checkboxes)
                {
                    switch (c.CheckState)
                    {
                    case CheckState.Checked: t.SetFlag(c.Tag.ToString(), true); break;

                    case CheckState.Unchecked: t.SetFlag(c.Tag.ToString(), false); break;
                    }
                }

                // Action/tags
                t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag);                 //mxd
                if (!action.Empty)
                {
                    t.Action = action.Value;
                }

                //mxd. Apply args
                argscontrol.Apply(t, offset);

                // Update settings
                t.UpdateConfiguration();

                //mxd. Increase offset...
                offset++;
            }

            // Set as defaults
            foreach (CheckBox c in flags.Checkboxes)
            {
                if (c.CheckState == CheckState.Checked)
                {
                    defaultflags.Add(c.Tag.ToString());
                }
            }
            General.Settings.DefaultThingType  = thingtype.GetResult(General.Settings.DefaultThingType);
            General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
            General.Settings.SetDefaultThingFlags(defaultflags);

            // Done
            General.Map.IsChanged = true;
            if (OnValuesChanged != null)
            {
                OnValuesChanged(this, EventArgs.Empty);                                         //mxd
            }
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
示例#27
0
        //mxd
        protected void AlignTextureToSlopeLine(Linedef slopeSource, float slopeAngle, bool isFront, bool alignx, bool aligny)
        {
            bool isFloor = (geometrytype == VisualGeometryType.FLOOR);

            Sector.Sector.Fields.BeforeFieldsChange();
            float sourceAngle = (float)Math.Round(General.ClampAngle(isFront ? -Angle2D.RadToDeg(slopeSource.Angle) + 90 : -Angle2D.RadToDeg(slopeSource.Angle) - 90), 1);

            if (isFloor)
            {
                if ((isFront && slopeSource.Front.Sector.FloorHeight > slopeSource.Back.Sector.FloorHeight) ||
                    (!isFront && slopeSource.Front.Sector.FloorHeight < slopeSource.Back.Sector.FloorHeight))
                {
                    sourceAngle = General.ClampAngle(sourceAngle + 180);
                }
            }
            else
            {
                if ((isFront && slopeSource.Front.Sector.CeilHeight < slopeSource.Back.Sector.CeilHeight) ||
                    (!isFront && slopeSource.Front.Sector.CeilHeight > slopeSource.Back.Sector.CeilHeight))
                {
                    sourceAngle = General.ClampAngle(sourceAngle + 180);
                }
            }

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

            //update scaleY
            string xScaleKey = (isFloor ? "xscalefloor" : "xscaleceiling");
            string yScaleKey = (isFloor ? "yscalefloor" : "yscaleceiling");

            float scaleX = Sector.Sector.Fields.GetValue(xScaleKey, 1.0f);
            float scaleY;

            //set scale
            if (aligny)
            {
                scaleY = (float)Math.Round(scaleX * (1 / (float)Math.Cos(slopeAngle)), 2);
                UniFields.SetFloat(Sector.Sector.Fields, yScaleKey, scaleY, 1.0f);
            }
            else
            {
                scaleY = Sector.Sector.Fields.GetValue(yScaleKey, 1.0f);
            }

            //update texture offsets
            Vector2D offset;

            if (isFloor)
            {
                if ((isFront && slopeSource.Front.Sector.FloorHeight < slopeSource.Back.Sector.FloorHeight) ||
                    (!isFront && slopeSource.Front.Sector.FloorHeight > slopeSource.Back.Sector.FloorHeight))
                {
                    offset = slopeSource.End.Position;
                }
                else
                {
                    offset = slopeSource.Start.Position;
                }
            }
            else
            {
                if ((isFront && slopeSource.Front.Sector.CeilHeight > slopeSource.Back.Sector.CeilHeight) ||
                    (!isFront && slopeSource.Front.Sector.CeilHeight < slopeSource.Back.Sector.CeilHeight))
                {
                    offset = slopeSource.End.Position;
                }
                else
                {
                    offset = slopeSource.Start.Position;
                }
            }

            offset = offset.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);
        }
示例#28
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);
        }
示例#29
0
        // This is called to update UV dragging
        protected virtual void UpdateDragUV()
        {
            float u_ray = 1.0f;

            // Calculate intersection position
            this.Level.plane.GetIntersection(General.Map.VisualCamera.Position, General.Map.VisualCamera.Target, ref u_ray);
            Vector3D intersect = General.Map.VisualCamera.Position + (General.Map.VisualCamera.Target - General.Map.VisualCamera.Position) * u_ray;

            // Calculate offsets
            Vector3D dragdelta = intersect - dragorigin;
            float    offsetx   = dragdelta.x;
            float    offsety   = dragdelta.y;

            bool lockX = General.Interface.CtrlState && !General.Interface.ShiftState;
            bool lockY = !General.Interface.CtrlState && General.Interface.ShiftState;

            if (lockX || lockY)
            {
                float camAngle = Angle2D.RadToDeg(General.Map.VisualCamera.AngleXY);

                if (camAngle > 315 || camAngle < 46)
                {
                    if (lockX)
                    {
                        offsetx = 0;
                    }
                    if (lockY)
                    {
                        offsety = 0;
                    }
                }
                else if (camAngle > 225)
                {
                    if (lockX)
                    {
                        offsety = 0;
                    }
                    if (lockY)
                    {
                        offsetx = 0;
                    }
                }
                else if (camAngle > 135)
                {
                    if (lockX)
                    {
                        offsetx = 0;
                    }
                    if (lockY)
                    {
                        offsety = 0;
                    }
                }
                else
                {
                    if (lockX)
                    {
                        offsety = 0;
                    }
                    if (lockY)
                    {
                        offsetx = 0;
                    }
                }
            }

            //mxd. Modify offsets based on surface and camera angles
            float angle;

            if (GeometryType == VisualGeometryType.CEILING)
            {
                angle = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationceiling", 0f));
            }
            else
            {
                angle = Angle2D.DegToRad(level.sector.Fields.GetValue("rotationfloor", 0f));
            }

            Vector2D v = new Vector2D(offsetx, offsety).GetRotated(angle);

            offsetx = (int)Math.Round(v.x);
            offsety = (int)Math.Round(v.y);

            // Calculate deltas
            int deltax, deltay;

            if (General.Interface.CtrlState && General.Interface.ShiftState)
            {
                //mxd. Clamp to grid size?
                int newoffsetx = startoffsetx - (int)Math.Round(offsetx);
                int newoffsety = startoffsety + (int)Math.Round(offsety);
                deltax = prevoffsetx - newoffsetx;
                deltay = prevoffsety - newoffsety;

                if (Math.Abs(deltax) >= General.Map.Grid.GridSize)
                {
                    deltax      = General.Map.Grid.GridSize * Math.Sign(deltax);
                    prevoffsetx = newoffsetx;
                }
                else
                {
                    deltax = 0;
                }

                if (Math.Abs(deltay) >= General.Map.Grid.GridSize)
                {
                    deltay      = General.Map.Grid.GridSize * Math.Sign(deltay);
                    prevoffsety = newoffsety;
                }
                else
                {
                    deltay = 0;
                }
            }
            else
            {
                int newoffsetx = startoffsetx - (int)Math.Round(offsetx);
                int newoffsety = startoffsety + (int)Math.Round(offsety);

                deltax = prevoffsetx - newoffsetx;
                deltay = prevoffsety - newoffsety;

                prevoffsetx = newoffsetx;
                prevoffsety = newoffsety;
            }

            //mxd. Apply offset?
            if (deltax != 0 || deltay != 0)
            {
                mode.ApplyFlatOffsetChange(deltax, deltay);
            }
            mode.ShowTargetInfo();
        }
示例#30
0
        // Apply clicked
        private void apply_Click(object sender, EventArgs e)
        {
            List <string> defaultflags = new List <string>();
            string        undodesc     = "thing";

            // Verify the tag
            if (General.Map.FormatInterface.HasThingTag && ((tag.GetResult(0) < General.Map.FormatInterface.MinTag) || (tag.GetResult(0) > General.Map.FormatInterface.MaxTag)))
            {
                General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
                return;
            }

            // Verify the type
            if (((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)))
            {
                General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
                return;
            }

            // Verify the action
            if (General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction)))
            {
                General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK);
                return;
            }

            // Make undo
            if (things.Count > 1)
            {
                undodesc = things.Count + " things";
            }
            General.Map.UndoRedo.CreateUndo("Edit " + undodesc);

            // Go for all the things
            foreach (Thing t in things)
            {
                // Thing type index
                t.Type = General.Clamp(thingtype.GetResult(t.Type), General.Map.FormatInterface.MinThingType, General.Map.FormatInterface.MaxThingType);

                // Coordination
                t.Rotate(angle.GetResult(t.AngleDoom));
                t.Move(t.Position.x, t.Position.y, (float)height.GetResult((int)t.Position.z));

                // Apply all flags
                foreach (CheckBox c in flags.Checkboxes)
                {
                    if (c.CheckState == CheckState.Checked)
                    {
                        t.SetFlag(c.Tag.ToString(), true);
                    }
                    else if (c.CheckState == CheckState.Unchecked)
                    {
                        t.SetFlag(c.Tag.ToString(), false);
                    }
                }

                // Action/tags
                t.Tag = tag.GetResult(t.Tag);
                if (!action.Empty)
                {
                    t.Action = action.Value;
                }
                t.Args[0] = arg0.GetResult(t.Args[0]);
                t.Args[1] = arg1.GetResult(t.Args[1]);
                t.Args[2] = arg2.GetResult(t.Args[2]);
                t.Args[3] = arg3.GetResult(t.Args[3]);
                t.Args[4] = arg4.GetResult(t.Args[4]);

                // Custom fields
                fieldslist.Apply(t.Fields);

                // Update settings
                t.UpdateConfiguration();
            }

            // Set as defaults
            foreach (CheckBox c in flags.Checkboxes)
            {
                if (c.CheckState == CheckState.Checked)
                {
                    defaultflags.Add(c.Tag.ToString());
                }
            }
            General.Settings.DefaultThingType  = thingtype.GetResult(General.Settings.DefaultThingType);
            General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
            General.Settings.SetDefaultThingFlags(defaultflags);

            // Done
            General.Map.IsChanged = true;
            Cleanup();
            this.DialogResult = DialogResult.OK;
            this.Close();
        }