From 0979c0597e89deaeab1417f29229801b0bbd3bdc Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 30 Sep 2015 13:49:37 +1000 Subject: [PATCH] Fix translucent blocks, fix clipboard crashing the client. --- .../{GdiDrawer2D.cs => GdiPlusDrawer2D.cs} | 11 +- ClassicalSharp/2D/Drawing/IDrawer2D.cs | 2 +- .../2D/Screens/BlockSelectScreen.cs | 3 +- ClassicalSharp/2D/Screens/NormalScreen.cs | 1 - ClassicalSharp/2D/Screens/Screen.cs | 2 +- ClassicalSharp/2D/Widgets/ButtonWidget.cs | 4 +- ClassicalSharp/2D/Widgets/TextInputWidget.cs | 1 + ClassicalSharp/ClassicalSharp.csproj | 2 +- ClassicalSharp/Entities/Player.Rendering.cs | 1 + ClassicalSharp/Game/Game.cs | 11 +- ClassicalSharp/GraphicsAPI/Direct3D9Api.cs | 14 +- ClassicalSharp/GraphicsAPI/IGraphicsApi.cs | 10 +- ClassicalSharp/GraphicsAPI/OpenGLApi.cs | 6 +- ClassicalSharp/Model/PlayerModel.cs | 9 +- .../Rendering/MapRenderer.Rendering.cs | 49 ++++++- ClassicalSharp/Rendering/MapRenderer.cs | 2 + ClassicalSharp/Utils/StringBuffer.cs | 2 +- Launcher2/Game.cs | 137 ++++++++++++++++++ 18 files changed, 223 insertions(+), 44 deletions(-) rename ClassicalSharp/2D/Drawing/{GdiDrawer2D.cs => GdiPlusDrawer2D.cs} (89%) create mode 100644 Launcher2/Game.cs diff --git a/ClassicalSharp/2D/Drawing/GdiDrawer2D.cs b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs similarity index 89% rename from ClassicalSharp/2D/Drawing/GdiDrawer2D.cs rename to ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs index e9e380925..d3ab9f2a6 100644 --- a/ClassicalSharp/2D/Drawing/GdiDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.cs @@ -3,10 +3,11 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; +using ClassicalSharp.GraphicsAPI; namespace ClassicalSharp { - public sealed class GdiDrawer2D : IDrawer2D { + public sealed class GdiPlusDrawer2D : IDrawer2D { StringFormat format; Bitmap measuringBmp; @@ -15,8 +16,8 @@ namespace ClassicalSharp { Graphics g; - public GdiDrawer2D( Game game ) { - graphics = game.Graphics; + public GdiPlusDrawer2D( IGraphicsApi graphics ) { + this.graphics = graphics; format = StringFormat.GenericTypographic; format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; format.Trimming = StringTrimming.None; @@ -64,11 +65,11 @@ namespace ClassicalSharp { g.DrawRectangle( pen, x, y, width, height ); } - public override void DrawRoundedRect( Color colour, float x, float y, float width, float height ) { + public override void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height ) { GraphicsPath path = new GraphicsPath(); float x1 = x, y1 = y, x2 = x + width, y2 = y + height; - const float r = 3, dia = r * 2; + float r = radius, dia = radius * 2; path.AddArc( x1, y1, dia, dia, 180, 90 ); path.AddLine( x1 + r, y1, x2 - r, y1 ); path.AddArc( x2 - dia, y1, dia, dia, 270, 90 ); diff --git a/ClassicalSharp/2D/Drawing/IDrawer2D.cs b/ClassicalSharp/2D/Drawing/IDrawer2D.cs index 999ae6e8c..a3b73f3cb 100644 --- a/ClassicalSharp/2D/Drawing/IDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/IDrawer2D.cs @@ -19,7 +19,7 @@ namespace ClassicalSharp { public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height ); - public abstract void DrawRoundedRect( Color colour, float x, float y, float width, float height ); + public abstract void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height ); /// Disposes of any resources used by this class that are associated with the underlying bitmap. public abstract void Dispose(); diff --git a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs index 26897ecc2..f12369928 100644 --- a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs +++ b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs @@ -230,7 +230,8 @@ namespace ClassicalSharp { } public override bool HandlesKeyDown( Key key ) { - if( key == game.Keys[KeyMapping.PauseOrExit] ) { + if( key == game.Keys[KeyMapping.PauseOrExit] || + key == game.Keys[KeyMapping.OpenInventory] ) { game.SetNewScreen( new NormalScreen( game ) ); } return true; diff --git a/ClassicalSharp/2D/Screens/NormalScreen.cs b/ClassicalSharp/2D/Screens/NormalScreen.cs index 1716f11e8..1fd2ab6f9 100644 --- a/ClassicalSharp/2D/Screens/NormalScreen.cs +++ b/ClassicalSharp/2D/Screens/NormalScreen.cs @@ -66,7 +66,6 @@ namespace ClassicalSharp { public override void Init() { playerFont = new Font( "Arial", 12 ); chat = new ChatScreen( game ); - chat.game = game; const int blockSize = 32; chat.ChatLogYOffset = blockSize + blockSize; chat.ChatInputYOffset = blockSize + blockSize / 2; diff --git a/ClassicalSharp/2D/Screens/Screen.cs b/ClassicalSharp/2D/Screens/Screen.cs index dd113d400..073120fcf 100644 --- a/ClassicalSharp/2D/Screens/Screen.cs +++ b/ClassicalSharp/2D/Screens/Screen.cs @@ -6,7 +6,7 @@ namespace ClassicalSharp { public abstract class Screen : IDisposable { - protected internal Game game; + protected Game game; protected IGraphicsApi graphicsApi; public Screen( Game game ) { diff --git a/ClassicalSharp/2D/Widgets/ButtonWidget.cs b/ClassicalSharp/2D/Widgets/ButtonWidget.cs index eb9df3324..27b61742e 100644 --- a/ClassicalSharp/2D/Widgets/ButtonWidget.cs +++ b/ClassicalSharp/2D/Widgets/ButtonWidget.cs @@ -93,8 +93,8 @@ namespace ClassicalSharp { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) { using( IDrawer2D drawer = game.Drawer2D ) { drawer.SetBitmap( bmp ); - drawer.DrawRoundedRect( shadowCol, 1.3f, 1.3f, baseSize.Width, baseSize.Height ); - drawer.DrawRoundedRect( boxCol, 0, 0, baseSize.Width, baseSize.Height ); + drawer.DrawRoundedRect( shadowCol, 3, 1.3f, 1.3f, baseSize.Width, baseSize.Height ); + drawer.DrawRoundedRect( boxCol, 3, 0, 0, baseSize.Width, baseSize.Height ); DrawTextArgs args = new DrawTextArgs( text, true ); args.SkipPartsCheck = true; diff --git a/ClassicalSharp/2D/Widgets/TextInputWidget.cs b/ClassicalSharp/2D/Widgets/TextInputWidget.cs index 85eb6a1b3..7e40d715b 100644 --- a/ClassicalSharp/2D/Widgets/TextInputWidget.cs +++ b/ClassicalSharp/2D/Widgets/TextInputWidget.cs @@ -221,6 +221,7 @@ namespace ClassicalSharp { } else { chatInputText.Append( caretPos, text ); caretPos += text.Length; + if( caretPos >= chatInputText.Length ) caretPos = -1; } Dispose(); Init(); diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index bf6f44646..a0e4c9002 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -66,7 +66,7 @@ - + diff --git a/ClassicalSharp/Entities/Player.Rendering.cs b/ClassicalSharp/Entities/Player.Rendering.cs index 2100cb915..eb270ecaa 100644 --- a/ClassicalSharp/Entities/Player.Rendering.cs +++ b/ClassicalSharp/Entities/Player.Rendering.cs @@ -10,6 +10,7 @@ namespace ClassicalSharp { protected IGraphicsApi api; protected Texture nameTex; protected internal int PlayerTextureId = -1, MobTextureId = -1; + internal bool RenderHat = true; public override void Despawn() { if( api == null ) return; diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 51fd4e097..b38028729 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -99,7 +99,7 @@ namespace ClassicalSharp { Utils.LogWarning( "Unable to load options.txt" ); } Keys = new KeyMap(); - Drawer2D = new GdiDrawer2D( this ); + Drawer2D = new GdiPlusDrawer2D( Graphics ); ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 ); defaultIb = Graphics.MakeDefaultIb(); ModelCache = new ModelCache( this ); @@ -129,6 +129,8 @@ namespace ClassicalSharp { } else { Network = new NetworkProcessor( this ); } + Graphics.LostContextFunction = Network.Tick; + firstPersonCam = new FirstPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this ); Camera = firstPersonCam; @@ -290,17 +292,14 @@ namespace ClassicalSharp { Screen activeScreen; public void SetNewScreen( Screen screen ) { - if( activeScreen != null ) { + if( activeScreen != null ) activeScreen.Dispose(); - } if( activeScreen != null && activeScreen.HandlesAllInput ) lastClick = DateTime.UtcNow; activeScreen = screen; - if( screen != null ) { - screen.game = this; + if( screen != null ) screen.Init(); - } if( Network.UsingPlayerClick ) { byte targetId = Players.GetClosetPlayer( this ); ButtonStateChanged( MouseButton.Left, false, targetId ); diff --git a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs index ef95c8e22..2264d75de 100644 --- a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs +++ b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs @@ -3,10 +3,10 @@ using System; using System.Drawing; using System.Drawing.Imaging; using System.Threading; +using OpenTK; using SharpDX; using SharpDX.Direct3D9; using D3D = SharpDX.Direct3D9; -using Matrix4 = OpenTK.Matrix4; using WinWindowInfo = OpenTK.Platform.Windows.WinWindowInfo; namespace ClassicalSharp.GraphicsAPI { @@ -395,11 +395,11 @@ namespace ClassicalSharp.GraphicsAPI { #endregion - public override void BeginFrame( Game game ) { + public override void BeginFrame( GameWindow game ) { device.BeginScene(); } - public override void EndFrame( Game game ) { + public override void EndFrame( GameWindow game ) { device.EndScene(); int code = device.Present(); if( code >= 0 ) return; @@ -417,22 +417,22 @@ namespace ClassicalSharp.GraphicsAPI { RecreateDevice( game ); break; } - game.Network.Tick( 1 / 20.0 ); + LostContextFunction( 1 / 20.0 ); } } bool vsync = false; - public override void SetVSync( Game game, bool value ) { + public override void SetVSync( GameWindow game, bool value ) { vsync = value; game.VSync = value; RecreateDevice( game ); } - public override void OnWindowResize( Game game ) { + public override void OnWindowResize( GameWindow game ) { RecreateDevice( game ); } - void RecreateDevice( Game game ) { + void RecreateDevice( GameWindow game ) { PresentParameters args = GetPresentArgs( game.Width, game.Height ); for( int i = 0; i < dynamicvBuffers.Length; i++ ) { DynamicDataBuffer buffer = dynamicvBuffers[i]; diff --git a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs index dfab09060..dac05ca31 100644 --- a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs +++ b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs @@ -172,13 +172,15 @@ namespace ClassicalSharp.GraphicsAPI { Console.ResetColor(); } - public abstract void BeginFrame( Game game ); + public abstract void BeginFrame( GameWindow game ); - public abstract void EndFrame( Game game ); + public abstract void EndFrame( GameWindow game ); - public abstract void SetVSync( Game game, bool value ); + public abstract void SetVSync( GameWindow game, bool value ); - public abstract void OnWindowResize( Game game ); + public abstract void OnWindowResize( GameWindow game ); + + public Action LostContextFunction; protected void InitDynamicBuffers() { quadVb = CreateDynamicVb( VertexFormat.Pos3fCol4b, 4 ); diff --git a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs index 720f4e633..e6a259b2e 100644 --- a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs +++ b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs @@ -353,14 +353,14 @@ namespace ClassicalSharp.GraphicsAPI { #endregion - public override void BeginFrame( Game game ) { + public override void BeginFrame( GameWindow game ) { } - public override void EndFrame( Game game ) { + public override void EndFrame( GameWindow game ) { game.SwapBuffers(); } - public override void SetVSync( Game game, bool value ) { + public override void SetVSync( GameWindow game, bool value ) { game.VSync = value; } diff --git a/ClassicalSharp/Model/PlayerModel.cs b/ClassicalSharp/Model/PlayerModel.cs index 0c8b0f60b..6551b2be6 100644 --- a/ClassicalSharp/Model/PlayerModel.cs +++ b/ClassicalSharp/Model/PlayerModel.cs @@ -89,12 +89,13 @@ namespace ClassicalSharp.Model { DrawRotate( 0, 12/16f, 0, p.rightLegXRot, 0, 0, model.RightLeg ); DrawRotate( -6/16f, 22/16f, 0, p.leftArmXRot, 0, p.leftArmZRot, model.LeftArm ); DrawRotate( 6/16f, 22/16f, 0, p.rightArmXRot, 0, p.rightArmZRot, model.RightArm ); - graphics.AlphaTest = true; - DrawRotate( 0, 23.5f/16f, 0, -p.PitchRadians, 0, 0, model.Hat ); + if( p.RenderHat ) { + graphics.AlphaTest = true; + DrawRotate( 0, 23.5f/16f, 0, -p.PitchRadians, 0, 0, model.Hat ); + } } - class ModelSet { - + class ModelSet { public ModelPart Head, Torso, LeftLeg, RightLeg, LeftArm, RightArm, Hat; } } diff --git a/ClassicalSharp/Rendering/MapRenderer.Rendering.cs b/ClassicalSharp/Rendering/MapRenderer.Rendering.cs index bbfb2c8f2..c2b230dc7 100644 --- a/ClassicalSharp/Rendering/MapRenderer.Rendering.cs +++ b/ClassicalSharp/Rendering/MapRenderer.Rendering.cs @@ -21,7 +21,7 @@ namespace ClassicalSharp { if( part.IndicesCount > maxIndices ) { DrawBigPart( info, ref part ); } else { - DrawPart( info, ref part, true ); + DrawPart( info, ref part ); } if( part.spriteCount > 0 ) @@ -37,7 +37,7 @@ namespace ClassicalSharp { ChunkPartInfo part = info.TranslucentParts[batch]; if( part.IndicesCount == 0 ) continue; - DrawPart( info, ref part, false ); + DrawTranslucentPart( info, ref part ); game.Vertices += part.IndicesCount; } } @@ -49,11 +49,11 @@ namespace ClassicalSharp { ChunkPartInfo part = info.TranslucentParts[batch]; if( part.IndicesCount == 0 ) continue; - DrawPart( info, ref part, false ); + DrawTranslucentPart( info, ref part ); } } - void DrawPart( ChunkInfo info, ref ChunkPartInfo part, bool faceCulling ) { + void DrawPart( ChunkInfo info, ref ChunkPartInfo part ) { api.BindVb( part.VbId ); bool drawLeft = info.DrawLeft && part.leftCount > 0; bool drawRight = info.DrawRight && part.rightCount > 0; @@ -63,7 +63,7 @@ namespace ClassicalSharp { bool drawBack = info.DrawBack && part.backCount > 0; if( drawLeft && drawRight ) { - api.FaceCulling = faceCulling; + api.FaceCulling = true; api.DrawIndexedVb_TrisT2fC4b( part.leftCount + part.rightCount, part.leftIndex ); api.FaceCulling = false; } else if( drawLeft ) { @@ -73,7 +73,7 @@ namespace ClassicalSharp { } if( drawFront && drawBack ) { - api.FaceCulling = faceCulling; + api.FaceCulling = true; api.DrawIndexedVb_TrisT2fC4b( part.frontCount + part.backCount, part.frontIndex ); api.FaceCulling = false; } else if( drawFront ) { @@ -83,7 +83,7 @@ namespace ClassicalSharp { } if( drawBottom && drawTop ) { - api.FaceCulling = faceCulling; + api.FaceCulling = true; api.DrawIndexedVb_TrisT2fC4b( part.bottomCount + part.topCount, part.bottomIndex ); api.FaceCulling = false; } else if( drawBottom ) { @@ -93,6 +93,41 @@ namespace ClassicalSharp { } } + bool drawAllFaces = false; + void DrawTranslucentPart( ChunkInfo info, ref ChunkPartInfo part ) { + api.BindVb( part.VbId ); + bool drawLeft = (drawAllFaces || info.DrawLeft) && part.leftCount > 0; + bool drawRight = (drawAllFaces || info.DrawRight) && part.rightCount > 0; + bool drawBottom = (drawAllFaces || info.DrawBottom) && part.bottomCount > 0; + bool drawTop = (drawAllFaces || info.DrawTop) && part.topCount > 0; + bool drawFront = (drawAllFaces || info.DrawFront) && part.frontCount > 0; + bool drawBack = (drawAllFaces || info.DrawBack) && part.backCount > 0; + + if( drawLeft && drawRight ) { + api.DrawIndexedVb_TrisT2fC4b( part.leftCount + part.rightCount, part.leftIndex ); + } else if( drawLeft ) { + api.DrawIndexedVb_TrisT2fC4b( part.leftCount, part.leftIndex ); + } else if( drawRight ) { + api.DrawIndexedVb_TrisT2fC4b( part.rightCount, part.rightIndex ); + } + + if( drawFront && drawBack ) { + api.DrawIndexedVb_TrisT2fC4b( part.frontCount + part.backCount, part.frontIndex ); + } else if( drawFront ) { + api.DrawIndexedVb_TrisT2fC4b( part.frontCount, part.frontIndex ); + } else if( drawBack ) { + api.DrawIndexedVb_TrisT2fC4b( part.backCount, part.backIndex ); + } + + if( drawBottom && drawTop ) { + api.DrawIndexedVb_TrisT2fC4b( part.bottomCount + part.topCount, part.bottomIndex ); + } else if( drawBottom ) { + api.DrawIndexedVb_TrisT2fC4b( part.bottomCount, part.bottomIndex ); + } else if( drawTop ) { + api.DrawIndexedVb_TrisT2fC4b( part.topCount, part.topIndex ); + } + } + void DrawBigPart( ChunkInfo info, ref ChunkPartInfo part ) { api.BindVb( part.VbId ); bool drawLeft = info.DrawLeft && part.leftCount > 0; diff --git a/ClassicalSharp/Rendering/MapRenderer.cs b/ClassicalSharp/Rendering/MapRenderer.cs index d6c2e2934..48a195e44 100644 --- a/ClassicalSharp/Rendering/MapRenderer.cs +++ b/ClassicalSharp/Rendering/MapRenderer.cs @@ -275,6 +275,8 @@ namespace ClassicalSharp { // Render translucent(liquid) blocks. These 'blend' into other blocks. void RenderTranslucent() { + Block block = game.LocalPlayer.BlockAtHead; + drawAllFaces = block == Block.Water || block == Block.StillWater; // First fill depth buffer int[] texIds = game.TerrainAtlas1D.TexIds; api.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); diff --git a/ClassicalSharp/Utils/StringBuffer.cs b/ClassicalSharp/Utils/StringBuffer.cs index eb9a11b60..32d5189f2 100644 --- a/ClassicalSharp/Utils/StringBuffer.cs +++ b/ClassicalSharp/Utils/StringBuffer.cs @@ -3,7 +3,7 @@ using System.Reflection; namespace ClassicalSharp { - internal sealed unsafe class StringBuffer { + public sealed unsafe class StringBuffer { internal string value; internal int capacity; diff --git a/Launcher2/Game.cs b/Launcher2/Game.cs new file mode 100644 index 000000000..2bccb48a5 --- /dev/null +++ b/Launcher2/Game.cs @@ -0,0 +1,137 @@ +using System; +using ClassicalSharp; +using ClassicalSharp.GraphicsAPI; +using OpenTK; +using System.Drawing; + +namespace Launcher2 { + + public partial class Game : GameWindow { + + public IGraphicsApi Graphics; + FpsScreen fpsScreen; + public IDrawer2D Drawer2D; + + protected override void OnLoad( EventArgs e ) { + #if !USE_DX + //Graphics = new OpenGLApi(); + #else + Graphics = new Direct3D9Api( this ); + #endif + Graphics.SetVSync( this, true ); + Graphics.DepthTest = true; + Graphics.DepthTestFunc( CompareFunc.LessEqual ); + Graphics.AlphaBlendFunc( BlendFunc.SourceAlpha, BlendFunc.InvSourceAlpha ); + Graphics.AlphaTestFunc( CompareFunc.Greater, 0.5f ); + Title = Utils.AppName; + Width = width; + Height = height; + fpsScreen = new FpsScreen( Graphics ); + fpsScreen.Init(); + } + int width, height; + + protected override void OnRenderFrame( FrameEventArgs e ) { + Graphics.BeginFrame( this ); + + Graphics.Clear(); + Graphics.Mode2D( Width, Height ); + fpsScreen.Render( e.Time ); + if( activeScreen != null ) { + activeScreen.Render( e.Time ); + } + Graphics.Mode3D(); + + Graphics.EndFrame( this ); + } + + protected override void OnResize( EventArgs e ) { + base.OnResize( e ); + Graphics.OnWindowResize( this ); + if( activeScreen != null ) { + activeScreen.OnResize( width, height, Width, Height ); + } + width = Width; + height = Height; + } + + Screen activeScreen; + public void SetNewScreen( Screen screen ) { + if( activeScreen != null ) { + activeScreen.Dispose(); + } + + activeScreen = screen; + if( screen != null ) { + screen.Init(); + } + } + + public override void Dispose() { + if( activeScreen != null ) { + activeScreen.Dispose(); + } + Graphics.Dispose(); + Drawer2D.DisposeInstance(); + base.Dispose(); + } + } + + public class FpsScreen : Screen { + + readonly Font font; + StringBuffer text; + public FpsScreen( IGraphicsApi gfx ) : base( gfx ) { + font = new Font( "Arial", 13 ); + text = new StringBuffer( 96 ); + } + + TextWidget fpsTextWidget; + + public override void Render( double delta ) { + UpdateFPS( delta ); + if( game.HideGui ) return; + + graphicsApi.Texturing = true; + fpsTextWidget.Render( delta ); + graphicsApi.Texturing = false; + } + + double accumulator, maxDelta; + int fpsCount; + unsafe void UpdateFPS( double delta ) { + fpsCount++; + maxDelta = Math.Max( maxDelta, delta ); + accumulator += delta; + + if( accumulator >= 1 ) { + fixed( char* ptr = text.value ) { + char* ptr2 = ptr; + text.Clear( ptr2 ) + .Append( ref ptr2, "FPS: " ).AppendNum( ref ptr2, (int)( fpsCount / accumulator ) ) + .Append( ref ptr2, " (min " ).AppendNum( ref ptr2, (int)( 1f / maxDelta ) ) + .Append( ref ptr2, "), chunks/s: " ).AppendNum( ref ptr2, game.ChunkUpdates ) + .Append( ref ptr2, ", vertices: " ).AppendNum( ref ptr2, game.Vertices ); + } + + string textString = text.GetString(); + fpsTextWidget.SetText( textString ); + maxDelta = 0; + accumulator = 0; + fpsCount = 0; + game.ChunkUpdates = 0; + } + } + + public override void Init() { + fpsTextWidget = new TextWidget( game, font ); + fpsTextWidget.Init(); + fpsTextWidget.SetText( "FPS: no data yet" ); + } + + public override void Dispose() { + font.Dispose(); + fpsTextWidget.Dispose(); + } + } +}