2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using CodeImp.DoomBuilder.Map ;
using SlimDX.Direct3D9 ;
using SlimDX ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Data ;
using CodeImp.DoomBuilder.Editing ;
2013-04-11 11:04:16 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ; //mxd
2013-11-27 12:45:28 +00:00
using CodeImp.DoomBuilder.Config ; //mxd
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
/ * This renders a 2D presentation of the map . This is done in several
* layers which each are optimized for a different purpose . Set the
* PresentationLayer ( s ) to specify how to present these layers .
* /
2013-07-29 08:50:50 +00:00
internal sealed class Renderer2D : Renderer , IRenderer2D
2009-04-19 18:07:22 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
private const float FSAA_FACTOR = 0.6f ;
2015-08-04 23:28:02 +00:00
private const int MAP_CENTER_SIZE = 16 ; //mxd
2015-08-03 22:02:39 +00:00
private const float THING_ARROW_SIZE = 1.4f ;
//private const float THING_ARROW_SHRINK = 2f;
2015-07-14 23:34:31 +00:00
//private const float THING_CIRCLE_SIZE = 1f;
2013-11-27 12:45:28 +00:00
private const float THING_SPRITE_SHRINK = 2f ;
2010-08-16 13:31:53 +00:00
private const int THING_BUFFER_SIZE = 100 ;
2013-07-29 08:50:50 +00:00
private const float MINIMUM_THING_RADIUS = 1.5f ; //mxd
2016-04-01 10:49:19 +00:00
private const float MINIMUM_SPRITE_RADIUS = 8.0f ; //mxd
2016-04-04 22:20:49 +00:00
internal const float FIXED_THING_SIZE = 48.0f ; //mxd
2009-04-19 18:07:22 +00:00
internal const int NUM_VIEW_MODES = 4 ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Rendertargets
private Texture backtex ;
private Texture plottertex ;
private Texture thingstex ;
private Texture overlaytex ;
private Texture surfacetex ;
// Locking data
private DataRectangle plotlocked ;
private Surface targetsurface ;
// Rendertarget sizes
private Size windowsize ;
private Size structsize ;
private Size thingssize ;
private Size overlaysize ;
private Size backsize ;
// Geometry plotter
private Plotter plotter ;
// Vertices to present the textures
private VertexBuffer screenverts ;
private FlatVertex [ ] backimageverts ;
// Batch buffer for things rendering
private VertexBuffer thingsvertices ;
// Render settings
private int vertexsize ;
private RenderLayers renderlayer = RenderLayers . None ;
2009-06-04 20:21:31 +00:00
// Surfaces
private SurfaceManager surfaces ;
2009-04-19 18:07:22 +00:00
// View settings (world coordinates)
private ViewMode viewmode ;
private float scale ;
private float scaleinv ;
private float offsetx ;
private float offsety ;
private float translatex ;
private float translatey ;
private float linenormalsize ;
2015-08-31 22:06:44 +00:00
private float minlinelength ; //mxd. Linedef should be longer than this to be rendered
private float minlinenormallength ; //mxd. Linedef direction indicator should be longer than this to be rendered
2016-06-16 22:05:17 +00:00
private bool drawmapcenter = true ; //mxd
private bool lastdrawmapcenter = true ; //mxd
2009-04-19 18:07:22 +00:00
private float lastgridscale = - 1f ;
private int lastgridsize ;
private float lastgridx ;
private float lastgridy ;
2010-08-14 09:30:54 +00:00
private RectangleF viewport ;
private RectangleF yviewport ;
2009-04-19 18:07:22 +00:00
// Presentation
private Presentation present ;
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public float OffsetX { get { return offsetx ; } }
public float OffsetY { get { return offsety ; } }
public float TranslateX { get { return translatex ; } }
public float TranslateY { get { return translatey ; } }
public float Scale { get { return scale ; } }
public int VertexSize { get { return vertexsize ; } }
2016-06-16 22:05:17 +00:00
public bool DrawMapCenter { get { return drawmapcenter ; } set { drawmapcenter = value ; } } //mxd
2009-04-19 18:07:22 +00:00
public ViewMode ViewMode { get { return viewmode ; } }
2009-06-04 20:21:31 +00:00
public SurfaceManager Surfaces { get { return surfaces ; } }
2013-06-13 11:32:00 +00:00
public RectangleF Viewport { get { return viewport ; } } //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
internal Renderer2D ( D3DDevice graphics ) : base ( graphics )
{
2009-06-04 20:21:31 +00:00
// Create surface manager
surfaces = new SurfaceManager ( ) ;
2009-04-19 18:07:22 +00:00
// Create rendertargets
CreateRendertargets ( ) ;
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
2016-02-01 22:04:00 +00:00
public override void Dispose ( )
2009-04-19 18:07:22 +00:00
{
// Not already disposed?
if ( ! isdisposed )
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
2009-06-04 20:21:31 +00:00
// Dispose surface manager
surfaces . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Presenting
// This sets the presentation to use
public void SetPresentation ( Presentation present )
{
this . present = new Presentation ( present ) ;
}
// This draws the image on screen
2013-07-29 08:50:50 +00:00
public unsafe void Present ( )
2009-04-19 18:07:22 +00:00
{
2010-08-22 12:09:32 +00:00
General . Plugins . OnPresentDisplayBegin ( ) ;
2009-04-19 18:07:22 +00:00
// Start drawing
if ( graphics . StartRendering ( true , General . Colors . Background . ToColorValue ( ) , graphics . BackBuffer , graphics . DepthBuffer ) )
{
// Renderstates that count for this whole sequence
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Device . SetStreamSource ( 0 , screenverts , 0 , sizeof ( FlatVertex ) ) ;
graphics . Device . SetTransform ( TransformState . World , Matrix . Identity ) ;
graphics . Shaders . Display2D . Begin ( ) ;
// Go for all layers
foreach ( PresentLayer layer in present . layers )
{
int aapass ;
// Set blending mode
switch ( layer . blending )
{
case BlendingMode . None :
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
break ;
case BlendingMode . Mask :
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
break ;
case BlendingMode . Alpha :
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , ( new Color4 ( layer . alpha , 1f , 1f , 1f ) ) . ToArgb ( ) ) ;
break ;
case BlendingMode . Additive :
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , ( new Color4 ( layer . alpha , 1f , 1f , 1f ) ) . ToArgb ( ) ) ;
break ;
}
// Check which pass to use
2009-05-03 20:21:52 +00:00
if ( layer . antialiasing & & General . Settings . QualityDisplay ) aapass = 0 ; else aapass = 1 ;
2009-04-19 18:07:22 +00:00
// Render layer
switch ( layer . layer )
{
// BACKGROUND
case RendererLayer . Background :
if ( ( backimageverts = = null ) | | ( General . Map . Grid . Background . Texture = = null ) ) break ;
graphics . Shaders . Display2D . Texture1 = General . Map . Grid . Background . Texture ;
graphics . Shaders . Display2D . SetSettings ( 1f / windowsize . Width , 1f / windowsize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
2015-12-27 21:54:50 +00:00
graphics . Device . DrawUserPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 , backimageverts ) ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Device . SetStreamSource ( 0 , screenverts , 0 , sizeof ( FlatVertex ) ) ;
break ;
// GRID
case RendererLayer . Grid :
graphics . Shaders . Display2D . Texture1 = backtex ;
graphics . Shaders . Display2D . SetSettings ( 1f / backsize . Width , 1f / backsize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
break ;
// GEOMETRY
case RendererLayer . Geometry :
graphics . Shaders . Display2D . Texture1 = plottertex ;
graphics . Shaders . Display2D . SetSettings ( 1f / structsize . Width , 1f / structsize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
break ;
// THINGS
case RendererLayer . Things :
graphics . Shaders . Display2D . Texture1 = thingstex ;
graphics . Shaders . Display2D . SetSettings ( 1f / thingssize . Width , 1f / thingssize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
break ;
// OVERLAY
case RendererLayer . Overlay :
graphics . Shaders . Display2D . Texture1 = overlaytex ;
graphics . Shaders . Display2D . SetSettings ( 1f / overlaysize . Width , 1f / overlaysize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
break ;
// SURFACE
case RendererLayer . Surface :
graphics . Shaders . Display2D . Texture1 = surfacetex ;
graphics . Shaders . Display2D . SetSettings ( 1f / overlaysize . Width , 1f / overlaysize . Height , FSAA_FACTOR , layer . alpha , false ) ;
graphics . Shaders . Display2D . BeginPass ( aapass ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
break ;
}
}
// Done
graphics . Shaders . Display2D . End ( ) ;
graphics . FinishRendering ( ) ;
graphics . Present ( ) ;
// Release binds
graphics . Shaders . Display2D . Texture1 = null ;
graphics . Device . SetStreamSource ( 0 , null , 0 , 0 ) ;
}
else
{
// Request delayed redraw
General . MainWindow . DelayedRedraw ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Management
// This is called before a device is reset
// (when resized or display adapter was changed)
public override void UnloadResource ( )
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
}
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public override void ReloadResource ( )
{
// Re-create rendertargets
CreateRendertargets ( ) ;
}
// This resets the graphics
2016-01-14 22:15:54 +00:00
/ * public override void Reset ( )
2009-04-19 18:07:22 +00:00
{
UnloadResource ( ) ;
ReloadResource ( ) ;
2016-01-14 22:15:54 +00:00
} * /
2009-04-19 18:07:22 +00:00
// This destroys the rendertargets
public void DestroyRendertargets ( )
{
// Trash rendertargets
if ( plottertex ! = null ) plottertex . Dispose ( ) ;
if ( thingstex ! = null ) thingstex . Dispose ( ) ;
if ( overlaytex ! = null ) overlaytex . Dispose ( ) ;
if ( surfacetex ! = null ) surfacetex . Dispose ( ) ;
if ( backtex ! = null ) backtex . Dispose ( ) ;
if ( screenverts ! = null ) screenverts . Dispose ( ) ;
plottertex = null ;
thingstex = null ;
backtex = null ;
screenverts = null ;
overlaytex = null ;
surfacetex = null ;
// Trash things batch buffer
if ( thingsvertices ! = null ) thingsvertices . Dispose ( ) ;
thingsvertices = null ;
lastgridscale = - 1f ;
lastgridsize = 0 ;
}
// Allocates new image memory to render on
2013-07-29 08:50:50 +00:00
public unsafe void CreateRendertargets ( )
2009-04-19 18:07:22 +00:00
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
// Get new width and height
windowsize . Width = graphics . RenderTarget . ClientSize . Width ;
windowsize . Height = graphics . RenderTarget . ClientSize . Height ;
// Create rendertargets textures
plottertex = new Texture ( graphics . Device , windowsize . Width , windowsize . Height , 1 , Usage . None , Format . A8R8G8B8 , Pool . Managed ) ;
thingstex = new Texture ( graphics . Device , windowsize . Width , windowsize . Height , 1 , Usage . RenderTarget , Format . A8R8G8B8 , Pool . Default ) ;
backtex = new Texture ( graphics . Device , windowsize . Width , windowsize . Height , 1 , Usage . None , Format . A8R8G8B8 , Pool . Managed ) ;
overlaytex = new Texture ( graphics . Device , windowsize . Width , windowsize . Height , 1 , Usage . RenderTarget , Format . A8R8G8B8 , Pool . Default ) ;
surfacetex = new Texture ( graphics . Device , windowsize . Width , windowsize . Height , 1 , Usage . RenderTarget , Format . A8R8G8B8 , Pool . Default ) ;
// Get the real surface sizes
2015-12-14 12:34:31 +00:00
SurfaceDescription sd = plottertex . GetLevelDescription ( 0 ) ;
2009-04-19 18:07:22 +00:00
structsize . Width = sd . Width ;
structsize . Height = sd . Height ;
sd = thingstex . GetLevelDescription ( 0 ) ;
thingssize . Width = sd . Width ;
thingssize . Height = sd . Height ;
sd = backtex . GetLevelDescription ( 0 ) ;
backsize . Width = sd . Width ;
backsize . Height = sd . Height ;
sd = overlaytex . GetLevelDescription ( 0 ) ;
overlaysize . Width = sd . Width ;
overlaysize . Height = sd . Height ;
// Clear rendertargets
2009-05-14 18:50:08 +00:00
// This may cause a crash when resetting because it recursively
// calls Reset in the Start functions and doesn't get to Finish
//StartPlotter(true); Finish();
//StartThings(true); Finish();
//StartOverlay(true); Finish();
2009-05-14 19:23:27 +00:00
graphics . ClearRendertarget ( General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , thingstex . GetSurfaceLevel ( 0 ) , null ) ;
graphics . ClearRendertarget ( General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , overlaytex . GetSurfaceLevel ( 0 ) , null ) ;
2009-04-19 18:07:22 +00:00
// Create vertex buffers
screenverts = new VertexBuffer ( graphics . Device , 4 * sizeof ( FlatVertex ) , Usage . Dynamic | Usage . WriteOnly , VertexFormat . None , Pool . Default ) ;
2010-08-16 13:31:53 +00:00
thingsvertices = new VertexBuffer ( graphics . Device , THING_BUFFER_SIZE * 12 * sizeof ( FlatVertex ) , Usage . Dynamic | Usage . WriteOnly , VertexFormat . None , Pool . Default ) ;
2009-04-19 18:07:22 +00:00
// Make screen vertices
2015-12-14 12:34:31 +00:00
DataStream stream = screenverts . Lock ( 0 , 4 * sizeof ( FlatVertex ) , LockFlags . Discard | LockFlags . NoSystemLock ) ;
FlatVertex [ ] verts = CreateScreenVerts ( structsize ) ;
stream . WriteRange ( verts ) ;
2009-04-19 18:07:22 +00:00
screenverts . Unlock ( ) ;
stream . Dispose ( ) ;
// Force update of view
lastgridscale = - 1f ;
lastgridsize = 0 ;
lastgridx = 0.0f ;
lastgridy = 0.0f ;
UpdateTransformations ( ) ;
}
// This makes screen vertices for display
2014-05-20 09:09:28 +00:00
private static FlatVertex [ ] CreateScreenVerts ( Size texturesize )
2009-04-19 18:07:22 +00:00
{
FlatVertex [ ] screenverts = new FlatVertex [ 4 ] ;
screenverts [ 0 ] . x = 0.5f ;
screenverts [ 0 ] . y = 0.5f ;
screenverts [ 0 ] . c = - 1 ;
screenverts [ 0 ] . u = 1f / texturesize . Width ;
screenverts [ 0 ] . v = 1f / texturesize . Height ;
screenverts [ 1 ] . x = texturesize . Width - 1.5f ;
screenverts [ 1 ] . y = 0.5f ;
screenverts [ 1 ] . c = - 1 ;
screenverts [ 1 ] . u = 1f - 1f / texturesize . Width ;
screenverts [ 1 ] . v = 1f / texturesize . Height ;
screenverts [ 2 ] . x = 0.5f ;
screenverts [ 2 ] . y = texturesize . Height - 1.5f ;
screenverts [ 2 ] . c = - 1 ;
screenverts [ 2 ] . u = 1f / texturesize . Width ;
screenverts [ 2 ] . v = 1f - 1f / texturesize . Height ;
screenverts [ 3 ] . x = texturesize . Width - 1.5f ;
screenverts [ 3 ] . y = texturesize . Height - 1.5f ;
screenverts [ 3 ] . c = - 1 ;
screenverts [ 3 ] . u = 1f - 1f / texturesize . Width ;
screenverts [ 3 ] . v = 1f - 1f / texturesize . Height ;
return screenverts ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = View
// This changes view mode
public void SetViewMode ( ViewMode mode )
{
viewmode = mode ;
}
// This changes view position
public void PositionView ( float x , float y )
{
// Change position in world coordinates
offsetx = x ;
offsety = y ;
UpdateTransformations ( ) ;
}
// This changes zoom
public void ScaleView ( float scale )
{
// Change zoom scale
this . scale = scale ;
UpdateTransformations ( ) ;
// Show zoom on main window
General . MainWindow . UpdateZoom ( scale ) ;
}
// This updates some maths
private void UpdateTransformations ( )
{
scaleinv = 1f / scale ;
translatex = - offsetx + ( windowsize . Width * 0.5f ) * scaleinv ;
translatey = - offsety - ( windowsize . Height * 0.5f ) * scaleinv ;
linenormalsize = 10f * scaleinv ;
2015-08-31 22:06:44 +00:00
minlinelength = linenormalsize * 0.0625f ; //mxd
minlinenormallength = linenormalsize * 2f ; //mxd
2012-09-07 10:45:49 +00:00
2013-09-11 09:47:53 +00:00
vertexsize = ( int ) ( 1.7f * General . Settings . GZVertexScale2D * scale + 0.5f ) ; //mxd. added GZVertexScale2D
2009-04-19 18:07:22 +00:00
if ( vertexsize < 0 ) vertexsize = 0 ;
if ( vertexsize > 4 ) vertexsize = 4 ;
2012-09-07 10:45:49 +00:00
2013-09-11 08:49:45 +00:00
Matrix scaling = Matrix . Scaling ( ( 1f / windowsize . Width ) * 2f , ( 1f / windowsize . Height ) * - 2f , 1f ) ;
2009-04-19 18:07:22 +00:00
Matrix translate = Matrix . Translation ( - ( float ) windowsize . Width * 0.5f , - ( float ) windowsize . Height * 0.5f , 0f ) ;
2015-10-02 14:47:34 +00:00
graphics . Device . SetTransform ( TransformState . View , translate * scaling ) ;
2009-04-19 18:07:22 +00:00
graphics . Device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
2010-08-14 09:30:54 +00:00
Vector2D lt = DisplayToMap ( new Vector2D ( 0.0f , 0.0f ) ) ;
2013-09-11 08:49:45 +00:00
Vector2D rb = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
2010-08-14 09:30:54 +00:00
viewport = new RectangleF ( lt . x , lt . y , rb . x - lt . x , rb . y - lt . y ) ;
yviewport = new RectangleF ( lt . x , rb . y , rb . x - lt . x , lt . y - rb . y ) ;
2009-04-19 18:07:22 +00:00
}
// This sets the world matrix for transformation
private void SetWorldTransformation ( bool transform )
{
if ( transform )
{
Matrix translate = Matrix . Translation ( translatex , translatey , 0f ) ;
Matrix scaling = Matrix . Scaling ( scale , - scale , 1f ) ;
2015-10-02 14:47:34 +00:00
graphics . Device . SetTransform ( TransformState . World , translate * scaling ) ;
2009-04-19 18:07:22 +00:00
}
else
{
graphics . Device . SetTransform ( TransformState . World , Matrix . Identity ) ;
}
}
2009-08-21 14:11:18 +00:00
/// <summary>
/// This unprojects display coordinates (screen space) to map coordinates
/// </summary>
public Vector2D DisplayToMap ( Vector2D mousepos )
2009-04-19 18:07:22 +00:00
{
return mousepos . GetInvTransformed ( - translatex , - translatey , scaleinv , - scaleinv ) ;
}
2009-08-21 14:11:18 +00:00
/// <summary>
/// This projects map coordinates to display coordinates (screen space)
/// </summary>
public Vector2D MapToDisplay ( Vector2D mappos )
{
return mappos . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Colors
// This returns the color for a thing
public PixelColor DetermineThingColor ( Thing t )
{
// Determine color
2015-12-14 12:34:31 +00:00
if ( t . Selected ) return General . Colors . Selection ;
//mxd. If thing is light, set it's color to light color:
2014-12-03 23:15:26 +00:00
if ( Array . IndexOf ( GZBuilder . GZGeneral . GZ_LIGHTS , t . Type ) ! = - 1 )
{
2015-12-14 12:34:31 +00:00
if ( t . Type = = 1502 ) //vavoom light
2013-09-11 09:47:53 +00:00
return new PixelColor ( 255 , 255 , 255 , 255 ) ;
2015-12-14 12:34:31 +00:00
if ( t . Type = = 1503 ) //vavoom colored light
2013-09-11 09:47:53 +00:00
return new PixelColor ( 255 , ( byte ) t . Args [ 1 ] , ( byte ) t . Args [ 2 ] , ( byte ) t . Args [ 3 ] ) ;
return new PixelColor ( 255 , ( byte ) t . Args [ 0 ] , ( byte ) t . Args [ 1 ] , ( byte ) t . Args [ 2 ] ) ;
}
return t . Color ;
2009-04-19 18:07:22 +00:00
}
// This returns the color for a vertex
public int DetermineVertexColor ( Vertex v )
{
// Determine color
if ( v . Selected ) return ColorCollection . SELECTION ;
2013-03-18 13:52:27 +00:00
return ColorCollection . VERTICES ;
2009-04-19 18:07:22 +00:00
}
// This returns the color for a linedef
public PixelColor DetermineLinedefColor ( Linedef l )
{
2013-07-29 08:50:50 +00:00
if ( l . Selected ) return General . Colors . Selection ;
//mxd. Impassable lines
2014-12-03 23:15:26 +00:00
if ( l . ImpassableFlag )
{
2013-07-29 08:50:50 +00:00
if ( l . ColorPresetIndex ! = - 1 )
return General . Map . ConfigSettings . LinedefColorPresets [ l . ColorPresetIndex ] . Color ;
return General . Colors . Linedefs ;
2009-04-19 18:07:22 +00:00
}
2013-03-18 13:52:27 +00:00
2013-07-29 08:50:50 +00:00
//mxd. Passable lines
if ( l . ColorPresetIndex ! = - 1 )
return General . Map . ConfigSettings . LinedefColorPresets [ l . ColorPresetIndex ] . Color . WithAlpha ( General . Settings . DoubleSidedAlphaByte ) ;
return General . Colors . Linedefs . WithAlpha ( General . Settings . DoubleSidedAlphaByte ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-29 08:50:50 +00:00
//mxd. This collects indices of linedefs, which are parts of sectors with 3d floors
2014-12-03 23:15:26 +00:00
public void UpdateExtraFloorFlag ( )
{
2015-07-28 15:04:21 +00:00
HashSet < int > tags = new HashSet < int > ( ) ;
2013-07-29 08:50:50 +00:00
//find lines with 3d floor action and collect sector tags
2014-12-03 23:15:26 +00:00
foreach ( Linedef l in General . Map . Map . Linedefs )
{
if ( l . Action = = 160 )
{
2015-07-26 23:35:34 +00:00
int sectortag = ( General . Map . UDMF | | ( l . Args [ 1 ] & 8 ) ! = 0 ) ? l . Args [ 0 ] : l . Args [ 0 ] + ( l . Args [ 4 ] < < 8 ) ;
2015-07-28 15:04:21 +00:00
if ( sectortag ! = 0 & & ! tags . Contains ( sectortag ) ) tags . Add ( sectortag ) ;
2013-07-29 08:50:50 +00:00
}
}
2013-05-20 10:43:34 +00:00
2013-07-29 08:50:50 +00:00
//find lines, which are related to sectors with 3d floors, and collect their valuable indices
2014-12-03 23:15:26 +00:00
foreach ( Linedef l in General . Map . Map . Linedefs )
{
2015-07-28 15:04:21 +00:00
if ( l . Front ! = null & & l . Front . Sector ! = null & & l . Front . Sector . Tag ! = 0 & & tags . Overlaps ( l . Front . Sector . Tags ) )
2014-12-03 23:15:26 +00:00
{
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = true ;
continue ;
}
2015-07-28 15:04:21 +00:00
if ( l . Back ! = null & & l . Back . Sector ! = null & & l . Back . Sector . Tag ! = 0 & & tags . Overlaps ( l . Back . Sector . Tags ) )
2014-12-03 23:15:26 +00:00
{
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = true ;
continue ;
2013-05-20 10:43:34 +00:00
}
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = false ;
2013-05-20 10:43:34 +00:00
}
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Start / Finish
// This begins a drawing session
public unsafe bool StartPlotter ( bool clear )
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2013-03-18 13:52:27 +00:00
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Plotter ;
// Rendertargets available?
if ( plottertex ! = null )
{
// Lock structures rendertarget memory
plotlocked = plottertex . LockRectangle ( 0 , LockFlags . NoSystemLock ) ;
// Create structures plotter
plotter = new Plotter ( ( PixelColor * ) plotlocked . Data . DataPointer . ToPointer ( ) , plotlocked . Pitch / sizeof ( PixelColor ) , structsize . Height , structsize . Width , structsize . Height ) ;
// Redraw grid when structures image was cleared
if ( clear )
{
2013-05-20 10:43:34 +00:00
plotter . Clear ( ) ;
2009-04-19 18:07:22 +00:00
RenderBackgroundGrid ( ) ;
SetupBackground ( ) ;
}
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This begins a drawing session
2013-07-29 08:50:50 +00:00
public bool StartThings ( bool clear )
2009-04-19 18:07:22 +00:00
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2013-03-18 13:52:27 +00:00
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Things ;
// Rendertargets available?
if ( thingstex ! = null )
{
// Set the rendertarget to the things texture
targetsurface = thingstex . GetSurfaceLevel ( 0 ) ;
if ( graphics . StartRendering ( clear , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , targetsurface , null ) )
{
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
}
2013-07-29 08:50:50 +00:00
2009-04-19 18:07:22 +00:00
// Can't render!
Finish ( ) ;
return false ;
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This begins a drawing session
2013-07-29 08:50:50 +00:00
public bool StartOverlay ( bool clear )
2009-04-19 18:07:22 +00:00
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Overlay ;
// Rendertargets available?
if ( overlaytex ! = null )
{
// Set the rendertarget to the things texture
targetsurface = overlaytex . GetSurfaceLevel ( 0 ) ;
if ( graphics . StartRendering ( clear , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , targetsurface , null ) )
{
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
}
2013-07-29 08:50:50 +00:00
2009-04-19 18:07:22 +00:00
// Can't render!
Finish ( ) ;
return false ;
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This ends a drawing session
public void Finish ( )
{
// Clean up plotter
if ( renderlayer = = RenderLayers . Plotter )
{
if ( plottertex ! = null ) plottertex . UnlockRectangle ( 0 ) ;
if ( plotlocked . Data ! = null ) plotlocked . Data . Dispose ( ) ;
plotter = null ;
}
// Clean up things / overlay
if ( ( renderlayer = = RenderLayers . Things ) | | ( renderlayer = = RenderLayers . Overlay ) | | ( renderlayer = = RenderLayers . Surface ) )
{
// Stop rendering
graphics . FinishRendering ( ) ;
// Release rendertarget
try
{
graphics . Device . DepthStencilSurface = graphics . DepthBuffer ;
graphics . Device . SetRenderTarget ( 0 , graphics . BackBuffer ) ;
}
catch ( Exception ) { }
if ( targetsurface ! = null ) targetsurface . Dispose ( ) ;
targetsurface = null ;
}
// Done
renderlayer = RenderLayers . None ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Background
// This sets up background image vertices
private void SetupBackground ( )
{
// Only if a background image is set
2014-01-13 08:06:56 +00:00
if ( ( General . Map . Grid . Background ! = null ) & & ! ( General . Map . Grid . Background is UnknownImage ) )
2009-04-19 18:07:22 +00:00
{
2014-01-13 08:06:56 +00:00
Vector2D backoffset = new Vector2D ( General . Map . Grid . BackgroundX , General . Map . Grid . BackgroundY ) ;
Vector2D backimagesize = new Vector2D ( General . Map . Grid . Background . ScaledWidth , General . Map . Grid . Background . ScaledHeight ) ;
Vector2D backimagescale = new Vector2D ( General . Map . Grid . BackgroundScaleX , General . Map . Grid . BackgroundScaleY ) ;
// Scale the background image size
backimagesize * = backimagescale ;
2009-04-19 18:07:22 +00:00
// Make vertices
backimageverts = CreateScreenVerts ( windowsize ) ;
// Determine map coordinates for view window
2015-12-27 21:54:50 +00:00
Vector2D ltpos = DisplayToMap ( new Vector2D ( 0f , 0f ) ) ;
Vector2D rbpos = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
2009-04-19 18:07:22 +00:00
// Offset by given background offset
ltpos - = backoffset ;
rbpos - = backoffset ;
// Calculate UV coordinates
// NOTE: backimagesize.y is made negative to match Doom's coordinate system
backimageverts [ 0 ] . u = ltpos . x / backimagesize . x ;
backimageverts [ 0 ] . v = ltpos . y / - backimagesize . y ;
backimageverts [ 1 ] . u = rbpos . x / backimagesize . x ;
backimageverts [ 1 ] . v = ltpos . y / - backimagesize . y ;
backimageverts [ 2 ] . u = ltpos . x / backimagesize . x ;
backimageverts [ 2 ] . v = rbpos . y / - backimagesize . y ;
backimageverts [ 3 ] . u = rbpos . x / backimagesize . x ;
backimageverts [ 3 ] . v = rbpos . y / - backimagesize . y ;
}
else
{
// No background image
backimageverts = null ;
}
}
// This renders all grid
2013-07-29 08:50:50 +00:00
private unsafe void RenderBackgroundGrid ( )
2009-04-19 18:07:22 +00:00
{
// Do we need to redraw grid?
2016-06-16 22:05:17 +00:00
if ( lastgridsize ! = General . Map . Grid . GridSize | | lastgridscale ! = scale | |
lastgridx ! = offsetx | | lastgridy ! = offsety | | drawmapcenter ! = lastdrawmapcenter )
2009-04-19 18:07:22 +00:00
{
// Lock background rendertarget memory
2015-08-04 23:28:02 +00:00
DataRectangle lockedrect = backtex . LockRectangle ( 0 , LockFlags . NoSystemLock ) ;
2009-04-19 18:07:22 +00:00
// Create a plotter
2015-08-04 23:28:02 +00:00
Plotter gridplotter = new Plotter ( ( PixelColor * ) lockedrect . Data . DataPointer . ToPointer ( ) , lockedrect . Pitch / sizeof ( PixelColor ) , backsize . Height , backsize . Width , backsize . Height ) ;
2009-04-19 18:07:22 +00:00
gridplotter . Clear ( ) ;
2015-08-04 23:28:02 +00:00
if ( General . Settings . RenderGrid ) //mxd
{
// Render normal grid
RenderGrid ( General . Map . Grid . GridSize , General . Colors . Grid , gridplotter ) ;
2009-04-19 18:07:22 +00:00
2015-08-04 23:28:02 +00:00
// Render 64 grid
if ( General . Map . Grid . GridSize < = 64 ) RenderGrid ( 64f , General . Colors . Grid64 , gridplotter ) ;
}
else
{
//mxd. Render map format bounds
Vector2D tl = new Vector2D ( General . Map . Config . LeftBoundary , General . Map . Config . TopBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D rb = new Vector2D ( General . Map . Config . RightBoundary , General . Map . Config . BottomBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
PixelColor g = General . Colors . Grid64 ;
gridplotter . DrawGridLineH ( ( int ) tl . y , ( int ) tl . x , ( int ) rb . x , ref g ) ;
gridplotter . DrawGridLineH ( ( int ) rb . y , ( int ) tl . x , ( int ) rb . x , ref g ) ;
gridplotter . DrawGridLineV ( ( int ) tl . x , ( int ) tl . y , ( int ) rb . y , ref g ) ;
gridplotter . DrawGridLineV ( ( int ) rb . x , ( int ) tl . y , ( int ) rb . y , ref g ) ;
}
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
//mxd. Render center of map
2016-06-16 22:05:17 +00:00
if ( drawmapcenter )
{
Vector2D center = new Vector2D ( ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
int cx = ( int ) center . x ;
int cy = ( int ) center . y ;
PixelColor c = General . Colors . Highlight ;
gridplotter . DrawLineSolid ( cx , cy + MAP_CENTER_SIZE , cx , cy - MAP_CENTER_SIZE , ref c ) ;
gridplotter . DrawLineSolid ( cx - MAP_CENTER_SIZE , cy , cx + MAP_CENTER_SIZE , cy , ref c ) ;
}
2012-06-28 21:19:32 +00:00
2009-04-19 18:07:22 +00:00
// Done
backtex . UnlockRectangle ( 0 ) ;
lockedrect . Data . Dispose ( ) ;
lastgridscale = scale ;
lastgridsize = General . Map . Grid . GridSize ;
lastgridx = offsetx ;
lastgridy = offsety ;
2016-06-16 22:05:17 +00:00
lastdrawmapcenter = drawmapcenter ; //mxd
2009-04-19 18:07:22 +00:00
}
}
// This renders the grid
private void RenderGrid ( float size , PixelColor c , Plotter gridplotter )
{
Vector2D pos = new Vector2D ( ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
//mxd. Increase rendered grid size if needed
2015-08-20 14:09:28 +00:00
if ( ! General . Settings . DynamicGridSize & & size * scale < = 6f )
do { size * = 2 ; } while ( size * scale < = 6f ) ;
2013-12-17 08:19:40 +00:00
float sizeinv = 1f / size ;
2009-04-19 18:07:22 +00:00
2013-12-17 08:19:40 +00:00
// Determine map coordinates for view window
2015-12-27 21:54:50 +00:00
Vector2D ltpos = DisplayToMap ( new Vector2D ( 0 , 0 ) ) ;
Vector2D rbpos = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Clip to nearest grid
ltpos = GridSetup . SnappedToGrid ( ltpos , size , sizeinv ) ;
rbpos = GridSetup . SnappedToGrid ( rbpos , size , sizeinv ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Translate top left boundary and right bottom boundary of map to screen coords
2015-12-27 21:54:50 +00:00
Vector2D tlb = new Vector2D ( General . Map . Config . LeftBoundary , General . Map . Config . TopBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D rbb = new Vector2D ( General . Map . Config . RightBoundary , General . Map . Config . BottomBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Draw all horizontal grid lines
2015-12-27 21:54:50 +00:00
float ystart = rbpos . y > General . Map . Config . BottomBoundary ? rbpos . y : General . Map . Config . BottomBoundary ;
float yend = ltpos . y < General . Map . Config . TopBoundary ? ltpos . y : General . Map . Config . TopBoundary ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
for ( float y = ystart ; y < yend + size ; y + = size )
{
if ( y > General . Map . Config . TopBoundary ) y = General . Map . Config . TopBoundary ;
else if ( y < General . Map . Config . BottomBoundary ) y = General . Map . Config . BottomBoundary ;
2010-08-13 18:32:21 +00:00
2015-12-27 21:54:50 +00:00
float from = tlb . x < 0 ? 0 : tlb . x ;
float to = rbb . x > windowsize . Width ? windowsize . Width : rbb . x ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
pos . y = y ;
pos = pos . GetTransformed ( translatex , translatey , scale , - scale ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter . DrawGridLineH ( ( int ) pos . y , ( int ) Math . Round ( from + 0.49999f ) , ( int ) Math . Round ( to + 0.49999f ) , ref c ) ;
}
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Draw all vertical grid lines
2015-12-27 21:54:50 +00:00
float xstart = ltpos . x > General . Map . Config . LeftBoundary ? ltpos . x : General . Map . Config . LeftBoundary ;
float xend = rbpos . x < General . Map . Config . RightBoundary ? rbpos . x : General . Map . Config . RightBoundary ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
for ( float x = xstart ; x < xend + size ; x + = size )
{
if ( x > General . Map . Config . RightBoundary ) x = General . Map . Config . RightBoundary ;
else if ( x < General . Map . Config . LeftBoundary ) x = General . Map . Config . LeftBoundary ;
2010-08-13 18:32:21 +00:00
2015-12-27 21:54:50 +00:00
float from = tlb . y < 0 ? 0 : tlb . y ;
float to = rbb . y > windowsize . Height ? windowsize . Height : rbb . y ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
pos . x = x ;
pos = pos . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter . DrawGridLineV ( ( int ) pos . x , ( int ) Math . Round ( from + 0.49999f ) , ( int ) Math . Round ( to + 0.49999f ) , ref c ) ;
2009-04-19 18:07:22 +00:00
}
}
2015-08-04 23:28:02 +00:00
//mxd
internal void GridVisibilityChanged ( )
{
lastgridscale = - 1 ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Things
// This makes vertices for a thing
// Returns false when not on the screen
2016-04-01 10:49:19 +00:00
private bool CreateThingBoxVerts ( Thing t , ref FlatVertex [ ] verts , ref List < Line3D > bboxes , Dictionary < Thing , Vector3D > thingsByPosition , int offset , PixelColor c , byte bboxalpha )
2009-04-19 18:07:22 +00:00
{
2013-07-29 08:50:50 +00:00
if ( t . Size * scale < MINIMUM_THING_RADIUS ) return false ; //mxd. Don't render tiny little things
2013-11-27 12:45:28 +00:00
2016-02-22 15:20:08 +00:00
// Determine sizes
2016-04-04 12:09:38 +00:00
float circlesize , bboxsize ;
if ( t . FixedSize & & scale > 1.0f )
{
circlesize = t . Size ;
bboxsize = - 1 ;
}
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
{
circlesize = FIXED_THING_SIZE ;
bboxsize = t . Size * scale ;
}
else
{
circlesize = t . Size * scale ;
bboxsize = - 1 ;
}
2016-04-01 10:49:19 +00:00
float screensize = ( bboxsize > 0 ? bboxsize : circlesize ) ; //mxd
2009-04-19 18:07:22 +00:00
// Transform to screen coordinates
Vector2D screenpos = ( ( Vector2D ) t . Position ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Check if the thing is actually on screen
2016-02-22 15:20:08 +00:00
if ( ( ( screenpos . x + screensize ) < = 0.0f ) | | ( ( screenpos . x - screensize ) > = windowsize . Width ) | |
( ( screenpos . y + screensize ) < = 0.0f ) | | ( ( screenpos . y - screensize ) > = windowsize . Height ) )
2013-11-27 12:45:28 +00:00
return false ;
2013-07-29 08:50:50 +00:00
2013-11-27 12:45:28 +00:00
// Get integral color
int color = c . ToInt ( ) ;
// Setup fixed rect for circle
verts [ offset ] . x = screenpos . x - circlesize ;
verts [ offset ] . y = screenpos . y - circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0f ;
verts [ offset ] . v = 0f ;
offset + + ;
verts [ offset ] . x = screenpos . x + circlesize ;
verts [ offset ] . y = screenpos . y - circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0.5f ;
verts [ offset ] . v = 0f ;
offset + + ;
verts [ offset ] . x = screenpos . x - circlesize ;
verts [ offset ] . y = screenpos . y + circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0f ;
verts [ offset ] . v = 1f ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x + circlesize ;
verts [ offset ] . y = screenpos . y + circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0.5f ;
verts [ offset ] . v = 1f ;
//mxd. Add to list
thingsByPosition . Add ( t , screenpos ) ;
2013-07-29 08:50:50 +00:00
2016-02-22 15:20:08 +00:00
//mxd. Add bounding box?
if ( bboxsize > 0 )
{
PixelColor boxcolor = c . WithAlpha ( bboxalpha ) ;
Vector2D tl = new Vector2D ( screenpos . x - bboxsize , screenpos . y - bboxsize ) ;
Vector2D tr = new Vector2D ( screenpos . x + bboxsize , screenpos . y - bboxsize ) ;
Vector2D bl = new Vector2D ( screenpos . x - bboxsize , screenpos . y + bboxsize ) ;
Vector2D br = new Vector2D ( screenpos . x + bboxsize , screenpos . y + bboxsize ) ;
bboxes . Add ( new Line3D ( tl , tr , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( tr , br , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( bl , br , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( tl , bl , boxcolor , false ) ) ;
}
2013-11-27 12:45:28 +00:00
// Done
return true ;
}
//mxd
2016-04-01 10:49:19 +00:00
private void CreateThingArrowVerts ( Thing t , ref FlatVertex [ ] verts , Vector3D screenpos , int offset )
2014-12-03 23:15:26 +00:00
{
2013-11-27 12:45:28 +00:00
// Determine size
2016-04-04 12:09:38 +00:00
float arrowsize ;
if ( t . FixedSize & & scale > 1.0f )
arrowsize = t . Size * THING_ARROW_SIZE ;
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
arrowsize = FIXED_THING_SIZE * THING_ARROW_SIZE ;
else
arrowsize = t . Size * scale * THING_ARROW_SIZE ;
2013-11-27 12:45:28 +00:00
// Setup rotated rect for arrow
float sinarrowsize = ( float ) Math . Sin ( t . Angle + Angle2D . PI * 0.25f ) * arrowsize ;
float cosarrowsize = ( float ) Math . Cos ( t . Angle + Angle2D . PI * 0.25f ) * arrowsize ;
2016-04-01 10:49:19 +00:00
// Sprite is not rendered?
float ut , ub , ul , ur ;
if ( screenpos . z < 0 )
{
ul = 0.625f ;
ur = 0.874f ;
ut = - 0.039f ;
ub = 0.46f ;
}
else
{
ul = 0.501f ;
ur = 0.999f ;
ut = 0.001f ;
ub = 0.999f ;
}
2013-11-27 12:45:28 +00:00
verts [ offset ] . x = screenpos . x + sinarrowsize ;
verts [ offset ] . y = screenpos . y + cosarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ul ;
verts [ offset ] . v = ut ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] . x = screenpos . x - cosarrowsize ;
verts [ offset ] . y = screenpos . y + sinarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ur ;
verts [ offset ] . v = ut ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] . x = screenpos . x + cosarrowsize ;
verts [ offset ] . y = screenpos . y - sinarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ul ;
verts [ offset ] . v = ub ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x - sinarrowsize ;
verts [ offset ] . y = screenpos . y - cosarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ur ;
verts [ offset ] . v = ub ;
2013-11-27 12:45:28 +00:00
}
//mxd
2016-04-08 14:02:08 +00:00
private static void CreateThingSpriteVerts ( Vector2D screenpos , float width , float height , ref FlatVertex [ ] verts , int offset , int color , bool mirror )
2014-05-20 09:09:28 +00:00
{
2016-04-08 14:02:08 +00:00
float ul = ( mirror ? 1f : 0f ) ;
float ur = ( mirror ? 0f : 1f ) ;
2013-11-27 12:45:28 +00:00
// Setup fixed rect for circle
verts [ offset ] . x = screenpos . x - width ;
verts [ offset ] . y = screenpos . y - height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ul ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 0 ;
offset + + ;
verts [ offset ] . x = screenpos . x + width ;
verts [ offset ] . y = screenpos . y - height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ur ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 0 ;
offset + + ;
verts [ offset ] . x = screenpos . x - width ;
verts [ offset ] . y = screenpos . y + height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ul ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 1 ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x + width ;
verts [ offset ] . y = screenpos . y + height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ur ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 1 ;
2009-04-19 18:07:22 +00:00
}
// This draws a set of things
2010-08-16 13:31:53 +00:00
private void RenderThingsBatch ( ICollection < Thing > things , float alpha , bool fixedcolor , PixelColor c )
2009-04-19 18:07:22 +00:00
{
// Anything to render?
2010-08-16 13:31:53 +00:00
if ( things . Count > 0 )
2009-04-19 18:07:22 +00:00
{
2015-08-03 22:02:39 +00:00
DataStream stream ;
2009-04-19 18:07:22 +00:00
// Make alpha color
Color4 alphacolor = new Color4 ( alpha , 1.0f , 1.0f , 1.0f ) ;
2016-02-23 13:55:53 +00:00
bool isthingsmode = ( General . Editing . Mode . GetType ( ) . Name = = "ThingsMode" ) ;
2009-04-19 18:07:22 +00:00
// Set renderstates for things rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , alphacolor . ToArgb ( ) ) ;
graphics . Device . SetStreamSource ( 0 , thingsvertices , 0 , FlatVertex . Stride ) ;
2010-08-16 13:31:53 +00:00
2015-08-03 22:02:39 +00:00
// Set things texture
2016-04-01 10:49:19 +00:00
graphics . Shaders . Things2D . Texture1 = General . Map . Data . ThingTexture . Texture ; //mxd
2009-04-19 18:07:22 +00:00
SetWorldTransformation ( false ) ;
graphics . Shaders . Things2D . SetSettings ( alpha ) ;
2010-08-16 13:31:53 +00:00
// Begin drawing
2009-04-19 18:07:22 +00:00
graphics . Shaders . Things2D . Begin ( ) ;
graphics . Shaders . Things2D . BeginPass ( 0 ) ;
2010-08-16 17:53:28 +00:00
// Determine next lock size
2010-08-16 13:31:53 +00:00
int locksize = ( things . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : things . Count ;
2013-11-27 12:45:28 +00:00
FlatVertex [ ] verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2016-02-22 15:20:08 +00:00
List < Line3D > bboxes = new List < Line3D > ( locksize ) ; //mxd
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2013-11-27 12:45:28 +00:00
Dictionary < int , List < Thing > > thingsByType = new Dictionary < int , List < Thing > > ( ) ;
Dictionary < int , List < Thing > > modelsByType = new Dictionary < int , List < Thing > > ( ) ;
2016-04-01 10:49:19 +00:00
Dictionary < Thing , Vector3D > thingsByPosition = new Dictionary < Thing , Vector3D > ( ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// Go for all things
2010-08-16 13:31:53 +00:00
int buffercount = 0 ;
int totalcount = 0 ;
2009-04-19 18:07:22 +00:00
foreach ( Thing t in things )
{
2015-08-03 22:02:39 +00:00
//mxd. Highlighted thing should be rendered separately
if ( ! fixedcolor & & t . Highlighted ) continue ;
2016-07-04 18:25:47 +00:00
// Collect models
2016-07-11 22:13:43 +00:00
if ( t . RenderMode = = ThingRenderMode . MODEL | | t . RenderMode = = ThingRenderMode . VOXEL )
2014-12-03 23:15:26 +00:00
{
2013-11-27 12:45:28 +00:00
if ( ! modelsByType . ContainsKey ( t . Type ) ) modelsByType . Add ( t . Type , new List < Thing > ( ) ) ;
modelsByType [ t . Type ] . Add ( t ) ;
}
2013-09-11 09:47:53 +00:00
// Create vertices
2015-12-28 15:01:53 +00:00
PixelColor tc = fixedcolor ? c : DetermineThingColor ( t ) ;
2016-02-23 13:55:53 +00:00
byte bboxalpha = ( byte ) ( alpha * ( ( ! fixedcolor & & ! t . Selected & & isthingsmode ) ? 128 : 255 ) ) ;
2016-02-22 15:20:08 +00:00
if ( CreateThingBoxVerts ( t , ref verts , ref bboxes , thingsByPosition , buffercount * 6 , tc , bboxalpha ) )
2014-12-03 23:15:26 +00:00
{
2010-08-16 13:31:53 +00:00
buffercount + + ;
2013-11-27 12:45:28 +00:00
//mxd
if ( ! thingsByType . ContainsKey ( t . Type ) ) thingsByType . Add ( t . Type , new List < Thing > ( ) ) ;
thingsByType [ t . Type ] . Add ( t ) ;
}
2010-08-16 13:31:53 +00:00
totalcount + + ;
// Buffer filled?
if ( buffercount = = locksize )
2009-04-19 18:07:22 +00:00
{
2010-08-16 17:53:28 +00:00
// Write to buffer
2013-11-27 12:45:28 +00:00
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
2010-08-16 13:31:53 +00:00
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
// Draw!
2013-11-27 12:45:28 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2010-08-16 13:31:53 +00:00
buffercount = 0 ;
2010-08-16 17:53:28 +00:00
// Determine next lock size
locksize = ( ( things . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( things . Count - totalcount ) ;
2009-04-19 18:07:22 +00:00
}
}
2010-08-16 17:53:28 +00:00
// Write to buffer
2013-11-27 12:45:28 +00:00
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
if ( buffercount > 0 ) stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
2010-08-16 17:53:28 +00:00
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
2010-08-16 13:31:53 +00:00
// Draw what's still remaining
if ( buffercount > 0 )
2013-11-27 12:45:28 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
// Done
graphics . Shaders . Things2D . EndPass ( ) ;
//mxd. Render sprites
int selectionColor = General . Colors . Selection . ToInt ( ) ;
graphics . Shaders . Things2D . BeginPass ( 1 ) ;
2014-12-03 09:06:05 +00:00
foreach ( KeyValuePair < int , List < Thing > > group in thingsByType )
{
2016-04-01 22:23:05 +00:00
// Skip when all things of this type will be rendered as models
2016-07-11 22:13:43 +00:00
if ( ( group . Value [ 0 ] . RenderMode = = ThingRenderMode . MODEL | | group . Value [ 0 ] . RenderMode = = ThingRenderMode . VOXEL )
& & ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ALL ) ) continue ;
2016-04-01 22:23:05 +00:00
2013-11-27 12:45:28 +00:00
// Find thing information
ThingTypeInfo info = General . Map . Data . GetThingInfo ( group . Key ) ;
// Find sprite texture
if ( info . Sprite . Length = = 0 ) continue ;
2016-04-08 14:02:08 +00:00
// Sort by sprite angle...
Dictionary < int , List < Thing > > thingsbyangle = new Dictionary < int , List < Thing > > ( group . Value . Count ) ;
if ( info . SpriteFrame . Length = = 8 )
2016-04-01 22:23:05 +00:00
{
2016-04-08 14:02:08 +00:00
foreach ( Thing t in group . Value )
2016-04-04 12:09:38 +00:00
{
2016-04-08 14:02:08 +00:00
// Choose which sprite angle to show
int spriteangle = General . ClampAngle ( - t . AngleDoom + 270 ) / 45 ; // Convert to [0..7] range
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Add to collection
if ( ! thingsbyangle . ContainsKey ( spriteangle ) ) thingsbyangle . Add ( spriteangle , new List < Thing > ( ) ) ;
thingsbyangle [ spriteangle ] . Add ( t ) ;
2016-04-04 12:09:38 +00:00
}
2016-04-08 14:02:08 +00:00
}
else
{
thingsbyangle [ 0 ] = group . Value ;
}
2016-04-04 12:09:38 +00:00
2016-04-08 14:02:08 +00:00
foreach ( KeyValuePair < int , List < Thing > > framegroup in thingsbyangle )
{
SpriteFrameInfo sfi = info . SpriteFrame [ framegroup . Key ] ;
ImageData sprite = General . Map . Data . GetSpriteImage ( sfi . Sprite ) ;
if ( sprite = = null ) continue ;
if ( ! sprite . IsImageLoaded )
2016-04-01 10:49:19 +00:00
{
2016-04-08 14:02:08 +00:00
sprite . SetUsedInMap ( true ) ;
continue ;
2016-04-01 10:49:19 +00:00
}
2016-04-08 14:02:08 +00:00
if ( sprite . Texture = = null ) sprite . CreateTexture ( ) ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
graphics . Shaders . Things2D . Texture1 = sprite . Texture ;
graphics . Shaders . Things2D . ApplySettings ( ) ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Determine next lock size
locksize = ( framegroup . Value . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : framegroup . Value . Count ;
verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Go for all things
buffercount = 0 ;
totalcount = 0 ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
foreach ( Thing t in framegroup . Value )
{
2016-07-11 22:13:43 +00:00
if ( ( t . RenderMode = = ThingRenderMode . MODEL | | t . RenderMode = = ThingRenderMode . VOXEL )
& & ( ( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & t . Selected ) | | ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ACTIVE_THINGS_FILTER & & alpha = = 1.0f ) ) )
2016-04-08 14:02:08 +00:00
continue ;
bool forcespriterendering ;
float spritewidth , spriteheight , spritescale ;
// Determine sizes
if ( t . FixedSize & & scale > 1.0f )
{
spritescale = 1.0f ;
forcespriterendering = true ; // Always render sprite when thing size is affected by FixedSize setting
}
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
{
spritescale = FIXED_THING_SIZE / t . Size ;
forcespriterendering = true ; // Always render sprite when thing size is affected by FixedThingsScale setting
}
else
{
spritescale = scale ;
forcespriterendering = false ;
}
// Calculate scaled sprite size
if ( sprite . Width > sprite . Height )
{
spritewidth = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spriteheight = spritewidth * ( ( float ) sprite . Height / sprite . Width ) ;
}
else if ( sprite . Width < sprite . Height )
{
spriteheight = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spritewidth = spriteheight * ( ( float ) sprite . Width / sprite . Height ) ;
}
else
{
spritewidth = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spriteheight = spritewidth ;
}
float spritesize = Math . Max ( spritewidth , spriteheight ) ;
if ( ! forcespriterendering & & spritesize < MINIMUM_SPRITE_RADIUS )
{
// Hackish way to tell arrow rendering code to draw bigger arrow...
Vector3D v = thingsByPosition [ t ] ;
v . z = - 1 ;
thingsByPosition [ t ] = v ;
// Don't render tiny little sprites
continue ;
}
CreateThingSpriteVerts ( thingsByPosition [ t ] , spritewidth , spriteheight , ref verts , buffercount * 6 , ( t . Selected ? selectionColor : 0xFFFFFF ) , sfi . Mirror ) ;
buffercount + + ;
totalcount + + ;
// Buffer filled?
if ( buffercount = = locksize )
{
// Write to buffer
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
// Draw!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
buffercount = 0 ;
// Determine next lock size
locksize = ( ( framegroup . Value . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( framegroup . Value . Count - totalcount ) ;
}
2013-11-27 12:45:28 +00:00
}
2016-04-08 14:02:08 +00:00
// Write to buffer
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
if ( buffercount > 0 ) stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Draw what's still remaining
if ( buffercount > 0 ) graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
}
2013-11-27 12:45:28 +00:00
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Done
graphics . Shaders . Things2D . EndPass ( ) ;
2012-04-17 19:13:47 +00:00
2013-11-27 12:45:28 +00:00
//mxd. Render thing arrows
2016-04-01 10:49:19 +00:00
graphics . Shaders . Things2D . Texture1 = General . Map . Data . ThingTexture . Texture ;
2013-11-27 12:45:28 +00:00
graphics . Shaders . Things2D . BeginPass ( 0 ) ;
2013-12-03 10:50:33 +00:00
// Determine next lock size
locksize = ( thingsByPosition . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : thingsByPosition . Count ;
verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2013-11-27 12:45:28 +00:00
// Go for all things
buffercount = 0 ;
totalcount = 0 ;
2016-04-01 10:49:19 +00:00
foreach ( KeyValuePair < Thing , Vector3D > group in thingsByPosition )
2014-12-03 09:06:05 +00:00
{
2013-11-27 12:45:28 +00:00
if ( ! group . Key . IsDirectional ) continue ;
CreateThingArrowVerts ( group . Key , ref verts , group . Value , buffercount * 6 ) ;
buffercount + + ;
totalcount + + ;
// Buffer filled?
2014-12-03 09:06:05 +00:00
if ( buffercount = = locksize )
{
2013-11-27 12:45:28 +00:00
// Write to buffer
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
// Draw!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
buffercount = 0 ;
// Determine next lock size
2013-12-03 10:50:33 +00:00
locksize = ( ( thingsByPosition . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( thingsByPosition . Count - totalcount ) ;
2013-11-27 12:45:28 +00:00
}
}
// Write to buffer
stream = thingsvertices . Lock ( 0 , locksize * 6 * FlatVertex . Stride , LockFlags . Discard ) ;
if ( buffercount > 0 ) stream . WriteRange ( verts , 0 , buffercount * 6 ) ;
thingsvertices . Unlock ( ) ;
stream . Dispose ( ) ;
// Draw what's still remaining
if ( buffercount > 0 )
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
//Done with this pass
graphics . Shaders . Things2D . EndPass ( ) ;
2013-09-11 09:47:53 +00:00
//mxd. Render models
2015-12-28 15:01:53 +00:00
if ( General . Settings . GZDrawModelsMode ! = ModelRenderMode . NONE )
2014-10-20 12:16:51 +00:00
{
2013-09-11 09:47:53 +00:00
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2013-03-18 13:52:27 +00:00
graphics . Device . SetRenderState ( RenderState . FillMode , FillMode . Wireframe ) ;
2012-04-17 19:13:47 +00:00
2013-11-27 12:45:28 +00:00
graphics . Shaders . Things2D . BeginPass ( 2 ) ;
2012-07-28 20:36:28 +00:00
2015-07-05 23:20:18 +00:00
Color4 cSelection = General . Colors . Selection . ToColorValue ( ) ;
Color4 cWire = ( ( c . ToInt ( ) = = General . Colors . Highlight . ToInt ( ) ) ? General . Colors . Highlight . ToColorValue ( ) : General . Colors . ModelWireframe . ToColorValue ( ) ) ;
cSelection . Alpha = ( ( alpha < 1.0f ) ? alpha * 0.25f : 0.6f ) ;
cWire . Alpha = cSelection . Alpha ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
Matrix viewscale = Matrix . Scaling ( scale , - scale , 0.0f ) ;
2013-07-29 08:50:50 +00:00
2015-12-28 15:01:53 +00:00
foreach ( KeyValuePair < int , List < Thing > > group in modelsByType )
2014-10-20 12:16:51 +00:00
{
2016-04-01 10:49:19 +00:00
ModelData mde = General . Map . Data . ModeldefEntries [ group . Key ] ;
2014-10-20 12:16:51 +00:00
foreach ( Thing t in group . Value )
{
2015-06-27 09:10:24 +00:00
if ( ( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & ! t . Selected ) | | ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ACTIVE_THINGS_FILTER & & alpha < 1.0f ) ) continue ;
2014-12-22 21:36:49 +00:00
Vector2D screenpos = ( ( Vector2D ) t . Position ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
float modelScale = scale * t . ActorScale . Width * t . ScaleX ;
2013-11-27 12:45:28 +00:00
//should we render this model?
2015-06-22 19:52:23 +00:00
if ( ( ( screenpos . x + mde . Model . Radius * modelScale ) < = 0.0f ) | | ( ( screenpos . x - mde . Model . Radius * modelScale ) > = windowsize . Width ) | |
( ( screenpos . y + mde . Model . Radius * modelScale ) < = 0.0f ) | | ( ( screenpos . y - mde . Model . Radius * modelScale ) > = windowsize . Height ) )
2013-11-27 12:45:28 +00:00
continue ;
2014-05-03 14:44:59 +00:00
2015-07-05 23:20:18 +00:00
graphics . Shaders . Things2D . FillColor = ( t . Selected ? cSelection : cWire ) ;
2013-07-30 09:25:27 +00:00
2015-12-28 15:01:53 +00:00
// Set transform settings
float sx = t . ScaleX * t . ActorScale . Width ;
float sy = t . ScaleY * t . ActorScale . Height ;
Matrix modelscale = Matrix . Scaling ( sx , sx , sy ) ;
2016-07-17 00:00:29 +00:00
Matrix rotation = Matrix . RotationY ( - t . RollRad ) * Matrix . RotationX ( - t . PitchRad ) * Matrix . RotationZ ( t . Angle ) ;
2015-12-28 15:01:53 +00:00
Matrix position = Matrix . Translation ( screenpos . x , screenpos . y , 0.0f ) ;
Matrix world = General . Map . Data . ModeldefEntries [ t . Type ] . Transform * modelscale * rotation * viewscale * position ;
graphics . Shaders . Things2D . SetTransformSettings ( world ) ;
graphics . Shaders . Things2D . ApplySettings ( ) ;
// Draw
foreach ( Mesh mesh in mde . Model . Meshes ) mesh . DrawSubset ( 0 ) ;
2013-07-29 08:50:50 +00:00
}
}
2012-07-28 20:36:28 +00:00
2013-11-27 12:45:28 +00:00
//Done with this pass
2013-09-11 09:47:53 +00:00
graphics . Shaders . Things2D . EndPass ( ) ;
2013-03-18 13:52:27 +00:00
graphics . Device . SetRenderState ( RenderState . FillMode , FillMode . Solid ) ;
2013-09-11 09:47:53 +00:00
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
graphics . Shaders . Things2D . End ( ) ;
2016-02-22 15:20:08 +00:00
//mxd. Render thing boxes
RenderArrows ( bboxes , false ) ;
2009-04-19 18:07:22 +00:00
}
}
2010-08-16 13:31:53 +00:00
// This adds a thing in the things buffer for rendering
public void RenderThing ( Thing t , PixelColor c , float alpha )
{
List < Thing > things = new List < Thing > ( 1 ) ;
things . Add ( t ) ;
RenderThingsBatch ( things , alpha , true , c ) ;
}
// This adds a thing in the things buffer for rendering
public void RenderThingSet ( ICollection < Thing > things , float alpha )
{
RenderThingsBatch ( things , alpha , false , new PixelColor ( ) ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Surface
// This redraws the surface
public void RedrawSurface ( )
{
2013-07-29 08:50:50 +00:00
if ( renderlayer ! = RenderLayers . None ) return ; //mxd
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Surface ;
// Rendertargets available?
if ( surfacetex ! = null )
{
// Set the rendertarget to the surface texture
targetsurface = surfacetex . GetSurfaceLevel ( 0 ) ;
if ( graphics . StartRendering ( true , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , targetsurface , null ) )
{
// Make sure anything we need is loaded
General . Map . Data . UnknownTexture3D . CreateTexture ( ) ;
2013-08-26 11:09:37 +00:00
General . Map . Data . MissingTexture3D . CreateTexture ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Set transformations
UpdateTransformations ( ) ;
2009-06-04 20:21:31 +00:00
// Set states
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( true ) ;
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Prepare for rendering
2009-04-19 18:07:22 +00:00
switch ( viewmode )
{
2009-06-04 20:21:31 +00:00
case ViewMode . Brightness :
2010-08-14 09:30:54 +00:00
surfaces . RenderSectorBrightness ( yviewport ) ;
2009-06-04 20:21:31 +00:00
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
case ViewMode . FloorTextures :
2010-08-14 09:30:54 +00:00
surfaces . RenderSectorFloors ( yviewport ) ;
2009-06-04 20:21:31 +00:00
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
case ViewMode . CeilingTextures :
2010-08-14 09:30:54 +00:00
surfaces . RenderSectorCeilings ( yviewport ) ;
2009-06-04 20:21:31 +00:00
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
2009-04-19 18:07:22 +00:00
}
}
}
// Done
Finish ( ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Overlay
// This renders geometry
// The geometry must be a triangle list
public void RenderGeometry ( FlatVertex [ ] vertices , ImageData texture , bool transformcoords )
{
if ( vertices . Length > 0 )
{
2014-02-21 14:42:12 +00:00
Texture t ;
2009-04-19 18:07:22 +00:00
if ( texture ! = null )
{
// Make sure the texture is loaded
if ( ! texture . IsImageLoaded ) texture . LoadImage ( ) ;
if ( texture . Texture = = null ) texture . CreateTexture ( ) ;
t = texture . Texture ;
}
else
{
2009-06-04 20:21:31 +00:00
t = General . Map . Data . WhiteTexture . Texture ;
2009-04-19 18:07:22 +00:00
}
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Shaders . Display2D . Texture1 = t ;
SetWorldTransformation ( transformcoords ) ;
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
2014-02-21 14:42:12 +00:00
graphics . Device . DrawUserPrimitives ( PrimitiveType . TriangleList , 0 , vertices . Length / 3 , vertices ) ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
}
2013-12-10 12:19:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public void RenderHighlight ( FlatVertex [ ] vertices , int color )
{
2013-12-10 12:19:27 +00:00
if ( vertices . Length < 3 ) return ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( true ) ;
graphics . Shaders . Things2D . FillColor = new Color4 ( color ) ;
graphics . Shaders . Things2D . SetSettings ( 1.0f ) ;
// Draw
graphics . Shaders . Things2D . Begin ( ) ;
graphics . Shaders . Things2D . BeginPass ( 2 ) ;
graphics . Device . DrawUserPrimitives ( PrimitiveType . TriangleList , 0 , vertices . Length / 3 , vertices ) ;
graphics . Shaders . Things2D . EndPass ( ) ;
graphics . Shaders . Things2D . End ( ) ;
}
2016-05-19 21:44:39 +00:00
//mxd. This renders text (DB2 compatibility)
[Obsolete("Method is deprecated, please use RenderText(ITextLabel label) method instead.")]
public void RenderText ( TextLabel label ) { RenderText ( ( ITextLabel ) label ) ; }
2009-04-19 18:07:22 +00:00
// This renders text
2016-04-25 14:48:39 +00:00
public void RenderText ( ITextLabel label )
2009-04-19 18:07:22 +00:00
{
2016-03-30 23:25:03 +00:00
//mxd. Update the text if needed
Sectors, Linedefs, Things modes: optimized text label rendering.
Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
2016-04-05 22:24:36 +00:00
label . Update ( translatex , translatey , scale , - scale ) ;
if ( label . SkipRendering ) return ;
2009-04-19 18:07:22 +00:00
2016-03-30 23:25:03 +00:00
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Shaders . Display2D . Texture1 = label . Texture ;
SetWorldTransformation ( false ) ;
2016-04-06 11:44:38 +00:00
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , false ) ;
2016-03-30 23:25:03 +00:00
graphics . Device . SetStreamSource ( 0 , label . VertexBuffer , 0 , FlatVertex . Stride ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ; //mxd
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
//mxd. This renders text
2016-04-25 14:48:39 +00:00
public void RenderText ( IList < ITextLabel > labels )
2016-03-30 23:25:03 +00:00
{
// Update labels
int skipped = 0 ;
2016-04-25 14:48:39 +00:00
foreach ( ITextLabel label in labels )
2009-04-19 18:07:22 +00:00
{
2016-03-30 23:25:03 +00:00
// Update the text if needed
Sectors, Linedefs, Things modes: optimized text label rendering.
Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
2016-04-05 22:24:36 +00:00
label . Update ( translatex , translatey , scale , - scale ) ;
if ( label . SkipRendering ) skipped + + ;
2016-03-30 23:25:03 +00:00
}
if ( labels . Count = = skipped ) return ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
2016-04-06 11:44:38 +00:00
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , false ) ;
2016-03-30 23:25:03 +00:00
// Begin drawing
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
2016-04-25 14:48:39 +00:00
foreach ( ITextLabel label in labels )
2016-03-30 23:25:03 +00:00
{
// Text is created?
if ( ! label . SkipRendering )
{
graphics . Shaders . Display2D . Texture1 = label . Texture ;
graphics . Shaders . Display2D . ApplySettings ( ) ;
graphics . Device . SetStreamSource ( 0 , label . VertexBuffer , 0 , FlatVertex . Stride ) ;
// Draw
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
}
2009-04-19 18:07:22 +00:00
}
2016-03-30 23:25:03 +00:00
// Finish drawing
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
2009-04-19 18:07:22 +00:00
}
// This renders a rectangle with given border size and color
public void RenderRectangle ( RectangleF rect , float bordersize , PixelColor c , bool transformrect )
{
FlatQuad [ ] quads = new FlatQuad [ 4 ] ;
/ *
* Rectangle setup :
*
* - - - - - - - - - - - - - - - - - - - - - - - - - -
* | ___________0____________ |
* | | | |
* | | | |
* | | | |
* | 2 | | 3 |
* | | | |
* | | | |
* | __ | __________________ | __ |
* | 1 |
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Don ' t you just love ASCII art ?
* /
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quads
quads [ 0 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , lt . y - bordersize ) ;
quads [ 1 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , rb . y + bordersize , rb . x , rb . y ) ;
quads [ 2 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y - bordersize , lt . x + bordersize , rb . y + bordersize ) ;
quads [ 3 ] = new FlatQuad ( PrimitiveType . TriangleStrip , rb . x - bordersize , lt . y - bordersize , rb . x , rb . y + bordersize ) ;
quads [ 0 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 1 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 2 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 3 ] . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
2009-06-04 20:21:31 +00:00
graphics . Shaders . Display2D . Texture1 = General . Map . Data . WhiteTexture . Texture ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
quads [ 0 ] . Render ( graphics ) ;
quads [ 1 ] . Render ( graphics ) ;
quads [ 2 ] . Render ( graphics ) ;
quads [ 3 ] . Render ( graphics ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
// This renders a filled rectangle with given color
public void RenderRectangleFilled ( RectangleF rect , PixelColor c , bool transformrect )
{
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quad
FlatQuad quad = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , rb . y ) ;
quad . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
2009-06-04 20:21:31 +00:00
graphics . Shaders . Display2D . Texture1 = General . Map . Data . WhiteTexture . Texture ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
quad . Render ( graphics ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
2009-08-02 18:48:38 +00:00
// This renders a filled rectangle with given color
public void RenderRectangleFilled ( RectangleF rect , PixelColor c , bool transformrect , ImageData texture )
{
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quad
FlatQuad quad = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , rb . y ) ;
quad . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
graphics . Shaders . Display2D . Texture1 = texture . Texture ;
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
quad . Render ( graphics ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
2012-09-17 21:57:08 +00:00
//mxd
2016-02-22 15:20:08 +00:00
public void RenderArrows ( ICollection < Line3D > lines ) { RenderArrows ( lines , true ) ; }
public void RenderArrows ( ICollection < Line3D > lines , bool transformcoords )
2014-12-03 23:15:26 +00:00
{
2015-06-24 21:21:19 +00:00
if ( lines . Count = = 0 ) return ;
2015-08-08 21:56:43 +00:00
int pointscount = 0 ;
2015-12-14 12:34:31 +00:00
// Translate to screen coords, determine renderability
foreach ( Line3D line in lines )
{
2016-02-22 15:20:08 +00:00
// Calculate screen positions?
if ( transformcoords )
{
line . Start2D = ( ( Vector2D ) line . Start ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //start
line . End2D = ( ( Vector2D ) line . End ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //end
}
2015-12-14 12:34:31 +00:00
float maxx = Math . Max ( line . Start2D . x , line . End2D . x ) ;
float minx = Math . Min ( line . Start2D . x , line . End2D . x ) ;
float maxy = Math . Max ( line . Start2D . y , line . End2D . y ) ;
float miny = Math . Min ( line . Start2D . y , line . End2D . y ) ;
// Too small / not on screen?
if ( ( ( line . End2D - line . Start2D ) . GetLengthSq ( ) < MINIMUM_SPRITE_RADIUS ) | | ( ( maxx < = 0.0f ) | | ( minx > = windowsize . Width ) | | ( maxy < = 0.0f ) | | ( miny > = windowsize . Height ) ) )
{
line . SkipRendering = true ;
}
else
{
pointscount + = ( line . RenderArrowhead ? 6 : 2 ) ; // 4 extra points for the arrowhead
line . SkipRendering = false ;
}
}
// Anything to do?
2015-08-08 21:56:43 +00:00
if ( pointscount < 2 ) return ;
FlatVertex [ ] verts = new FlatVertex [ pointscount ] ;
2015-06-24 21:21:19 +00:00
float scaler = 16f / scale ;
2013-06-13 11:32:00 +00:00
2015-06-24 21:21:19 +00:00
// Create verts array
2015-08-08 21:56:43 +00:00
pointscount = 0 ;
foreach ( Line3D line in lines )
2015-06-24 21:21:19 +00:00
{
2015-12-14 12:34:31 +00:00
if ( line . SkipRendering ) continue ;
2015-12-28 15:01:53 +00:00
int color = line . Color . ToInt ( ) ;
2015-08-08 21:56:43 +00:00
// Add regular points
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . Start2D . x ;
verts [ pointscount ] . y = line . Start2D . y ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . End2D . x ;
verts [ pointscount ] . y = line . End2D . y ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
// Add arrowhead
2015-12-14 12:34:31 +00:00
if ( line . RenderArrowhead )
2015-08-08 21:56:43 +00:00
{
float angle = line . GetAngle ( ) ;
2015-12-14 12:34:31 +00:00
Vector2D a1 = new Vector2D ( line . End . x - scaler * ( float ) Math . Sin ( angle - 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle - 0.46f ) ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //arrowhead end 1
Vector2D a2 = new Vector2D ( line . End . x - scaler * ( float ) Math . Sin ( angle + 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle + 0.46f ) ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //arrowhead end 2
2015-08-08 21:56:43 +00:00
verts [ pointscount ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 1 ] . x = a1 . x ;
verts [ pointscount + 1 ] . y = a1 . y ;
verts [ pointscount + 1 ] . c = color ;
verts [ pointscount + 2 ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 3 ] . x = a2 . x ;
verts [ pointscount + 3 ] . y = a2 . y ;
verts [ pointscount + 3 ] . c = color ;
pointscount + = 4 ;
}
2015-06-24 21:21:19 +00:00
}
2012-09-17 21:57:08 +00:00
2015-06-24 21:21:19 +00:00
// Write to buffer
VertexBuffer vb = new VertexBuffer ( General . Map . Graphics . Device , FlatVertex . Stride * verts . Length , Usage . WriteOnly | Usage . Dynamic , VertexFormat . None , Pool . Default ) ;
DataStream s = vb . Lock ( 0 , FlatVertex . Stride * verts . Length , LockFlags . Discard ) ;
s . WriteRange ( verts ) ;
vb . Unlock ( ) ;
s . Dispose ( ) ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
graphics . Shaders . Display2D . Texture1 = General . Map . Data . WhiteTexture . Texture ;
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2013-06-13 11:32:00 +00:00
2015-06-24 21:21:19 +00:00
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
graphics . Device . SetStreamSource ( 0 , vb , 0 , FlatVertex . Stride ) ;
2015-08-08 21:56:43 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , pointscount / 2 ) ;
2015-06-24 21:21:19 +00:00
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
vb . Dispose ( ) ;
2012-09-17 21:57:08 +00:00
}
2009-04-19 18:07:22 +00:00
// This renders a line with given color
public void RenderLine ( Vector2D start , Vector2D end , float thickness , PixelColor c , bool transformcoords )
{
FlatVertex [ ] verts = new FlatVertex [ 4 ] ;
// Calculate positions
if ( transformcoords )
{
start = start . GetTransformed ( translatex , translatey , scale , - scale ) ;
end = end . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Calculate offsets
Vector2D delta = end - start ;
Vector2D dn = delta . GetNormal ( ) * thickness ;
// Make vertices
verts [ 0 ] . x = start . x - dn . x + dn . y ;
verts [ 0 ] . y = start . y - dn . y - dn . x ;
verts [ 0 ] . z = 0.0f ;
verts [ 0 ] . c = c . ToInt ( ) ;
verts [ 1 ] . x = start . x - dn . x - dn . y ;
verts [ 1 ] . y = start . y - dn . y + dn . x ;
verts [ 1 ] . z = 0.0f ;
verts [ 1 ] . c = c . ToInt ( ) ;
verts [ 2 ] . x = end . x + dn . x + dn . y ;
verts [ 2 ] . y = end . y + dn . y - dn . x ;
verts [ 2 ] . z = 0.0f ;
verts [ 2 ] . c = c . ToInt ( ) ;
verts [ 3 ] . x = end . x + dn . x - dn . y ;
verts [ 3 ] . y = end . y + dn . y + dn . x ;
verts [ 3 ] . z = 0.0f ;
verts [ 3 ] . c = c . ToInt ( ) ;
// Set renderstates for rendering
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
SetWorldTransformation ( false ) ;
2009-06-04 20:21:31 +00:00
graphics . Shaders . Display2D . Texture1 = General . Map . Data . WhiteTexture . Texture ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . SetSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . BeginPass ( 0 ) ;
2015-06-24 21:21:19 +00:00
graphics . Device . DrawUserPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 , verts ) ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Geometry
// This renders the linedefs of a sector with special color
public void PlotSector ( Sector s , PixelColor c )
{
// Go for all sides in the sector
foreach ( Sidedef sd in s . Sidedefs )
{
// Render this linedef
PlotLinedef ( sd . Line , c ) ;
// Render the two vertices on top
PlotVertex ( sd . Line . Start , DetermineVertexColor ( sd . Line . Start ) ) ;
PlotVertex ( sd . Line . End , DetermineVertexColor ( sd . Line . End ) ) ;
}
}
// This renders the linedefs of a sector
public void PlotSector ( Sector s )
{
// Go for all sides in the sector
foreach ( Sidedef sd in s . Sidedefs )
{
// Render this linedef
PlotLinedef ( sd . Line , DetermineLinedefColor ( sd . Line ) ) ;
// Render the two vertices on top
PlotVertex ( sd . Line . Start , DetermineVertexColor ( sd . Line . Start ) ) ;
PlotVertex ( sd . Line . End , DetermineVertexColor ( sd . Line . End ) ) ;
}
}
// This renders a simple line
2016-06-16 22:05:17 +00:00
public void PlotLine ( Vector2D start , Vector2D end , PixelColor c ) { PlotLine ( start , end , c , 0.0625f ) ; }
public void PlotLine ( Vector2D start , Vector2D end , PixelColor c , float lengthscaler )
2009-04-19 18:07:22 +00:00
{
// Transform coordinates
Vector2D v1 = start . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = end . GetTransformed ( translatex , translatey , scale , - scale ) ;
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
2016-06-16 22:05:17 +00:00
if ( ( v2 - v1 ) . GetLengthSq ( ) < linenormalsize * lengthscaler ) return ;
2009-04-19 18:07:22 +00:00
// Draw line
plotter . DrawLineSolid ( ( int ) v1 . x , ( int ) v1 . y , ( int ) v2 . x , ( int ) v2 . y , ref c ) ;
}
// This renders a single linedef
public void PlotLinedef ( Linedef l , PixelColor c )
{
// Transform vertex coordinates
Vector2D v1 = l . Start . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = l . End . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
float lengthsq = ( v2 - v1 ) . GetLengthSq ( ) ;
if ( lengthsq < minlinelength ) return ; //mxd
2009-04-19 18:07:22 +00:00
2013-05-20 10:43:34 +00:00
// Draw line. mxd: added 3d-floor indication
2014-12-03 23:15:26 +00:00
if ( l . ExtraFloorFlag & & General . Settings . GZMarkExtraFloors )
2013-05-20 10:43:34 +00:00
plotter . DrawLine3DFloor ( v1 , v2 , ref c , General . Colors . ThreeDFloor ) ;
2014-12-03 23:15:26 +00:00
else
2013-05-20 10:43:34 +00:00
plotter . DrawLineSolid ( ( int ) v1 . x , ( int ) v1 . y , ( int ) v2 . x , ( int ) v2 . y , ref c ) ;
2009-04-19 18:07:22 +00:00
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
if ( lengthsq < minlinenormallength ) return ; //mxd
2009-04-19 18:07:22 +00:00
// Calculate normal indicator
float mx = ( v2 . x - v1 . x ) * 0.5f ;
float my = ( v2 . y - v1 . y ) * 0.5f ;
// Draw normal indicator
plotter . DrawLineSolid ( ( int ) ( v1 . x + mx ) , ( int ) ( v1 . y + my ) ,
( int ) ( ( v1 . x + mx ) - ( my * l . LengthInv ) * linenormalsize ) ,
( int ) ( ( v1 . y + my ) + ( mx * l . LengthInv ) * linenormalsize ) , ref c ) ;
}
// This renders a set of linedefs
public void PlotLinedefSet ( ICollection < Linedef > linedefs )
{
// Go for all linedefs
2015-08-31 22:06:44 +00:00
foreach ( Linedef l in linedefs )
{
// Transform vertex coordinates
Vector2D v1 = l . Start . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = l . End . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
//mxd. Should we bother?
float lengthsq = ( v2 - v1 ) . GetLengthSq ( ) ;
if ( lengthsq < minlinelength ) continue ; //mxd
// Determine color
PixelColor c = DetermineLinedefColor ( l ) ;
// Draw line. mxd: added 3d-floor indication
if ( l . ExtraFloorFlag & & General . Settings . GZMarkExtraFloors )
plotter . DrawLine3DFloor ( v1 , v2 , ref c , General . Colors . ThreeDFloor ) ;
else
plotter . DrawLineSolid ( ( int ) v1 . x , ( int ) v1 . y , ( int ) v2 . x , ( int ) v2 . y , ref c ) ;
//mxd. Should we bother?
if ( lengthsq < minlinenormallength ) continue ; //mxd
// Calculate normal indicator
float mx = ( v2 . x - v1 . x ) * 0.5f ;
float my = ( v2 . y - v1 . y ) * 0.5f ;
// Draw normal indicator
plotter . DrawLineSolid ( ( int ) ( v1 . x + mx ) , ( int ) ( v1 . y + my ) ,
( int ) ( ( v1 . x + mx ) - ( my * l . LengthInv ) * linenormalsize ) ,
( int ) ( ( v1 . y + my ) + ( mx * l . LengthInv ) * linenormalsize ) , ref c ) ;
}
2009-04-19 18:07:22 +00:00
}
// This renders a single vertex
public void PlotVertex ( Vertex v , int colorindex )
{
// Transform vertex coordinates
Vector2D nv = v . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Draw pixel here
plotter . DrawVertexSolid ( ( int ) nv . x , ( int ) nv . y , vertexsize , ref General . Colors . Colors [ colorindex ] , ref General . Colors . BrightColors [ colorindex ] , ref General . Colors . DarkColors [ colorindex ] ) ;
}
// This renders a single vertex at specified coordinates
public void PlotVertexAt ( Vector2D v , int colorindex )
{
// Transform vertex coordinates
Vector2D nv = v . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Draw pixel here
plotter . DrawVertexSolid ( ( int ) nv . x , ( int ) nv . y , vertexsize , ref General . Colors . Colors [ colorindex ] , ref General . Colors . BrightColors [ colorindex ] , ref General . Colors . DarkColors [ colorindex ] ) ;
}
// This renders a set of vertices
public void PlotVerticesSet ( ICollection < Vertex > vertices )
{
// Go for all vertices
foreach ( Vertex v in vertices ) PlotVertex ( v , DetermineVertexColor ( v ) ) ;
}
#endregion
}
}