mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 02:56:09 -04:00
Make text input bar have a small background when empty, allowing entering colour codes directly into chat, add support for clicking on urls.
This commit is contained in:
parent
97a38f3cf4
commit
7208d2e7dc
@ -64,7 +64,7 @@ namespace ClassicalSharp {
|
||||
public abstract void DrawBitmappedText( ref DrawTextArgs args, int x, int y );
|
||||
|
||||
/// <summary> Draws a string using the specified arguments, using the specified font or
|
||||
/// the current bitmapped font depending on the 'useFont' argument, at the
|
||||
/// the current bitmapped font depending on 'UseBitmappedChat', at the
|
||||
/// specified coordinates in the currently bound bitmap. </summary>
|
||||
public void DrawChatText( ref DrawTextArgs args, int windowX, int windowY ) {
|
||||
if( !UseBitmappedChat )
|
||||
@ -81,7 +81,7 @@ namespace ClassicalSharp {
|
||||
public abstract Size MeasureBitmappedSize( ref DrawTextArgs args );
|
||||
|
||||
/// <summary> Returns the size of a bitmap needed to contain the specified text with the given arguments,
|
||||
/// when drawn with the specified font or the current bitmapped font depending on the 'useFont' argument. </summary>
|
||||
/// when drawn with the specified font or the current bitmapped font depending on 'UseBitmappedChat'. </summary>
|
||||
public Size MeasureChatSize( ref DrawTextArgs args ) {
|
||||
return !UseBitmappedChat ? MeasureSize( ref args ) :
|
||||
MeasureBitmappedSize( ref args );
|
||||
@ -94,24 +94,28 @@ namespace ClassicalSharp {
|
||||
/// <summary> Draws the specified string from the arguments into a new bitmap,
|
||||
/// then creates a 2D texture with origin at the specified window coordinates. </summary>
|
||||
public Texture MakeTextTexture( ref DrawTextArgs args, int windowX, int windowY ) {
|
||||
Size size = MeasureSize( ref args );
|
||||
if( parts.Count == 0 )
|
||||
return new Texture( -1, windowX, windowY, 0, 0, 1, 1 );
|
||||
return MakeTextureImpl( size, ref args, windowX, windowY, false );
|
||||
return MakeTextureImpl( ref args, windowX, windowY, false );
|
||||
}
|
||||
|
||||
/// <summary> Draws the specified string from the arguments into a new bitmap,
|
||||
/// using the current bitmap font, then creates a 2D texture with origin at the
|
||||
/// specified window coordinates. </summary>
|
||||
public Texture MakeBitmappedTextTexture( ref DrawTextArgs args, int windowX, int windowY ) {
|
||||
Size size = MeasureBitmappedSize( ref args );
|
||||
if( parts.Count == 0 )
|
||||
return new Texture( -1, windowX, windowY, 0, 0, 1, 1 );
|
||||
return MakeTextureImpl( size, ref args, windowX, windowY, true );
|
||||
return MakeTextureImpl( ref args, windowX, windowY, true );
|
||||
}
|
||||
|
||||
Texture MakeTextureImpl( Size size, ref DrawTextArgs args,
|
||||
int windowX, int windowY, bool bitmapped ) {
|
||||
/// <summary> Draws the specified string from the arguments into a new bitmap,
|
||||
/// using the specified font or the current bitmapped font depending on 'UseBitmappedChat',
|
||||
/// then creates a 2D texture with origin at the specified window coordinates. </summary>
|
||||
public Texture MakeChatTextTexture( ref DrawTextArgs args, int windowX, int windowY ) {
|
||||
return MakeTextureImpl( ref args, windowX, windowY, UseBitmappedChat );
|
||||
}
|
||||
|
||||
Texture MakeTextureImpl( ref DrawTextArgs args, int windowX, int windowY, bool bitmapped ) {
|
||||
Size size = bitmapped ? MeasureBitmappedSize( ref args ) : MeasureSize( ref args );
|
||||
if( parts.Count == 0 )
|
||||
return new Texture( -1, windowX, windowY, 0, 0, 1, 1 );
|
||||
|
||||
using( Bitmap bmp = CreatePow2Bitmap( size ) ) {
|
||||
SetBitmap( bmp );
|
||||
args.SkipPartsCheck = true;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using OpenTK.Input;
|
||||
|
||||
@ -76,25 +77,27 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
Font chatFont, chatInputFont, announcementFont;
|
||||
Font chatFont, chatInputFont, chatUnderlineFont, announcementFont;
|
||||
public override void Init() {
|
||||
chatFont = new Font( "Arial", game.Chat.FontSize );
|
||||
chatInputFont = new Font( "Arial", game.Chat.FontSize, FontStyle.Bold );
|
||||
int fontSize = game.Chat.FontSize;//(int)(14 * Utils.GuiScale( game.Width, game.Height ));
|
||||
chatFont = new Font( "Arial", fontSize );
|
||||
chatInputFont = new Font( "Arial", fontSize, FontStyle.Bold );
|
||||
chatUnderlineFont = new Font( "Arial", fontSize, FontStyle.Underline );
|
||||
announcementFont = new Font( "Arial", 14 );
|
||||
blockSize = (int)(40 * Utils.GuiScale( game.Width, game.Height ));
|
||||
|
||||
textInput = new TextInputWidget( game, chatFont, chatInputFont );
|
||||
textInput.YOffset = blockSize + 5;
|
||||
status = new TextGroupWidget( game, 3, chatFont );
|
||||
status = new TextGroupWidget( game, 3, chatFont, chatUnderlineFont );
|
||||
status.VerticalAnchor = Anchor.LeftOrTop;
|
||||
status.HorizontalAnchor = Anchor.BottomOrRight;
|
||||
status.Init();
|
||||
bottomRight = new TextGroupWidget( game, 3, chatFont );
|
||||
bottomRight = new TextGroupWidget( game, 3, chatFont, chatUnderlineFont );
|
||||
bottomRight.VerticalAnchor = Anchor.BottomOrRight;
|
||||
bottomRight.HorizontalAnchor = Anchor.BottomOrRight;
|
||||
bottomRight.YOffset = blockSize * 3 / 2;
|
||||
bottomRight.Init();
|
||||
normalChat = new TextGroupWidget( game, chatLines, chatFont );
|
||||
normalChat = new TextGroupWidget( game, chatLines, chatFont, chatUnderlineFont );
|
||||
normalChat.XOffset = 10;
|
||||
normalChat.YOffset = blockSize * 2 + 15;
|
||||
normalChat.HorizontalAnchor = Anchor.LeftOrTop;
|
||||
@ -152,6 +155,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
chatFont.Dispose();
|
||||
chatInputFont.Dispose();
|
||||
chatUnderlineFont.Dispose();
|
||||
announcementFont.Dispose();
|
||||
|
||||
normalChat.Dispose();
|
||||
@ -280,21 +284,41 @@ namespace ClassicalSharp {
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
|
||||
if( !HandlesAllInput ) return false;
|
||||
if( normalChat.Bounds.Contains( mouseX, mouseY ) ) {
|
||||
int height = normalChat.GetUsedHeight();
|
||||
int y = normalChat.Y + normalChat.Height - height;
|
||||
if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) ) {
|
||||
string text = normalChat.GetSelected( mouseX, mouseY );
|
||||
if( text != null ) {
|
||||
textInput.AppendText(text);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return textInput.HandlesMouseClick( mouseX, mouseY, button );
|
||||
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
|
||||
if( !HandlesAllInput ) return false;
|
||||
if( normalChat.Bounds.Contains( mouseX, mouseY ) ) {
|
||||
int height = normalChat.GetUsedHeight();
|
||||
int y = normalChat.Y + normalChat.Height - height;
|
||||
if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) ) {
|
||||
string text = normalChat.GetSelected( mouseX, mouseY );
|
||||
if( text != null ) {
|
||||
if( Utils.IsUrlPrefix( text ) ) {
|
||||
game.ShowWarning( new WarningScreen(
|
||||
game, text, OpenUrl, AppendUrl,
|
||||
"Are you sure you want to go to this url?",
|
||||
text,
|
||||
"Be careful - urls from strangers may link to websites that",
|
||||
" may have viruses, or things you may not want to open/see."
|
||||
) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return textInput.HandlesMouseClick( mouseX, mouseY, button );
|
||||
}
|
||||
|
||||
void OpenUrl( object metadata ) {
|
||||
try {
|
||||
Process.Start( (string)metadata );
|
||||
} catch( Exception ex ) {
|
||||
ErrorHandler.LogError( "ChatScreen.OpenUrl", ex );
|
||||
}
|
||||
}
|
||||
|
||||
void AppendUrl( object metadata ) {
|
||||
textInput.AppendText( (string)metadata );
|
||||
}
|
||||
|
||||
void ResetIndex() {
|
||||
|
@ -72,20 +72,17 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
public void LoseFocus() {
|
||||
if( playerList != null ) {
|
||||
if( playerList != null )
|
||||
playerList.Dispose();
|
||||
}
|
||||
if( !game.CursorVisible )
|
||||
game.CursorVisible = true;
|
||||
}
|
||||
|
||||
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {
|
||||
chat.OnResize( oldWidth, oldHeight, width, height );
|
||||
hotbar.OnResize( oldWidth, oldHeight, width, height );
|
||||
if( playerList != null ) {
|
||||
int deltaX = CalcDelta( width, oldWidth, Anchor.Centre );
|
||||
playerList.MoveTo( playerList.X + deltaX, height / 4 );
|
||||
}
|
||||
PlayerListWidget widget = playerList;
|
||||
game.RefreshHud();
|
||||
if( widget != null )
|
||||
CreatePlayerListWidget();
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
@ -113,22 +110,26 @@ namespace ClassicalSharp {
|
||||
|
||||
public override bool HandlesKeyDown( Key key ) {
|
||||
if( key == game.Mapping( KeyBinding.PlayerList ) ) {
|
||||
if( playerList == null ) {
|
||||
if( game.Network.UsingExtPlayerList ) {
|
||||
playerList = new ExtPlayerListWidget( game, playerFont );
|
||||
} else {
|
||||
playerList = new NormalPlayerListWidget( game, playerFont );
|
||||
}
|
||||
playerList.Init();
|
||||
playerList.MoveTo( playerList.X, game.Height / 4 );
|
||||
}
|
||||
}
|
||||
if( chat.HandlesKeyDown( key ) ) {
|
||||
if( playerList == null )
|
||||
CreatePlayerListWidget();
|
||||
return true;
|
||||
}
|
||||
|
||||
if( chat.HandlesKeyDown( key ) )
|
||||
return true;
|
||||
return hotbar.HandlesKeyDown( key );
|
||||
}
|
||||
|
||||
void CreatePlayerListWidget() {
|
||||
if( game.Network.UsingExtPlayerList ) {
|
||||
playerList = new ExtPlayerListWidget( game, playerFont );
|
||||
} else {
|
||||
playerList = new NormalPlayerListWidget( game, playerFont );
|
||||
}
|
||||
playerList.Init();
|
||||
playerList.MoveTo( playerList.X, game.Height / 4 );
|
||||
}
|
||||
|
||||
public override bool HandlesKeyUp( Key key ) {
|
||||
if( key == game.Mapping( KeyBinding.PlayerList ) ) {
|
||||
if( playerList != null ) {
|
||||
|
@ -40,21 +40,21 @@ namespace ClassicalSharp {
|
||||
MakeBackgroundTexture( width );
|
||||
MakeSelectionTexture();
|
||||
}
|
||||
|
||||
|
||||
public override void Render( double delta ) {
|
||||
graphicsApi.Texturing = true;
|
||||
background.Render( graphicsApi );
|
||||
graphicsApi.BindTexture( game.TerrainAtlas.TexId );
|
||||
graphicsApi.BindTexture( game.TerrainAtlas.TexId );
|
||||
graphicsApi.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
|
||||
|
||||
for( int i = 0; i < hotbarCount; i++ ) {
|
||||
int x = X + i * blockSize;
|
||||
IsometricBlockDrawer.Draw( game, (byte)game.Inventory.Hotbar[i], blockSize / 2 - borderSize - 2,
|
||||
IsometricBlockDrawer.Draw( game, (byte)game.Inventory.Hotbar[i], blockSize / 2 - borderSize - 2,
|
||||
x + 1 + blockSize / 2, game.Height - blockSize / 2 );
|
||||
if( i == game.Inventory.HeldBlockIndex )
|
||||
selectedBlock.X1 = x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
selectedBlock.Render( graphicsApi );
|
||||
graphicsApi.Texturing = false;
|
||||
}
|
||||
@ -73,27 +73,27 @@ namespace ClassicalSharp {
|
||||
|
||||
void MakeBackgroundTexture( int width ) {
|
||||
Size size = new Size( width, blockSize );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.Clear( backCol );
|
||||
for( int xx = 0; xx < hotbarCount; xx++ ) {
|
||||
drawer.DrawRectBounds( outlineCol, borderSize, xx * blockSize,
|
||||
0, blockSize, blockSize );
|
||||
}
|
||||
background = drawer.Make2DTexture( bmp, size, X, Y );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.Clear( backCol );
|
||||
for( int xx = 0; xx < hotbarCount; xx++ ) {
|
||||
drawer.DrawRectBounds( outlineCol, borderSize, xx * blockSize,
|
||||
0, blockSize, blockSize );
|
||||
}
|
||||
background = drawer.Make2DTexture( bmp, size, X, Y );
|
||||
}
|
||||
}
|
||||
|
||||
void MakeSelectionTexture() {
|
||||
Size size = new Size( blockSize, blockSize );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRectBounds( selCol, borderSize, 0, 0, blockSize, blockSize );
|
||||
selectedBlock = drawer.Make2DTexture( bmp, size, 0, Y );
|
||||
}
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRectBounds( selCol, borderSize, 0, 0, blockSize, blockSize );
|
||||
selectedBlock = drawer.Make2DTexture( bmp, size, 0, Y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,17 +88,17 @@ namespace ClassicalSharp {
|
||||
const int borderSize = 3; // 1 px for base border, 2 px for shadow, 1 px for offset text
|
||||
size.Width += borderSize; size.Height += borderSize;
|
||||
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRoundedRect( shadowCol, 3, IDrawer2D.Offset, IDrawer2D.Offset,
|
||||
baseSize.Width, baseSize.Height );
|
||||
drawer.DrawRoundedRect( boxCol, 3, 0, 0, baseSize.Width, baseSize.Height );
|
||||
|
||||
args.SkipPartsCheck = true;
|
||||
drawer.DrawText( ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
|
||||
texture = drawer.Make2DTexture( bmp, size, 0, 0 );
|
||||
}
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRoundedRect( shadowCol, 3, IDrawer2D.Offset, IDrawer2D.Offset,
|
||||
baseSize.Width, baseSize.Height );
|
||||
drawer.DrawRoundedRect( boxCol, 3, 0, 0, baseSize.Width, baseSize.Height );
|
||||
|
||||
args.SkipPartsCheck = true;
|
||||
drawer.DrawText( ref args, 1 + xOffset / 2, 1 + yOffset / 2 );
|
||||
texture = drawer.Make2DTexture( bmp, size, 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace ClassicalSharp {
|
||||
public void Redraw() {
|
||||
Make( elements[selectedIndex], font );
|
||||
Width = texture.Width;
|
||||
Height = texture.Height;
|
||||
Height = texture.Height;
|
||||
}
|
||||
|
||||
unsafe void Make( Element e, Font font ) {
|
||||
@ -49,16 +49,16 @@ namespace ClassicalSharp {
|
||||
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 );
|
||||
DrawTitles( drawer, font );
|
||||
drawer.Clear( new FastColour( 30, 30, 30, 200 ), 0, titleHeight,
|
||||
size.Width, bodySize.Height );
|
||||
|
||||
DrawContent( drawer, font, e, titleHeight );
|
||||
texture = drawer.Make2DTexture( bmp, size, X, Y );
|
||||
}
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
DrawTitles( drawer, font );
|
||||
drawer.Clear( new FastColour( 30, 30, 30, 200 ), 0, titleHeight,
|
||||
size.Width, bodySize.Height );
|
||||
|
||||
DrawContent( drawer, font, e, titleHeight );
|
||||
texture = drawer.Make2DTexture( bmp, size, X, Y );
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +96,8 @@ namespace ClassicalSharp {
|
||||
if( index < e.Contents.Length ) {
|
||||
if( selectedIndex == 0 ) {
|
||||
// TODO: need to insert characters that don't affect caret index, adjust caret colour
|
||||
//parent.AppendChar( e.Contents[index * e.CharsPerItem] );
|
||||
//parent.AppendChar( e.Contents[index * e.CharsPerItem + 1] );
|
||||
parent.AppendChar( e.Contents[index * e.CharsPerItem] );
|
||||
parent.AppendChar( e.Contents[index * e.CharsPerItem + 1] );
|
||||
} else {
|
||||
parent.AppendChar( e.Contents[index] );
|
||||
}
|
||||
|
@ -32,9 +32,7 @@ namespace ClassicalSharp {
|
||||
Height = defaultHeight;
|
||||
} else {
|
||||
DrawTextArgs args = new DrawTextArgs( text, font, true );
|
||||
texture = game.Drawer2D.UseBitmappedChat ?
|
||||
game.Drawer2D.MakeBitmappedTextTexture( ref args, 0, 0 ) :
|
||||
game.Drawer2D.MakeTextTexture( ref args, 0, 0 );
|
||||
texture = game.Drawer2D.MakeChatTextTexture( ref args, 0, 0 );
|
||||
|
||||
X = texture.X1 = CalcOffset( game.Width, texture.Width, XOffset, HorizontalAnchor );
|
||||
Y = texture.Y1 = CalcOffset( game.Height, texture.Height, YOffset, VerticalAnchor );
|
||||
|
115
ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.Formatter.cs
Normal file
115
ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.Formatter.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed partial class TextGroupWidget : Widget {
|
||||
|
||||
public void SetText( int index, string text ) {
|
||||
graphicsApi.DeleteTexture( ref Textures[index] );
|
||||
DrawTextArgs args = new DrawTextArgs( text, font, true );
|
||||
Font underlineFont = new Font( font, FontStyle.Underline );
|
||||
urlBounds[index] = null;
|
||||
|
||||
if( !String.IsNullOrEmpty( text ) ) {
|
||||
Texture tex = NextToken( text, 0 ) == -1 ? DrawSimple( ref args ) :
|
||||
DrawAdvanced( ref args, index, text );
|
||||
tex.X1 = CalcOffset( game.Width, tex.Width, XOffset, HorizontalAnchor );
|
||||
tex.Y1 = CalcY( index, tex.Height );
|
||||
Textures[index] = tex;
|
||||
lines[index] = text;
|
||||
} else {
|
||||
Textures[index] = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
|
||||
lines[index] = null;
|
||||
}
|
||||
UpdateDimensions();
|
||||
}
|
||||
|
||||
Texture DrawSimple( ref DrawTextArgs args ) {
|
||||
return game.Drawer2D.MakeChatTextTexture( ref args, 0, 0 );
|
||||
}
|
||||
|
||||
Texture DrawAdvanced( ref DrawTextArgs args, int index, string text ) {
|
||||
string[] items = Split( index, text );
|
||||
Size total = Size.Empty;
|
||||
Size[] partSizes = new Size[items.Length];
|
||||
|
||||
for( int i = 0; i < items.Length; i++ ) {
|
||||
args.Text = items[i];
|
||||
args.Font = (i & 1) == 0 ? font : underlineFont;
|
||||
partSizes[i] = game.Drawer2D.MeasureChatSize( ref args );
|
||||
total.Height = Math.Max( partSizes[i].Height, total.Height );
|
||||
total.Width += partSizes[i].Width;
|
||||
}
|
||||
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( total ) )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
int x = 0;
|
||||
|
||||
for( int i = 0; i < items.Length; i++ ) {
|
||||
args.Text = items[i];
|
||||
args.Font = (i & 1) == 0 ? font : underlineFont;
|
||||
Size size = partSizes[i];
|
||||
|
||||
drawer.DrawChatText( ref args, x, 0 );
|
||||
urlBounds[index][i].X = x;
|
||||
urlBounds[index][i].Width = size.Width;
|
||||
x += size.Width;
|
||||
}
|
||||
return drawer.Make2DTexture( bmp, total, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
string[] Split( int index, string line ) {
|
||||
int start = 0, lastEnd = 0, count = 0;
|
||||
string[] items = new string[GetTokensCount( line )];
|
||||
Rectangle[] parts = new Rectangle[items.Length];
|
||||
|
||||
while( (start = NextToken( line, start )) >= 0 ) {
|
||||
int nextEnd = line.IndexOf( ' ', start );
|
||||
if( nextEnd == -1 )
|
||||
nextEnd = line.Length;
|
||||
|
||||
parts[count].Y = lastEnd << 12 | (start - lastEnd);
|
||||
items[count++] = line.Substring( lastEnd, start - lastEnd ); // word bit
|
||||
parts[count].Y = start << 12 | (nextEnd - start);
|
||||
items[count++] = line.Substring( start, nextEnd - start ); // url bit
|
||||
start = nextEnd;
|
||||
lastEnd = nextEnd;
|
||||
}
|
||||
|
||||
if( lastEnd < line.Length ) {
|
||||
parts[count].Y = lastEnd << 12 | (line.Length - lastEnd);
|
||||
items[count++] = line.Substring( lastEnd, line.Length - lastEnd );
|
||||
}
|
||||
urlBounds[index] = parts;
|
||||
return items;
|
||||
}
|
||||
|
||||
int NextToken( string line, int start ) {
|
||||
int nextHttp = line.IndexOf( "http://", start );
|
||||
int nextHttps = line.IndexOf( "https://", start );
|
||||
return nextHttp == -1 ? nextHttps : nextHttp;
|
||||
}
|
||||
|
||||
int GetTokensCount( string line ) {
|
||||
int start = 0, lastEnd = 0, count = 0;
|
||||
while( (start = NextToken( line, start )) >= 0 ) {
|
||||
int nextEnd = line.IndexOf( ' ', start );
|
||||
if( nextEnd == -1 )
|
||||
nextEnd = line.Length;
|
||||
|
||||
start = nextEnd;
|
||||
lastEnd = nextEnd;
|
||||
count += 2;
|
||||
}
|
||||
|
||||
if( lastEnd < line.Length )
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,22 +4,26 @@ using System.Drawing;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public sealed class TextGroupWidget : Widget {
|
||||
public sealed partial class TextGroupWidget : Widget {
|
||||
|
||||
public TextGroupWidget( Game game, int elementsCount, Font font ) : base( game ) {
|
||||
public TextGroupWidget( Game game, int elementsCount,
|
||||
Font font, Font underlineFont ) : base( game ) {
|
||||
ElementsCount = elementsCount;
|
||||
this.font = font;
|
||||
this.underlineFont = underlineFont;
|
||||
}
|
||||
|
||||
public Texture[] Textures;
|
||||
string[] lines;
|
||||
Rectangle[][] urlBounds;
|
||||
int ElementsCount, defaultHeight;
|
||||
public int XOffset = 0, YOffset = 0;
|
||||
readonly Font font;
|
||||
readonly Font font, underlineFont;
|
||||
|
||||
public override void Init() {
|
||||
Textures = new Texture[ElementsCount];
|
||||
lines = new string[ElementsCount];
|
||||
urlBounds = new Rectangle[ElementsCount][];
|
||||
DrawTextArgs args = new DrawTextArgs( "I", font, true );
|
||||
defaultHeight = game.Drawer2D.MeasureChatSize( ref args ).Height;
|
||||
|
||||
@ -28,26 +32,6 @@ namespace ClassicalSharp {
|
||||
UpdateDimensions();
|
||||
}
|
||||
|
||||
public void SetText( int index, string text ) {
|
||||
graphicsApi.DeleteTexture( ref Textures[index] );
|
||||
DrawTextArgs args = new DrawTextArgs( text, font, true );
|
||||
|
||||
if( !String.IsNullOrEmpty( text ) ) {
|
||||
Texture tex = game.Drawer2D.UseBitmappedChat ?
|
||||
game.Drawer2D.MakeBitmappedTextTexture( ref args, 0, 0 ) :
|
||||
game.Drawer2D.MakeTextTexture( ref args, 0, 0 );
|
||||
|
||||
tex.X1 = CalcOffset( game.Width, tex.Width, XOffset, HorizontalAnchor );
|
||||
tex.Y1 = CalcY( index, tex.Height );
|
||||
Textures[index] = tex;
|
||||
lines[index] = text;
|
||||
} else {
|
||||
Textures[index] = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
|
||||
lines[index] = null;
|
||||
}
|
||||
UpdateDimensions();
|
||||
}
|
||||
|
||||
public void PushUpAndReplaceLast( string text ) {
|
||||
int y = Y;
|
||||
graphicsApi.DeleteTexture( ref Textures[0] );
|
||||
@ -81,7 +65,7 @@ namespace ClassicalSharp {
|
||||
y -= newHeight;
|
||||
for( int i = 0; i < index; i++ ) {
|
||||
Textures[i].Y1 -= deltaY;
|
||||
}
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
@ -96,11 +80,11 @@ namespace ClassicalSharp {
|
||||
}
|
||||
|
||||
void UpdateDimensions() {
|
||||
Width = 0;
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
for( int i = 0; i < Textures.Length; i++ ) {
|
||||
Width = Math.Max( Width, Textures[i].Width );
|
||||
Height += Textures[i].Height;
|
||||
Height += Textures[i].Height;
|
||||
}
|
||||
|
||||
X = CalcOffset( game.Width, Width, XOffset, HorizontalAnchor );
|
||||
@ -131,9 +115,27 @@ namespace ClassicalSharp {
|
||||
|
||||
public string GetSelected( int mouseX, int mouseY ) {
|
||||
for( int i = 0; i < Textures.Length; i++ ) {
|
||||
if( Textures[i].IsValid &&
|
||||
Textures[i].Bounds.Contains( mouseX, mouseY ) )
|
||||
return lines[i];
|
||||
Texture tex = Textures[i];
|
||||
if( tex.IsValid && tex.Bounds.Contains( mouseX, mouseY ) ) {
|
||||
return GetUrl( i, mouseX ) ?? lines[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
string GetUrl( int index, int mouseX ) {
|
||||
Rectangle[] partBounds = urlBounds[index];
|
||||
if( partBounds == null )
|
||||
return null;
|
||||
Texture tex = Textures[index];
|
||||
mouseX -= tex.X1;
|
||||
string text = lines[index];
|
||||
|
||||
for( int i = 1; i < partBounds.Length; i += 2 ) {
|
||||
if( mouseX >= partBounds[i].Left && mouseX < partBounds[i].Right ) {
|
||||
int packed = partBounds[i].Y;
|
||||
return text.Substring( packed >> 12, packed & 0xFFF );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -15,21 +15,24 @@ namespace ClassicalSharp {
|
||||
VerticalAnchor = Anchor.BottomOrRight;
|
||||
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
|
||||
|
||||
chatInputText = new WrappableStringBuffer( len );
|
||||
DrawTextArgs args = new DrawTextArgs( "A", boldFont, true );
|
||||
Size defSize = game.Drawer2D.MeasureChatSize( ref args );
|
||||
defaultWidth = defSize.Width; defaultHeight = defSize.Height;
|
||||
Width = defaultWidth; Height = defaultHeight;
|
||||
|
||||
this.font = font;
|
||||
this.boldFont = boldFont;
|
||||
chatInputText = new WrappableStringBuffer( len );
|
||||
DrawTextArgs args = new DrawTextArgs( "_", boldFont, false );
|
||||
defaultHeight = game.Drawer2D.MeasureChatSize( ref args ).Height;
|
||||
Height = defaultHeight;
|
||||
altText = new AltTextInputWidget( game, font, boldFont, this );
|
||||
altText.Init();
|
||||
}
|
||||
|
||||
public int RealHeight { get { return Height + altText.Height; } }
|
||||
|
||||
Texture chatInputTexture, caretTexture;
|
||||
Texture inputTex, caretTex;
|
||||
int caretPos = -1, typingLogPos = 0;
|
||||
public int YOffset, defaultHeight;
|
||||
public int YOffset;
|
||||
int defaultWidth, defaultHeight;
|
||||
internal WrappableStringBuffer chatInputText;
|
||||
readonly Font font, boldFont;
|
||||
|
||||
@ -38,8 +41,19 @@ namespace ClassicalSharp {
|
||||
FastColour caretCol;
|
||||
static FastColour backColour = new FastColour( 60, 60, 60, 200 );
|
||||
public override void Render( double delta ) {
|
||||
chatInputTexture.Render( graphicsApi );
|
||||
caretTexture.Render( graphicsApi, caretCol );
|
||||
graphicsApi.Texturing = false;
|
||||
int y = Y, x = X;
|
||||
for( int i = 0; i < sizes.Length; i++ ) {
|
||||
int offset = (caretTex.Y1 == y) ? defaultWidth : 0;
|
||||
graphicsApi.Draw2DQuad( x + 5, y, sizes[i].Width + offset, sizes[i].Height, backColour );
|
||||
y += sizes[i].Height;
|
||||
}
|
||||
if( sizes.Length == 0 || sizes[0] == Size.Empty )
|
||||
graphicsApi.Draw2DQuad( x + 5, y, defaultWidth, defaultHeight, backColour );
|
||||
graphicsApi.Texturing = true;
|
||||
|
||||
inputTex.Render( graphicsApi );
|
||||
caretTex.Render( graphicsApi, caretCol );
|
||||
if( altText.Active )
|
||||
altText.Render( delta );
|
||||
}
|
||||
@ -51,14 +65,12 @@ namespace ClassicalSharp {
|
||||
|
||||
public override void Init() {
|
||||
X = 5;
|
||||
DrawTextArgs args = new DrawTextArgs( "_", boldFont, false );
|
||||
caretTexture = game.Drawer2D.UseBitmappedChat ?
|
||||
game.Drawer2D.MakeBitmappedTextTexture( ref args, 0, 0 ) :
|
||||
game.Drawer2D.MakeTextTexture( ref args, 0, 0 );
|
||||
DrawTextArgs args = new DrawTextArgs( "_", boldFont, true );
|
||||
caretTex = game.Drawer2D.MakeChatTextTexture( ref args, 0, 0 );
|
||||
chatInputText.WordWrap( ref parts, ref partLens, 64 );
|
||||
|
||||
maxWidth = 0;
|
||||
args = new DrawTextArgs( null, font, false );
|
||||
args = new DrawTextArgs( null, font, true );
|
||||
for( int i = 0; i < lines; i++ ) {
|
||||
args.Text = parts[i];
|
||||
sizes[i] = game.Drawer2D.MeasureChatSize( ref args );
|
||||
@ -84,23 +96,23 @@ namespace ClassicalSharp {
|
||||
if( indexX == -1 ) indexX = partLens[indexY];
|
||||
|
||||
if( indexX == 64 ) {
|
||||
caretTexture.X1 = 10 + sizes[indexY].Width;
|
||||
sizes[indexY].Width += caretTexture.Width;
|
||||
caretTex.X1 = 10 + sizes[indexY].Width;
|
||||
sizes[indexY].Width += caretTex.Width;
|
||||
|
||||
maxWidth = Math.Max( maxWidth, sizes[indexY].Width );
|
||||
caretTexture.Y1 = sizes[0].Height * indexY;
|
||||
caretTex.Y1 = sizes[0].Height * indexY;
|
||||
caretCol = nextCaretCol;
|
||||
} else {
|
||||
args.Text = parts[indexY].Substring( 0, indexX );
|
||||
Size trimmedSize = game.Drawer2D.MeasureChatSize( ref args );
|
||||
caretTexture.X1 = 10 + trimmedSize.Width;
|
||||
caretTex.X1 = 10 + trimmedSize.Width;
|
||||
|
||||
string line = parts[indexY];
|
||||
args.Text = indexX < line.Length ? new String( line[indexX], 1 ) : " ";
|
||||
Size charSize = game.Drawer2D.MeasureChatSize( ref args );
|
||||
caretTexture.Width = charSize.Width;
|
||||
caretTex.Width = charSize.Width;
|
||||
|
||||
caretTexture.Y1 = sizes[0].Height * indexY;
|
||||
caretTex.Y1 = sizes[0].Height * indexY;
|
||||
caretCol = normalCaretCol;
|
||||
}
|
||||
DrawString();
|
||||
@ -115,40 +127,39 @@ namespace ClassicalSharp {
|
||||
Size size = new Size( maxWidth, totalHeight );
|
||||
|
||||
int realHeight = 0;
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
DrawTextArgs args = new DrawTextArgs( null, font, false );
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
DrawTextArgs args = new DrawTextArgs( null, font, true );
|
||||
|
||||
for( int i = 0; i < parts.Length; i++ ) {
|
||||
if( parts[i] == null ) break;
|
||||
args.Text = parts[i];
|
||||
|
||||
for( int i = 0; i < parts.Length; i++ ) {
|
||||
if( parts[i] == null ) break;
|
||||
args.Text = parts[i];
|
||||
|
||||
drawer.Clear( backColour, 0, realHeight, sizes[i].Width, sizes[i].Height );
|
||||
drawer.DrawChatText( ref args, 0, realHeight );
|
||||
realHeight += sizes[i].Height;
|
||||
}
|
||||
chatInputTexture = drawer.Make2DTexture( bmp, size, 10, 0 );
|
||||
drawer.DrawChatText( ref args, 0, realHeight );
|
||||
realHeight += sizes[i].Height;
|
||||
}
|
||||
inputTex = drawer.Make2DTexture( bmp, size, 10, 0 );
|
||||
}
|
||||
|
||||
Height = realHeight == 0 ? defaultHeight : realHeight;
|
||||
Y = game.Height - Height - YOffset;
|
||||
chatInputTexture.Y1 = Y;
|
||||
caretTexture.Y1 += Y;
|
||||
inputTex.Y1 = Y;
|
||||
caretTex.Y1 += Y;
|
||||
Width = size.Width;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
graphicsApi.DeleteTexture( ref caretTexture );
|
||||
graphicsApi.DeleteTexture( ref chatInputTexture );
|
||||
graphicsApi.DeleteTexture( ref caretTex );
|
||||
graphicsApi.DeleteTexture( ref inputTex );
|
||||
}
|
||||
|
||||
public override void MoveTo( int newX, int newY ) {
|
||||
int diffX = newX - X, diffY = newY - Y;
|
||||
X = newX; Y = newY;
|
||||
caretTexture.Y1 += diffY;
|
||||
chatInputTexture.Y1 += diffY;
|
||||
caretTex.Y1 += diffY;
|
||||
inputTex.Y1 += diffY;
|
||||
|
||||
altText.texture.Y1 = game.Height - (YOffset + Height + altText.texture.Height);
|
||||
altText.Y = altText.texture.Y1;
|
||||
|
@ -60,23 +60,23 @@ namespace ClassicalSharp {
|
||||
Size size = new Size( Math.Max( textSize.Width, DesiredMaxWidth ),
|
||||
Math.Max( textSize.Height, DesiredMaxHeight ) );
|
||||
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
|
||||
using( IDrawer2D drawer = game.Drawer2D ) {
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRect( backColour, 0, 0, size.Width, size.Height );
|
||||
args.SkipPartsCheck = true;
|
||||
drawer.DrawText( ref args, 0, 0 );
|
||||
|
||||
args.Text = Validator.Range;
|
||||
args.SkipPartsCheck = false;
|
||||
Size hintSize = drawer.MeasureSize( ref args );
|
||||
|
||||
args.SkipPartsCheck = true;
|
||||
int hintX = size.Width - hintSize.Width;
|
||||
if( textSize.Width < hintX )
|
||||
drawer.DrawText( ref args, hintX, 0 );
|
||||
chatInputTexture = drawer.Make2DTexture( bmp, size, 0, 0 );
|
||||
}
|
||||
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
||||
using( IDrawer2D drawer = game.Drawer2D )
|
||||
{
|
||||
drawer.SetBitmap( bmp );
|
||||
drawer.DrawRect( backColour, 0, 0, size.Width, size.Height );
|
||||
args.SkipPartsCheck = true;
|
||||
drawer.DrawText( ref args, 0, 0 );
|
||||
|
||||
args.Text = Validator.Range;
|
||||
args.SkipPartsCheck = false;
|
||||
Size hintSize = drawer.MeasureSize( ref args );
|
||||
|
||||
args.SkipPartsCheck = true;
|
||||
int hintX = size.Width - hintSize.Width;
|
||||
if( textSize.Width < hintX )
|
||||
drawer.DrawText( ref args, hintX, 0 );
|
||||
chatInputTexture = drawer.Make2DTexture( bmp, size, 0, 0 );
|
||||
}
|
||||
|
||||
X = CalcOffset( game.Width, size.Width, XOffset, HorizontalAnchor );
|
||||
|
@ -109,6 +109,7 @@
|
||||
<Compile Include="2D\Widgets\Chat\ChatTextWidget.cs" />
|
||||
<Compile Include="2D\Widgets\Chat\AltTextInputWidget.cs" />
|
||||
<Compile Include="2D\Widgets\Chat\TextGroupWidget.cs" />
|
||||
<Compile Include="2D\Widgets\Chat\TextGroupWidget.Formatter.cs" />
|
||||
<Compile Include="2D\Widgets\Chat\TextInputWidget.cs" />
|
||||
<Compile Include="2D\Widgets\Chat\TextInputWidget.Handlers.cs" />
|
||||
<Compile Include="2D\Widgets\ExtPlayerListWidget.cs" />
|
||||
|
@ -7,8 +7,8 @@ namespace ClassicalSharp {
|
||||
|
||||
public sealed class ChatLog : IDisposable {
|
||||
|
||||
public ChatLine Status1, Status2, Status3, BottomRight1,
|
||||
BottomRight2, BottomRight3, Announcement;
|
||||
public ChatLine Status1, Status2, Status3, BottomRight1 = "F",
|
||||
BottomRight2 = "G", BottomRight3 = "H", Announcement;
|
||||
|
||||
Game game;
|
||||
public ChatLog( Game game ) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user