From cc0dd16c4295036025eb4ff089e88285aff87d24 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 11 Nov 2015 11:18:29 +1100 Subject: [PATCH] Default.png should only not show pixels with A = 0, make clouds height be able to set to +-10,000, make snow/rain nicer, more work on 'alt text' input box. --- .../2D/Drawing/GdiPlusDrawer2D.TextMC.cs | 2 +- .../2D/Screens/Menu/EnvSettingsScreen.cs | 2 +- .../Widgets/Chat/AltTextInputWidget.Types.cs | 107 ++++++++++++++++++ .../2D/Widgets/Chat/AltTextInputWidget.cs | 97 +++++++++++----- .../2D/Widgets/Chat/TextInputWidget.cs | 22 +++- ClassicalSharp/ClassicalSharp.csproj | 1 + ClassicalSharp/Rendering/WeatherRenderer.cs | 20 ++-- ClassicalSharp/Selections/SelectionBox.cs | 10 +- ClassicalSharp/Selections/SelectionManager.cs | 4 +- OpenTK/Math/Vector3.cs | 20 ++-- 10 files changed, 223 insertions(+), 62 deletions(-) create mode 100644 ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.Types.cs diff --git a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.TextMC.cs b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.TextMC.cs index 56ecc0d8c..c1915cf41 100644 --- a/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.TextMC.cs +++ b/ClassicalSharp/2D/Drawing/GdiPlusDrawer2D.TextMC.cs @@ -90,7 +90,7 @@ namespace ClassicalSharp { int fontX = srcX + xx * srcWidth / dstWidth; int pixel = fontRow[fontX]; - if( (byte)(pixel >> 24) < 127 ) continue; + if( (byte)(pixel >> 24) == 0 ) continue; int col = pixel & ~0xFFFFFF; col |= ((pixel & 0xFF) * textCol.B / 255); diff --git a/ClassicalSharp/2D/Screens/Menu/EnvSettingsScreen.cs b/ClassicalSharp/2D/Screens/Menu/EnvSettingsScreen.cs index 59d01e67d..5642c041b 100644 --- a/ClassicalSharp/2D/Screens/Menu/EnvSettingsScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/EnvSettingsScreen.cs @@ -59,7 +59,7 @@ namespace ClassicalSharp { new HexColourValidator(), new HexColourValidator(), new RealValidator( 0, 1000 ), - new IntegerValidator( -1000, 1000 ), + new IntegerValidator( -10000, 10000 ), new HexColourValidator(), new HexColourValidator(), new IntegerValidator( 0, 2 ), diff --git a/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.Types.cs b/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.Types.cs new file mode 100644 index 000000000..f0d136487 --- /dev/null +++ b/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.Types.cs @@ -0,0 +1,107 @@ +using System; +using System.Drawing; + +namespace ClassicalSharp { + + public sealed partial class AltTextInputWidget : Widget { + + Element[] elements; + + void InitData() { + elements = new Element[] { + new Element( "Colours", 8 * 3, 3, "&0█&1█&2█&3█&4█&5█&6█&7█&8█&9█&a█&b█&c█&d█&e█&f█" ), + new Element( "Math", 16, 1, "ƒ½¼αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°√ⁿ²" ), + new Element( "Line/Box", 17, 1, "░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀■" ), + new Element( "Letters", 17, 1, "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜáíóúñÑ" ), + new Element( "Other", 16, 1, "☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼⌂¢£¥₧ªº¿⌐¬¡«»∙·" ), + }; + } + + struct Element { + public string Title; + public Size TitleSize; + public string Contents; + public int ItemsPerRow; + public int CharsPerItem; + + public Element( string title, int itemsPerRow, int charsPerItem, string contents ) { + Title = title; + TitleSize = Size.Empty; + Contents = contents; + ItemsPerRow = itemsPerRow; + CharsPerItem = charsPerItem; + } + } + + unsafe void MeasureContentSizes( Element e, Font font, Size* sizes ) { + string s = new String( '\0', e.CharsPerItem ); + DrawTextArgs args = new DrawTextArgs( s, font, false ); + // avoid allocating temporary strings here + fixed( char* ptr = s ) { + for( int i = 0; i < e.Contents.Length; i += e.CharsPerItem ) { + for( int j = 0; j < e.CharsPerItem; j++ ) + ptr[j] = e.Contents[i + j]; + sizes[i / e.CharsPerItem] = game.Drawer2D.MeasureChatSize( ref args ); + } + } + } + + unsafe Size CalculateContentSize( Element e, Size* sizes, out Size elemSize ) { + int wrap = e.ItemsPerRow / e.CharsPerItem; + elemSize = Size.Empty; + for( int i = 0; i < e.Contents.Length; i += e.CharsPerItem ) + elemSize.Width = Math.Max( elemSize.Width, sizes[i / e.CharsPerItem].Width ); + + elemSize.Width += contentSpacing; + elemSize.Height = sizes[0].Height + contentSpacing; + int rows = Utils.CeilDiv( e.Contents.Length / e.CharsPerItem, wrap ); + return new Size( elemSize.Width * wrap, elemSize.Height * rows ); + } + + const int titleSpacing = 10, contentSpacing = 5; + int MeasureTitles( Font font ) { + int totalWidth = 0; + DrawTextArgs args = new DrawTextArgs( null, font, false ); + for( int i = 0; i < elements.Length; i++ ) { + args.Text = elements[i].Title; + elements[i].TitleSize = game.Drawer2D.MeasureChatSize( ref args ); + elements[i].TitleSize.Width += titleSpacing; + totalWidth += elements[i].TitleSize.Width; + } + return totalWidth; + } + + void DrawTitles( IDrawer2D drawer, Font font ) { + int x = 0; + DrawTextArgs args = new DrawTextArgs( null, font, false ); + for( int i = 0; i < elements.Length; i++ ) { + args.Text = elements[i].Title; + FastColour col = i == selectedIndex ? new FastColour( 30, 30, 30, 200 ) : + new FastColour( 60, 60, 60, 200 ); + Size size = elements[i].TitleSize; + + drawer.Clear( col, x, 0, size.Width, size.Height ); + drawer.DrawChatText( ref args, x + titleSpacing / 2, 0 ); + x += size.Width; + } + } + + unsafe void DrawContent( IDrawer2D drawer, Font font, Element e, int yOffset ) { + string s = new String( '\0', e.CharsPerItem ); + int wrap = e.ItemsPerRow; + DrawTextArgs args = new DrawTextArgs( s, font, false ); + + fixed( char* ptr = s ) { + for( int i = 0; i < e.Contents.Length; i += e.CharsPerItem ) { + for( int j = 0; j < e.CharsPerItem; j++ ) + ptr[j] = e.Contents[i + j]; + int item = i / e.CharsPerItem; + + int x = (item % wrap) * elementSize.Width, y = (item / wrap) * elementSize.Height; + y += yOffset; + drawer.DrawChatText( ref args, x, y ); + } + } + } + } +} \ No newline at end of file diff --git a/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.cs b/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.cs index b40ba35e3..42b96b50a 100644 --- a/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.cs +++ b/ClassicalSharp/2D/Widgets/Chat/AltTextInputWidget.cs @@ -1,7 +1,6 @@ using System; using System.Drawing; using OpenTK.Input; -using System.Windows.Forms; namespace ClassicalSharp { @@ -9,7 +8,7 @@ namespace ClassicalSharp { public AltTextInputWidget( Game game, Font font, Font boldFont, TextInputWidget parent ) : base( game ) { HorizontalAnchor = Anchor.LeftOrTop; - VerticalAnchor = Anchor.LeftOrTop; + VerticalAnchor = Anchor.BottomOrRight; this.font = font; this.boldFont = boldFont; this.parent = parent; @@ -18,55 +17,91 @@ namespace ClassicalSharp { Texture chatInputTexture; readonly Font font, boldFont; TextInputWidget parent; - Size partSize; + Size elementSize; + public int YOffset; + + public bool Active; + public void SetActive( bool active ) { + Active = active; + Height = active ? chatInputTexture.Height : 0; + } public override void Render( double delta ) { chatInputTexture.Render( graphicsApi ); } public override void Init() { - X = 5; Y = 45; - DrawString(); + X = 5; Y = YOffset; + InitData(); + Redraw(); + } + + void Redraw() { + Make( elements[selectedIndex], font ); + Width = chatInputTexture.Width; + Height = chatInputTexture.Height; } - static FastColour backColour = new FastColour( 60, 60, 60, 200 ); - void DrawString() { - DrawTextArgs args = new DrawTextArgs( "Text ", font, false ); - partSize = game.Drawer2D.MeasureChatSize( ref args ); - Size size = new Size( partSize.Width * 6, partSize.Height * 3 ); + unsafe void Make( Element e, Font font ) { + Size* sizes = stackalloc Size[e.Contents.Length / e.CharsPerItem]; + MeasureContentSizes( e, font, sizes ); + Size bodySize = CalculateContentSize( e, sizes, out elementSize ); + int titleWidth = MeasureTitles( font ), titleHeight = elements[0].TitleSize.Height; + Size size = new Size( Math.Max( bodySize.Width, titleWidth ), bodySize.Height + titleHeight ); using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) { using( IDrawer2D drawer = game.Drawer2D ) { drawer.SetBitmap( bmp ); - drawer.Clear( backColour, 0, 0, size.Width, size.Height ); - for( int code = 0; code <= 15; code++ ) { - int c = code < 10 ? '0' + code : 'a' + (code - 10); - args.Text = "&" + (char)c + "Text"; - - int x = (code % 6); - int y = (code / 6); - drawer.DrawChatText( ref args, x * partSize.Width, y * partSize.Height ); - } + DrawTitles( drawer, font ); + drawer.Clear( new FastColour( 30, 30, 30, 200 ), 0, titleHeight, + size.Width, bodySize.Height ); + + DrawContent( drawer, font, e, titleHeight ); chatInputTexture = drawer.Make2DTexture( bmp, size, X, Y ); } - } - Height = size.Height; - Width = size.Width; + } } - public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) { + int selectedIndex = 0; + public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) { mouseX -= X; mouseY -= Y; - mouseX /= partSize.Width; mouseY /= partSize.Height; - game.Chat.Add( "CLICKY CLICK" + mouseX + "," + mouseY ); - - int code = mouseY * 6 + mouseX; - if( code <= 15 ) { - int c = code < 10 ? '0' + code : 'a' + (code - 10); - string text = "&" + (char)c; - parent.AppendText( text ); + if( IntersectsHeader( mouseX, mouseY ) ) { + Dispose(); + Redraw(); + } else { + IntersectsBody( mouseX, mouseY ); } return true; } + + bool IntersectsHeader( int widgetX, int widgetY ) { + Rectangle bounds = new Rectangle( 0, 0, 0, 0 ); + for( int i = 0; i < elements.Length; i++ ) { + Size size = elements[i].TitleSize; + bounds.Width = size.Width; bounds.Height = size.Height; + if( bounds.Contains( widgetX, widgetY ) ) { + selectedIndex = i; + return true; + } + bounds.X += size.Width; + } + return false; + } + + void IntersectsBody( int widgetX, int widgetY ) { + widgetY -= elements[0].TitleSize.Height; + widgetX /= elementSize.Width; widgetY /= elementSize.Height; + Element e = elements[selectedIndex]; + int index = widgetY * e.ItemsPerRow + widgetX; + if( index < e.Contents.Length ) { + if( selectedIndex == 0 ) { + parent.AppendChar( e.Contents[index * e.CharsPerItem] ); + parent.AppendChar( e.Contents[index * e.CharsPerItem + 1] ); + } else { + parent.AppendChar( e.Contents[index] ); + } + } + } public override void Dispose() { graphicsApi.DeleteTexture( ref chatInputTexture ); diff --git a/ClassicalSharp/2D/Widgets/Chat/TextInputWidget.cs b/ClassicalSharp/2D/Widgets/Chat/TextInputWidget.cs index 7936ecb9a..bed085586 100644 --- a/ClassicalSharp/2D/Widgets/Chat/TextInputWidget.cs +++ b/ClassicalSharp/2D/Widgets/Chat/TextInputWidget.cs @@ -21,6 +21,7 @@ namespace ClassicalSharp { DrawTextArgs args = new DrawTextArgs( "_", boldFont, false ); defaultHeight = game.Drawer2D.MeasureChatSize( ref args ).Height; Height = defaultHeight; + //altText = new AltTextInputWidget( game, font, boldFont, this ); } Texture chatInputTexture, caretTexture; @@ -45,7 +46,6 @@ namespace ClassicalSharp { int maxWidth = 0; public override void Init() { - //altText = new AltTextInputWidget( game, font, boldFont, this ); //altText.Init(); X = 5; DrawTextArgs args = new DrawTextArgs( "_", boldFont, false ); @@ -131,13 +131,14 @@ namespace ClassicalSharp { Y = game.Height - Height - YOffset; chatInputTexture.Y1 = Y; caretTexture.Y1 += Y; - Width = size.Width; + Width = size.Width; } public override void Dispose() { graphicsApi.DeleteTexture( ref caretTexture ); graphicsApi.DeleteTexture( ref chatInputTexture ); - //altText.Dispose(); + //if( altText != null ) + // altText.Dispose(); } public override void MoveTo( int newX, int newY ) { @@ -205,6 +206,7 @@ namespace ClassicalSharp { if( chatInputText.Length + text.Length > len ) { text = text.Substring( 0, len - chatInputText.Length ); } + if( text == "" ) return; if( caretPos == -1 ) { chatInputText.InsertAt( chatInputText.Length, text ); @@ -216,5 +218,19 @@ namespace ClassicalSharp { Dispose(); Init(); } + + public void AppendChar( char c ) { + if( chatInputText.Length == len ) return; + + if( caretPos == -1 ) { + chatInputText.InsertAt( chatInputText.Length, c ); + } else { + chatInputText.InsertAt( caretPos, c ); + caretPos++; + if( caretPos >= chatInputText.Length ) caretPos = -1; + } + Dispose(); + Init(); + } } } \ No newline at end of file diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 8fe8fddbb..6d9eb207f 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -105,6 +105,7 @@ + diff --git a/ClassicalSharp/Rendering/WeatherRenderer.cs b/ClassicalSharp/Rendering/WeatherRenderer.cs index 44fa0bd74..1ee0a2a66 100644 --- a/ClassicalSharp/Rendering/WeatherRenderer.cs +++ b/ClassicalSharp/Rendering/WeatherRenderer.cs @@ -40,8 +40,8 @@ namespace ClassicalSharp { FastColour col = FastColour.White; for( int dx = -extent; dx <= extent; dx++ ) { for( int dz = -extent; dz <= extent; dz++ ) { - int rainY = Math.Max( pos.Y, GetRainHeight( pos.X + dx, pos.Z + dz ) + 1 ); - int height = Math.Min( 20 - (rainY - pos.Y), 20 ); + float rainY = GetRainHeight( pos.X + dx, pos.Z + dz ); + float height = Math.Max( game.Map.Height, pos.Y + 64 ) - rainY; if( height <= 0 ) continue; col.A = (byte)Math.Max( 0, AlphaAt( dx * dx + dz * dz ) ); @@ -64,9 +64,10 @@ namespace ClassicalSharp { return 0.05f * x * x - 7 * x + 178; } - void MakeRainForSquare( int x, int y, int height, int z, FastColour col, ref int index ) { - float v1 = vOffset + (z & 0x01) * 0.5f - (x & 0x0F) * 0.0625f; - float v2 = height / 6f + v1; + void MakeRainForSquare( int x, float y, float height, int z, FastColour col, ref int index ) { + float worldV = vOffset + (z & 1) / 2f - (x & 0x0F) / 16f; + float v1 = y / 6f + worldV; + float v2 = (y + height) / 6f + worldV; vertices[index++] = new VertexPos3fTex2fCol4b( x, y, z, 0, v2, col ); vertices[index++] = new VertexPos3fTex2fCol4b( x, y + height, z, 0, v1, col ); @@ -107,11 +108,12 @@ namespace ClassicalSharp { graphics.DeleteDynamicVb( weatherVb ); } - int GetRainHeight( int x, int z ) { - if( x < 0 || z < 0 || x >= width || z >= length ) return map.EdgeHeight - 1; - int index = ( x * length ) + z; + float GetRainHeight( int x, int z ) { + if( x < 0 || z < 0 || x >= width || z >= length ) return map.EdgeHeight; + int index = (x * length) + z; int height = heightmap[index]; - return height == short.MaxValue ? CalcHeightAt( x, maxY, z, index ) : height; + int y = height == short.MaxValue ? CalcHeightAt( x, maxY, z, index ) : height; + return y + game.BlockInfo.Height[map.GetBlock( x, y, z )]; } int CalcHeightAt( int x, int maxY, int z, int index ) { diff --git a/ClassicalSharp/Selections/SelectionBox.cs b/ClassicalSharp/Selections/SelectionBox.cs index cec000fbe..9c444a566 100644 --- a/ClassicalSharp/Selections/SelectionBox.cs +++ b/ClassicalSharp/Selections/SelectionBox.cs @@ -16,10 +16,14 @@ namespace ClassicalSharp.Selections { Colour = col; } - public void Render( double delta, VertexPos3fCol4b[] vertices, VertexPos3fCol4b[] lineVertices, + public void Render( double delta, Vector3 cameraPos, VertexPos3fCol4b[] vertices, VertexPos3fCol4b[] lineVertices, ref int index, ref int lineIndex ) { - Vector3 p1 = (Vector3)Min + new Vector3( 1/16f, 1/16f, 1/16f ); - Vector3 p2 = (Vector3)Max - new Vector3( 1/16f, 1/16f, 1/16f ); + float dist = Math.Min( Utils.DistanceSquared( (Vector3)Min, cameraPos ), + Utils.DistanceSquared( (Vector3)Max, cameraPos ) ); + float offset = dist < 32 * 32 ? 1/32f : 1/16f; + Vector3 p1 = (Vector3)Min + new Vector3( offset ); + Vector3 p2 = (Vector3)Max - new Vector3( offset ); + FastColour col = Colour; YQuad( vertices, ref index, p1.X, p1.Z, p2.X, p2.Z, p1.Y, col ); // bottom diff --git a/ClassicalSharp/Selections/SelectionManager.cs b/ClassicalSharp/Selections/SelectionManager.cs index c906074d2..cb4fcd1e4 100644 --- a/ClassicalSharp/Selections/SelectionManager.cs +++ b/ClassicalSharp/Selections/SelectionManager.cs @@ -43,7 +43,7 @@ namespace ClassicalSharp.Selections { // TODO: Proper selection box sorting. But this is very difficult because // we can have boxes within boxes, intersecting boxes, etc. Probably not worth it. - comparer.pos = player.Position; + comparer.pos = game.Camera.GetCameraPos( player.EyePosition ); selections.Sort( comparer ); if( vertices == null ) InitData(); // lazy init as most servers don't use this. @@ -51,7 +51,7 @@ namespace ClassicalSharp.Selections { int index = 0, lineIndex = 0; for( int i = 0; i < selections.Count; i++ ) { SelectionBox box = selections[i]; - box.Render( delta, vertices, lineVertices, ref index, ref lineIndex ); + box.Render( delta, comparer.pos, vertices, lineVertices, ref index, ref lineIndex ); } Graphics.SetBatchFormat( VertexFormat.Pos3fCol4b ); diff --git a/OpenTK/Math/Vector3.cs b/OpenTK/Math/Vector3.cs index 98fc3e748..660cfa281 100644 --- a/OpenTK/Math/Vector3.cs +++ b/OpenTK/Math/Vector3.cs @@ -37,27 +37,23 @@ namespace OpenTK { public float Z; public Vector3(float x, float y, float z) { - X = x; - Y = y; - Z = z; + X = x; Y = y; Z = z; + } + + public Vector3(float value) { + X = value; Y = value; Z = value; } public Vector3(Vector2 v) { - X = v.X; - Y = v.Y; - Z = 0.0f; + X = v.X; Y = v.Y; Z = 0.0f; } public Vector3(Vector3 v) { - X = v.X; - Y = v.Y; - Z = v.Z; + X = v.X; Y = v.Y; Z = v.Z; } public Vector3(Vector4 v) { - X = v.X; - Y = v.Y; - Z = v.Z; + X = v.X; Y = v.Y; Z = v.Z; } public float Length {