mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 12:50:52 +00:00
Added, Visual mode: thing sprites are now angle-dependent.
This commit is contained in:
parent
c861f8ecff
commit
c3392f8399
4 changed files with 325 additions and 265 deletions
|
@ -95,21 +95,16 @@ namespace CodeImp.DoomBuilder
|
||||||
|
|
||||||
#region ================== Methods
|
#region ================== Methods
|
||||||
|
|
||||||
public static void Write(string text)
|
public static void SetText(string text) { Write(DebugMessageType.INFO, text, false); } // Useful to display frequently updated text without flickering
|
||||||
{
|
public static void WriteLine(string text) { Write(DebugMessageType.INFO, text + Environment.NewLine, true); }
|
||||||
Write(DebugMessageType.INFO, text);
|
public static void WriteLine(DebugMessageType type, string text) { Write(type, text + Environment.NewLine, true); }
|
||||||
}
|
public static void Write(string text) { Write(DebugMessageType.INFO, text, true); }
|
||||||
|
public static void Write(DebugMessageType type, string text) { Write(type, text, true); }
|
||||||
public static void WriteLine(string text)
|
public static void Write(DebugMessageType type, string text, bool append)
|
||||||
{
|
|
||||||
Write(DebugMessageType.INFO, text + Environment.NewLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Write(DebugMessageType type, string text)
|
|
||||||
{
|
{
|
||||||
if(me != null && me.InvokeRequired)
|
if(me != null && me.InvokeRequired)
|
||||||
{
|
{
|
||||||
me.Invoke(new Action<DebugMessageType, string>(Write), new object[] { type, text });
|
me.Invoke(new Action<DebugMessageType, string, bool>(Write), new object[] { type, text, append });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -117,16 +112,11 @@ namespace CodeImp.DoomBuilder
|
||||||
messages.Add(new KeyValuePair<DebugMessageType, string>(type, text));
|
messages.Add(new KeyValuePair<DebugMessageType, string>(type, text));
|
||||||
if(me != null && (me.filters & type) == type)
|
if(me != null && (me.filters & type) == type)
|
||||||
{
|
{
|
||||||
me.AddMessage(type, text, true);
|
me.AddMessage(type, text, true, append);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteLine(DebugMessageType type, string text)
|
|
||||||
{
|
|
||||||
Write(type, text + Environment.NewLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
{
|
||||||
if(me != null && me.InvokeRequired)
|
if(me != null && me.InvokeRequired)
|
||||||
|
@ -226,12 +216,13 @@ namespace CodeImp.DoomBuilder
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddMessage(DebugMessageType type, string text, bool scroll)
|
private void AddMessage(DebugMessageType type, string text, bool scroll, bool append)
|
||||||
{
|
{
|
||||||
text = textheaders[type] + text;
|
text = textheaders[type] + text;
|
||||||
console.SelectionStart = console.TextLength;
|
console.SelectionStart = console.TextLength;
|
||||||
console.SelectionColor = textcolors[type];
|
console.SelectionColor = textcolors[type];
|
||||||
console.AppendText(text);
|
if(append) console.AppendText(text);
|
||||||
|
else console.Text = text;
|
||||||
if(scroll && autoscroll.Checked) console.ScrollToCaret();
|
if(scroll && autoscroll.Checked) console.ScrollToCaret();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +248,7 @@ namespace CodeImp.DoomBuilder
|
||||||
{
|
{
|
||||||
if((filters & pair.Key) == pair.Key && CheckTextFilter(pair.Value, searchbox.Text))
|
if((filters & pair.Key) == pair.Key && CheckTextFilter(pair.Value, searchbox.Text))
|
||||||
{
|
{
|
||||||
AddMessage(pair.Key, pair.Value, false);
|
AddMessage(pair.Key, pair.Value, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1107,6 +1107,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
// Render things collected
|
// Render things collected
|
||||||
foreach(VisualThing t in thingspass)
|
foreach(VisualThing t in thingspass)
|
||||||
{
|
{
|
||||||
|
t.UpdateSpriteFrame(); // Set correct texture, geobuffer and triangles count
|
||||||
if(t.Texture is UnknownImage) continue;
|
if(t.Texture is UnknownImage) continue;
|
||||||
|
|
||||||
// Change blend mode?
|
// Change blend mode?
|
||||||
|
@ -1720,28 +1721,35 @@ namespace CodeImp.DoomBuilder.Rendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Gather regular things
|
// Gather regular things
|
||||||
else if(t.Texture != null) //Must have a texture!
|
else
|
||||||
{
|
{
|
||||||
//mxd
|
//mxd. Set correct texture, geobuffer and triangles count
|
||||||
switch(t.RenderPass)
|
t.UpdateSpriteFrame();
|
||||||
|
|
||||||
|
//Must have a texture!
|
||||||
|
if(t.Texture != null)
|
||||||
{
|
{
|
||||||
case RenderPass.Solid:
|
//mxd
|
||||||
if(!solidthings.ContainsKey(t.Texture)) solidthings.Add(t.Texture, new List<VisualThing>());
|
switch(t.RenderPass)
|
||||||
solidthings[t.Texture].Add(t);
|
{
|
||||||
break;
|
case RenderPass.Solid:
|
||||||
|
if(!solidthings.ContainsKey(t.Texture)) solidthings.Add(t.Texture, new List<VisualThing>());
|
||||||
|
solidthings[t.Texture].Add(t);
|
||||||
|
break;
|
||||||
|
|
||||||
case RenderPass.Mask:
|
case RenderPass.Mask:
|
||||||
if(!maskedthings.ContainsKey(t.Texture)) maskedthings.Add(t.Texture, new List<VisualThing>());
|
if(!maskedthings.ContainsKey(t.Texture)) maskedthings.Add(t.Texture, new List<VisualThing>());
|
||||||
maskedthings[t.Texture].Add(t);
|
maskedthings[t.Texture].Add(t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderPass.Additive:
|
case RenderPass.Additive:
|
||||||
case RenderPass.Alpha:
|
case RenderPass.Alpha:
|
||||||
translucentthings.Add(t);
|
translucentthings.Add(t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException("Thing rendering of " + t.RenderPass + " render pass is not implemented!");
|
throw new NotImplementedException("Thing rendering of " + t.RenderPass + " render pass is not implemented!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,17 +48,18 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
//mxd. Info
|
//mxd. Info
|
||||||
protected ThingTypeInfo info;
|
protected ThingTypeInfo info;
|
||||||
|
|
||||||
// Texture
|
// Textures
|
||||||
private ImageData texture;
|
protected ImageData[] textures;
|
||||||
|
|
||||||
// Geometry
|
// Geometry
|
||||||
private WorldVertex[] vertices;
|
private WorldVertex[][] vertices;
|
||||||
private VertexBuffer geobuffer;
|
private VertexBuffer[] geobuffers;
|
||||||
private VertexBuffer cagebuffer; //mxd
|
private VertexBuffer cagebuffer; //mxd
|
||||||
private int cagelength; //mxd
|
private int cagelength; //mxd
|
||||||
private bool updategeo;
|
private bool updategeo;
|
||||||
private bool updatecage; //mxd
|
private bool updatecage; //mxd
|
||||||
private int triangles;
|
private int[] triangles;
|
||||||
|
private int spriteframe; //mxd
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
private RenderPass renderpass;
|
private RenderPass renderpass;
|
||||||
|
@ -97,17 +98,17 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
|
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
|
||||||
internal VertexBuffer GeometryBuffer { get { return geobuffer; } }
|
internal VertexBuffer GeometryBuffer { get { return geobuffers[spriteframe]; } }
|
||||||
internal VertexBuffer CageBuffer { get { return cagebuffer; } } //mxd
|
internal VertexBuffer CageBuffer { get { return cagebuffer; } } //mxd
|
||||||
internal int CageLength { get { return cagelength; } } //mxd
|
internal int CageLength { get { return cagelength; } } //mxd
|
||||||
internal bool NeedsUpdateGeo { get { return updategeo; } }
|
internal bool NeedsUpdateGeo { get { return updategeo; } }
|
||||||
internal int Triangles { get { return triangles; } }
|
internal int Triangles { get { return triangles[spriteframe]; } }
|
||||||
internal Matrix Position { get { return position; } }
|
internal Matrix Position { get { return position; } }
|
||||||
internal Color4 CageColor { get { return cagecolor; } }
|
internal Color4 CageColor { get { return cagecolor; } }
|
||||||
public ThingTypeInfo Info { get { return info; } } //mxd
|
public ThingTypeInfo Info { get { return info; } } //mxd
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
internal int VertexColor { get { return vertices.Length > 0 ? vertices[0].c : 0;} }
|
internal int VertexColor { get { return vertices.Length > 0 && vertices[0].Length > 0 ? vertices[0][0].c : 0; } }
|
||||||
public int CameraDistance { get { return cameradistance; } }
|
public int CameraDistance { get { return cameradistance; } }
|
||||||
public float FogFactor { get { return fogfactor; } }
|
public float FogFactor { get { return fogfactor; } }
|
||||||
public Vector3 Center
|
public Vector3 Center
|
||||||
|
@ -142,7 +143,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Image to use as texture on the geometry.
|
/// Image to use as texture on the geometry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ImageData Texture { get { return texture; } set { texture = value; } }
|
public ImageData Texture { get { return textures[spriteframe]; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposed or not?
|
/// Disposed or not?
|
||||||
|
@ -186,8 +187,12 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
if(!isdisposed)
|
if(!isdisposed)
|
||||||
{
|
{
|
||||||
// Clean up
|
// Clean up
|
||||||
if(geobuffer != null) geobuffer.Dispose();
|
if(geobuffers != null) //mxd
|
||||||
geobuffer = null;
|
{
|
||||||
|
foreach(VertexBuffer buffer in geobuffers) buffer.Dispose();
|
||||||
|
geobuffers = null;
|
||||||
|
}
|
||||||
|
|
||||||
if(cagebuffer != null) cagebuffer.Dispose(); //mxd
|
if(cagebuffer != null) cagebuffer.Dispose(); //mxd
|
||||||
cagebuffer = null; //mxd
|
cagebuffer = null; //mxd
|
||||||
|
|
||||||
|
@ -213,8 +218,18 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
public void UnloadResource()
|
public void UnloadResource()
|
||||||
{
|
{
|
||||||
// Trash geometry buffers
|
// Trash geometry buffers
|
||||||
if(geobuffer != null) geobuffer.Dispose();
|
if(geobuffers != null) //mxd
|
||||||
geobuffer = null;
|
{
|
||||||
|
foreach(VertexBuffer buffer in geobuffers) buffer.Dispose();
|
||||||
|
geobuffers = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(textures != null) //mxd
|
||||||
|
{
|
||||||
|
foreach(ImageData texture in textures) texture.Dispose();
|
||||||
|
textures = null;
|
||||||
|
}
|
||||||
|
|
||||||
if(cagebuffer != null) cagebuffer.Dispose(); //mxd
|
if(cagebuffer != null) cagebuffer.Dispose(); //mxd
|
||||||
cagebuffer = null; //mxd
|
cagebuffer = null; //mxd
|
||||||
updategeo = true;
|
updategeo = true;
|
||||||
|
@ -256,132 +271,143 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
}
|
}
|
||||||
|
|
||||||
// This sets the vertices for the thing sprite
|
// This sets the vertices for the thing sprite
|
||||||
protected void SetVertices(ICollection<WorldVertex> verts, Plane floor, Plane ceiling)
|
protected void SetVertices(WorldVertex[][] verts, Plane floor, Plane ceiling)
|
||||||
{
|
{
|
||||||
// Copy vertices
|
// Copy vertices
|
||||||
vertices = new WorldVertex[verts.Count];
|
vertices = new WorldVertex[verts.Length][];
|
||||||
verts.CopyTo(vertices, 0);
|
triangles = new int[verts.Length];
|
||||||
triangles = vertices.Length / 3;
|
|
||||||
|
//mxd
|
||||||
|
for(int i = 0; i < verts.Length; i++)
|
||||||
|
{
|
||||||
|
vertices[i] = new WorldVertex[verts[i].Length];
|
||||||
|
verts[i].CopyTo(vertices[i], 0);
|
||||||
|
triangles[i] = vertices[i].Length / 3;
|
||||||
|
}
|
||||||
|
|
||||||
updategeo = true;
|
updategeo = true;
|
||||||
|
|
||||||
//mxd. Do some GLOOME shenanigans...
|
//mxd. Do some GLOOME shenanigans...
|
||||||
if(triangles < 2) return;
|
for(int c = 0; c < vertices.Length; c++)
|
||||||
float localcenterz = vertices[1].z * 0.5f;
|
|
||||||
Matrix m;
|
|
||||||
|
|
||||||
switch(info.RenderMode)
|
|
||||||
{
|
{
|
||||||
// TODO: Currently broken in GLOOME...
|
if(triangles[c] < 2) continue;
|
||||||
case Thing.SpriteRenderMode.WALL_SPRITE:
|
float localcenterz = vertices[c][1].z * 0.5f;
|
||||||
m = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(Thing.RollRad) * Matrix.RotationZ(thing.Angle) * Matrix.Translation(0f, 0f, localcenterz);
|
Matrix m;
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
{
|
|
||||||
Vector4 transformed = Vector3.Transform(new Vector3(vertices[i].x, vertices[i].y, vertices[i].z), m);
|
|
||||||
vertices[i].x = transformed.X;
|
|
||||||
vertices[i].y = transformed.Y;
|
|
||||||
vertices[i].z = transformed.Z;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Thing.SpriteRenderMode.FLOOR_SPRITE:
|
switch(info.RenderMode)
|
||||||
Matrix floorrotation = Matrix.RotationZ(info.RollSprite ? Thing.RollRad : 0f)
|
{
|
||||||
* Matrix.RotationY(Thing.Angle)
|
// TODO: Currently broken in GLOOME...
|
||||||
* Matrix.RotationX(Angle2D.PIHALF);
|
case Thing.SpriteRenderMode.WALL_SPRITE:
|
||||||
|
m = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(Thing.RollRad) * Matrix.RotationZ(thing.Angle) * Matrix.Translation(0f, 0f, localcenterz);
|
||||||
m = Matrix.Translation(0f, 0f, -localcenterz) * floorrotation * Matrix.Translation(0f, 0f, localcenterz);
|
for(int i = 0; i < vertices[c].Length; i++)
|
||||||
|
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
{
|
|
||||||
Vector4 transformed = Vector3.Transform(new Vector3(vertices[i].x, vertices[i].y, vertices[i].z), m);
|
|
||||||
vertices[i].x = transformed.X;
|
|
||||||
vertices[i].y = transformed.Y;
|
|
||||||
vertices[i].z = transformed.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this won't work on things with AbsoluteZ flag
|
|
||||||
// TODO: +ROLLSPRITE implies +STICKTOPLANE?
|
|
||||||
if(info.StickToPlane || info.RollSprite)
|
|
||||||
{
|
|
||||||
// Calculate vertical offset
|
|
||||||
float floorz = floor.GetZ(Thing.Position);
|
|
||||||
float ceilz = ceiling.GetZ(Thing.Position);
|
|
||||||
|
|
||||||
if(!float.IsNaN(floorz) && !float.IsNaN(ceilz))
|
|
||||||
{
|
{
|
||||||
float voffset;
|
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), m);
|
||||||
if(info.Hangs)
|
vertices[c][i].x = transformed.X;
|
||||||
{
|
vertices[c][i].y = transformed.Y;
|
||||||
float thingz = ceilz - Thing.Position.z + Thing.Height;
|
vertices[c][i].z = transformed.Z;
|
||||||
voffset = 0.01f - floorz - General.Clamp(thingz, 0, ceilz - floorz);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
voffset = 0.01f - floorz - General.Clamp(Thing.Position.z, 0, ceilz - floorz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply it
|
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
vertices[i].z = floor.GetZ(vertices[i].x + Thing.Position.x, vertices[i].y + Thing.Position.y) + voffset;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case Thing.SpriteRenderMode.CEILING_SPRITE:
|
case Thing.SpriteRenderMode.FLOOR_SPRITE:
|
||||||
Matrix ceilrotation = Matrix.RotationZ(info.RollSprite ? Thing.RollRad : 0f)
|
Matrix floorrotation = Matrix.RotationZ(info.RollSprite ? Thing.RollRad : 0f)
|
||||||
* Matrix.RotationY(Thing.Angle)
|
* Matrix.RotationY(Thing.Angle)
|
||||||
* Matrix.RotationX(Angle2D.PIHALF);
|
* Matrix.RotationX(Angle2D.PIHALF);
|
||||||
|
|
||||||
m = Matrix.Translation(0f, 0f, -localcenterz) * ceilrotation * Matrix.Translation(0f, 0f, localcenterz);
|
m = Matrix.Translation(0f, 0f, -localcenterz) * floorrotation * Matrix.Translation(0f, 0f, localcenterz);
|
||||||
|
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
{
|
|
||||||
Vector4 transformed = Vector3.Transform(new Vector3(vertices[i].x, vertices[i].y, vertices[i].z), m);
|
|
||||||
vertices[i].x = transformed.X;
|
|
||||||
vertices[i].y = transformed.Y;
|
|
||||||
vertices[i].z = transformed.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this won't work on things with AbsoluteZ flag
|
for(int i = 0; i < vertices[c].Length; i++)
|
||||||
// TODO: +ROLLSPRITE implies +STICKTOPLANE?
|
|
||||||
if(info.StickToPlane || info.RollSprite)
|
|
||||||
{
|
|
||||||
// Calculate vertical offset
|
|
||||||
float floorz = floor.GetZ(Thing.Position);
|
|
||||||
float ceilz = ceiling.GetZ(Thing.Position);
|
|
||||||
|
|
||||||
if(!float.IsNaN(floorz) && !float.IsNaN(ceilz))
|
|
||||||
{
|
{
|
||||||
float voffset;
|
Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), m);
|
||||||
if(info.Hangs)
|
vertices[c][i].x = transformed.X;
|
||||||
{
|
vertices[c][i].y = transformed.Y;
|
||||||
float thingz = ceilz - Math.Max(0, Thing.Position.z) - Thing.Height;
|
vertices[c][i].z = transformed.Z;
|
||||||
voffset = -0.01f - General.Clamp(thingz, 0, ceilz - floorz);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
voffset = -0.01f - floorz - General.Clamp(Thing.Position.z, 0, ceilz - floorz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply it
|
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
vertices[i].z = ceiling.GetZ(vertices[i].x + Thing.Position.x, vertices[i].y + Thing.Position.y) + voffset;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// TODO: this won't work on things with AbsoluteZ flag
|
||||||
if(info.RollSprite)
|
// TODO: +ROLLSPRITE implies +STICKTOPLANE?
|
||||||
{
|
if(info.StickToPlane || info.RollSprite)
|
||||||
m = Matrix.Translation(0f, 0f, -localcenterz) * Matrix.RotationY(Thing.RollRad) * Matrix.Translation(0f, 0f, localcenterz);
|
|
||||||
for(int i = 0; i < vertices.Length; i++)
|
|
||||||
{
|
{
|
||||||
Vector4 transformed = Vector3.Transform(new Vector3(vertices[i].x, vertices[i].y, vertices[i].z), m);
|
// Calculate vertical offset
|
||||||
vertices[i].x = transformed.X;
|
float floorz = floor.GetZ(Thing.Position);
|
||||||
vertices[i].y = transformed.Y;
|
float ceilz = ceiling.GetZ(Thing.Position);
|
||||||
vertices[i].z = transformed.Z;
|
|
||||||
|
if(!float.IsNaN(floorz) && !float.IsNaN(ceilz))
|
||||||
|
{
|
||||||
|
float voffset;
|
||||||
|
if(info.Hangs)
|
||||||
|
{
|
||||||
|
float thingz = ceilz - Thing.Position.z + Thing.Height;
|
||||||
|
voffset = 0.01f - floorz - General.Clamp(thingz, 0, ceilz - floorz);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voffset = 0.01f - floorz - General.Clamp(Thing.Position.z, 0, ceilz - floorz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply it
|
||||||
|
for(int i = 0; i < vertices[c].Length; i++)
|
||||||
|
vertices[c][i].z = floor.GetZ(vertices[c][i].x + Thing.Position.x, vertices[c][i].y + Thing.Position.y) + voffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
case Thing.SpriteRenderMode.CEILING_SPRITE:
|
||||||
|
Matrix ceilrotation = Matrix.RotationZ(info.RollSprite ? Thing.RollRad : 0f)
|
||||||
|
* Matrix.RotationY(Thing.Angle)
|
||||||
|
* Matrix.RotationX(Angle2D.PIHALF);
|
||||||
|
|
||||||
|
m = Matrix.Translation(0f, 0f, -localcenterz) * ceilrotation * 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);
|
||||||
|
vertices[c][i].x = transformed.X;
|
||||||
|
vertices[c][i].y = transformed.Y;
|
||||||
|
vertices[c][i].z = transformed.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this won't work on things with AbsoluteZ flag
|
||||||
|
// TODO: +ROLLSPRITE implies +STICKTOPLANE?
|
||||||
|
if(info.StickToPlane || info.RollSprite)
|
||||||
|
{
|
||||||
|
// Calculate vertical offset
|
||||||
|
float floorz = floor.GetZ(Thing.Position);
|
||||||
|
float ceilz = ceiling.GetZ(Thing.Position);
|
||||||
|
|
||||||
|
if(!float.IsNaN(floorz) && !float.IsNaN(ceilz))
|
||||||
|
{
|
||||||
|
float voffset;
|
||||||
|
if(info.Hangs)
|
||||||
|
{
|
||||||
|
float thingz = ceilz - Math.Max(0, Thing.Position.z) - Thing.Height;
|
||||||
|
voffset = -0.01f - General.Clamp(thingz, 0, ceilz - floorz);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voffset = -0.01f - floorz - General.Clamp(Thing.Position.z, 0, ceilz - floorz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply it
|
||||||
|
for(int i = 0; i < vertices[c].Length; i++)
|
||||||
|
vertices[c][i].z = ceiling.GetZ(vertices[c][i].x + Thing.Position.x, vertices[c][i].y + Thing.Position.y) + voffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(info.RollSprite)
|
||||||
|
{
|
||||||
|
m = 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);
|
||||||
|
vertices[c][i].x = transformed.X;
|
||||||
|
vertices[c][i].y = transformed.Y;
|
||||||
|
vertices[c][i].z = transformed.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,22 +417,26 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
// Do we need to update the geometry buffer?
|
// Do we need to update the geometry buffer?
|
||||||
if(updategeo)
|
if(updategeo)
|
||||||
{
|
{
|
||||||
// Trash geometry buffer
|
//mxd. Trash geometry buffers
|
||||||
if(geobuffer != null) geobuffer.Dispose();
|
if(geobuffers != null)
|
||||||
geobuffer = null;
|
foreach(VertexBuffer geobuffer in geobuffers) geobuffer.Dispose();
|
||||||
|
|
||||||
// Any vertics?
|
// Any vertics?
|
||||||
if(vertices.Length > 0)
|
if(vertices.Length > 0)
|
||||||
{
|
{
|
||||||
// Make a new buffer
|
geobuffers = new VertexBuffer[vertices.Length];
|
||||||
geobuffer = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vertices.Length,
|
for(int i = 0; i < vertices.Length; i++)
|
||||||
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
|
{
|
||||||
|
// Make a new buffer
|
||||||
|
geobuffers[i] = new VertexBuffer(General.Map.Graphics.Device, WorldVertex.Stride * vertices[i].Length,
|
||||||
|
Usage.WriteOnly | Usage.Dynamic, VertexFormat.None, Pool.Default);
|
||||||
|
|
||||||
// Fill the buffer
|
// Fill the buffer
|
||||||
DataStream bufferstream = geobuffer.Lock(0, WorldVertex.Stride * vertices.Length, LockFlags.Discard);
|
DataStream bufferstream = geobuffers[i].Lock(0, WorldVertex.Stride * vertices[i].Length, LockFlags.Discard);
|
||||||
bufferstream.WriteRange(vertices);
|
bufferstream.WriteRange(vertices[i]);
|
||||||
geobuffer.Unlock();
|
geobuffers[i].Unlock();
|
||||||
bufferstream.Dispose();
|
bufferstream.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Check if thing is light
|
//mxd. Check if thing is light
|
||||||
|
@ -707,6 +737,15 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
boundingBox[7] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z + h2);
|
boundingBox[7] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z + h2);
|
||||||
boundingBox[8] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z + h2);
|
boundingBox[8] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z + h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mxd. This updates the sprite frame to be rendered
|
||||||
|
internal void UpdateSpriteFrame()
|
||||||
|
{
|
||||||
|
if(textures.Length != 8)
|
||||||
|
spriteframe = 0;
|
||||||
|
else
|
||||||
|
spriteframe = (General.ClampAngle((int)Angle2D.RadToDeg((General.Map.VisualCamera.Position - thing.Position).GetAngleXY()) - thing.AngleDoom + 292)) / 45; // Convert to [0..7] range; 292 == 270 + 45/2
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is called when the thing must be tested for line intersection. This should reject
|
/// This is called when the thing must be tested for line intersection. This should reject
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
|
||||||
private bool isloaded;
|
private bool isloaded;
|
||||||
private bool nointeraction; //mxd
|
private bool nointeraction; //mxd
|
||||||
private ImageData sprite;
|
private ImageData[] sprites;
|
||||||
private float cageradius2;
|
private float cageradius2;
|
||||||
private Vector2D pos2d;
|
private Vector2D pos2d;
|
||||||
private Vector3D boxp1;
|
private Vector3D boxp1;
|
||||||
|
@ -76,11 +76,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
//mxd. When true, the thing can be moved below floor/above ceiling
|
//mxd. When true, the thing can be moved below floor/above ceiling
|
||||||
nointeraction = (info.Actor != null && info.Actor.GetFlagValue("nointeraction", false));
|
nointeraction = (info.Actor != null && info.Actor.GetFlagValue("nointeraction", false));
|
||||||
|
|
||||||
// Find sprite texture
|
//mxd. Find sprite textures
|
||||||
if(info.Sprite.Length > 0)
|
sprites = new ImageData[info.SpriteFrame.Length];
|
||||||
|
for(int i = 0; i < info.SpriteFrame.Length; i++)
|
||||||
{
|
{
|
||||||
sprite = General.Map.Data.GetSpriteImage(info.Sprite);
|
sprites[i] = General.Map.Data.GetSpriteImage(info.SpriteFrame[i].Sprite);
|
||||||
if(sprite != null) sprite.AddReference();
|
if(sprites[i] != null) sprites[i].AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
@ -191,98 +192,103 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
sizeless = false;
|
sizeless = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sprite != null)
|
Plane floor = new Plane(); //mxd
|
||||||
|
Plane ceiling = new Plane(); //mxd
|
||||||
|
if(Thing.Sector != null)
|
||||||
{
|
{
|
||||||
Plane floor = new Plane(); //mxd
|
SectorData sd = mode.GetSectorData(Thing.Sector);
|
||||||
Plane ceiling = new Plane(); //mxd
|
floor = sd.Floor.plane; //mxd
|
||||||
if(Thing.Sector != null)
|
ceiling = sd.Ceiling.plane; //mxd
|
||||||
|
|
||||||
|
if(!info.Bright)
|
||||||
{
|
{
|
||||||
SectorData sd = mode.GetSectorData(Thing.Sector);
|
Vector3D thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
|
||||||
floor = sd.Floor.plane; //mxd
|
SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
||||||
ceiling = sd.Ceiling.plane; //mxd
|
|
||||||
|
|
||||||
if(!info.Bright)
|
//mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
|
||||||
|
if(nointeraction && level == null && sd.LightLevels.Count > 0) level = sd.LightLevels[sd.LightLevels.Count - 1];
|
||||||
|
|
||||||
|
//mxd. Use the light level of the highest surface when a thing is above highest sector level.
|
||||||
|
if(level != null)
|
||||||
{
|
{
|
||||||
Vector3D thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
|
// TECH: In GZDoom, ceiling glow doesn't affect thing brightness
|
||||||
SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
// Use sector brightness for color shading
|
||||||
|
int brightness = level.brightnessbelow;
|
||||||
|
|
||||||
//mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
|
// Level is glowing
|
||||||
if(nointeraction && level == null && sd.LightLevels.Count > 0) level = sd.LightLevels[sd.LightLevels.Count - 1];
|
if(level.affectedbyglow && level.type == SectorLevelType.Floor)
|
||||||
|
|
||||||
//mxd. Use the light level of the highest surface when a thing is above highest sector level.
|
|
||||||
if(level != null)
|
|
||||||
{
|
{
|
||||||
// TECH: In GZDoom, ceiling glow doesn't affect thing brightness
|
// Extrafloor glow doesn't affect thing brightness
|
||||||
// Use sector brightness for color shading
|
if(level.sector == Thing.Sector)
|
||||||
int brightness = level.brightnessbelow;
|
|
||||||
|
|
||||||
// Level is glowing
|
|
||||||
if(level.affectedbyglow && level.type == SectorLevelType.Floor)
|
|
||||||
{
|
{
|
||||||
// Extrafloor glow doesn't affect thing brightness
|
float planez = level.plane.GetZ(thingpos);
|
||||||
if(level.sector == Thing.Sector)
|
|
||||||
{
|
|
||||||
float planez = level.plane.GetZ(thingpos);
|
|
||||||
|
|
||||||
// Get glow brightness
|
// Get glow brightness
|
||||||
int glowbrightness = sd.FloorGlow.Brightness / 2;
|
int glowbrightness = sd.FloorGlow.Brightness / 2;
|
||||||
SectorLevel nexthigher = sd.GetLevelAbove(new Vector3D(thingpos, planez));
|
SectorLevel nexthigher = sd.GetLevelAbove(new Vector3D(thingpos, planez));
|
||||||
|
|
||||||
// Interpolate thing brightness between glow and regular ones
|
|
||||||
if(nexthigher != null)
|
|
||||||
{
|
|
||||||
float higherz = nexthigher.plane.GetZ(thingpos);
|
|
||||||
float delta = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
|
|
||||||
brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Level below this one is glowing. Only possible for floor glow(?)
|
|
||||||
else if(level.type == SectorLevelType.Glow)
|
|
||||||
{
|
|
||||||
// Interpolate thing brightness between glow and regular ones
|
// Interpolate thing brightness between glow and regular ones
|
||||||
if(sd.Floor != null && sd.FloorGlow != null)
|
if(nexthigher != null)
|
||||||
{
|
{
|
||||||
// Get glow brightness
|
float higherz = nexthigher.plane.GetZ(thingpos);
|
||||||
float glowz = level.plane.GetZ(thingpos);
|
float delta = General.Clamp(1.0f - (thingpos.z - planez) / (higherz - planez), 0f, 1f);
|
||||||
float floorz = floor.GetZ(thingpos);
|
brightness = (int)((glowbrightness + level.sector.Brightness / 2) * delta + nexthigher.sector.Brightness * (1.0f - delta));
|
||||||
float delta = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);
|
|
||||||
|
|
||||||
brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
|
|
||||||
PixelColor areacolor = PixelColor.Modulate(level.colorbelow, areabrightness);
|
|
||||||
sectorcolor = areacolor.WithAlpha(alpha).ToInt();
|
|
||||||
|
|
||||||
//mxd. Calculate fogfactor
|
|
||||||
fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, brightness);
|
|
||||||
}
|
}
|
||||||
}
|
// Level below this one is glowing. Only possible for floor glow(?)
|
||||||
//TECH: even Bright Thing frames are affected by custom fade...
|
else if(level.type == SectorLevelType.Glow)
|
||||||
else
|
|
||||||
{
|
|
||||||
Vector3D thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
|
|
||||||
SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
|
||||||
|
|
||||||
if(level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
|
|
||||||
{
|
{
|
||||||
//mxd. Calculate fogfactor
|
// Interpolate thing brightness between glow and regular ones
|
||||||
fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, level.brightnessbelow);
|
if(sd.Floor != null && sd.FloorGlow != null)
|
||||||
|
{
|
||||||
|
// Get glow brightness
|
||||||
|
float glowz = level.plane.GetZ(thingpos);
|
||||||
|
float floorz = floor.GetZ(thingpos);
|
||||||
|
float delta = General.Clamp((thingpos.z - floorz) / (glowz - floorz), 0f, 1f);
|
||||||
|
|
||||||
|
brightness = (int)((sd.FloorGlow.Brightness / 2 + sd.Floor.sector.Brightness / 2) * (1.0f - delta) + sd.Floor.sector.Brightness * delta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PixelColor areabrightness = PixelColor.FromInt(mode.CalculateBrightness(brightness));
|
||||||
|
PixelColor areacolor = PixelColor.Modulate(level.colorbelow, areabrightness);
|
||||||
|
sectorcolor = areacolor.WithAlpha(alpha).ToInt();
|
||||||
|
|
||||||
|
//mxd. Calculate fogfactor
|
||||||
|
fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, brightness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//TECH: even Bright Thing frames are affected by custom fade...
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector3D thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position));
|
||||||
|
SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
||||||
|
|
||||||
|
if(level != null && level.sector.FogMode > SectorFogMode.CLASSIC)
|
||||||
|
{
|
||||||
|
//mxd. Calculate fogfactor
|
||||||
|
fogfactor = VisualGeometry.CalculateFogFactor(level.sector.FogMode, level.brightnessbelow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mxd. Create verts for all sprite angles
|
||||||
|
WorldVertex[][] allverts = new WorldVertex[info.SpriteFrame.Length][];
|
||||||
|
base.textures = new ImageData[info.SpriteFrame.Length];
|
||||||
|
|
||||||
|
for(int i = 0; i < sprites.Length; i++)
|
||||||
|
{
|
||||||
// Check if the texture is loaded
|
// Check if the texture is loaded
|
||||||
|
ImageData sprite = sprites[i];
|
||||||
sprite.LoadImage();
|
sprite.LoadImage();
|
||||||
isloaded = sprite.IsImageLoaded;
|
isloaded = sprite.IsImageLoaded;
|
||||||
if(isloaded)
|
if(isloaded)
|
||||||
{
|
{
|
||||||
float offsetx = 0.0f;
|
float offsetx = 0.0f;
|
||||||
float offsety = 0.0f;
|
float offsety = 0.0f;
|
||||||
|
|
||||||
base.Texture = sprite;
|
base.textures[i] = sprite;
|
||||||
|
|
||||||
// Determine sprite size and offset
|
// Determine sprite size and offset
|
||||||
float radius = sprite.ScaledWidth * 0.5f;
|
float radius = sprite.ScaledWidth * 0.5f;
|
||||||
|
@ -304,30 +310,34 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Make vertices
|
// Make vertices
|
||||||
WorldVertex[] verts = new WorldVertex[6];
|
WorldVertex[] verts = new WorldVertex[6];
|
||||||
|
|
||||||
|
//mxd. Sprite mirroring
|
||||||
|
float ul = (info.SpriteFrame[i].Mirror ? 1f : 0f);
|
||||||
|
float ur = (info.SpriteFrame[i].Mirror ? 0f : 1f);
|
||||||
|
|
||||||
if(sizeless) //mxd
|
if(sizeless) //mxd
|
||||||
{
|
{
|
||||||
float hh = height / 2;
|
float hh = height / 2;
|
||||||
verts[0] = new WorldVertex(-radius + offsetx, 0.0f, offsety - hh, sectorcolor, 0.0f, 1.0f);
|
verts[0] = new WorldVertex(-radius + offsetx, 0.0f, offsety - hh, sectorcolor, ul, 1.0f);
|
||||||
verts[1] = new WorldVertex(-radius + offsetx, 0.0f, hh + offsety, sectorcolor, 0.0f, 0.0f);
|
verts[1] = new WorldVertex(-radius + offsetx, 0.0f, hh + offsety, sectorcolor, ul, 0.0f);
|
||||||
verts[2] = new WorldVertex(+radius + offsetx, 0.0f, hh + offsety, sectorcolor, 1.0f, 0.0f);
|
verts[2] = new WorldVertex(+radius + offsetx, 0.0f, hh + offsety, sectorcolor, ur, 0.0f);
|
||||||
verts[3] = verts[0];
|
verts[3] = verts[0];
|
||||||
verts[4] = verts[2];
|
verts[4] = verts[2];
|
||||||
verts[5] = new WorldVertex(+radius + offsetx, 0.0f, offsety - hh, sectorcolor, 1.0f, 1.0f);
|
verts[5] = new WorldVertex(+radius + offsetx, 0.0f, offsety - hh, sectorcolor, ur, 1.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
verts[0] = new WorldVertex(-radius + offsetx, 0.0f, offsety, sectorcolor, 0.0f, 1.0f);
|
verts[0] = new WorldVertex(-radius + offsetx, 0.0f, offsety, sectorcolor, ul, 1.0f);
|
||||||
verts[1] = new WorldVertex(-radius + offsetx, 0.0f, height + offsety, sectorcolor, 0.0f, 0.0f);
|
verts[1] = new WorldVertex(-radius + offsetx, 0.0f, height + offsety, sectorcolor, ul, 0.0f);
|
||||||
verts[2] = new WorldVertex(+radius + offsetx, 0.0f, height + offsety, sectorcolor, 1.0f, 0.0f);
|
verts[2] = new WorldVertex(+radius + offsetx, 0.0f, height + offsety, sectorcolor, ur, 0.0f);
|
||||||
verts[3] = verts[0];
|
verts[3] = verts[0];
|
||||||
verts[4] = verts[2];
|
verts[4] = verts[2];
|
||||||
verts[5] = new WorldVertex(+radius + offsetx, 0.0f, offsety, sectorcolor, 1.0f, 1.0f);
|
verts[5] = new WorldVertex(+radius + offsetx, 0.0f, offsety, sectorcolor, ur, 1.0f);
|
||||||
}
|
}
|
||||||
SetVertices(verts, floor, ceiling);
|
allverts[i] = verts;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
base.Texture = General.Map.Data.Hourglass3D;
|
base.textures[i] = General.Map.Data.Hourglass3D;
|
||||||
|
|
||||||
// Determine sprite size
|
// Determine sprite size
|
||||||
float radius = Math.Min(thingradius, thingheight / 2f);
|
float radius = Math.Min(thingradius, thingheight / 2f);
|
||||||
|
@ -341,9 +351,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
verts[3] = verts[0];
|
verts[3] = verts[0];
|
||||||
verts[4] = verts[2];
|
verts[4] = verts[2];
|
||||||
verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, sectorcolor, 1.0f, 1.0f);
|
verts[5] = new WorldVertex(+radius, 0.0f, 0.0f, sectorcolor, 1.0f, 1.0f);
|
||||||
SetVertices(verts, floor, ceiling);
|
allverts[i] = verts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mxd
|
||||||
|
SetVertices(allverts, floor, ceiling);
|
||||||
|
|
||||||
// Determine position
|
// Determine position
|
||||||
Vector3D pos = Thing.Position;
|
Vector3D pos = Thing.Position;
|
||||||
|
@ -439,10 +452,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
if(!IsDisposed)
|
if(!IsDisposed)
|
||||||
{
|
{
|
||||||
if(sprite != null)
|
if(sprites != null) //mxd
|
||||||
{
|
{
|
||||||
sprite.RemoveReference();
|
foreach(ImageData sprite in sprites) sprite.RemoveReference();
|
||||||
sprite = null;
|
sprites = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose();
|
base.Dispose();
|
||||||
|
@ -462,11 +475,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
//mxd. When true, the thing can be moved below floor/above ceiling
|
//mxd. When true, the thing can be moved below floor/above ceiling
|
||||||
nointeraction = (info.Actor != null && info.Actor.GetFlagValue("nointeraction", false));
|
nointeraction = (info.Actor != null && info.Actor.GetFlagValue("nointeraction", false));
|
||||||
|
|
||||||
// Find sprite texture
|
//mxd. Find sprite textures
|
||||||
if(info.Sprite.Length > 0)
|
sprites = new ImageData[info.SpriteFrame.Length];
|
||||||
|
for(int i = 0; i < info.SpriteFrame.Length; i++)
|
||||||
{
|
{
|
||||||
sprite = General.Map.Data.GetSpriteImage(info.Sprite);
|
sprites[i] = General.Map.Data.GetSpriteImage(info.SpriteFrame[i].Sprite);
|
||||||
if(sprite != null) sprite.AddReference();
|
if(sprites[i] != null) sprites[i].AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup visual thing
|
// Setup visual thing
|
||||||
|
@ -478,11 +492,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
if(!isloaded)
|
if(!isloaded)
|
||||||
{
|
{
|
||||||
// Rebuild sprite geometry when sprite is loaded
|
//mxd. Rebuild sprite geometry when all sprites are loaded
|
||||||
if(sprite.IsImageLoaded)
|
bool allloaded = true;
|
||||||
|
foreach(ImageData sprite in sprites)
|
||||||
{
|
{
|
||||||
Setup();
|
if(!sprite.IsImageLoaded)
|
||||||
|
{
|
||||||
|
allloaded = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(allloaded) Setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the base update
|
// Let the base update
|
||||||
|
@ -757,13 +778,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
//mxd
|
//mxd
|
||||||
public void OnChangeScale(int incrementX, int incrementY)
|
public void OnChangeScale(int incrementX, int incrementY)
|
||||||
{
|
{
|
||||||
if(!General.Map.UDMF || !sprite.IsImageLoaded) return;
|
if(!General.Map.UDMF || sprites == null || !sprites[0].IsImageLoaded) return;
|
||||||
|
|
||||||
if((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
|
if((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
|
||||||
undoticket = mode.CreateUndo("Change thing scale");
|
undoticket = mode.CreateUndo("Change thing scale");
|
||||||
|
|
||||||
float scaleX = Thing.ScaleX;
|
float scaleX = Thing.ScaleX;
|
||||||
float scaleY = Thing.ScaleY;
|
float scaleY = Thing.ScaleY;
|
||||||
|
ImageData sprite = sprites[0];
|
||||||
|
|
||||||
if(incrementX != 0)
|
if(incrementX != 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue