Added, Visual mode: added support for FLATSPRITE, ROLLSPRITE, WALLSPRITE and DONTFLIP sprite rendering flags. Removed the older GLOOME-specific implementation.

Changed, "Align Things to Nearest Linedef" action: the action can now also align things with FLATSPRITE and WALLSPRITE flags (previously only things with attached models were aligned).
Changed, "Align Things to Nearest Linedef" action: the action can now align things to the middle part of double-sided linedef, if it has a middle texture assigned.
This commit is contained in:
MaxED 2016-07-04 18:25:47 +00:00
parent 7ab0a86a92
commit 04de976acf
13 changed files with 161 additions and 108 deletions

View file

@ -705,7 +705,7 @@
<Compile Include="Actions\HintsManager.cs" />
<Compile Include="Config\AllTexturesSet.cs" />
<Compile Include="Config\FlagTranslation.cs" />
<Compile Include="Config\ModelAndLightRenderModes.cs" />
<Compile Include="Config\RenderModeEnums.cs" />
<Compile Include="Config\PasteOptions.cs" />
<Compile Include="Config\ScriptDocumentSettings.cs" />
<Compile Include="Config\SectorEffectData.cs" />

View file

@ -14,4 +14,12 @@
ALL,
ALL_ANIMATED,
}
public enum ThingRenderMode
{
NORMAL,
MODEL,
WALLSPRITE,
FLATSPRITE,
}
}

View file

@ -85,10 +85,10 @@ namespace CodeImp.DoomBuilder.Config
private bool obsolete; //mxd
private string obsoletemessage; //mxd
//mxd. GLOOME rendering settings
private Thing.SpriteRenderMode rendermode;
//mxd. GZDoom rendering properties
private ThingRenderMode rendermode;
private bool rollsprite;
private bool sticktoplane;
private bool dontflip;
#endregion
@ -125,10 +125,10 @@ namespace CodeImp.DoomBuilder.Config
public string ClassName { get { return classname; } } //mxd. Need this to add model overrides for things defined in configs
public string LightName { get { return lightname; } } //mxd
//mxd. GLOOME rendering flags
public Thing.SpriteRenderMode RenderMode { get { return rendermode; } }
//mxd. GZDoom rendering properties
public ThingRenderMode RenderMode { get { return rendermode; } }
public bool RollSprite { get { return rollsprite; } }
public bool StickToPlane { get { return sticktoplane; } }
public bool DontFlip { get { return dontflip; } }
#endregion
@ -391,9 +391,9 @@ namespace CodeImp.DoomBuilder.Config
this.xybillboard = other.xybillboard; //mxd
this.spritescale = new SizeF(other.spritescale.Width, other.spritescale.Height);
//mxd. Copy GLOOME properties
//mxd. Copy GZDoom rendering properties
this.rendermode = other.rendermode;
this.sticktoplane = other.sticktoplane;
this.dontflip = other.dontflip;
this.rollsprite = other.rollsprite;
// We have no destructor
@ -527,13 +527,22 @@ namespace CodeImp.DoomBuilder.Config
blocking = actor.GetFlagValue("solid", (blocking != 0)) ? blockvalue : 0;
xybillboard = actor.GetFlagValue("forcexybillboard", false); //mxd
//mxd. GLOOME rendering flags. ORDER: WALLSPRITE -> FLOORSPRITE || CEILSPRITE
//mxd. GZDoom rendering flags
rollsprite = actor.GetFlagValue("rollsprite", false);
if(actor.GetFlagValue("wallsprite", false)) rendermode = Thing.SpriteRenderMode.WALL_SPRITE;
else if(actor.GetFlagValue("floorsprite", false)) rendermode = Thing.SpriteRenderMode.FLOOR_SPRITE;
else if(actor.GetFlagValue("ceilsprite", false)) rendermode = Thing.SpriteRenderMode.CEILING_SPRITE;
if(rendermode == Thing.SpriteRenderMode.FLOOR_SPRITE || rendermode == Thing.SpriteRenderMode.CEILING_SPRITE)
sticktoplane = actor.GetFlagValue("sticktoplane", false); // Works only for Floor/Ceil sprites
if(actor.GetFlagValue("wallsprite", false)) rendermode = ThingRenderMode.WALLSPRITE;
if(actor.GetFlagValue("flatsprite", false))
{
// WALLSPRITE + FLATSPRITE = HORRIBLE GLITCHES in GZDoom
if(rendermode == ThingRenderMode.WALLSPRITE)
{
General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". WALLSPRITE and FLATSPRITE flags can not be combined");
}
else
{
rendermode = ThingRenderMode.FLATSPRITE;
dontflip = actor.GetFlagValue("dontflip", false);
}
}
//mxd
if(blocking > THING_BLOCKING_NONE) errorcheck = THING_ERROR_INSIDE_STUCK;

View file

@ -2052,7 +2052,8 @@ namespace CodeImp.DoomBuilder.Geometry
if(side < 0)
{
//got any walls to align to?
if(CanAlignThingTo(t, l.Front.Sector, l.Back.Sector))
if((l.Front.LongMiddleTexture != MapSet.EmptyLongName && CanAlignThingTo(t, l.Front.Sector))
|| CanAlignThingTo(t, l.Front.Sector, l.Back.Sector))
{
AlignThingToLine(t, l, true);
return true;
@ -2063,7 +2064,8 @@ namespace CodeImp.DoomBuilder.Geometry
//thing is on back side of the line
//got any walls to align to?
if(CanAlignThingTo(t, l.Back.Sector, l.Front.Sector))
if((l.Back.LongMiddleTexture != MapSet.EmptyLongName && CanAlignThingTo(t, l.Back.Sector))
|| CanAlignThingTo(t, l.Back.Sector, l.Front.Sector))
{
AlignThingToLine(t, l, false);
return true;

View file

@ -36,18 +36,10 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Constants
public const int NUM_ARGS = 5;
#endregion
#region ================== Enums
public enum SpriteRenderMode
public static HashSet<ThingRenderMode> AlignableRenderModes = new HashSet<ThingRenderMode>
{
NORMAL,
WALL_SPRITE,
FLOOR_SPRITE,
CEILING_SPRITE
}
ThingRenderMode.FLATSPRITE, ThingRenderMode.WALLSPRITE, ThingRenderMode.MODEL
};
#endregion
@ -78,10 +70,10 @@ namespace CodeImp.DoomBuilder.Map
private int roll; //mxd. Used in model rendering
private float pitchrad; //mxd
private float rollrad; //mxd
private bool ismodel; //mxd
private bool highlighted; //mxd
//mxd. GLOOME rendering settings
//mxd. GZDoom rendering properties
private ThingRenderMode rendermode;
private bool rollsprite; //mxd
// Configuration
@ -116,7 +108,7 @@ namespace CodeImp.DoomBuilder.Map
public bool FixedSize { get { return fixedsize; } }
public int Tag { get { return tag; } set { BeforePropsChange(); tag = value; if((tag < General.Map.FormatInterface.MinTag) || (tag > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
public Sector Sector { get { return sector; } }
public bool IsModel { get { return ismodel; } } //mxd
public ThingRenderMode RenderMode { get { return rendermode; } } //mxd
public bool IsDirectional { get { return directional; } } //mxd
public bool Highlighted { get { return highlighted; } set { highlighted = value; } } //mxd
@ -250,7 +242,7 @@ namespace CodeImp.DoomBuilder.Map
t.color = color;
t.directional = directional;
t.fixedsize = fixedsize;
t.ismodel = ismodel; //mxd
t.rendermode = rendermode; //mxd
t.rollsprite = rollsprite; //mxd
base.CopyPropertiesTo(t);
@ -451,7 +443,8 @@ namespace CodeImp.DoomBuilder.Map
BeforePropsChange();
pitch = General.ClampAngle(newpitch);
pitchrad = ((ismodel && General.Map.Data.ModeldefEntries[type].InheritActorPitch) ? Angle2D.DegToRad(pitch) : 0);
pitchrad = ((rendermode == ThingRenderMode.FLATSPRITE || (rendermode == ThingRenderMode.MODEL && General.Map.Data.ModeldefEntries[type].InheritActorPitch))
? Angle2D.DegToRad(pitch) : 0);
if(type != General.Map.Config.Start3DModeThingType)
General.Map.IsChanged = true;
@ -463,7 +456,8 @@ namespace CodeImp.DoomBuilder.Map
BeforePropsChange();
roll = General.ClampAngle(newroll);
rollrad = ( (rollsprite || (ismodel && General.Map.Data.ModeldefEntries[type].InheritActorRoll)) ? Angle2D.DegToRad(roll) : 0);
rollrad = ((rollsprite || (rendermode == ThingRenderMode.MODEL && General.Map.Data.ModeldefEntries[type].InheritActorRoll))
? Angle2D.DegToRad(roll) : 0);
if(type != General.Map.Config.Start3DModeThingType)
General.Map.IsChanged = true;
@ -539,37 +533,49 @@ namespace CodeImp.DoomBuilder.Map
}
directional = ti.Arrow; //mxd
rendermode = ti.RenderMode; //mxd
rollsprite = ti.RollSprite; //mxd
UpdateCache(); //mxd
}
//mxd. This checks if the thing has model override
//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)
{
ismodel = false;
return;
}
if(General.Map.Data == null) return;
ismodel = General.Map.Data.ModeldefEntries.ContainsKey(type);
if(ismodel && General.Map.Data.ModeldefEntries[type].LoadState == ModelLoadState.None)
ismodel = General.Map.Data.ProcessModel(type);
if(ismodel)
// Check if the thing has model override
if(General.Map.Data.ModeldefEntries.ContainsKey(type))
{
rollrad = (General.Map.Data.ModeldefEntries[type].InheritActorRoll ? Angle2D.DegToRad(roll) : 0);
pitchrad = (General.Map.Data.ModeldefEntries[type].InheritActorPitch ? Angle2D.DegToRad(pitch) : 0);
}
else if(rollsprite)
if(General.Map.Data.ModeldefEntries[type].LoadState == ModelLoadState.None)
{
rollrad = Angle2D.DegToRad(roll);
pitchrad = 0;
if(General.Map.Data.ProcessModel(type)) rendermode = ThingRenderMode.MODEL;
}
else
{
rollrad = 0;
rendermode = ThingRenderMode.MODEL;
}
}
// Update radian versions of pitch and roll
switch(rendermode)
{
case ThingRenderMode.MODEL:
rollrad = (General.Map.Data.ModeldefEntries[type].InheritActorRoll ? Angle2D.DegToRad(roll) : 0);
pitchrad = (General.Map.Data.ModeldefEntries[type].InheritActorPitch ? Angle2D.DegToRad(pitch) : 0);
break;
case ThingRenderMode.FLATSPRITE:
rollrad = (rollsprite ? Angle2D.DegToRad(roll) : 0);
pitchrad = Angle2D.DegToRad(pitch);
break;
case ThingRenderMode.WALLSPRITE:
case ThingRenderMode.NORMAL:
rollrad = (rollsprite ? Angle2D.DegToRad(roll) : 0);
pitchrad = 0;
break;
default: throw new NotImplementedException("Unknown ThingRenderMode");
}
}
@ -580,10 +586,7 @@ namespace CodeImp.DoomBuilder.Map
// This checks and returns a flag without creating it
public bool IsFlagSet(string flagname)
{
if(flags.ContainsKey(flagname))
return flags[flagname];
else
return false;
return flags.ContainsKey(flagname) && flags[flagname];
}
// This sets a flag

View file

@ -1174,8 +1174,8 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd. Highlighted thing should be rendered separately
if(!fixedcolor && t.Highlighted) continue;
//collect models
if(t.IsModel)
// Collect models
if(t.RenderMode == ThingRenderMode.MODEL)
{
if(!modelsByType.ContainsKey(t.Type)) modelsByType.Add(t.Type, new List<Thing>());
modelsByType[t.Type].Add(t);
@ -1233,7 +1233,7 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(KeyValuePair<int, List<Thing>> group in thingsByType)
{
// Skip when all things of this type will be rendered as models
if(group.Value[0].IsModel && (General.Settings.GZDrawModelsMode == ModelRenderMode.ALL)) continue;
if(group.Value[0].RenderMode == ThingRenderMode.MODEL && (General.Settings.GZDrawModelsMode == ModelRenderMode.ALL)) continue;
// Find thing information
ThingTypeInfo info = General.Map.Data.GetThingInfo(group.Key);
@ -1285,7 +1285,7 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(Thing t in framegroup.Value)
{
if(t.IsModel && ((General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha == 1.0f)))
if(t.RenderMode == ThingRenderMode.MODEL && ((General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha == 1.0f)))
continue;
bool forcespriterendering;

View file

@ -1238,10 +1238,11 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd
private Matrix CreateThingPositionMatrix(VisualThing t)
{
//mxd. Create the matrix for positioning
if(t.Info.RenderMode == Thing.SpriteRenderMode.NORMAL) // Apply billboarding?
// Create the matrix for positioning
switch(t.Thing.RenderMode)
{
if(t.Info.XYBillboard)
case ThingRenderMode.NORMAL:
if(t.Info.XYBillboard) // Apply billboarding?
{
return Matrix.Translation(0f, 0f, -t.LocalCenterZ)
* Matrix.RotationX(Angle2D.PI - General.Map.VisualCamera.AngleZ)
@ -1256,11 +1257,18 @@ namespace CodeImp.DoomBuilder.Rendering
* Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY)
* t.Position;
}
}
else
{
return Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY)
* t.Position;
case ThingRenderMode.FLATSPRITE:
// Apply DontFlip flag?
float sx = ((t.Info.DontFlip && Angle2D.Normalized((General.Map.VisualCamera.Position - t.Thing.Position).GetAngleXY() - t.Thing.Angle + Angle2D.PIHALF) > Angle2D.PI) ? -1 : 1)
* t.Thing.ScaleX;
return Matrix.Scaling(sx, sx, t.Thing.ScaleY) * t.Position;
case ThingRenderMode.WALLSPRITE:
case ThingRenderMode.MODEL:
return Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY) * t.Position;
default: throw new NotImplementedException("Unknown ThingRenderMode");
}
}
@ -1714,7 +1722,7 @@ namespace CodeImp.DoomBuilder.Rendering
}
//mxd. Gather models
if(t.Thing.IsModel &&
if(t.Thing.RenderMode == ThingRenderMode.MODEL &&
(General.Settings.GZDrawModelsMode == ModelRenderMode.ALL ||
General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER ||
(General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && t.Selected)))

View file

@ -265,7 +265,7 @@ namespace CodeImp.DoomBuilder.VisualModes
}
// This sets the vertices for the thing sprite
protected void SetVertices(WorldVertex[][] verts, Plane floor, Plane ceiling)
protected void SetVertices(WorldVertex[][] verts/*, Plane floor, Plane ceiling*/)
{
// Copy vertices
vertices = new WorldVertex[verts.Length][];
@ -281,28 +281,47 @@ namespace CodeImp.DoomBuilder.VisualModes
updategeo = true;
//mxd. Do some GLOOME shenanigans...
//mxd. Do some special GZDoom rendering shenanigans...
for(int c = 0; c < vertices.Length; c++)
{
if(triangles[c] < 2) continue;
float localcenterz = vertices[c][1].z * 0.5f;
Matrix m;
Matrix transform, rotation;
switch(info.RenderMode)
switch(thing.RenderMode)
{
// TODO: Currently broken in GLOOME...
case Thing.SpriteRenderMode.WALL_SPRITE:
m = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(Thing.RollRad) * Matrix.RotationZ(thing.Angle) * Matrix.Translation(0f, 0f, localcenterz);
// Don't do anything
case ThingRenderMode.MODEL: break;
// Actor becomes a flat sprite which can be tilted with the use of the Pitch actor property.
case ThingRenderMode.FLATSPRITE:
rotation = (info.RollSprite ? Matrix.RotationY(-thing.RollRad) * Matrix.RotationX(thing.PitchRad) : Matrix.RotationX(thing.PitchRad))
* Matrix.RotationZ(thing.Angle);
transform = Matrix.Translation(0f, 0f, -localcenterz) * rotation * Matrix.Translation(0f, 0f, localcenterz);
for(int i = 0; i < vertices[c].Length; i++)
{
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), m);
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform);
vertices[c][i].x = transformed.X;
vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z;
}
break;
case Thing.SpriteRenderMode.FLOOR_SPRITE:
// Similar to FLATSPRITE but is not affected by pitch.
case ThingRenderMode.WALLSPRITE:
rotation = (info.RollSprite ? Matrix.RotationY(-thing.RollRad) * Matrix.RotationZ(thing.Angle) : Matrix.RotationZ(thing.Angle));
transform = Matrix.Translation(0f, 0f, -localcenterz) * rotation * Matrix.Translation(0f, 0f, localcenterz);
for(int i = 0; i < vertices[c].Length; i++)
{
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform);
vertices[c][i].x = transformed.X;
vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z;
}
break;
// Some old GLOOME stuff
/*case Thing.SpriteRenderMode.FLOOR_SPRITE:
Matrix floorrotation = Matrix.RotationZ(info.RollSprite ? Thing.RollRad : 0f)
* Matrix.RotationY(Thing.Angle)
* Matrix.RotationX(Angle2D.PIHALF);
@ -386,15 +405,15 @@ namespace CodeImp.DoomBuilder.VisualModes
vertices[c][i].z = ceiling.GetZ(vertices[c][i].x + Thing.Position.x, vertices[c][i].y + Thing.Position.y) + voffset;
}
}
break;
break;*/
default:
if(info.RollSprite)
{
m = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(Thing.RollRad) * Matrix.Translation(0f, 0f, localcenterz);
transform = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(-thing.RollRad) * Matrix.Translation(0f, 0f, localcenterz);
for(int i = 0; i < vertices[c].Length; i++)
{
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), m);
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform);
vertices[c][i].x = transformed.X;
vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z;

View file

@ -18,12 +18,12 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing;
using CodeImp.DoomBuilder.Editing;
#endregion
@ -430,7 +430,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
snaptogridincrement = (!snaptocardinaldirection && General.Interface.AltState); //mxd
//mxd. Snap to nearest linedef
if(selectedthings.Count == 1 && dragitem.IsModel && snaptonearest && !snaptocardinaldirection && MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, false, false))
if(selectedthings.Count == 1 && snaptonearest && !snaptocardinaldirection
&& Thing.AlignableRenderModes.Contains(dragitem.RenderMode)
&& MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, false, false))
{
Linedef l = General.Map.Map.NearestLinedefRange(oldpositions[0] + mousemappos - dragstartmappos, BuilderPlug.Me.StitchRange / renderer.Scale);
bool restoresettings = false;

View file

@ -1410,12 +1410,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
List<Thing> toAlign = new List<Thing>();
foreach(Thing t in selected) if(t.IsModel) toAlign.Add(t);
foreach(Thing t in selected)
{
if(Thing.AlignableRenderModes.Contains(t.RenderMode)) toAlign.Add(t);
}
if(toAlign.Count == 0)
{
General.Interface.DisplayStatus(StatusType.Warning, "This action only works for things with models!");
General.Interface.DisplayStatus(StatusType.Warning, "This action only works for models or things with FLATSPRITE/WALLSPRITE flags!");
return;
}

View file

@ -461,7 +461,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.alignToWallItem.Name = "alignToWallItem";
this.alignToWallItem.Size = new System.Drawing.Size(245, 22);
this.alignToWallItem.Tag = "thingaligntowall";
this.alignToWallItem.Text = "&Align To Closest Linedef";
this.alignToWallItem.Text = "&Align Things to Nearest Linedef";
this.alignToWallItem.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// pointAtCursorItem
@ -766,7 +766,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.buttonAlignThingsToWall.Name = "buttonAlignThingsToWall";
this.buttonAlignThingsToWall.Size = new System.Drawing.Size(23, 22);
this.buttonAlignThingsToWall.Tag = "thingaligntowall";
this.buttonAlignThingsToWall.ToolTipText = "Align selected things to closest linedef";
this.buttonAlignThingsToWall.ToolTipText = "Align Things to Nearest Linedef";
this.buttonAlignThingsToWall.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// buttonTextureOffsetLock

View file

@ -415,9 +415,9 @@ mergesectors
//mxd
thingaligntowall
{
title = "Align Things To Linedef";
title = "Align Things to Nearest Linedef";
category = "things";
description = "Aligns selected things to closest linedef.";
description = "Aligns selected things to the nearest linedef.";
allowkeys = true;
allowmouse = true;
allowscroll = true;

View file

@ -357,7 +357,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
//mxd
SetVertices(allverts, floor, ceiling);
SetVertices(allverts/*, floor, ceiling*/);
// Determine position
Vector3D pos = Thing.Position;