feat: backporting existing raylib-cs examples and new official raylib examples to WASM, adopting raylib's original code style
This commit is contained in:
parent
768fa93c41
commit
732b7aa346
234 changed files with 38999 additions and 10578 deletions
|
|
@ -1,13 +1,15 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Codepoints loading
|
||||
* raylib [text] example - codepoints loading
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 2.5
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2022-2023 Ramon Santamaria (@raysan5)
|
||||
* Copyright (c) 2022-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -19,32 +21,37 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
class CodepointsLoading
|
||||
public partial class CodepointsLoading : IExample
|
||||
{
|
||||
public unsafe static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// Text to be displayed, must be UTF-8 (save this code file as UTF-8)
|
||||
// NOTE: It can contain all the required text for the game,
|
||||
// this text will be scanned to get all the required codepoints
|
||||
private const string text =
|
||||
"いろはにほへと ちりぬるを\nわかよたれそ つねならむ\nうゐのおくやま けふこえて\nあさきゆめみし ゑひもせす";
|
||||
|
||||
public string Name => "Text / Codepoints Loading";
|
||||
|
||||
public string Title => "raylib [text] example - codepoints loading";
|
||||
|
||||
private List<int> codepoints;
|
||||
private int[] codepointsNoDuplicates;
|
||||
private Font font;
|
||||
private bool showFontAtlas;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - codepoints loading");
|
||||
|
||||
// Text to be displayed, must be UTF-8 (save this code file as UTF-8)
|
||||
// NOTE: It can contain all the required text for the game,
|
||||
// this text will be scanned to get all the required codepoints
|
||||
const string text =
|
||||
"いろはにほへと ちりぬるを\nわかよたれそ つねならむ\nうゐのおくやま けふこえて\nあさきゆめみし ゑひもせす";
|
||||
|
||||
// Get codepoints from text
|
||||
List<int> codepoints = GetCodePoints(text);
|
||||
codepoints = GetCodePoints(text);
|
||||
|
||||
// Remove duplicate codepoints to generate smaller font atlas
|
||||
int[] codepointsNoDuplicates = codepoints.Distinct().ToArray();
|
||||
codepointsNoDuplicates = codepoints.Distinct().ToArray();
|
||||
|
||||
// Load font containing all the provided codepoint glyphs
|
||||
// A texture font atlas is automatically generated
|
||||
Font font = LoadFontEx(
|
||||
font = LoadFontEx(
|
||||
"resources/fonts/DotGothic16-Regular.ttf",
|
||||
36,
|
||||
codepointsNoDuplicates,
|
||||
|
|
@ -54,64 +61,58 @@ class CodepointsLoading
|
|||
// Set bilinear scale filter for better font scaling
|
||||
SetTextureFilter(font.Texture, TextureFilter.Bilinear);
|
||||
|
||||
bool showFontAtlas = false;
|
||||
SetTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
showFontAtlas = false;
|
||||
}
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
showFontAtlas = !showFontAtlas;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
showFontAtlas = !showFontAtlas;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth(), 70, Color.Black);
|
||||
DrawText($"Total codepoints contained in provided text: {codepoints.Count}", 10, 10, 20, Color.Green);
|
||||
DrawText(
|
||||
$"Total codepoints required for font atlas (duplicates excluded): {codepointsNoDuplicates.Length}",
|
||||
10,
|
||||
40,
|
||||
20,
|
||||
Color.Green
|
||||
);
|
||||
DrawRectangle(0, 0, GetScreenWidth(), 70, Color.Black);
|
||||
DrawText($"Total codepoints contained in provided text: {codepoints.Count}", 10, 10, 20, Color.Green);
|
||||
DrawText(
|
||||
$"Total codepoints required for font atlas (duplicates excluded): {codepointsNoDuplicates.Length}",
|
||||
10,
|
||||
40,
|
||||
20,
|
||||
Color.Green
|
||||
);
|
||||
|
||||
if (showFontAtlas)
|
||||
{
|
||||
// Draw generated font texture atlas containing provided codepoints
|
||||
DrawTexture(font.Texture, 150, 100, Color.Black);
|
||||
DrawRectangleLines(150, 100, font.Texture.Width, font.Texture.Height, Color.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw provided text with laoded font, containing all required codepoint glyphs
|
||||
DrawTextEx(font, text, new Vector2(160, 110), 48, 5, Color.Black);
|
||||
}
|
||||
|
||||
DrawText("Press SPACE to toggle font atlas view!", 10, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
if (showFontAtlas)
|
||||
{
|
||||
// Draw generated font texture atlas containing provided codepoints
|
||||
DrawTexture(font.Texture, 150, 100, Color.Black);
|
||||
DrawRectangleLines(150, 100, font.Texture.Width, font.Texture.Height, Color.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw provided text with loaded font, containing all required codepoint glyphs
|
||||
DrawTextEx(font, text, new Vector2(160, 110), 48, 5, Color.Black);
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(font);
|
||||
DrawText("Press SPACE to toggle font atlas view!", 10, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
return 0;
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(font); // Unload font
|
||||
}
|
||||
|
||||
private static List<int> GetCodePoints(string text)
|
||||
|
|
@ -119,14 +120,42 @@ class CodepointsLoading
|
|||
List<int> codePoints = new();
|
||||
|
||||
StringInfo stringInfo = new(text);
|
||||
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(text);
|
||||
var enumerator = StringInfo.GetTextElementEnumerator(text);
|
||||
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
int codePoint = char.ConvertToUtf32(enumerator.Current.ToString(), 0);
|
||||
var codePoint = char.ConvertToUtf32(enumerator.Current.ToString(), 0);
|
||||
codePoints.Add(codePoint);
|
||||
}
|
||||
|
||||
return codePoints;
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - codepoints loading");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new CodepointsLoading();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Font filters
|
||||
* raylib [text] example - font filters
|
||||
*
|
||||
* After font loading, font texture atlas filter could be configured for a softer
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: After font loading, font texture atlas filter could be configured for a softer
|
||||
* display of the font when scaling it to different sizes, that way, it's not required
|
||||
* to generate multiple fonts at multiple sizes (as long as the scaling is not very different)
|
||||
*
|
||||
* This example has been created using raylib 1.3.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.2
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -18,129 +22,164 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class FontFilters
|
||||
public partial class FontFilters : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Font Filters";
|
||||
|
||||
public string Title => "raylib [text] example - font filters";
|
||||
|
||||
private string msg;
|
||||
private Font font;
|
||||
private float fontSize;
|
||||
private Vector2 fontPosition;
|
||||
private Vector2 textSize;
|
||||
private TextureFilter currentFontFilter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters");
|
||||
|
||||
string msg = "Loaded Font";
|
||||
msg = "Loaded Font";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
// TTF Font loading with custom generation parameters
|
||||
Font font = LoadFontEx("resources/fonts/KAISG.ttf", 96, null, 0);
|
||||
font = LoadFontEx("resources/fonts/KAISG.ttf", 96, null, 0);
|
||||
|
||||
// Generate mipmap levels to use trilinear filtering
|
||||
// NOTE: On 2D drawing it won't be noticeable, it looks like TEXTURE_FILTER_BILINEAR
|
||||
// NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR
|
||||
GenTextureMipmaps(ref font.Texture);
|
||||
|
||||
float fontSize = font.BaseSize;
|
||||
Vector2 fontPosition = new(40, screenHeight / 2 - 80);
|
||||
Vector2 textSize = new(0.0f, 0.0f);
|
||||
fontSize = font.BaseSize;
|
||||
fontPosition = new(40, screenHeight / 2 - 80);
|
||||
textSize = new(0.0f, 0.0f);
|
||||
|
||||
// Setup texture scaling filter
|
||||
SetTextureFilter(font.Texture, TextureFilter.Point);
|
||||
TextureFilter currentFontFilter = TextureFilter.Point;
|
||||
currentFontFilter = TextureFilter.Point; // TEXTURE_FILTER_POINT
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
fontSize += GetMouseWheelMove() * 4.0f;
|
||||
|
||||
// Choose font texture filter method
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
SetTextureFilter(font.Texture, TextureFilter.Point);
|
||||
currentFontFilter = TextureFilter.Point;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
SetTextureFilter(font.Texture, TextureFilter.Bilinear);
|
||||
currentFontFilter = TextureFilter.Bilinear;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
// NOTE: Trilinear filter won't be noticed on 2D drawing
|
||||
SetTextureFilter(font.Texture, TextureFilter.Trilinear);
|
||||
currentFontFilter = TextureFilter.Trilinear;
|
||||
}
|
||||
|
||||
textSize = MeasureTextEx(font, msg, fontSize, 0);
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
fontPosition.X -= 10;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
fontPosition.X += 10;
|
||||
}
|
||||
|
||||
#if BROWSER
|
||||
// NOTE: drag-and-drop font loading is not supported in the browser host; default loaded font is kept.
|
||||
#else
|
||||
// Load a dropped TTF file dynamically (at current fontSize)
|
||||
if (IsFileDropped())
|
||||
{
|
||||
var files = Raylib.GetDroppedFiles();
|
||||
|
||||
// NOTE: We only support first ttf file dropped
|
||||
if (IsFileExtension(files[0], ".ttf"))
|
||||
{
|
||||
UnloadFont(font);
|
||||
font = LoadFontEx(files[0], (int)fontSize, null, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Use mouse wheel to change font size", 20, 20, 10, Color.Gray);
|
||||
DrawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, Color.Gray);
|
||||
DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, Color.Gray);
|
||||
DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, Color.DarkGray);
|
||||
|
||||
DrawTextEx(font, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
|
||||
// TODO: It seems texSize measurement is not accurate due to chars offsets...
|
||||
//DrawRectangleLines((int)fontPosition.X, (int)fontPosition.Y, (int)textSize.X, (int)textSize.Y, Color.Red);
|
||||
|
||||
DrawRectangle(0, screenHeight - 80, screenWidth, 80, Color.LightGray);
|
||||
DrawText($"Font size: {fontSize:00.00}", 20, screenHeight - 50, 10, Color.DarkGray);
|
||||
DrawText($"Text size: [{textSize.X:00.00}, {textSize.Y:00.00}]", 20, screenHeight - 30, 10, Color.DarkGray);
|
||||
DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, Color.Gray);
|
||||
|
||||
if (currentFontFilter == TextureFilter.Point)
|
||||
{
|
||||
DrawText("POINT", 570, 400, 20, Color.Black);
|
||||
}
|
||||
else if (currentFontFilter == TextureFilter.Bilinear)
|
||||
{
|
||||
DrawText("BILINEAR", 570, 400, 20, Color.Black);
|
||||
}
|
||||
else if (currentFontFilter == TextureFilter.Trilinear)
|
||||
{
|
||||
DrawText("TRILINEAR", 570, 400, 20, Color.Black);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(font); // Font unloading
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new FontFilters();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
fontSize += GetMouseWheelMove() * 4.0f;
|
||||
|
||||
// Choose font texture filter method
|
||||
if (IsKeyPressed(KeyboardKey.One))
|
||||
{
|
||||
SetTextureFilter(font.Texture, TextureFilter.Point);
|
||||
currentFontFilter = TextureFilter.Point;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Two))
|
||||
{
|
||||
SetTextureFilter(font.Texture, TextureFilter.Bilinear);
|
||||
currentFontFilter = TextureFilter.Bilinear;
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Three))
|
||||
{
|
||||
// NOTE: Trilinear filter won't be noticed on 2D drawing
|
||||
SetTextureFilter(font.Texture, TextureFilter.Trilinear);
|
||||
currentFontFilter = TextureFilter.Trilinear;
|
||||
}
|
||||
|
||||
textSize = MeasureTextEx(font, msg, fontSize, 0);
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Left))
|
||||
{
|
||||
fontPosition.X -= 10;
|
||||
}
|
||||
else if (IsKeyDown(KeyboardKey.Right))
|
||||
{
|
||||
fontPosition.X += 10;
|
||||
}
|
||||
|
||||
// Load a dropped TTF file dynamically (at current fontSize)
|
||||
if (IsFileDropped())
|
||||
{
|
||||
string[] files = Raylib.GetDroppedFiles();
|
||||
|
||||
// NOTE: We only support first ttf file dropped
|
||||
if (IsFileExtension(files[0], ".ttf"))
|
||||
{
|
||||
UnloadFont(font);
|
||||
font = LoadFontEx(files[0], (int)fontSize, null, 0);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Use mouse wheel to change font size", 20, 20, 10, Color.Gray);
|
||||
DrawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, Color.Gray);
|
||||
DrawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, Color.Gray);
|
||||
DrawText("Drop a new TTF font for dynamic loading", 20, 80, 10, Color.DarkGray);
|
||||
|
||||
DrawTextEx(font, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
|
||||
DrawRectangle(0, screenHeight - 80, screenWidth, 80, Color.LightGray);
|
||||
DrawText("CURRENT TEXTURE FILTER:", 250, 400, 20, Color.Gray);
|
||||
|
||||
if (currentFontFilter == TextureFilter.Point)
|
||||
{
|
||||
DrawText("POINT", 570, 400, 20, Color.Black);
|
||||
}
|
||||
else if (currentFontFilter == TextureFilter.Point)
|
||||
{
|
||||
DrawText("BILINEAR", 570, 400, 20, Color.Black);
|
||||
}
|
||||
else if (currentFontFilter == TextureFilter.Trilinear)
|
||||
{
|
||||
DrawText("TRILINEAR", 570, 400, 20, Color.Black);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(font);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,24 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Font loading
|
||||
* raylib [text] example - font loading
|
||||
*
|
||||
* raylib can load fonts from multiple file formats:
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: raylib can load fonts from multiple input file formats:
|
||||
*
|
||||
* - TTF/OTF > Sprite font atlas is generated on loading, user can configure
|
||||
* some of the generation parameters (size, characters to include)
|
||||
* - BMFonts > Angel code font fileformat, sprite font image must be provided
|
||||
* together with the .fnt file, font generation cna not be configured
|
||||
* together with the .fnt file, font generation can not be configured
|
||||
* - XNA Spritefont > Sprite font image, following XNA Spritefont conventions,
|
||||
* Characters in image must follow some spacing and order rules
|
||||
*
|
||||
* This example has been created using raylib 2.6 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.4, last time updated with raylib 3.0
|
||||
*
|
||||
* Copyright (c) 2016-2019 Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -23,78 +27,105 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class FontLoading
|
||||
public partial class FontLoading : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Font Loading";
|
||||
|
||||
public string Title => "raylib [text] example - font loading";
|
||||
|
||||
private string msg;
|
||||
private Font fontBm;
|
||||
private Font fontTtf;
|
||||
private bool useTtf;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font loading");
|
||||
|
||||
// Define characters to draw
|
||||
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
||||
string msg = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||
msg = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
||||
Font fontBm = LoadFont("resources/fonts/pixantiqua.fnt");
|
||||
fontBm = LoadFont("resources/fonts/pixantiqua.fnt"); // Requires "resources/fonts/pixantiqua.png"
|
||||
|
||||
// TTF font : Font data and atlas are generated directly from TTF
|
||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||
Font fontTtf = LoadFontEx("resources/fonts/pixantiqua.ttf", 32, null, 250);
|
||||
fontTtf = LoadFontEx("resources/fonts/pixantiqua.ttf", 32, null, 250);
|
||||
|
||||
bool useTtf = false;
|
||||
SetTextLineSpacing(16); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||
|
||||
SetTargetFPS(60);
|
||||
useTtf = false;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
useTtf = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
useTtf = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Hold SPACE to use TTF generated font", 20, 20, 20, Color.LightGray);
|
||||
|
||||
if (!useTtf)
|
||||
{
|
||||
DrawTextEx(fontBm, msg, new Vector2(20.0f, 100.0f), fontBm.BaseSize, 2, Color.Maroon);
|
||||
DrawText("Using BMFont (Angelcode) imported", 20, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextEx(fontTtf, msg, new Vector2(20.0f, 100.0f), fontTtf.BaseSize, 2, Color.Lime);
|
||||
DrawText("Using TTF font generated", 20, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(fontBm); // AngelCode Font unloading
|
||||
UnloadFont(fontTtf); // TTF Font unloading
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font loading");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new FontLoading();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
useTtf = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
useTtf = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("Hold SPACE to use TTF generated font", 20, 20, 20, Color.LightGray);
|
||||
|
||||
if (!useTtf)
|
||||
{
|
||||
DrawTextEx(fontBm, msg, new Vector2(20.0f, 100.0f), fontBm.BaseSize, 2, Color.Maroon);
|
||||
DrawText("Using BMFont (Angelcode) imported", 20, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextEx(fontTtf, msg, new Vector2(20.0f, 100.0f), fontTtf.BaseSize, 2, Color.Lime);
|
||||
DrawText("Using TTF font generated", 20, GetScreenHeight() - 30, 20, Color.Gray);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(fontBm);
|
||||
UnloadFont(fontTtf);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - TTF loading and usage
|
||||
* raylib [text] example - font sdf
|
||||
*
|
||||
* This example has been created using raylib 1.3.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -16,23 +20,44 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class FontSdf
|
||||
public partial class FontSdf : IExample
|
||||
{
|
||||
public unsafe static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
public string Name => "Text / Font SDF";
|
||||
|
||||
public string Title => "raylib [text] example - font sdf";
|
||||
|
||||
private string msg;
|
||||
|
||||
private Font fontDefault;
|
||||
private Font fontSDF;
|
||||
private Shader shader;
|
||||
|
||||
private Vector2 fontPosition;
|
||||
private Vector2 textSize;
|
||||
private float fontSize;
|
||||
private int currentFont;
|
||||
|
||||
public unsafe void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts");
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
string msg = "Signed Distance Fields";
|
||||
|
||||
msg = "Signed Distance Fields";
|
||||
|
||||
// Loading file to memory
|
||||
int fileSize = 0;
|
||||
byte* fileData = LoadFileData("resources/fonts/anonymous_pro_bold.ttf", ref fileSize);
|
||||
var fileSize = 0;
|
||||
var fileData = LoadFileData("resources/fonts/anonymous_pro_bold.ttf", ref fileSize);
|
||||
|
||||
// Build the fonts in locals first: taking the address of a struct's field (&font.GlyphCount,
|
||||
// &font.Recs) is only allowed for a stack local, not a heap field. Assign to the fields after.
|
||||
|
||||
// Default font generation from TTF font
|
||||
Font fontDefault = new();
|
||||
|
|
@ -40,121 +65,141 @@ public class FontSdf
|
|||
fontDefault.GlyphCount = 95;
|
||||
|
||||
// Loading font data from memory data
|
||||
// Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array)
|
||||
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array)
|
||||
fontDefault.Glyphs = LoadFontData(fileData, (int)fileSize, 16, null, 95, FontType.Default, &fontDefault.GlyphCount);
|
||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default)
|
||||
Image atlas = GenImageFontAtlas(fontDefault.Glyphs, &fontDefault.Recs, 95, 16, 4, 0);
|
||||
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default)
|
||||
var atlas = GenImageFontAtlas(fontDefault.Glyphs, &fontDefault.Recs, 95, 16, 4, 0);
|
||||
fontDefault.Texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
this.fontDefault = fontDefault;
|
||||
|
||||
// SDF font generation from TTF font
|
||||
Font fontSDF = new();
|
||||
fontSDF.BaseSize = 16;
|
||||
fontSDF.GlyphCount = 95;
|
||||
// Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95)
|
||||
fontSDF.Glyphs = LoadFontData(fileData, (int)fileSize, 16, null, 0, FontType.Sdf, &fontDefault.GlyphCount);
|
||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm)
|
||||
// Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95)
|
||||
fontSDF.Glyphs = LoadFontData(fileData, (int)fileSize, 16, null, 0, FontType.Sdf, &fontSDF.GlyphCount);
|
||||
// Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm)
|
||||
atlas = GenImageFontAtlas(fontSDF.Glyphs, &fontSDF.Recs, 95, 16, 0, 1);
|
||||
fontSDF.Texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
this.fontSDF = fontSDF;
|
||||
|
||||
// Free memory from loaded file
|
||||
UnloadFileData(fileData);
|
||||
UnloadFileData(fileData); // Free memory from loaded file
|
||||
|
||||
// Load SDF required shader (we use default vertex shader)
|
||||
Shader shader = LoadShader(null, "resources/shaders/glsl330/sdf.fs");
|
||||
// Required for SDF font
|
||||
SetTextureFilter(fontSDF.Texture, TextureFilter.Bilinear);
|
||||
shader = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/sdf.fs");
|
||||
SetTextureFilter(fontSDF.Texture, TextureFilter.Bilinear); // Required for SDF font
|
||||
|
||||
Vector2 fontPosition = new(40, screenHeight / 2 - 50);
|
||||
Vector2 textSize = new(0.0f);
|
||||
float fontSize = 16.0f;
|
||||
// 0 - fontDefault, 1 - fontSDF
|
||||
int currentFont = 0;
|
||||
fontPosition = new(40, screenHeight / 2.0f - 50);
|
||||
textSize = new(0.0f);
|
||||
fontSize = 16.0f;
|
||||
currentFont = 0; // 0 - fontDefault, 1 - fontSDF
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
fontSize += GetMouseWheelMove() * 8.0f;
|
||||
|
||||
if (fontSize < 6)
|
||||
{
|
||||
fontSize = 6;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
currentFont = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentFont = 0;
|
||||
}
|
||||
|
||||
if (currentFont == 0)
|
||||
{
|
||||
textSize = MeasureTextEx(fontDefault, msg, fontSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textSize = MeasureTextEx(fontSDF, msg, fontSize, 0);
|
||||
}
|
||||
|
||||
fontPosition.X = GetScreenWidth() / 2 - textSize.X / 2;
|
||||
fontPosition.Y = GetScreenHeight() / 2 - textSize.Y / 2 + 80;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (currentFont == 1)
|
||||
{
|
||||
// NOTE: SDF fonts require a custom SDf shader to compute fragment color
|
||||
BeginShaderMode(shader); // Activate SDF font shader
|
||||
DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
EndShaderMode(); // Activate our default shader for next drawings
|
||||
|
||||
DrawTexture(fontSDF.Texture, 10, 10, Color.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
DrawTexture(fontDefault.Texture, 10, 10, Color.Black);
|
||||
}
|
||||
|
||||
if (currentFont == 1)
|
||||
{
|
||||
DrawText("SDF!", 320, 20, 80, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("default font", 315, 40, 30, Color.Gray);
|
||||
}
|
||||
|
||||
DrawText("FONT SIZE: 16.0", GetScreenWidth() - 240, 20, 20, Color.DarkGray);
|
||||
DrawText($"RENDER SIZE: {fontSize:00.00}", GetScreenWidth() - 240, 50, 20, Color.DarkGray);
|
||||
DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, Color.DarkGray);
|
||||
|
||||
DrawText("HOLD SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(fontDefault); // Default font unloading
|
||||
UnloadFont(fontSDF); // SDF font unloading
|
||||
|
||||
UnloadShader(shader); // Unload SDF shader
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font sdf");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new FontSdf();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
fontSize += GetMouseWheelMove() * 8.0f;
|
||||
|
||||
if (fontSize < 6)
|
||||
{
|
||||
fontSize = 6;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
currentFont = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentFont = 0;
|
||||
}
|
||||
|
||||
if (currentFont == 0)
|
||||
{
|
||||
textSize = MeasureTextEx(fontDefault, msg, fontSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
textSize = MeasureTextEx(fontSDF, msg, fontSize, 0);
|
||||
}
|
||||
|
||||
fontPosition.X = GetScreenWidth() / 2 - textSize.X / 2;
|
||||
fontPosition.Y = GetScreenHeight() / 2 - textSize.Y / 2 + 80;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
if (currentFont == 1)
|
||||
{
|
||||
// NOTE: SDF fonts require a custom SDf shader to compute fragment color
|
||||
BeginShaderMode(shader);
|
||||
DrawTextEx(fontSDF, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
EndShaderMode();
|
||||
|
||||
DrawTexture(fontSDF.Texture, 10, 10, Color.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextEx(fontDefault, msg, fontPosition, fontSize, 0, Color.Black);
|
||||
DrawTexture(fontDefault.Texture, 10, 10, Color.Black);
|
||||
}
|
||||
|
||||
if (currentFont == 1)
|
||||
{
|
||||
DrawText("SDF!", 320, 20, 80, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("default font", 315, 40, 30, Color.Gray);
|
||||
}
|
||||
|
||||
DrawText("FONT SIZE: 16.0", GetScreenWidth() - 240, 20, 20, Color.DarkGray);
|
||||
DrawText($"RENDER SIZE: {fontSize:2F}", GetScreenWidth() - 240, 50, 20, Color.DarkGray);
|
||||
DrawText("Use MOUSE WHEEL to SCALE TEXT!", GetScreenWidth() - 240, 90, 10, Color.DarkGray);
|
||||
|
||||
DrawText("PRESS SPACE to USE SDF FONT VERSION!", 340, GetScreenHeight() - 30, 20, Color.Maroon);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(fontDefault);
|
||||
UnloadFont(fontSDF);
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,25 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Sprite font loading
|
||||
* raylib [text] example - font spritefont
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: Sprite fonts should be generated following this conventions:
|
||||
*
|
||||
* Loaded sprite fonts have been generated following XNA SpriteFont conventions:
|
||||
* - Characters must be ordered starting with character 32 (Space)
|
||||
* - Every character must be contained within the same Rectangle height
|
||||
* - Every character and every line must be separated the same distance
|
||||
* - Rectangles must be defined by a magenta color background
|
||||
* - Every character and every line must be separated by the same distance (margin/padding)
|
||||
* - Rectangles must be defined by a MAGENTA color background
|
||||
*
|
||||
* If following this constraints, a font can be provided just by an image,
|
||||
* this is quite handy to avoid additional information files (like BMFonts use).
|
||||
* Following those constraints, a font can be provided just by an image,
|
||||
* this is quite handy to avoid additional font descriptor files (like BMFonts use)
|
||||
*
|
||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -23,72 +28,104 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class FontSpritefont
|
||||
public partial class FontSpritefont : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Font Spritefont";
|
||||
|
||||
public string Title => "raylib [text] example - font spritefont";
|
||||
|
||||
private string msg1;
|
||||
private string msg2;
|
||||
private string msg3;
|
||||
|
||||
private Font font1;
|
||||
private Font font2;
|
||||
private Font font3;
|
||||
|
||||
private Vector2 fontPosition1;
|
||||
private Vector2 fontPosition2;
|
||||
private Vector2 fontPosition3;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite font loading");
|
||||
|
||||
string msg1 = "THIS IS A custom SPRITE FONT...";
|
||||
string msg2 = "...and this is ANOTHER CUSTOM font...";
|
||||
string msg3 = "...and a THIRD one! GREAT! :D";
|
||||
msg1 = "THIS IS A custom SPRITE FONT...";
|
||||
msg2 = "...and this is ANOTHER CUSTOM font...";
|
||||
msg3 = "...and a THIRD one! GREAT! :D";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
Font font1 = LoadFont("resources/fonts/custom_mecha.png");
|
||||
Font font2 = LoadFont("resources/fonts/custom_alagard.png");
|
||||
Font font3 = LoadFont("resources/fonts/custom_jupiter_crash.png");
|
||||
font1 = LoadFont("resources/custom_mecha.png"); // Font loading
|
||||
font2 = LoadFont("resources/custom_alagard.png"); // Font loading
|
||||
font3 = LoadFont("resources/custom_jupiter_crash.png"); // Font loading
|
||||
|
||||
Vector2 fontPosition1 = new(
|
||||
fontPosition1 = new(
|
||||
screenWidth / 2 - MeasureTextEx(font1, msg1, font1.BaseSize, -3).X / 2,
|
||||
screenHeight / 2 - font1.BaseSize / 2 - 80
|
||||
);
|
||||
|
||||
Vector2 fontPosition2 = new(
|
||||
fontPosition2 = new(
|
||||
screenWidth / 2 - MeasureTextEx(font2, msg2, font2.BaseSize, -2).X / 2,
|
||||
screenHeight / 2 - font2.BaseSize / 2 - 10
|
||||
);
|
||||
|
||||
Vector2 fontPosition3 = new(
|
||||
fontPosition3 = new(
|
||||
screenWidth / 2 - MeasureTextEx(font3, msg3, font3.BaseSize, 2).X / 2,
|
||||
screenHeight / 2 - font3.BaseSize / 2 + 50
|
||||
);
|
||||
}
|
||||
|
||||
SetTargetFPS(60);
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update variables here...
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextEx(font1, msg1, fontPosition1, font1.BaseSize, -3, Color.White);
|
||||
DrawTextEx(font2, msg2, fontPosition2, font2.BaseSize, -2, Color.White);
|
||||
DrawTextEx(font3, msg3, fontPosition3, font3.BaseSize, 2, Color.White);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(font1); // Font unloading
|
||||
UnloadFont(font2); // Font unloading
|
||||
UnloadFont(font3); // Font unloading
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - font spritefont");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new FontSpritefont();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update variables here...
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawTextEx(font1, msg1, fontPosition1, font1.BaseSize, -3, Color.White);
|
||||
DrawTextEx(font2, msg2, fontPosition2, font2.BaseSize, -2, Color.White);
|
||||
DrawTextEx(font3, msg3, fontPosition3, font3.BaseSize, 2, Color.White);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(font1);
|
||||
UnloadFont(font2);
|
||||
UnloadFont(font3);
|
||||
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Text formatting
|
||||
* raylib [text] example - format text
|
||||
*
|
||||
* This example has been created using raylib 1.1 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 3.0
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -13,49 +17,72 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class FormatText
|
||||
public partial class FormatText : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Format Text";
|
||||
|
||||
public string Title => "raylib [text] example - format text";
|
||||
|
||||
private int score;
|
||||
private int hiscore;
|
||||
private int lives;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
score = 100020;
|
||||
hiscore = 200450;
|
||||
lives = 5;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText($"Score: {score:D8}", 200, 80, 20, Color.Red);
|
||||
|
||||
DrawText($"HiScore: {hiscore:D8}", 200, 120, 20, Color.Green);
|
||||
|
||||
DrawText($"Lives: {lives:D2}", 200, 160, 40, Color.Blue);
|
||||
|
||||
DrawText($"Elapsed Time: {GetFrameTime() * 1000:F2} ms", 200, 220, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - format text");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting");
|
||||
|
||||
int score = 100020;
|
||||
int hiscore = 200450;
|
||||
int lives = 5;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new FormatText();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText($"Score: {score}", 200, 80, 20, Color.Red);
|
||||
DrawText($"HiScore: {hiscore}", 200, 120, 20, Color.Green);
|
||||
DrawText($"Lives: {lives}", 200, 160, 40, Color.Blue);
|
||||
DrawText($"Elapsed Time: {GetFrameTime() * 1000} ms", 200, 220, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
312
Examples/Text/InlineStyling.cs
Normal file
312
Examples/Text/InlineStyling.cs
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - inline styling
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Wagner Barongello (@SultansOfCode) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Wagner Barongello (@SultansOfCode) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Raylib_cs;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class InlineStyling : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Inline Styling";
|
||||
|
||||
public string Title => "raylib [text] example - inline styling";
|
||||
|
||||
private Vector2 textSize; // Measure text box for provided font and text
|
||||
private Color colRandom; // Random color used on text
|
||||
private int frameCounter; // Used to generate a new random color every certain frames
|
||||
|
||||
public void Init()
|
||||
{
|
||||
textSize = new(0, 0);
|
||||
colRandom = Color.Red;
|
||||
frameCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
frameCounter++;
|
||||
|
||||
if ((frameCounter % 20) == 0)
|
||||
{
|
||||
colRandom.R = (byte)GetRandomValue(0, 255);
|
||||
colRandom.G = (byte)GetRandomValue(0, 255);
|
||||
colRandom.B = (byte)GetRandomValue(0, 255);
|
||||
colRandom.A = 255;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Text inline styling strategy used: [ ] delimiters for format
|
||||
// - Define foreground color: [cRRGGBBAA]
|
||||
// - Define background color: [bRRGGBBAA]
|
||||
// - Reset formating: [r]
|
||||
// Colors defined with [cRRGGBBAA] or [bRRGGBBAA] are multiplied by the base color alpha
|
||||
// This allows global transparency control while keeping per-section styling (ex. text fade effects)
|
||||
// Example: [bAA00AAFF][cFF0000FF]red text on gray background[r] normal text
|
||||
|
||||
DrawTextStyled(GetFontDefault(), "This changes the [cFF0000FF]foreground color[r] of provided text!!!",
|
||||
new Vector2(100, 80), 20.0f, 2.0f, Color.Black);
|
||||
|
||||
DrawTextStyled(GetFontDefault(), "This changes the [bFF00FFFF]background color[r] of provided text!!!",
|
||||
new Vector2(100, 120), 20.0f, 2.0f, Color.Black);
|
||||
|
||||
DrawTextStyled(GetFontDefault(), "This changes the [c00ff00ff][bff0000ff]foreground and background colors[r]!!!",
|
||||
new Vector2(100, 160), 20.0f, 2.0f, Color.Black);
|
||||
|
||||
DrawTextStyled(GetFontDefault(), "This changes the [c00ff00ff]alpha[r] relative [cffffffff][b000000ff]from source[r] [cff000088]color[r]!!!",
|
||||
new Vector2(100, 200), 20.0f, 2.0f, new Color(0, 0, 0, 100));
|
||||
|
||||
// Get pointer to formated text
|
||||
string text = $"Let's be [c{colRandom.R:x2}{colRandom.G:x2}{colRandom.B:x2}FF]CREATIVE[r] !!!";
|
||||
DrawTextStyled(GetFontDefault(), text, new Vector2(100, 240), 40.0f, 2.0f, Color.Black);
|
||||
|
||||
textSize = MeasureTextStyled(GetFontDefault(), text, 40.0f, 2.0f);
|
||||
DrawRectangleLines(100, 240, (int)textSize.X, (int)textSize.Y, Color.Green);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw text using inline styling
|
||||
// PARAM: color is the default text color, background color is BLANK by default
|
||||
// NOTE: Using input color as the base alpha multiplied to inline styles
|
||||
private static unsafe void DrawTextStyled(Font font, string text, Vector2 position, float fontSize, float spacing, Color color)
|
||||
{
|
||||
// Text inline styling strategy used: [ ] delimiters for format
|
||||
// - Define foreground color: [cRRGGBBAA]
|
||||
// - Define background color: [bRRGGBBAA]
|
||||
// - Reset formating: [r]
|
||||
// Example: [bAA00AAFF][cFF0000FF]red text on gray background[r] normal text
|
||||
|
||||
if (font.Texture.Id == 0)
|
||||
{
|
||||
font = GetFontDefault();
|
||||
}
|
||||
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
sbyte* t = textNative.AsPointer();
|
||||
int textLen = Encoding.UTF8.GetByteCount(text);
|
||||
|
||||
Color colFront = color;
|
||||
Color colBack = Color.Blank;
|
||||
int backRecPadding = 4; // Background rectangle padding
|
||||
|
||||
float textOffsetY = 0.0f;
|
||||
float textOffsetX = 0.0f;
|
||||
float textLineSpacing = 0.0f;
|
||||
float scaleFactor = fontSize / font.BaseSize;
|
||||
|
||||
for (int i = 0; i < textLen;)
|
||||
{
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepointNext(&t[i], &codepointByteCount);
|
||||
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
textOffsetY += (fontSize + textLineSpacing);
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codepoint == '[') // Process pipe styling
|
||||
{
|
||||
if (((i + 2) < textLen) && ((char)t[i + 1] == 'r') && ((char)t[i + 2] == ']')) // Reset styling
|
||||
{
|
||||
colFront = color;
|
||||
colBack = Color.Blank;
|
||||
|
||||
i += 3; // Skip "[r]"
|
||||
continue; // Do not draw characters
|
||||
}
|
||||
else if (((i + 1) < textLen) && (((char)t[i + 1] == 'c') || ((char)t[i + 1] == 'b')))
|
||||
{
|
||||
i += 2; // Skip "[c" or "[b" to start parsing color
|
||||
|
||||
// Parse following color
|
||||
var colHexText = new StringBuilder();
|
||||
int colHexCount = 0;
|
||||
while ((i + colHexCount < textLen) && (t[i + colHexCount] != 0) && ((char)t[i + colHexCount] != ']'))
|
||||
{
|
||||
char ch = (char)t[i + colHexCount];
|
||||
if (((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch <= 'F')) ||
|
||||
((ch >= 'a') && (ch <= 'f')))
|
||||
{
|
||||
colHexText.Append(ch);
|
||||
colHexCount++;
|
||||
}
|
||||
else break; // Only affects while loop
|
||||
}
|
||||
|
||||
// Convert hex color text into actual Color
|
||||
uint colHexValue = colHexText.Length > 0 ? Convert.ToUInt32(colHexText.ToString(), 16) : 0;
|
||||
if ((char)t[i - 1] == 'c')
|
||||
{
|
||||
colFront = GetColor(colHexValue);
|
||||
}
|
||||
else if ((char)t[i - 1] == 'b')
|
||||
{
|
||||
colBack = GetColor(colHexValue);
|
||||
}
|
||||
|
||||
i += (colHexCount + 1); // Skip color value retrieved and ']'
|
||||
continue; // Do not draw characters
|
||||
}
|
||||
}
|
||||
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
float increaseX = 0.0f;
|
||||
|
||||
if (font.Glyphs[index].AdvanceX == 0) increaseX = (font.Recs[index].Width * scaleFactor + spacing);
|
||||
else increaseX += (font.Glyphs[index].AdvanceX * scaleFactor + spacing);
|
||||
|
||||
// Draw background rectangle color (if required)
|
||||
if (colBack.A > 0) DrawRectangleRec(new Rectangle(position.X + textOffsetX, position.Y + textOffsetY - backRecPadding, increaseX, fontSize + 2 * backRecPadding), colBack);
|
||||
|
||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||
{
|
||||
DrawTextCodepoint(font, codepoint, new Vector2(position.X + textOffsetX, position.Y + textOffsetY), fontSize, colFront);
|
||||
}
|
||||
|
||||
textOffsetX += increaseX;
|
||||
}
|
||||
|
||||
i += codepointByteCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Measure inline styled text
|
||||
// NOTE: Measuring styled text requires skipping styling data
|
||||
// WARNING: Not considering line breaks
|
||||
private static unsafe Vector2 MeasureTextStyled(Font font, string text, float fontSize, float spacing)
|
||||
{
|
||||
Vector2 textSize = new(0, 0);
|
||||
|
||||
if ((font.Texture.Id == 0) || (text == null) || (text.Length == 0)) return textSize; // Security check
|
||||
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
sbyte* t = textNative.AsPointer();
|
||||
int textLen = Encoding.UTF8.GetByteCount(text); // Get size in bytes of text
|
||||
|
||||
float textWidth = 0.0f;
|
||||
float textHeight = fontSize;
|
||||
float scaleFactor = fontSize / (float)font.BaseSize;
|
||||
|
||||
int codepoint = 0; // Current character
|
||||
int index = 0; // Index position in sprite font
|
||||
int validCodepointCounter = 0;
|
||||
|
||||
for (int i = 0; i < textLen;)
|
||||
{
|
||||
int codepointByteCount = 0;
|
||||
codepoint = GetCodepointNext(&t[i], &codepointByteCount);
|
||||
|
||||
if (codepoint == '[') // Ignore pipe inline styling
|
||||
{
|
||||
if (((i + 2) < textLen) && ((char)t[i + 1] == 'r') && ((char)t[i + 2] == ']')) // Reset styling
|
||||
{
|
||||
i += 3; // Skip "[r]"
|
||||
continue; // Do not measure characters
|
||||
}
|
||||
else if (((i + 1) < textLen) && (((char)t[i + 1] == 'c') || ((char)t[i + 1] == 'b')))
|
||||
{
|
||||
i += 2; // Skip "[c" or "[b" to start parsing color
|
||||
|
||||
int colHexCount = 0;
|
||||
while ((i + colHexCount < textLen) && (t[i + colHexCount] != 0) && ((char)t[i + colHexCount] != ']'))
|
||||
{
|
||||
char ch = (char)t[i + colHexCount];
|
||||
if (((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch <= 'F')) ||
|
||||
((ch >= 'a') && (ch <= 'f')))
|
||||
{
|
||||
colHexCount++;
|
||||
}
|
||||
else break; // Only affects while loop
|
||||
}
|
||||
|
||||
i += (colHexCount + 1); // Skip color value retrieved and ']'
|
||||
continue; // Do not measure characters
|
||||
}
|
||||
}
|
||||
else if (codepoint != '\n')
|
||||
{
|
||||
index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
if (font.Glyphs[index].AdvanceX > 0) textWidth += font.Glyphs[index].AdvanceX;
|
||||
else textWidth += (font.Recs[index].Width + font.Glyphs[index].OffsetX);
|
||||
|
||||
validCodepointCounter++;
|
||||
i += codepointByteCount;
|
||||
}
|
||||
}
|
||||
|
||||
textSize.X = textWidth * scaleFactor + (validCodepointCounter - 1) * spacing;
|
||||
textSize.Y = textHeight;
|
||||
|
||||
return textSize;
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - inline styling");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InlineStyling();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Input Box
|
||||
* raylib [text] example - input box
|
||||
*
|
||||
* This example has been created using raylib 1.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2017 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.7, last time updated with raylib 3.5
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -13,149 +17,179 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class InputBox
|
||||
public partial class InputBox : IExample
|
||||
{
|
||||
public const int MaxInputChars = 9;
|
||||
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Input Box";
|
||||
|
||||
public string Title => "raylib [text] example - input box";
|
||||
|
||||
private char[] name;
|
||||
private int letterCount;
|
||||
|
||||
private Rectangle textBox;
|
||||
private bool mouseOnText;
|
||||
|
||||
private int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// NOTE: One extra space required for null terminator char '\0'
|
||||
name = new char[MaxInputChars + 1];
|
||||
letterCount = 0;
|
||||
|
||||
textBox = new(screenWidth / 2 - 100, 180, 225, 50);
|
||||
mouseOnText = false;
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (CheckCollisionPointRec(GetMousePosition(), textBox))
|
||||
{
|
||||
mouseOnText = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseOnText = false;
|
||||
}
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
// Set the window's cursor to the I-Beam
|
||||
SetMouseCursor(MouseCursor.IBeam);
|
||||
|
||||
// Get char pressed (unicode character) on the queue
|
||||
var key = GetCharPressed();
|
||||
|
||||
// Check if more characters have been pressed on the same frame
|
||||
while (key > 0)
|
||||
{
|
||||
// NOTE: Only allow keys in range [32..125]
|
||||
if ((key >= 32) && (key <= 125) && (letterCount < MaxInputChars))
|
||||
{
|
||||
name[letterCount] = (char)key;
|
||||
name[letterCount + 1] = '\0'; // Add null terminator at the end of the string
|
||||
letterCount++;
|
||||
}
|
||||
|
||||
key = GetCharPressed(); // Check next character in the queue
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Backspace))
|
||||
{
|
||||
letterCount -= 1;
|
||||
if (letterCount < 0)
|
||||
{
|
||||
letterCount = 0;
|
||||
}
|
||||
name[letterCount] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMouseCursor(MouseCursor.Default);
|
||||
}
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
framesCounter += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, Color.Gray);
|
||||
DrawRectangleRec(textBox, Color.LightGray);
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
DrawRectangleLines(
|
||||
(int)textBox.X,
|
||||
(int)textBox.Y,
|
||||
(int)textBox.Width,
|
||||
(int)textBox.Height,
|
||||
Color.Red
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLines(
|
||||
(int)textBox.X,
|
||||
(int)textBox.Y,
|
||||
(int)textBox.Width,
|
||||
(int)textBox.Height,
|
||||
Color.DarkGray
|
||||
);
|
||||
}
|
||||
|
||||
DrawText(new string(name), (int)textBox.X + 5, (int)textBox.Y + 8, 40, Color.Maroon);
|
||||
DrawText($"INPUT CHARS: {letterCount}/{MaxInputChars}", 315, 250, 20, Color.DarkGray);
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
if (letterCount < MaxInputChars)
|
||||
{
|
||||
// Draw blinking underscore char
|
||||
if ((framesCounter / 20 % 2) == 0)
|
||||
{
|
||||
DrawText(
|
||||
"_",
|
||||
(int)textBox.X + 8 + MeasureText(new string(name), 40),
|
||||
(int)textBox.Y + 12,
|
||||
40,
|
||||
Color.Maroon
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, Color.Gray);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - input box");
|
||||
|
||||
// NOTE: One extra space required for line ending char '\0'
|
||||
char[] name = new char[MaxInputChars];
|
||||
int letterCount = 0;
|
||||
|
||||
Rectangle textBox = new(screenWidth / 2 - 100, 180, 225, 50);
|
||||
bool mouseOnText = false;
|
||||
|
||||
int framesCounter = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new InputBox();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (CheckCollisionPointRec(GetMousePosition(), textBox))
|
||||
{
|
||||
mouseOnText = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseOnText = false;
|
||||
}
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
// Set the window's cursor to the I-Beam
|
||||
SetMouseCursor(MouseCursor.IBeam);
|
||||
|
||||
// Check if more characters have been pressed on the same frame
|
||||
int key = GetCharPressed();
|
||||
|
||||
while (key > 0)
|
||||
{
|
||||
// NOTE: Only allow keys in range [32..125]
|
||||
if ((key >= 32) && (key <= 125) && (letterCount < MaxInputChars))
|
||||
{
|
||||
name[letterCount] = (char)key;
|
||||
letterCount++;
|
||||
}
|
||||
|
||||
// Check next character in the queue
|
||||
key = GetCharPressed();
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Backspace))
|
||||
{
|
||||
letterCount -= 1;
|
||||
if (letterCount < 0)
|
||||
{
|
||||
letterCount = 0;
|
||||
}
|
||||
name[letterCount] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMouseCursor(MouseCursor.Default);
|
||||
}
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
framesCounter += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, Color.Gray);
|
||||
DrawRectangleRec(textBox, Color.LightGray);
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
DrawRectangleLines(
|
||||
(int)textBox.X,
|
||||
(int)textBox.Y,
|
||||
(int)textBox.Width,
|
||||
(int)textBox.Height,
|
||||
Color.Red
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLines(
|
||||
(int)textBox.X,
|
||||
(int)textBox.Y,
|
||||
(int)textBox.Width,
|
||||
(int)textBox.Height,
|
||||
Color.DarkGray
|
||||
);
|
||||
}
|
||||
|
||||
DrawText(new string(name), (int)textBox.X + 5, (int)textBox.Y + 8, 40, Color.Maroon);
|
||||
DrawText($"INPUT CHARS: {letterCount}/{MaxInputChars}", 315, 250, 20, Color.DarkGray);
|
||||
|
||||
if (mouseOnText)
|
||||
{
|
||||
if (letterCount < MaxInputChars)
|
||||
{
|
||||
// Draw blinking underscore char
|
||||
if ((framesCounter / 20 % 2) == 0)
|
||||
{
|
||||
DrawText(
|
||||
"_",
|
||||
(int)textBox.X + 8 + MeasureText(new string(name), 40),
|
||||
(int)textBox.Y + 12,
|
||||
40,
|
||||
Color.Maroon
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("Press BACKSPACE to delete chars...", 230, 300, 20, Color.Gray);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - raylib font loading and usage
|
||||
* raylib [text] example - sprite fonts
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: raylib is distributed with some free to use fonts (even for commercial pourposes!)
|
||||
* To view details and credits for those fonts, check raylib license file
|
||||
*
|
||||
* This example has been created using raylib 1.7 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example originally created with raylib 1.7, last time updated with raylib 3.7
|
||||
*
|
||||
* Copyright (c) 2017 Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2017-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -17,32 +21,38 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class RaylibFonts
|
||||
public partial class RaylibFonts : IExample
|
||||
{
|
||||
public const int MaxFonts = 8;
|
||||
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Raylib Fonts";
|
||||
|
||||
public string Title => "raylib [text] example - sprite fonts";
|
||||
|
||||
private Font[] fonts;
|
||||
private string[] messages;
|
||||
private int[] spacings;
|
||||
private Vector2[] positions;
|
||||
private Color[] colors;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts");
|
||||
|
||||
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
|
||||
Font[] fonts = new Font[MaxFonts];
|
||||
fonts = new Font[MaxFonts];
|
||||
|
||||
fonts[0] = LoadFont("resources/fonts/alagard.png");
|
||||
fonts[1] = LoadFont("resources/fonts/pixelplay.png");
|
||||
fonts[2] = LoadFont("resources/fonts/mecha.png");
|
||||
fonts[3] = LoadFont("resources/fonts/setback.png");
|
||||
fonts[4] = LoadFont("resources/fonts/romulus.png");
|
||||
fonts[5] = LoadFont("resources/fonts/pixantiqua.png");
|
||||
fonts[6] = LoadFont("resources/fonts/alpha_beta.png");
|
||||
fonts[7] = LoadFont("resources/fonts/jupiter_crash.png");
|
||||
fonts[0] = LoadFont("resources/sprite_fonts/alagard.png");
|
||||
fonts[1] = LoadFont("resources/sprite_fonts/pixelplay.png");
|
||||
fonts[2] = LoadFont("resources/sprite_fonts/mecha.png");
|
||||
fonts[3] = LoadFont("resources/sprite_fonts/setback.png");
|
||||
fonts[4] = LoadFont("resources/sprite_fonts/romulus.png");
|
||||
fonts[5] = LoadFont("resources/sprite_fonts/pixantiqua.png");
|
||||
fonts[6] = LoadFont("resources/sprite_fonts/alpha_beta.png");
|
||||
fonts[7] = LoadFont("resources/sprite_fonts/jupiter_crash.png");
|
||||
|
||||
string[] messages = new string[MaxFonts] {
|
||||
messages = new string[MaxFonts] {
|
||||
"ALAGARD FONT designed by Hewett Tsoi",
|
||||
"PIXELPLAY FONT designed by Aleksander Shevchuk",
|
||||
"MECHA FONT designed by Captain Falcon",
|
||||
|
|
@ -53,12 +63,12 @@ public class RaylibFonts
|
|||
"JUPITER_CRASH FONT designed by Brian Kent (AEnigma)"
|
||||
};
|
||||
|
||||
int[] spacings = new int[MaxFonts] { 2, 4, 8, 4, 3, 4, 4, 1 };
|
||||
Vector2[] positions = new Vector2[MaxFonts];
|
||||
spacings = new int[MaxFonts] { 2, 4, 8, 4, 3, 4, 4, 1 };
|
||||
positions = new Vector2[MaxFonts];
|
||||
|
||||
for (int i = 0; i < MaxFonts; i++)
|
||||
for (var i = 0; i < MaxFonts; i++)
|
||||
{
|
||||
float halfWidth = MeasureTextEx(fonts[i], messages[i], fonts[i].BaseSize * 2, spacings[i]).X / 2;
|
||||
var halfWidth = MeasureTextEx(fonts[i], messages[i], fonts[i].BaseSize * 2, spacings[i]).X / 2;
|
||||
positions[i].X = screenWidth / 2 - halfWidth;
|
||||
positions[i].Y = 60 + fonts[i].BaseSize + 45 * i;
|
||||
}
|
||||
|
|
@ -68,7 +78,7 @@ public class RaylibFonts
|
|||
positions[4].Y += 2;
|
||||
positions[7].Y -= 8;
|
||||
|
||||
Color[] colors = new Color[MaxFonts] {
|
||||
colors = new Color[MaxFonts] {
|
||||
Color.Maroon,
|
||||
Color.Orange,
|
||||
Color.DarkGreen,
|
||||
|
|
@ -78,44 +88,61 @@ public class RaylibFonts
|
|||
Color.Gold,
|
||||
Color.Red
|
||||
};
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
public void Update()
|
||||
{
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("free sprite fonts included with raylib", 220, 20, 20, Color.DarkGray);
|
||||
DrawLine(220, 50, 600, 50, Color.DarkGray);
|
||||
|
||||
for (var i = 0; i < MaxFonts; i++)
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("free fonts included with raylib", 250, 20, 20, Color.DarkGray);
|
||||
DrawLine(220, 50, 590, 50, Color.DarkGray);
|
||||
|
||||
for (int i = 0; i < MaxFonts; i++)
|
||||
{
|
||||
DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].BaseSize * 2, spacings[i], colors[i]);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
DrawTextEx(fonts[i], messages[i], positions[i], fonts[i].BaseSize * 2, spacings[i], colors[i]);
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < MaxFonts; i++)
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
// Fonts unloading
|
||||
for (var i = 0; i < MaxFonts; i++)
|
||||
{
|
||||
UnloadFont(fonts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CloseWindow();
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - sprite fonts");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new RaylibFonts();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,153 +1,172 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - rectangle bounds
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2018-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class RectangleBounds
|
||||
public partial class RectangleBounds : IExample
|
||||
{
|
||||
public static int Main()
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// Minimum width and heigh for the container rectangle
|
||||
private const float minWidth = 60;
|
||||
private const float minHeight = 60;
|
||||
private const float maxWidth = screenWidth - 50.0f;
|
||||
private const float maxHeight = screenHeight - 160.0f;
|
||||
|
||||
public string Name => "Text / Rectangle Bounds";
|
||||
|
||||
public string Title => "raylib [text] example - rectangle bounds";
|
||||
|
||||
private string text;
|
||||
private bool resizing;
|
||||
private bool wordWrap;
|
||||
|
||||
private Rectangle container;
|
||||
private Rectangle resizer;
|
||||
|
||||
private Vector2 lastMouse;
|
||||
private Color borderColor;
|
||||
private Font font;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
text = "Text cannot escape\tthis container\t...word wrap also works when active so here's " +
|
||||
"a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod " +
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget.";
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle");
|
||||
resizing = false;
|
||||
wordWrap = true;
|
||||
|
||||
string text = "";
|
||||
text += "Text cannot escape this container ...word wrap also works when active so here's a long text for testing.";
|
||||
text += "\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ";
|
||||
text += "incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget.";
|
||||
|
||||
bool resizing = false;
|
||||
bool wordWrap = true;
|
||||
|
||||
Rectangle container = new(25, 25, screenWidth - 50, screenHeight - 250);
|
||||
Rectangle resizer = new(
|
||||
container = new(25.0f, 25.0f, screenWidth - 50.0f, screenHeight - 250.0f);
|
||||
resizer = new(
|
||||
container.X + container.Width - 17,
|
||||
container.Y + container.Height - 17,
|
||||
14,
|
||||
14
|
||||
);
|
||||
|
||||
// Minimum width and heigh for the container rectangle
|
||||
const int minWidth = 60;
|
||||
const int minHeight = 60;
|
||||
const int maxWidth = screenWidth - 50;
|
||||
const int maxHeight = screenHeight - 160;
|
||||
lastMouse = new(0.0f, 0.0f); // Stores last mouse coordinates
|
||||
borderColor = Color.Maroon; // Container border color
|
||||
font = GetFontDefault(); // Get default system font
|
||||
}
|
||||
|
||||
Vector2 lastMouse = new(0.0f, 0.0f);
|
||||
Color borderColor = Color.Maroon;
|
||||
Font font = GetFontDefault();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
wordWrap = !wordWrap;
|
||||
}
|
||||
|
||||
Vector2 mouse = GetMousePosition();
|
||||
|
||||
// Check if the mouse is inside the container and toggle border color
|
||||
if (CheckCollisionPointRec(mouse, container))
|
||||
{
|
||||
borderColor = ColorAlpha(Color.Maroon, 0.4f);
|
||||
}
|
||||
else if (!resizing)
|
||||
{
|
||||
borderColor = Color.Maroon;
|
||||
}
|
||||
|
||||
// Container resizing logic
|
||||
if (resizing)
|
||||
{
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
resizing = false;
|
||||
}
|
||||
|
||||
int width = (int)(container.Width + (mouse.X - lastMouse.X));
|
||||
container.Width = (width > minWidth) ? ((width < maxWidth) ? width : maxWidth) : minWidth;
|
||||
|
||||
int height = (int)(container.Height + (mouse.Y - lastMouse.Y));
|
||||
container.Height = (height > minHeight) ? ((height < maxHeight) ? height : maxHeight) : minHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we're resizing
|
||||
if (IsMouseButtonDown(MouseButton.Left) && CheckCollisionPointRec(mouse, resizer))
|
||||
{
|
||||
resizing = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move resizer rectangle properly
|
||||
resizer.X = container.X + container.Width - 17;
|
||||
resizer.Y = container.Y + container.Height - 17;
|
||||
|
||||
lastMouse = mouse; // Update mouse
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw container border
|
||||
DrawRectangleLinesEx(container, 3, borderColor);
|
||||
|
||||
// Draw text in container (add some padding)
|
||||
DrawTextBoxed(
|
||||
font,
|
||||
text,
|
||||
new Rectangle(container.X + 4, container.Y + 4, container.Width - 4, container.Height - 4),
|
||||
20.0f,
|
||||
2.0f,
|
||||
wordWrap,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawRectangleRec(resizer, borderColor);
|
||||
|
||||
// Draw bottom info
|
||||
DrawRectangle(0, screenHeight - 54, screenWidth, 54, Color.Gray);
|
||||
DrawRectangleRec(new Rectangle(382, screenHeight - 34, 12, 12), Color.Maroon);
|
||||
|
||||
DrawText("Word Wrap: ", 313, screenHeight - 115, 20, Color.Black);
|
||||
|
||||
if (wordWrap)
|
||||
{
|
||||
DrawText("ON", 447, screenHeight - 115, 20, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("OFF", 447, screenHeight - 115, 20, Color.Black);
|
||||
}
|
||||
|
||||
DrawText("Press [SPACE] to toggle word wrap", 218, screenHeight - 86, 20, Color.Gray);
|
||||
DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, Color.RayWhite);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
wordWrap = !wordWrap;
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
var mouse = GetMousePosition();
|
||||
|
||||
return 0;
|
||||
// Check if the mouse is inside the container and toggle border color
|
||||
if (CheckCollisionPointRec(mouse, container))
|
||||
{
|
||||
borderColor = Fade(Color.Maroon, 0.4f);
|
||||
}
|
||||
else if (!resizing)
|
||||
{
|
||||
borderColor = Color.Maroon;
|
||||
}
|
||||
|
||||
// Container resizing logic
|
||||
if (resizing)
|
||||
{
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
resizing = false;
|
||||
}
|
||||
|
||||
var width = container.Width + (mouse.X - lastMouse.X);
|
||||
container.Width = (width > minWidth) ? ((width < maxWidth) ? width : maxWidth) : minWidth;
|
||||
|
||||
var height = container.Height + (mouse.Y - lastMouse.Y);
|
||||
container.Height = (height > minHeight) ? ((height < maxHeight) ? height : maxHeight) : minHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we're resizing
|
||||
if (IsMouseButtonDown(MouseButton.Left) && CheckCollisionPointRec(mouse, resizer))
|
||||
{
|
||||
resizing = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move resizer rectangle properly
|
||||
resizer.X = container.X + container.Width - 17;
|
||||
resizer.Y = container.Y + container.Height - 17;
|
||||
|
||||
lastMouse = mouse; // Update mouse
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawRectangleLinesEx(container, 3, borderColor); // Draw container border
|
||||
|
||||
// Draw text in container (add some padding)
|
||||
DrawTextBoxed(
|
||||
font,
|
||||
text,
|
||||
new Rectangle(container.X + 4, container.Y + 4, container.Width - 4, container.Height - 4),
|
||||
20.0f,
|
||||
2.0f,
|
||||
wordWrap,
|
||||
Color.Gray
|
||||
);
|
||||
|
||||
DrawRectangleRec(resizer, borderColor); // Draw the resize box
|
||||
|
||||
// Draw bottom info
|
||||
DrawRectangle(0, screenHeight - 54, screenWidth, 54, Color.Gray);
|
||||
DrawRectangleRec(new Rectangle(382, screenHeight - 34, 12, 12), Color.Maroon);
|
||||
|
||||
DrawText("Word Wrap: ", 313, screenHeight - 115, 20, Color.Black);
|
||||
|
||||
if (wordWrap)
|
||||
{
|
||||
DrawText("ON", 447, screenHeight - 115, 20, Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText("OFF", 447, screenHeight - 115, 20, Color.Black);
|
||||
}
|
||||
|
||||
DrawText("Press [SPACE] to toggle word wrap", 218, screenHeight - 86, 20, Color.Gray);
|
||||
DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, Color.RayWhite);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
// Draw text using font inside rectangle limits
|
||||
static void DrawTextBoxed(
|
||||
private static void DrawTextBoxed(
|
||||
Font font,
|
||||
string text,
|
||||
Rectangle rec,
|
||||
|
|
@ -161,7 +180,7 @@ public class RectangleBounds
|
|||
}
|
||||
|
||||
// Draw text using font inside rectangle limits with support for text selection
|
||||
static unsafe void DrawTextBoxedSelectable(
|
||||
private static unsafe void DrawTextBoxedSelectable(
|
||||
Font font,
|
||||
string text,
|
||||
Rectangle rec,
|
||||
|
|
@ -175,37 +194,37 @@ public class RectangleBounds
|
|||
Color selectBackTint
|
||||
)
|
||||
{
|
||||
int length = text.Length;
|
||||
var length = text.Length;
|
||||
|
||||
// Offset between lines (on line break '\n')
|
||||
float textOffsetY = 0;
|
||||
|
||||
// Offset X to next character to draw
|
||||
float textOffsetX = 0.0f;
|
||||
var textOffsetX = 0.0f;
|
||||
|
||||
// Character rectangle scaling factor
|
||||
float scaleFactor = fontSize / (float)font.BaseSize;
|
||||
var scaleFactor = fontSize / (float)font.BaseSize;
|
||||
|
||||
// Word/character wrapping mechanism variables
|
||||
bool shouldMeasure = wordWrap;
|
||||
var shouldMeasure = wordWrap;
|
||||
|
||||
// Index where to begin drawing (where a line begins)
|
||||
int startLine = -1;
|
||||
var startLine = -1;
|
||||
|
||||
// Index where to stop drawing (where a line ends)
|
||||
int endLine = -1;
|
||||
var endLine = -1;
|
||||
|
||||
// Holds last value of the character position
|
||||
int lastk = -1;
|
||||
var lastk = -1;
|
||||
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
|
||||
for (int i = 0, k = 0; i < length; i++, k++)
|
||||
{
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepoint(&textNative.AsPointer()[i], &codepointByteCount);
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
var codepointByteCount = 0;
|
||||
var codepoint = GetCodepoint(&textNative.AsPointer()[i], &codepointByteCount);
|
||||
var index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
|
|
@ -275,7 +294,7 @@ public class RectangleBounds
|
|||
glyphWidth = 0;
|
||||
|
||||
// Save character position when we switch states
|
||||
int tmp = lastk;
|
||||
var tmp = lastk;
|
||||
lastk = k - 1;
|
||||
k = tmp;
|
||||
}
|
||||
|
|
@ -305,7 +324,7 @@ public class RectangleBounds
|
|||
}
|
||||
|
||||
// Draw selection background
|
||||
bool isGlyphSelected = false;
|
||||
var isGlyphSelected = false;
|
||||
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
|
||||
{
|
||||
DrawRectangleRec(
|
||||
|
|
@ -354,4 +373,32 @@ public class RectangleBounds
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - rectangle bounds");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new RectangleBounds();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
530
Examples/Text/StringsManagement.cs
Normal file
530
Examples/Text/StringsManagement.cs
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - strings management
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 David Buzatto (@davidbuzatto)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Raylib_cs;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class StringsManagement : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
private const int MaxTextLength = 100;
|
||||
private const int MaxTextParticles = 100;
|
||||
private const int FontSize = 30;
|
||||
|
||||
public string Name => "Text / Strings Management";
|
||||
|
||||
public string Title => "raylib [text] example - strings management";
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
private class TextParticle
|
||||
{
|
||||
public string Text;
|
||||
public Rectangle Rect; // Boundary
|
||||
public Vector2 Vel; // Velocity
|
||||
public Vector2 Ppos; // Previous position
|
||||
public float Padding;
|
||||
public float BorderWidth;
|
||||
public float Friction;
|
||||
public float Elasticity;
|
||||
public Color Color;
|
||||
public bool Grabbed;
|
||||
}
|
||||
|
||||
private List<TextParticle> textParticles;
|
||||
private TextParticle grabbedTextParticle;
|
||||
private Vector2 pressOffset;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
textParticles = new();
|
||||
grabbedTextParticle = null;
|
||||
pressOffset = new(0, 0);
|
||||
|
||||
PrepareFirstTextParticle("raylib => fun videogames programming!");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float delta = GetFrameTime();
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
|
||||
// Checks if a text particle was grabbed
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
for (int i = textParticles.Count - 1; i >= 0; i--)
|
||||
{
|
||||
TextParticle tp = textParticles[i];
|
||||
if (CheckCollisionPointRec(mousePos, tp.Rect))
|
||||
{
|
||||
pressOffset.X = mousePos.X - tp.Rect.X;
|
||||
pressOffset.Y = mousePos.Y - tp.Rect.Y;
|
||||
tp.Grabbed = true;
|
||||
grabbedTextParticle = tp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Releases any text particle the was grabbed
|
||||
if (IsMouseButtonReleased(MouseButton.Left))
|
||||
{
|
||||
if (grabbedTextParticle != null)
|
||||
{
|
||||
grabbedTextParticle.Grabbed = false;
|
||||
grabbedTextParticle = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Slice os shatter a text particle
|
||||
if (IsMouseButtonPressed(MouseButton.Right))
|
||||
{
|
||||
for (int i = textParticles.Count - 1; i >= 0; i--)
|
||||
{
|
||||
TextParticle tp = textParticles[i];
|
||||
if (CheckCollisionPointRec(mousePos, tp.Rect))
|
||||
{
|
||||
if (IsKeyDown(KeyboardKey.LeftShift))
|
||||
{
|
||||
ShatterTextParticle(tp, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
SliceTextParticle(tp, i, tp.Text.Length / 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shake text particles
|
||||
if (IsMouseButtonPressed(MouseButton.Middle))
|
||||
{
|
||||
for (int i = 0; i < textParticles.Count; i++)
|
||||
{
|
||||
if (!textParticles[i].Grabbed)
|
||||
{
|
||||
textParticles[i].Vel = new Vector2(GetRandomValue(-2000, 2000), GetRandomValue(-2000, 2000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset using TextTo* functions
|
||||
if (IsKeyPressed(KeyboardKey.One)) PrepareFirstTextParticle("raylib => fun videogames programming!");
|
||||
if (IsKeyPressed(KeyboardKey.Two)) PrepareFirstTextParticle(TextToUpper("raylib => fun videogames programming!"));
|
||||
if (IsKeyPressed(KeyboardKey.Three)) PrepareFirstTextParticle(TextToLower("raylib => fun videogames programming!"));
|
||||
if (IsKeyPressed(KeyboardKey.Four)) PrepareFirstTextParticle(TextToPascal("raylib_fun_videogames_programming"));
|
||||
if (IsKeyPressed(KeyboardKey.Five)) PrepareFirstTextParticle(TextToSnake("RaylibFunVideogamesProgramming"));
|
||||
if (IsKeyPressed(KeyboardKey.Six)) PrepareFirstTextParticle(TextToCamel("raylib_fun_videogames_programming"));
|
||||
|
||||
// Slice by char pressed only when we have one text particle
|
||||
int charPressed = GetCharPressed();
|
||||
if ((charPressed >= 'A') && (charPressed <= 'z') && (textParticles.Count == 1))
|
||||
{
|
||||
SliceTextParticleByChar(textParticles[0], (char)charPressed);
|
||||
}
|
||||
|
||||
// Updates each text particle state
|
||||
for (int i = 0; i < textParticles.Count; i++)
|
||||
{
|
||||
TextParticle tp = textParticles[i];
|
||||
|
||||
// The text particle is not grabbed
|
||||
if (!tp.Grabbed)
|
||||
{
|
||||
// text particle repositioning using the velocity
|
||||
tp.Rect.X += tp.Vel.X * delta;
|
||||
tp.Rect.Y += tp.Vel.Y * delta;
|
||||
|
||||
// Does the text particle hit the screen right boundary?
|
||||
if ((tp.Rect.X + tp.Rect.Width) >= screenWidth)
|
||||
{
|
||||
tp.Rect.X = screenWidth - tp.Rect.Width; // Text particle repositioning
|
||||
tp.Vel.X = -tp.Vel.X * tp.Elasticity; // Elasticity makes the text particle lose 10% of its velocity on hit
|
||||
}
|
||||
// Does the text particle hit the screen left boundary?
|
||||
else if (tp.Rect.X <= 0)
|
||||
{
|
||||
tp.Rect.X = 0.0f;
|
||||
tp.Vel.X = -tp.Vel.X * tp.Elasticity;
|
||||
}
|
||||
|
||||
// The same for y axis
|
||||
if ((tp.Rect.Y + tp.Rect.Height) >= screenHeight)
|
||||
{
|
||||
tp.Rect.Y = screenHeight - tp.Rect.Height;
|
||||
tp.Vel.Y = -tp.Vel.Y * tp.Elasticity;
|
||||
}
|
||||
else if (tp.Rect.Y <= 0)
|
||||
{
|
||||
tp.Rect.Y = 0.0f;
|
||||
tp.Vel.Y = -tp.Vel.Y * tp.Elasticity;
|
||||
}
|
||||
|
||||
// Friction makes the text particle lose 1% of its velocity each frame
|
||||
tp.Vel.X = tp.Vel.X * tp.Friction;
|
||||
tp.Vel.Y = tp.Vel.Y * tp.Friction;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Text particle repositioning using the mouse position
|
||||
tp.Rect.X = mousePos.X - pressOffset.X;
|
||||
tp.Rect.Y = mousePos.Y - pressOffset.Y;
|
||||
|
||||
// While the text particle is grabbed, recalculates its velocity
|
||||
tp.Vel.X = (tp.Rect.X - tp.Ppos.X) / delta;
|
||||
tp.Vel.Y = (tp.Rect.Y - tp.Ppos.Y) / delta;
|
||||
tp.Ppos.X = tp.Rect.X;
|
||||
tp.Ppos.Y = tp.Rect.Y;
|
||||
|
||||
// Glue text particles when dragging and pressing left ctrl
|
||||
if (IsKeyDown(KeyboardKey.LeftControl))
|
||||
{
|
||||
for (int j = 0; j < textParticles.Count; j++)
|
||||
{
|
||||
if (textParticles[j] != grabbedTextParticle && grabbedTextParticle.Grabbed)
|
||||
{
|
||||
if (CheckCollisionRecs(grabbedTextParticle.Rect, textParticles[j].Rect))
|
||||
{
|
||||
GlueTextParticles(grabbedTextParticle, textParticles[j]);
|
||||
grabbedTextParticle = textParticles[textParticles.Count - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
for (int i = 0; i < textParticles.Count; i++)
|
||||
{
|
||||
TextParticle tp = textParticles[i];
|
||||
DrawRectangleRec(new Rectangle(tp.Rect.X - tp.BorderWidth, tp.Rect.Y - tp.BorderWidth, tp.Rect.Width + tp.BorderWidth * 2, tp.Rect.Height + tp.BorderWidth * 2), Color.Black);
|
||||
DrawRectangleRec(tp.Rect, tp.Color);
|
||||
DrawText(tp.Text, (int)(tp.Rect.X + tp.Padding), (int)(tp.Rect.Y + tp.Padding), FontSize, Color.Black);
|
||||
}
|
||||
|
||||
DrawText("grab a text particle by pressing with the mouse and throw it by releasing", 10, 10, 10, Color.DarkGray);
|
||||
DrawText("slice a text particle by pressing it with the mouse right button", 10, 30, 10, Color.DarkGray);
|
||||
DrawText("shatter a text particle keeping left shift pressed and pressing it with the mouse right button", 10, 50, 10, Color.DarkGray);
|
||||
DrawText("glue text particles by grabbing than and keeping left control pressed", 10, 70, 10, Color.DarkGray);
|
||||
DrawText("1 to 6 to reset", 10, 90, 10, Color.DarkGray);
|
||||
DrawText("when you have only one text particle, you can slice it by pressing a char", 10, 110, 10, Color.DarkGray);
|
||||
DrawText($"TEXT PARTICLE COUNT: {textParticles.Count}", 10, GetScreenHeight() - 30, 20, Color.Black);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
private void PrepareFirstTextParticle(string text)
|
||||
{
|
||||
TextParticle first = CreateTextParticle(
|
||||
text,
|
||||
GetScreenWidth() / 2.0f,
|
||||
GetScreenHeight() / 2.0f,
|
||||
Color.RayWhite
|
||||
);
|
||||
|
||||
textParticles.Clear();
|
||||
textParticles.Add(first);
|
||||
}
|
||||
|
||||
private static TextParticle CreateTextParticle(string text, float x, float y, Color color)
|
||||
{
|
||||
TextParticle tp = new()
|
||||
{
|
||||
Text = "",
|
||||
Rect = new Rectangle(x, y, 30, 30),
|
||||
Vel = new Vector2(GetRandomValue(-200, 200), GetRandomValue(-200, 200)),
|
||||
Ppos = new Vector2(0, 0),
|
||||
Padding = 5.0f,
|
||||
BorderWidth = 5.0f,
|
||||
Friction = 0.99f,
|
||||
Elasticity = 0.9f,
|
||||
Color = color,
|
||||
Grabbed = false
|
||||
};
|
||||
|
||||
// Emulate C TextCopy() into a fixed size buffer
|
||||
if (text.Length > MaxTextLength - 1)
|
||||
{
|
||||
text = text.Substring(0, MaxTextLength - 1);
|
||||
}
|
||||
tp.Text = text;
|
||||
|
||||
tp.Rect.Width = MeasureText(tp.Text, FontSize) + tp.Padding * 2;
|
||||
tp.Rect.Height = FontSize + tp.Padding * 2;
|
||||
return tp;
|
||||
}
|
||||
|
||||
private void SliceTextParticle(TextParticle tp, int particlePos, int sliceLength)
|
||||
{
|
||||
int length = tp.Text.Length;
|
||||
|
||||
if ((length > 1) && ((textParticles.Count + length) < MaxTextParticles))
|
||||
{
|
||||
for (int i = 0; i < length; i += sliceLength)
|
||||
{
|
||||
string text = sliceLength == 1 ? tp.Text[i].ToString() : Subtext(tp.Text, i, sliceLength);
|
||||
textParticles.Add(CreateTextParticle(
|
||||
text,
|
||||
tp.Rect.X + i * tp.Rect.Width / length,
|
||||
tp.Rect.Y,
|
||||
new Color(GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255)
|
||||
));
|
||||
}
|
||||
RealocateTextParticles(particlePos);
|
||||
}
|
||||
}
|
||||
|
||||
private void SliceTextParticleByChar(TextParticle tp, char charToSlice)
|
||||
{
|
||||
string[] tokens = tp.Text.Split(charToSlice);
|
||||
int tokenCount = tokens.Length;
|
||||
|
||||
if (tokenCount > 1)
|
||||
{
|
||||
int textLength = tp.Text.Length;
|
||||
for (int i = 0; i < textLength; i++)
|
||||
{
|
||||
if (tp.Text[i] == charToSlice)
|
||||
{
|
||||
textParticles.Add(CreateTextParticle(
|
||||
charToSlice.ToString(),
|
||||
tp.Rect.X,
|
||||
tp.Rect.Y,
|
||||
new Color(GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255)
|
||||
));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < tokenCount; i++)
|
||||
{
|
||||
int tokenLength = tokens[i].Length;
|
||||
textParticles.Add(CreateTextParticle(
|
||||
tokens[i],
|
||||
tp.Rect.X + i * tp.Rect.Width / tokenLength,
|
||||
tp.Rect.Y,
|
||||
new Color(GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255)
|
||||
));
|
||||
}
|
||||
RealocateTextParticles(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShatterTextParticle(TextParticle tp, int particlePos)
|
||||
{
|
||||
SliceTextParticle(tp, particlePos, 1);
|
||||
}
|
||||
|
||||
private void GlueTextParticles(TextParticle grabbed, TextParticle target)
|
||||
{
|
||||
int p1 = textParticles.IndexOf(grabbed);
|
||||
int p2 = textParticles.IndexOf(target);
|
||||
|
||||
if ((p1 != -1) && (p2 != -1))
|
||||
{
|
||||
TextParticle tp = CreateTextParticle(
|
||||
grabbed.Text + target.Text,
|
||||
grabbed.Rect.X,
|
||||
grabbed.Rect.Y,
|
||||
Color.RayWhite
|
||||
);
|
||||
tp.Grabbed = true;
|
||||
textParticles.Add(tp);
|
||||
grabbed.Grabbed = false;
|
||||
if (p1 < p2)
|
||||
{
|
||||
RealocateTextParticles(p2);
|
||||
RealocateTextParticles(p1);
|
||||
}
|
||||
else
|
||||
{
|
||||
RealocateTextParticles(p1);
|
||||
RealocateTextParticles(p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RealocateTextParticles(int particlePos)
|
||||
{
|
||||
textParticles.RemoveAt(particlePos);
|
||||
}
|
||||
|
||||
// Extract a substring, clamping length to the available characters (like raylib TextSubtext)
|
||||
private static string Subtext(string text, int position, int length)
|
||||
{
|
||||
if (position >= text.Length)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int maxLength = text.Length - position;
|
||||
if (length > maxLength)
|
||||
{
|
||||
length = maxLength;
|
||||
}
|
||||
|
||||
return text.Substring(position, length);
|
||||
}
|
||||
|
||||
// C# equivalents of raylib TextTo* helpers (behaviour kept identical)
|
||||
private static string TextToUpper(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text.Length);
|
||||
foreach (char c in text)
|
||||
{
|
||||
sb.Append((c >= 'a' && c <= 'z') ? (char)(c - 32) : c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string TextToLower(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text.Length);
|
||||
foreach (char c in text)
|
||||
{
|
||||
sb.Append((c >= 'A' && c <= 'Z') ? (char)(c + 32) : c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string TextToPascal(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text.Length);
|
||||
|
||||
if (text.Length > 0)
|
||||
{
|
||||
sb.Append(char.ToUpperInvariant(text[0]));
|
||||
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '_' && (i + 1) < text.Length)
|
||||
{
|
||||
sb.Append(char.ToUpperInvariant(text[i + 1]));
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(text[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string TextToSnake(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text.Length);
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
char c = text[i];
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
sb.Append('_');
|
||||
}
|
||||
sb.Append((char)(c + 32));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string TextToCamel(string text)
|
||||
{
|
||||
var sb = new StringBuilder(text.Length);
|
||||
|
||||
if (text.Length > 0)
|
||||
{
|
||||
sb.Append(char.ToLowerInvariant(text[0]));
|
||||
|
||||
for (int i = 1; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '_' && (i + 1) < text.Length)
|
||||
{
|
||||
sb.Append(char.ToUpperInvariant(text[i + 1]));
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(text[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - strings management");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new StringsManagement();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
739
Examples/Text/Text3D.cs
Normal file
739
Examples/Text/Text3D.cs
Normal file
|
|
@ -0,0 +1,739 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - 3d drawing
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set)
|
||||
* where the texture coodinates of each quad map to the texture coordinates of the glyphs
|
||||
* inside the font texture
|
||||
*
|
||||
* A more efficient approach, i believe, would be to render the text in a render texture and
|
||||
* map that texture to a plane and render that, or maybe a shader but my method allows more
|
||||
* flexibility...for example to change position of each letter individually to make somethink
|
||||
* like a wavy text effect
|
||||
*
|
||||
* Special thanks to:
|
||||
* @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle
|
||||
* Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader
|
||||
*
|
||||
* Example originally created with raylib 3.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2021-2025 Vlad Adrian (@demizdor)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Raylib_cs;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class Text3D : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
#if BROWSER
|
||||
const int GlslVersion = 100; // WebGL1 needs GLSL ES 100
|
||||
#else
|
||||
private const int GlslVersion = 330;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global variables
|
||||
//--------------------------------------------------------------------------------------
|
||||
private const float LetterBoundrySize = 0.25f;
|
||||
private const int TextMaxLayers = 32;
|
||||
private static readonly Color LetterBoundryColor = Color.Violet;
|
||||
|
||||
private bool showLetterBoundry;
|
||||
private bool showTextBoundry;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Configuration structure for waving the text
|
||||
private struct WaveTextConfig
|
||||
{
|
||||
public Vector3 WaveRange;
|
||||
public Vector3 WaveSpeed;
|
||||
public Vector3 WaveOffset;
|
||||
}
|
||||
|
||||
public string Name => "Text / Text 3D";
|
||||
|
||||
public string Title => "raylib [text] example - 3d drawing";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint | ConfigFlags.VSyncHint;
|
||||
|
||||
public bool CursorDisabled => true;
|
||||
|
||||
private bool spin; // Spin the camera?
|
||||
private bool multicolor; // Multicolor mode
|
||||
|
||||
private Camera3D camera;
|
||||
private CameraMode cameraMode;
|
||||
|
||||
private Vector3 cubePosition;
|
||||
private Vector3 cubeSize;
|
||||
|
||||
private Font font;
|
||||
private float fontSize;
|
||||
private float fontSpacing;
|
||||
private float lineSpacing;
|
||||
|
||||
private string text;
|
||||
private Vector3 tbox;
|
||||
private int layers;
|
||||
private int quads;
|
||||
private float layerDistance;
|
||||
|
||||
private WaveTextConfig wcfg;
|
||||
private float time;
|
||||
|
||||
private Color light;
|
||||
private Color dark;
|
||||
|
||||
private Shader alphaDiscard;
|
||||
private Color[] multi;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
spin = true; // Spin the camera?
|
||||
multicolor = false; // Multicolor mode
|
||||
showLetterBoundry = false;
|
||||
showTextBoundry = false;
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
camera = new();
|
||||
camera.Position = new Vector3(-10.0f, 15.0f, -10.0f); // Camera position
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera projection type
|
||||
|
||||
cameraMode = CameraMode.Orbital;
|
||||
|
||||
cubePosition = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
cubeSize = new Vector3(2.0f, 2.0f, 2.0f);
|
||||
|
||||
// Use the default font
|
||||
font = GetFontDefault();
|
||||
fontSize = 0.8f;
|
||||
fontSpacing = 0.05f;
|
||||
lineSpacing = -0.1f;
|
||||
|
||||
// Set the text (using markdown!)
|
||||
text = "Hello ~~World~~ in 3D!";
|
||||
tbox = new Vector3(0, 0, 0);
|
||||
layers = 1;
|
||||
quads = 0;
|
||||
layerDistance = 0.01f;
|
||||
|
||||
wcfg = new WaveTextConfig();
|
||||
wcfg.WaveSpeed.X = wcfg.WaveSpeed.Y = 3.0f; wcfg.WaveSpeed.Z = 0.5f;
|
||||
wcfg.WaveOffset.X = wcfg.WaveOffset.Y = wcfg.WaveOffset.Z = 0.35f;
|
||||
wcfg.WaveRange.X = wcfg.WaveRange.Y = wcfg.WaveRange.Z = 0.45f;
|
||||
|
||||
time = 0.0f;
|
||||
|
||||
// Setup a light and dark color
|
||||
light = Color.Maroon;
|
||||
dark = Color.Red;
|
||||
|
||||
// Load the alpha discard shader
|
||||
alphaDiscard = LoadShader(null, $"resources/shaders/glsl{GlslVersion}/alpha_discard.fs");
|
||||
|
||||
// Array filled with multiple random colors (when multicolor mode is set)
|
||||
multi = new Color[TextMaxLayers];
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(ref camera, cameraMode);
|
||||
|
||||
// Handle font files dropped
|
||||
if (IsFileDropped())
|
||||
{
|
||||
string[] droppedFiles = GetDroppedFiles();
|
||||
|
||||
// NOTE: We only support first ttf file dropped
|
||||
if (IsFileExtension(droppedFiles[0], ".ttf"))
|
||||
{
|
||||
UnloadFont(font);
|
||||
font = LoadFontEx(droppedFiles[0], (int)fontSize, null, 0);
|
||||
}
|
||||
else if (IsFileExtension(droppedFiles[0], ".fnt"))
|
||||
{
|
||||
UnloadFont(font);
|
||||
font = LoadFont(droppedFiles[0]);
|
||||
fontSize = (float)font.BaseSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Events
|
||||
if (IsKeyPressed(KeyboardKey.F1)) showLetterBoundry = !showLetterBoundry;
|
||||
if (IsKeyPressed(KeyboardKey.F2)) showTextBoundry = !showTextBoundry;
|
||||
if (IsKeyPressed(KeyboardKey.F3))
|
||||
{
|
||||
// Handle camera change
|
||||
spin = !spin;
|
||||
// we need to reset the camera when changing modes
|
||||
camera = new();
|
||||
camera.Target = new Vector3(0.0f, 0.0f, 0.0f); // Camera looking at point
|
||||
camera.Up = new Vector3(0.0f, 1.0f, 0.0f); // Camera up vector (rotation towards target)
|
||||
camera.FovY = 45.0f; // Camera field-of-view Y
|
||||
camera.Projection = CameraProjection.Perspective; // Camera mode type
|
||||
|
||||
if (spin)
|
||||
{
|
||||
camera.Position = new Vector3(-10.0f, 15.0f, -10.0f); // Camera position
|
||||
cameraMode = CameraMode.Orbital;
|
||||
}
|
||||
else
|
||||
{
|
||||
camera.Position = new Vector3(10.0f, 10.0f, -10.0f); // Camera position
|
||||
cameraMode = CameraMode.Free;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicking the cube
|
||||
if (IsMouseButtonPressed(MouseButton.Left))
|
||||
{
|
||||
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
RayCollision collision = GetRayCollisionBox(ray,
|
||||
new BoundingBox(
|
||||
new Vector3(cubePosition.X - cubeSize.X / 2, cubePosition.Y - cubeSize.Y / 2, cubePosition.Z - cubeSize.Z / 2),
|
||||
new Vector3(cubePosition.X + cubeSize.X / 2, cubePosition.Y + cubeSize.Y / 2, cubePosition.Z + cubeSize.Z / 2)));
|
||||
if (collision.Hit)
|
||||
{
|
||||
// Generate new random colors
|
||||
light = GenerateRandomColor(0.5f, 0.78f);
|
||||
dark = GenerateRandomColor(0.4f, 0.58f);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle text layers changes
|
||||
if (IsKeyPressed(KeyboardKey.Home)) { if (layers > 1) --layers; }
|
||||
else if (IsKeyPressed(KeyboardKey.End)) { if (layers < TextMaxLayers) ++layers; }
|
||||
|
||||
// Handle text changes
|
||||
if (IsKeyPressed(KeyboardKey.Left)) fontSize -= 0.5f;
|
||||
else if (IsKeyPressed(KeyboardKey.Right)) fontSize += 0.5f;
|
||||
else if (IsKeyPressed(KeyboardKey.Up)) fontSpacing -= 0.1f;
|
||||
else if (IsKeyPressed(KeyboardKey.Down)) fontSpacing += 0.1f;
|
||||
else if (IsKeyPressed(KeyboardKey.PageUp)) lineSpacing -= 0.1f;
|
||||
else if (IsKeyPressed(KeyboardKey.PageDown)) lineSpacing += 0.1f;
|
||||
else if (IsKeyDown(KeyboardKey.Insert)) layerDistance -= 0.001f;
|
||||
else if (IsKeyDown(KeyboardKey.Delete)) layerDistance += 0.001f;
|
||||
else if (IsKeyPressed(KeyboardKey.Tab))
|
||||
{
|
||||
multicolor = !multicolor; // Enable /disable multicolor mode
|
||||
|
||||
if (multicolor)
|
||||
{
|
||||
// Fill color array with random colors
|
||||
for (int i = 0; i < TextMaxLayers; i++)
|
||||
{
|
||||
multi[i] = GenerateRandomColor(0.5f, 0.8f);
|
||||
multi[i].A = (byte)GetRandomValue(0, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle text input
|
||||
int ch = GetCharPressed();
|
||||
if (IsKeyPressed(KeyboardKey.Backspace))
|
||||
{
|
||||
// Remove last char
|
||||
if (text.Length > 0) text = text.Substring(0, text.Length - 1);
|
||||
}
|
||||
else if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
// handle newline
|
||||
if (text.Length < 63) text += '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
// append only printable chars
|
||||
if ((ch != 0) && (text.Length < 63)) text += char.ConvertFromUtf32(ch);
|
||||
}
|
||||
|
||||
// Measure 3D text so we can center it
|
||||
tbox = MeasureTextWave3D(font, text, fontSize, fontSpacing, lineSpacing);
|
||||
|
||||
quads = 0; // Reset quad counter
|
||||
time += GetFrameTime(); // Update timer needed by `DrawTextWave3D()`
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawCubeV(cubePosition, cubeSize, dark);
|
||||
DrawCubeWires(cubePosition, 2.1f, 2.1f, 2.1f, light);
|
||||
|
||||
DrawGrid(10, 2.0f);
|
||||
|
||||
// Use a shader to handle the depth buffer issue with transparent textures
|
||||
// NOTE: more info at https://bedroomcoders.co.uk/posts/198
|
||||
BeginShaderMode(alphaDiscard);
|
||||
|
||||
// Draw the 3D text above the red cube
|
||||
Rlgl.PushMatrix();
|
||||
Rlgl.Rotatef(90.0f, 1.0f, 0.0f, 0.0f);
|
||||
Rlgl.Rotatef(90.0f, 0.0f, 0.0f, -1.0f);
|
||||
|
||||
for (int i = 0; i < layers; i++)
|
||||
{
|
||||
Color clr = light;
|
||||
if (multicolor) clr = multi[i];
|
||||
DrawTextWave3D(font, text, new Vector3(-tbox.X / 2.0f, layerDistance * i, -4.5f), fontSize, fontSpacing, lineSpacing, true, wcfg, time, clr);
|
||||
}
|
||||
|
||||
// Draw the text boundry if set
|
||||
if (showTextBoundry) DrawCubeWiresV(new Vector3(0.0f, 0.0f, -4.5f + tbox.Z / 2), tbox, dark);
|
||||
Rlgl.PopMatrix();
|
||||
|
||||
// Don't draw the letter boundries for the 3D text below
|
||||
bool slb = showLetterBoundry;
|
||||
showLetterBoundry = false;
|
||||
|
||||
// Draw 3D options (use default font)
|
||||
//-------------------------------------------------------------------------
|
||||
Rlgl.PushMatrix();
|
||||
Rlgl.Rotatef(180.0f, 0.0f, 1.0f, 0.0f);
|
||||
string opt = $"< SIZE: {fontSize:0.0} >";
|
||||
quads += opt.Length;
|
||||
Vector2 m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
Vector3 pos = new(-m.X / 2.0f, 0.01f, 2.0f);
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.Blue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = $"< SPACING: {fontSpacing:0.0} >";
|
||||
quads += opt.Length;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.Blue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = $"< LINE: {lineSpacing:0.0} >";
|
||||
quads += opt.Length;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.Blue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = $"< LBOX: {(slb ? "ON" : "OFF"),3} >";
|
||||
quads += opt.Length;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.Red);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = $"< TBOX: {(showTextBoundry ? "ON" : "OFF"),3} >";
|
||||
quads += opt.Length;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.Red);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = $"< LAYER DISTANCE: {layerDistance:0.000} >";
|
||||
quads += opt.Length;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.8f, 0.1f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.8f, 0.1f, 0.0f, false, Color.DarkPurple);
|
||||
Rlgl.PopMatrix();
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Draw 3D info text (use default font)
|
||||
//-------------------------------------------------------------------------
|
||||
opt = "All the text displayed here is in 3D";
|
||||
quads += 36;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 1.0f, 0.05f);
|
||||
pos = new Vector3(-m.X / 2.0f, 0.01f, 2.0f);
|
||||
DrawText3D(GetFontDefault(), opt, pos, 1.0f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
pos.Z += 1.5f + m.Y;
|
||||
|
||||
opt = "press [Left]/[Right] to change the font size";
|
||||
quads += 44;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.6f, 0.05f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.6f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = "press [Up]/[Down] to change the font spacing";
|
||||
quads += 44;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.6f, 0.05f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.6f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = "press [PgUp]/[PgDown] to change the line spacing";
|
||||
quads += 48;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.6f, 0.05f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.6f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = "press [F1] to toggle the letter boundry";
|
||||
quads += 39;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.6f, 0.05f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.6f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
pos.Z += 0.5f + m.Y;
|
||||
|
||||
opt = "press [F2] to toggle the text boundry";
|
||||
quads += 37;
|
||||
m = MeasureTextEx(GetFontDefault(), opt, 0.6f, 0.05f);
|
||||
pos.X = -m.X / 2.0f;
|
||||
DrawText3D(GetFontDefault(), opt, pos, 0.6f, 0.05f, 0.0f, false, Color.DarkBlue);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
showLetterBoundry = slb;
|
||||
EndShaderMode();
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw 2D info text & stats
|
||||
//-------------------------------------------------------------------------
|
||||
DrawText("Drag & drop a font file to change the font!\nType something, see what happens!\n\n" +
|
||||
"Press [F3] to toggle the camera", 10, 35, 10, Color.Black);
|
||||
|
||||
quads += TextLengthUtf8(text) * 2 * layers;
|
||||
string tmp = $"{layers,2} layer(s) | {(spin ? "ORBITAL" : "FREE")} camera | {quads,4} quads ({quads * 4,4} verts)";
|
||||
int width = MeasureText(tmp, 10);
|
||||
DrawText(tmp, screenWidth - 20 - width, 10, 10, Color.DarkGreen);
|
||||
|
||||
tmp = "[Home]/[End] to add/remove 3D text layers";
|
||||
width = MeasureText(tmp, 10);
|
||||
DrawText(tmp, screenWidth - 20 - width, 25, 10, Color.DarkGray);
|
||||
|
||||
tmp = "[Insert]/[Delete] to increase/decrease distance between layers";
|
||||
width = MeasureText(tmp, 10);
|
||||
DrawText(tmp, screenWidth - 20 - width, 40, 10, Color.DarkGray);
|
||||
|
||||
tmp = "click the [CUBE] for a random color";
|
||||
width = MeasureText(tmp, 10);
|
||||
DrawText(tmp, screenWidth - 20 - width, 55, 10, Color.DarkGray);
|
||||
|
||||
tmp = "[Tab] to toggle multicolor mode";
|
||||
width = MeasureText(tmp, 10);
|
||||
DrawText(tmp, screenWidth - 20 - width, 70, 10, Color.DarkGray);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(font);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definitions
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Get the total length in bytes of a UTF-8 string (raylib TextLength equivalent)
|
||||
private static int TextLengthUtf8(string text)
|
||||
{
|
||||
return Encoding.UTF8.GetByteCount(text);
|
||||
}
|
||||
|
||||
// Draw codepoint at specified position in 3D space
|
||||
private unsafe void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint)
|
||||
{
|
||||
// Character index position in sprite font
|
||||
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
float scale = fontSize / (float)font.BaseSize;
|
||||
|
||||
// Character destination rectangle on screen
|
||||
// NOTE: We consider charsPadding on drawing
|
||||
position.X += (font.Glyphs[index].OffsetX - font.GlyphPadding) * scale;
|
||||
position.Z += (font.Glyphs[index].OffsetY - font.GlyphPadding) * scale;
|
||||
|
||||
// Character source rectangle from font texture atlas
|
||||
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
||||
Rectangle srcRec = new(font.Recs[index].X - font.GlyphPadding, font.Recs[index].Y - font.GlyphPadding,
|
||||
font.Recs[index].Width + 2.0f * font.GlyphPadding, font.Recs[index].Height + 2.0f * font.GlyphPadding);
|
||||
|
||||
float width = (font.Recs[index].Width + 2.0f * font.GlyphPadding) * scale;
|
||||
float height = (font.Recs[index].Height + 2.0f * font.GlyphPadding) * scale;
|
||||
|
||||
if (font.Texture.Id > 0)
|
||||
{
|
||||
const float x = 0.0f;
|
||||
const float y = 0.0f;
|
||||
const float z = 0.0f;
|
||||
|
||||
// normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f)
|
||||
float tx = srcRec.X / font.Texture.Width;
|
||||
float ty = srcRec.Y / font.Texture.Height;
|
||||
float tw = (srcRec.X + srcRec.Width) / font.Texture.Width;
|
||||
float th = (srcRec.Y + srcRec.Height) / font.Texture.Height;
|
||||
|
||||
if (showLetterBoundry) DrawCubeWiresV(new Vector3(position.X + width / 2, position.Y, position.Z + height / 2), new Vector3(width, LetterBoundrySize, height), LetterBoundryColor);
|
||||
|
||||
Rlgl.CheckRenderBatchLimit(4 + 4 * (backface ? 1 : 0));
|
||||
Rlgl.SetTexture(font.Texture.Id);
|
||||
|
||||
Rlgl.PushMatrix();
|
||||
Rlgl.Translatef(position.X, position.Y, position.Z);
|
||||
|
||||
Rlgl.Begin(DrawMode.Quads);
|
||||
Rlgl.Color4ub(tint.R, tint.G, tint.B, tint.A);
|
||||
|
||||
// Front Face
|
||||
Rlgl.Normal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
|
||||
Rlgl.TexCoord2f(tx, ty); Rlgl.Vertex3f(x, y, z); // Top Left Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tx, th); Rlgl.Vertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tw, th); Rlgl.Vertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tw, ty); Rlgl.Vertex3f(x + width, y, z); // Top Right Of The Texture and Quad
|
||||
|
||||
if (backface)
|
||||
{
|
||||
// Back Face
|
||||
Rlgl.Normal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
|
||||
Rlgl.TexCoord2f(tx, ty); Rlgl.Vertex3f(x, y, z); // Top Right Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tw, ty); Rlgl.Vertex3f(x + width, y, z); // Top Left Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tw, th); Rlgl.Vertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad
|
||||
Rlgl.TexCoord2f(tx, th); Rlgl.Vertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad
|
||||
}
|
||||
Rlgl.End();
|
||||
Rlgl.PopMatrix();
|
||||
|
||||
Rlgl.SetTexture(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a 2D text in 3D space
|
||||
private unsafe void DrawText3D(Font font, string text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint)
|
||||
{
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
sbyte* t = textNative.AsPointer();
|
||||
int length = Encoding.UTF8.GetByteCount(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scale = fontSize / (float)font.BaseSize;
|
||||
|
||||
for (int i = 0; i < length;)
|
||||
{
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepoint(&t[i], &codepointByteCount);
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepointByteCount = 1;
|
||||
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += fontSize + lineSpacing;
|
||||
textOffsetX = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||
{
|
||||
DrawTextCodepoint3D(font, codepoint, new Vector3(position.X + textOffsetX, position.Y, position.Z + textOffsetY), fontSize, backface, tint);
|
||||
}
|
||||
|
||||
if (font.Glyphs[index].AdvanceX == 0) textOffsetX += font.Recs[index].Width * scale + fontSpacing;
|
||||
else textOffsetX += font.Glyphs[index].AdvanceX * scale + fontSpacing;
|
||||
}
|
||||
|
||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a 2D text in 3D space and wave the parts that start with `~~` and end with `~~`
|
||||
// This is a modified version of the original code by @Nighten found here https://github.com/NightenDushi/Raylib_DrawTextStyle
|
||||
private unsafe void DrawTextWave3D(Font font, string text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, WaveTextConfig config, float time, Color tint)
|
||||
{
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
sbyte* t = textNative.AsPointer();
|
||||
int length = Encoding.UTF8.GetByteCount(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scale = fontSize / (float)font.BaseSize;
|
||||
|
||||
bool wave = false;
|
||||
|
||||
for (int i = 0, k = 0; i < length; ++k)
|
||||
{
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepoint(&t[i], &codepointByteCount);
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepointByteCount = 1;
|
||||
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
textOffsetY += fontSize + lineSpacing;
|
||||
textOffsetX = 0.0f;
|
||||
k = 0;
|
||||
}
|
||||
else if (codepoint == '~')
|
||||
{
|
||||
if (GetCodepoint(&t[i + 1], &codepointByteCount) == '~')
|
||||
{
|
||||
codepointByteCount += 1;
|
||||
wave = !wave;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||
{
|
||||
Vector3 pos = position;
|
||||
if (wave) // Apply the wave effect
|
||||
{
|
||||
pos.X += MathF.Sin(time * config.WaveSpeed.X - k * config.WaveOffset.X) * config.WaveRange.X;
|
||||
pos.Y += MathF.Sin(time * config.WaveSpeed.Y - k * config.WaveOffset.Y) * config.WaveRange.Y;
|
||||
pos.Z += MathF.Sin(time * config.WaveSpeed.Z - k * config.WaveOffset.Z) * config.WaveRange.Z;
|
||||
}
|
||||
|
||||
DrawTextCodepoint3D(font, codepoint, new Vector3(pos.X + textOffsetX, pos.Y, pos.Z + textOffsetY), fontSize, backface, tint);
|
||||
}
|
||||
|
||||
if (font.Glyphs[index].AdvanceX == 0) textOffsetX += font.Recs[index].Width * scale + fontSpacing;
|
||||
else textOffsetX += font.Glyphs[index].AdvanceX * scale + fontSpacing;
|
||||
}
|
||||
|
||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
||||
}
|
||||
}
|
||||
|
||||
// Measure a text in 3D ignoring the `~~` chars
|
||||
private unsafe Vector3 MeasureTextWave3D(Font font, string text, float fontSize, float fontSpacing, float lineSpacing)
|
||||
{
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
sbyte* t = textNative.AsPointer();
|
||||
int len = Encoding.UTF8.GetByteCount(text);
|
||||
int tempLen = 0; // Used to count longer text line num chars
|
||||
int lenCounter = 0;
|
||||
|
||||
float tempTextWidth = 0.0f; // Used to count longer text line width
|
||||
|
||||
float scale = fontSize / (float)font.BaseSize;
|
||||
float textHeight = scale;
|
||||
float textWidth = 0.0f;
|
||||
|
||||
int letter = 0; // Current character
|
||||
int index = 0; // Index position in sprite font
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
int next = 0;
|
||||
letter = GetCodepoint(&t[i], &next);
|
||||
index = GetGlyphIndex(font, letter);
|
||||
|
||||
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1
|
||||
if (letter == 0x3f) next = 1;
|
||||
i += next - 1;
|
||||
|
||||
if (letter != '\n')
|
||||
{
|
||||
if (letter == '~' && GetCodepoint(&t[i + 1], &next) == '~')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
lenCounter++;
|
||||
if (font.Glyphs[index].AdvanceX != 0) textWidth += font.Glyphs[index].AdvanceX * scale;
|
||||
else textWidth += (font.Recs[index].Width + font.Glyphs[index].OffsetX) * scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
lenCounter = 0;
|
||||
textWidth = 0.0f;
|
||||
textHeight += fontSize + lineSpacing;
|
||||
}
|
||||
|
||||
if (tempLen < lenCounter) tempLen = lenCounter;
|
||||
}
|
||||
|
||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||
|
||||
Vector3 vec = new(0, 0, 0);
|
||||
vec.X = tempTextWidth + ((tempLen - 1) * fontSpacing); // Adds chars spacing to measure
|
||||
vec.Y = 0.25f;
|
||||
vec.Z = textHeight;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
// Generates a nice color with a random hue
|
||||
private static Color GenerateRandomColor(float s, float v)
|
||||
{
|
||||
const float Phi = 0.618033988749895f; // Golden ratio conjugate
|
||||
float h = (float)GetRandomValue(0, 360);
|
||||
h = (h + h * Phi) % 360.0f;
|
||||
return ColorFromHSV(h, s, v);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint | ConfigFlags.VSyncHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - 3d drawing");
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Text3D();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,228 +1,226 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Using unicode with raylib
|
||||
* raylib [text] example - unicode emojis
|
||||
*
|
||||
* This example has been created using raylib 2.5 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Copyright (c) 2019 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2019-2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Raylib_cs;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Color;
|
||||
|
||||
namespace Examples.Text
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class Unicode : IExample
|
||||
{
|
||||
public class Unicode
|
||||
{
|
||||
const int EMOJI_PER_WIDTH = 8;
|
||||
const int EMOJI_PER_HEIGHT = 4;
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// String containing 180 emoji codepoints separated by a '\0' char
|
||||
string emojiCodepoints = @"\xF0\x9F\x8C\x80\x00\xF0\x9F\x98\x80\x00\xF0\x9F\x98\x82\x00\xF0\x9F\xA4\xA3\x00\xF0\x9F\x98\x83\x00\xF0\x9F\x98\x86\x00\xF0\x9F\x98\x89\x00"
|
||||
"\xF0\x9F\x98\x8B\x00\xF0\x9F\x98\x8E\x00\xF0\x9F\x98\x8D\x00\xF0\x9F\x98\x98\x00\xF0\x9F\x98\x97\x00\xF0\x9F\x98\x99\x00\xF0\x9F\x98\x9A\x00\xF0\x9F\x99\x82\x00"
|
||||
"\xF0\x9F\xA4\x97\x00\xF0\x9F\xA4\xA9\x00\xF0\x9F\xA4\x94\x00\xF0\x9F\xA4\xA8\x00\xF0\x9F\x98\x90\x00\xF0\x9F\x98\x91\x00\xF0\x9F\x98\xB6\x00\xF0\x9F\x99\x84\x00"
|
||||
"\xF0\x9F\x98\x8F\x00\xF0\x9F\x98\xA3\x00\xF0\x9F\x98\xA5\x00\xF0\x9F\x98\xAE\x00\xF0\x9F\xA4\x90\x00\xF0\x9F\x98\xAF\x00\xF0\x9F\x98\xAA\x00\xF0\x9F\x98\xAB\x00"
|
||||
"\xF0\x9F\x98\xB4\x00\xF0\x9F\x98\x8C\x00\xF0\x9F\x98\x9B\x00\xF0\x9F\x98\x9D\x00\xF0\x9F\xA4\xA4\x00\xF0\x9F\x98\x92\x00\xF0\x9F\x98\x95\x00\xF0\x9F\x99\x83\x00"
|
||||
"\xF0\x9F\xA4\x91\x00\xF0\x9F\x98\xB2\x00\xF0\x9F\x99\x81\x00\xF0\x9F\x98\x96\x00\xF0\x9F\x98\x9E\x00\xF0\x9F\x98\x9F\x00\xF0\x9F\x98\xA4\x00\xF0\x9F\x98\xA2\x00"
|
||||
"\xF0\x9F\x98\xAD\x00\xF0\x9F\x98\xA6\x00\xF0\x9F\x98\xA9\x00\xF0\x9F\xA4\xAF\x00\xF0\x9F\x98\xAC\x00\xF0\x9F\x98\xB0\x00\xF0\x9F\x98\xB1\x00\xF0\x9F\x98\xB3\x00"
|
||||
"\xF0\x9F\xA4\xAA\x00\xF0\x9F\x98\xB5\x00\xF0\x9F\x98\xA1\x00\xF0\x9F\x98\xA0\x00\xF0\x9F\xA4\xAC\x00\xF0\x9F\x98\xB7\x00\xF0\x9F\xA4\x92\x00\xF0\x9F\xA4\x95\x00"
|
||||
"\xF0\x9F\xA4\xA2\x00\xF0\x9F\xA4\xAE\x00\xF0\x9F\xA4\xA7\x00\xF0\x9F\x98\x87\x00\xF0\x9F\xA4\xA0\x00\xF0\x9F\xA4\xAB\x00\xF0\x9F\xA4\xAD\x00\xF0\x9F\xA7\x90\x00"
|
||||
"\xF0\x9F\xA4\x93\x00\xF0\x9F\x98\x88\x00\xF0\x9F\x91\xBF\x00\xF0\x9F\x91\xB9\x00\xF0\x9F\x91\xBA\x00\xF0\x9F\x92\x80\x00\xF0\x9F\x91\xBB\x00\xF0\x9F\x91\xBD\x00"
|
||||
"\xF0\x9F\x91\xBE\x00\xF0\x9F\xA4\x96\x00\xF0\x9F\x92\xA9\x00\xF0\x9F\x98\xBA\x00\xF0\x9F\x98\xB8\x00\xF0\x9F\x98\xB9\x00\xF0\x9F\x98\xBB\x00\xF0\x9F\x98\xBD\x00"
|
||||
"\xF0\x9F\x99\x80\x00\xF0\x9F\x98\xBF\x00\xF0\x9F\x8C\xBE\x00\xF0\x9F\x8C\xBF\x00\xF0\x9F\x8D\x80\x00\xF0\x9F\x8D\x83\x00\xF0\x9F\x8D\x87\x00\xF0\x9F\x8D\x93\x00"
|
||||
"\xF0\x9F\xA5\x9D\x00\xF0\x9F\x8D\x85\x00\xF0\x9F\xA5\xA5\x00\xF0\x9F\xA5\x91\x00\xF0\x9F\x8D\x86\x00\xF0\x9F\xA5\x94\x00\xF0\x9F\xA5\x95\x00\xF0\x9F\x8C\xBD\x00"
|
||||
"\xF0\x9F\x8C\xB6\x00\xF0\x9F\xA5\x92\x00\xF0\x9F\xA5\xA6\x00\xF0\x9F\x8D\x84\x00\xF0\x9F\xA5\x9C\x00\xF0\x9F\x8C\xB0\x00\xF0\x9F\x8D\x9E\x00\xF0\x9F\xA5\x90\x00"
|
||||
"\xF0\x9F\xA5\x96\x00\xF0\x9F\xA5\xA8\x00\xF0\x9F\xA5\x9E\x00\xF0\x9F\xA7\x80\x00\xF0\x9F\x8D\x96\x00\xF0\x9F\x8D\x97\x00\xF0\x9F\xA5\xA9\x00\xF0\x9F\xA5\x93\x00"
|
||||
"\xF0\x9F\x8D\x94\x00\xF0\x9F\x8D\x9F\x00\xF0\x9F\x8D\x95\x00\xF0\x9F\x8C\xAD\x00\xF0\x9F\xA5\xAA\x00\xF0\x9F\x8C\xAE\x00\xF0\x9F\x8C\xAF\x00\xF0\x9F\xA5\x99\x00"
|
||||
"\xF0\x9F\xA5\x9A\x00\xF0\x9F\x8D\xB3\x00\xF0\x9F\xA5\x98\x00\xF0\x9F\x8D\xB2\x00\xF0\x9F\xA5\xA3\x00\xF0\x9F\xA5\x97\x00\xF0\x9F\x8D\xBF\x00\xF0\x9F\xA5\xAB\x00"
|
||||
"\xF0\x9F\x8D\xB1\x00\xF0\x9F\x8D\x98\x00\xF0\x9F\x8D\x9D\x00\xF0\x9F\x8D\xA0\x00\xF0\x9F\x8D\xA2\x00\xF0\x9F\x8D\xA5\x00\xF0\x9F\x8D\xA1\x00\xF0\x9F\xA5\x9F\x00"
|
||||
"\xF0\x9F\xA5\xA1\x00\xF0\x9F\x8D\xA6\x00\xF0\x9F\x8D\xAA\x00\xF0\x9F\x8E\x82\x00\xF0\x9F\x8D\xB0\x00\xF0\x9F\xA5\xA7\x00\xF0\x9F\x8D\xAB\x00\xF0\x9F\x8D\xAF\x00"
|
||||
"\xF0\x9F\x8D\xBC\x00\xF0\x9F\xA5\x9B\x00\xF0\x9F\x8D\xB5\x00\xF0\x9F\x8D\xB6\x00\xF0\x9F\x8D\xBE\x00\xF0\x9F\x8D\xB7\x00\xF0\x9F\x8D\xBB\x00\xF0\x9F\xA5\x82\x00"
|
||||
"\xF0\x9F\xA5\x83\x00\xF0\x9F\xA5\xA4\x00\xF0\x9F\xA5\xA2\x00\xF0\x9F\x91\x81\x00\xF0\x9F\x91\x85\x00\xF0\x9F\x91\x84\x00\xF0\x9F\x92\x8B\x00\xF0\x9F\x92\x98\x00"
|
||||
"\xF0\x9F\x92\x93\x00\xF0\x9F\x92\x97\x00\xF0\x9F\x92\x99\x00\xF0\x9F\x92\x9B\x00\xF0\x9F\xA7\xA1\x00\xF0\x9F\x92\x9C\x00\xF0\x9F\x96\xA4\x00\xF0\x9F\x92\x9D\x00"
|
||||
const int EmojiPerWidth = 8;
|
||||
const int EmojiPerHeight = 4;
|
||||
|
||||
public string Name => "Text / Unicode Emojis";
|
||||
|
||||
public string Title => "raylib [text] example - unicode emojis";
|
||||
|
||||
public ConfigFlags ConfigFlags => ConfigFlags.Msaa4xHint | ConfigFlags.VSyncHint;
|
||||
|
||||
// Arrays that holds the random emojis
|
||||
struct EmojiInfo
|
||||
{
|
||||
public int Index; // Index inside `emojiCodepoints`
|
||||
public int Message; // Message index
|
||||
public Color Color; // Emoji color
|
||||
}
|
||||
|
||||
private EmojiInfo[] emoji;
|
||||
|
||||
private int hovered;
|
||||
private int selected;
|
||||
|
||||
struct Message
|
||||
{
|
||||
public string Text;
|
||||
public string Language;
|
||||
|
||||
public Message(string text, string language)
|
||||
{
|
||||
Text = text;
|
||||
Language = language;
|
||||
}
|
||||
}
|
||||
|
||||
// String containing 180 emoji codepoints separated by a '\0' char
|
||||
const string EmojiCodepoints =
|
||||
"\xF0\x9F\x8C\x80\x00\xF0\x9F\x98\x80\x00\xF0\x9F\x98\x82\x00\xF0\x9F\xA4\xA3\x00\xF0\x9F\x98\x83\x00\xF0\x9F\x98\x86\x00\xF0\x9F\x98\x89\x00" +
|
||||
"\xF0\x9F\x98\x8B\x00\xF0\x9F\x98\x8E\x00\xF0\x9F\x98\x8D\x00\xF0\x9F\x98\x98\x00\xF0\x9F\x98\x97\x00\xF0\x9F\x98\x99\x00\xF0\x9F\x98\x9A\x00\xF0\x9F\x99\x82\x00" +
|
||||
"\xF0\x9F\xA4\x97\x00\xF0\x9F\xA4\xA9\x00\xF0\x9F\xA4\x94\x00\xF0\x9F\xA4\xA8\x00\xF0\x9F\x98\x90\x00\xF0\x9F\x98\x91\x00\xF0\x9F\x98\xB6\x00\xF0\x9F\x99\x84\x00" +
|
||||
"\xF0\x9F\x98\x8F\x00\xF0\x9F\x98\xA3\x00\xF0\x9F\x98\xA5\x00\xF0\x9F\x98\xAE\x00\xF0\x9F\xA4\x90\x00\xF0\x9F\x98\xAF\x00\xF0\x9F\x98\xAA\x00\xF0\x9F\x98\xAB\x00" +
|
||||
"\xF0\x9F\x98\xB4\x00\xF0\x9F\x98\x8C\x00\xF0\x9F\x98\x9B\x00\xF0\x9F\x98\x9D\x00\xF0\x9F\xA4\xA4\x00\xF0\x9F\x98\x92\x00\xF0\x9F\x98\x95\x00\xF0\x9F\x99\x83\x00" +
|
||||
"\xF0\x9F\xA4\x91\x00\xF0\x9F\x98\xB2\x00\xF0\x9F\x99\x81\x00\xF0\x9F\x98\x96\x00\xF0\x9F\x98\x9E\x00\xF0\x9F\x98\x9F\x00\xF0\x9F\x98\xA4\x00\xF0\x9F\x98\xA2\x00" +
|
||||
"\xF0\x9F\x98\xAD\x00\xF0\x9F\x98\xA6\x00\xF0\x9F\x98\xA9\x00\xF0\x9F\xA4\xAF\x00\xF0\x9F\x98\xAC\x00\xF0\x9F\x98\xB0\x00\xF0\x9F\x98\xB1\x00\xF0\x9F\x98\xB3\x00" +
|
||||
"\xF0\x9F\xA4\xAA\x00\xF0\x9F\x98\xB5\x00\xF0\x9F\x98\xA1\x00\xF0\x9F\x98\xA0\x00\xF0\x9F\xA4\xAC\x00\xF0\x9F\x98\xB7\x00\xF0\x9F\xA4\x92\x00\xF0\x9F\xA4\x95\x00" +
|
||||
"\xF0\x9F\xA4\xA2\x00\xF0\x9F\xA4\xAE\x00\xF0\x9F\xA4\xA7\x00\xF0\x9F\x98\x87\x00\xF0\x9F\xA4\xA0\x00\xF0\x9F\xA4\xAB\x00\xF0\x9F\xA4\xAD\x00\xF0\x9F\xA7\x90\x00" +
|
||||
"\xF0\x9F\xA4\x93\x00\xF0\x9F\x98\x88\x00\xF0\x9F\x91\xBF\x00\xF0\x9F\x91\xB9\x00\xF0\x9F\x91\xBA\x00\xF0\x9F\x92\x80\x00\xF0\x9F\x91\xBB\x00\xF0\x9F\x91\xBD\x00" +
|
||||
"\xF0\x9F\x91\xBE\x00\xF0\x9F\xA4\x96\x00\xF0\x9F\x92\xA9\x00\xF0\x9F\x98\xBA\x00\xF0\x9F\x98\xB8\x00\xF0\x9F\x98\xB9\x00\xF0\x9F\x98\xBB\x00\xF0\x9F\x98\xBD\x00" +
|
||||
"\xF0\x9F\x99\x80\x00\xF0\x9F\x98\xBF\x00\xF0\x9F\x8C\xBE\x00\xF0\x9F\x8C\xBF\x00\xF0\x9F\x8D\x80\x00\xF0\x9F\x8D\x83\x00\xF0\x9F\x8D\x87\x00\xF0\x9F\x8D\x93\x00" +
|
||||
"\xF0\x9F\xA5\x9D\x00\xF0\x9F\x8D\x85\x00\xF0\x9F\xA5\xA5\x00\xF0\x9F\xA5\x91\x00\xF0\x9F\x8D\x86\x00\xF0\x9F\xA5\x94\x00\xF0\x9F\xA5\x95\x00\xF0\x9F\x8C\xBD\x00" +
|
||||
"\xF0\x9F\x8C\xB6\x00\xF0\x9F\xA5\x92\x00\xF0\x9F\xA5\xA6\x00\xF0\x9F\x8D\x84\x00\xF0\x9F\xA5\x9C\x00\xF0\x9F\x8C\xB0\x00\xF0\x9F\x8D\x9E\x00\xF0\x9F\xA5\x90\x00" +
|
||||
"\xF0\x9F\xA5\x96\x00\xF0\x9F\xA5\xA8\x00\xF0\x9F\xA5\x9E\x00\xF0\x9F\xA7\x80\x00\xF0\x9F\x8D\x96\x00\xF0\x9F\x8D\x97\x00\xF0\x9F\xA5\xA9\x00\xF0\x9F\xA5\x93\x00" +
|
||||
"\xF0\x9F\x8D\x94\x00\xF0\x9F\x8D\x9F\x00\xF0\x9F\x8D\x95\x00\xF0\x9F\x8C\xAD\x00\xF0\x9F\xA5\xAA\x00\xF0\x9F\x8C\xAE\x00\xF0\x9F\x8C\xAF\x00\xF0\x9F\xA5\x99\x00" +
|
||||
"\xF0\x9F\xA5\x9A\x00\xF0\x9F\x8D\xB3\x00\xF0\x9F\xA5\x98\x00\xF0\x9F\x8D\xB2\x00\xF0\x9F\xA5\xA3\x00\xF0\x9F\xA5\x97\x00\xF0\x9F\x8D\xBF\x00\xF0\x9F\xA5\xAB\x00" +
|
||||
"\xF0\x9F\x8D\xB1\x00\xF0\x9F\x8D\x98\x00\xF0\x9F\x8D\x9D\x00\xF0\x9F\x8D\xA0\x00\xF0\x9F\x8D\xA2\x00\xF0\x9F\x8D\xA5\x00\xF0\x9F\x8D\xA1\x00\xF0\x9F\xA5\x9F\x00" +
|
||||
"\xF0\x9F\xA5\xA1\x00\xF0\x9F\x8D\xA6\x00\xF0\x9F\x8D\xAA\x00\xF0\x9F\x8E\x82\x00\xF0\x9F\x8D\xB0\x00\xF0\x9F\xA5\xA7\x00\xF0\x9F\x8D\xAB\x00\xF0\x9F\x8D\xAF\x00" +
|
||||
"\xF0\x9F\x8D\xBC\x00\xF0\x9F\xA5\x9B\x00\xF0\x9F\x8D\xB5\x00\xF0\x9F\x8D\xB6\x00\xF0\x9F\x8D\xBE\x00\xF0\x9F\x8D\xB7\x00\xF0\x9F\x8D\xBB\x00\xF0\x9F\xA5\x82\x00" +
|
||||
"\xF0\x9F\xA5\x83\x00\xF0\x9F\xA5\xA4\x00\xF0\x9F\xA5\xA2\x00\xF0\x9F\x91\x81\x00\xF0\x9F\x91\x85\x00\xF0\x9F\x91\x84\x00\xF0\x9F\x92\x8B\x00\xF0\x9F\x92\x98\x00" +
|
||||
"\xF0\x9F\x92\x93\x00\xF0\x9F\x92\x97\x00\xF0\x9F\x92\x99\x00\xF0\x9F\x92\x9B\x00\xF0\x9F\xA7\xA1\x00\xF0\x9F\x92\x9C\x00\xF0\x9F\x96\xA4\x00\xF0\x9F\x92\x9D\x00" +
|
||||
"\xF0\x9F\x92\x9F\x00\xF0\x9F\x92\x8C\x00\xF0\x9F\x92\xA4\x00\xF0\x9F\x92\xA2\x00\xF0\x9F\x92\xA3\x00";
|
||||
|
||||
struct {
|
||||
string text;
|
||||
string language;
|
||||
}
|
||||
const messages[] = { // Array containing all of the emojis messages
|
||||
{"\x46\x61\x6C\x73\x63\x68\x65\x73\x20\xC3\x9C\x62\x65\x6E\x20\x76\x6F\x6E\x20\x58\x79\x6C\x6F\x70\x68\x6F\x6E\x6D\x75\x73\x69\x6B\x20\x71\x75\xC3\xA4\x6C"
|
||||
"\x74\x20\x6A\x65\x64\x65\x6E\x20\x67\x72\xC3\xB6\xC3\x9F\x65\x72\x65\x6E\x20\x5A\x77\x65\x72\x67", "German"},
|
||||
{"\x42\x65\x69\xC3\x9F\x20\x6E\x69\x63\x68\x74\x20\x69\x6E\x20\x64\x69\x65\x20\x48\x61\x6E\x64\x2C\x20\x64\x69\x65\x20\x64\x69\x63\x68\x20\x66\xC3\xBC\x74"
|
||||
"\x74\x65\x72\x74\x2E", "German"},
|
||||
{"\x41\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\xC3\x9C\x62\x65\x6C\x20\x65\x72\x66\x6F\x72\x64\x65\x72\x6E\x20\x61\x75\xC3\x9F"
|
||||
"\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\x4D\x69\x74\x74\x65\x6C\x2E", "German"},
|
||||
{"\xD4\xBF\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB4\x20\xD5\xA1\xD5\xBA\xD5\xA1\xD5\xAF\xD5\xAB\x20\xD5\xB8\xD6\x82\xD5\xBF\xD5\xA5\xD5\xAC\x20\xD6\x87\x20\xD5\xAB"
|
||||
"\xD5\xB6\xD5\xAE\xD5\xAB\x20\xD5\xA1\xD5\xB6\xD5\xB0\xD5\xA1\xD5\xB6\xD5\xA3\xD5\xAB\xD5\xBD\xD5\xBF\x20\xD5\xB9\xD5\xA8\xD5\xB6\xD5\xA5\xD6\x80", "Armenian"},
|
||||
{"\xD4\xB5\xD6\x80\xD5\xA2\x20\xD5\xB8\xD6\x80\x20\xD5\xAF\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\xD5\xA8\x20\xD5\xA5\xD5\xAF\xD5\xA1\xD6\x82\x20\xD5\xA1\xD5\xB6\xD5"
|
||||
"\xBF\xD5\xA1\xD5\xBC\x2C\x20\xD5\xAE\xD5\xA1\xD5\xBC\xD5\xA5\xD6\x80\xD5\xA8\x20\xD5\xA1\xD5\xBD\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\x2E\x2E\x2E\x20\xC2\xAB\xD4\xBF"
|
||||
"\xD5\xB8\xD5\xBF\xD5\xA8\x20\xD5\xB4\xD5\xA5\xD6\x80\xD5\xB8\xD5\xB6\xD6\x81\xD5\xAB\xD6\x81\x20\xD5\xA7\x3A\xC2\xBB", "Armenian"},
|
||||
{"\xD4\xB3\xD5\xA1\xD5\xBC\xD5\xA8\xD5\x9D\x20\xD5\xA3\xD5\xA1\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB6\x2C\x20\xD5\xB1\xD5\xAB\xD6\x82\xD5\xB6\xD5\xA8\xD5\x9D\x20\xD5"
|
||||
"\xB1\xD5\xB4\xD5\xBC\xD5\xA1\xD5\xB6", "Armenian"},
|
||||
{"\x4A\x65\xC5\xBC\x75\x20\x6B\x6C\xC4\x85\x74\x77\x2C\x20\x73\x70\xC5\x82\xC3\xB3\x64\xC5\xBA\x20\x46\x69\x6E\x6F\x6D\x20\x63\x7A\xC4\x99\xC5\x9B\xC4\x87"
|
||||
"\x20\x67\x72\x79\x20\x68\x61\xC5\x84\x62\x21", "Polish"},
|
||||
{"\x44\x6F\x62\x72\x79\x6D\x69\x20\x63\x68\xC4\x99\x63\x69\x61\x6D\x69\x20\x6A\x65\x73\x74\x20\x70\x69\x65\x6B\xC5\x82\x6F\x20\x77\x79\x62\x72\x75\x6B\x6F"
|
||||
"\x77\x61\x6E\x65\x2E", "Polish"},
|
||||
{"\xC3\x8E\xC8\x9B\x69\x20\x6D\x75\x6C\xC8\x9B\x75\x6D\x65\x73\x63\x20\x63\xC4\x83\x20\x61\x69\x20\x61\x6C\x65\x73\x20\x72\x61\x79\x6C\x69\x62\x2E\x0A\xC8\x98"
|
||||
"\x69\x20\x73\x70\x65\x72\x20\x73\xC4\x83\x20\x61\x69\x20\x6F\x20\x7A\x69\x20\x62\x75\x6E\xC4\x83\x21", "Romanian"},
|
||||
{"\xD0\xAD\xD1\x85\x2C\x20\xD1\x87\xD1\x83\xD0\xB6\xD0\xB0\xD0\xBA\x2C\x20\xD0\xBE\xD0\xB1\xD1\x89\xD0\xB8\xD0\xB9\x20\xD1\x81\xD1\x8A\xD1\x91\xD0\xBC\x20"
|
||||
"\xD1\x86\xD0\xB5\xD0\xBD\x20\xD1\x88\xD0\xBB\xD1\x8F\xD0\xBF\x20\x28\xD1\x8E\xD1\x84\xD1\x82\xD1\x8C\x29\x20\xD0\xB2\xD0\xB4\xD1\x80\xD1\x8B\xD0\xB7\xD0\xB3\x21", "Russian"},
|
||||
{"\xD0\xAF\x20\xD0\xBB\xD1\x8E\xD0\xB1\xD0\xBB\xD1\x8E\x20\x72\x61\x79\x6C\x69\x62\x21", "Russian"},
|
||||
{"\xD0\x9C\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2C\x20\xD1\x81\xD0\xBA\xD1\x80\xD1\x8B\xD0\xB2\xD0\xB0\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\x20\xD1\x82\xD0\xB0\xD0\xB8"
|
||||
"\x0A\xD0\x98\x20\xD1\x87\xD1\x83\xD0\xB2\xD1\x81\xD1\x82\xD0\xB2\xD0\xB0\x20\xD0\xB8\x20\xD0\xBC\xD0\xB5\xD1\x87\xD1\x82\xD1\x8B\x20\xD1\x81\xD0\xB2\xD0\xBE\xD0\xB8\x20"
|
||||
"\xE2\x80\x93\x0A\xD0\x9F\xD1\x83\xD1\x81\xD0\xBA\xD0\xB0\xD0\xB9\x20\xD0\xB2\x20\xD0\xB4\xD1\x83\xD1\x88\xD0\xB5\xD0\xB2\xD0\xBD\xD0\xBE\xD0\xB9\x20\xD0\xB3\xD0\xBB\xD1"
|
||||
"\x83\xD0\xB1\xD0\xB8\xD0\xBD\xD0\xB5\x0A\xD0\x98\x20\xD0\xB2\xD1\x81\xD1\x85\xD0\xBE\xD0\xB4\xD1\x8F\xD1\x82\x20\xD0\xB8\x20\xD0\xB7\xD0\xB0\xD0\xB9\xD0\xB4\xD1\x83\xD1"
|
||||
"\x82\x20\xD0\xBE\xD0\xBD\xD0\xB5\x0A\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB7\xD0\xB2\xD0\xB5\xD0\xB7\xD0\xB4\xD1\x8B\x20\xD1\x8F\xD1\x81\xD0\xBD\xD1\x8B\xD0\xB5\x20\xD0\xB2"
|
||||
"\x20\xD0\xBD\xD0\xBE\xD1\x87\xD0\xB8\x2D\x0A\xD0\x9B\xD1\x8E\xD0\xB1\xD1\x83\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\xD0\xBC\xD0\xB8\x20\xE2\x80\x93\x20\xD0\xB8\x20\xD0\xBC"
|
||||
"\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2E", "Russian"},
|
||||
{"\x56\x6F\x69\x78\x20\x61\x6D\x62\x69\x67\x75\xC3\xAB\x20\x64\xE2\x80\x99\x75\x6E\x20\x63\xC5\x93\x75\x72\x20\x71\x75\x69\x20\x61\x75\x20\x7A\xC3\xA9\x70"
|
||||
"\x68\x79\x72\x20\x70\x72\xC3\xA9\x66\xC3\xA8\x72\x65\x20\x6C\x65\x73\x20\x6A\x61\x74\x74\x65\x73\x20\x64\x65\x20\x6B\x69\x77\x69", "French"},
|
||||
{"\x42\x65\x6E\x6A\x61\x6D\xC3\xAD\x6E\x20\x70\x69\x64\x69\xC3\xB3\x20\x75\x6E\x61\x20\x62\x65\x62\x69\x64\x61\x20\x64\x65\x20\x6B\x69\x77\x69\x20\x79\x20"
|
||||
"\x66\x72\x65\x73\x61\x3B\x20\x4E\x6F\xC3\xA9\x2C\x20\x73\x69\x6E\x20\x76\x65\x72\x67\xC3\xBC\x65\x6E\x7A\x61\x2C\x20\x6C\x61\x20\x6D\xC3\xA1\x73\x20\x65\x78"
|
||||
"\x71\x75\x69\x73\x69\x74\x61\x20\x63\x68\x61\x6D\x70\x61\xC3\xB1\x61\x20\x64\x65\x6C\x20\x6D\x65\x6E\xC3\xBA\x2E", "Spanish"},
|
||||
{"\xCE\xA4\xCE\xB1\xCF\x87\xCE\xAF\xCF\x83\xCF\x84\xCE\xB7\x20\xCE\xB1\xCE\xBB\xCF\x8E\xCF\x80\xCE\xB7\xCE\xBE\x20\xCE\xB2\xCE\xB1\xCF\x86\xCE\xAE\xCF\x82\x20"
|
||||
"\xCF\x88\xCE\xB7\xCE\xBC\xCE\xAD\xCE\xBD\xCE\xB7\x20\xCE\xB3\xCE\xB7\x2C\x20\xCE\xB4\xCF\x81\xCE\xB1\xCF\x83\xCE\xBA\xCE\xB5\xCE\xBB\xCE\xAF\xCE\xB6\xCE\xB5\xCE"
|
||||
"\xB9\x20\xCF\x85\xCF\x80\xCE\xAD\xCF\x81\x20\xCE\xBD\xCF\x89\xCE\xB8\xCF\x81\xCE\xBF\xCF\x8D\x20\xCE\xBA\xCF\x85\xCE\xBD\xCF\x8C\xCF\x82", "Greek"},
|
||||
{"\xCE\x97\x20\xCE\xBA\xCE\xB1\xCE\xBB\xCF\x8D\xCF\x84\xCE\xB5\xCF\x81\xCE\xB7\x20\xCE\xAC\xCE\xBC\xCF\x85\xCE\xBD\xCE\xB1\x20\xCE\xB5\xCE\xAF\xCE\xBD"
|
||||
"\xCE\xB1\xCE\xB9\x20\xCE\xB7\x20\xCE\xB5\xCF\x80\xCE\xAF\xCE\xB8\xCE\xB5\xCF\x83\xCE\xB7\x2E", "Greek"},
|
||||
{"\xCE\xA7\xCF\x81\xCF\x8C\xCE\xBD\xCE\xB9\xCE\xB1\x20\xCE\xBA\xCE\xB1\xCE\xB9\x20\xCE\xB6\xCE\xB1\xCE\xBC\xCE\xAC\xCE\xBD\xCE\xB9\xCE\xB1\x21", "Greek"},
|
||||
{"\xCE\xA0\xCF\x8E\xCF\x82\x20\xCF\x84\xCE\xB1\x20\xCF\x80\xCE\xB1\xCF\x82\x20\xCF\x83\xCE\xAE\xCE\xBC\xCE\xB5\xCF\x81\xCE\xB1\x3B", "Greek"},
|
||||
|
||||
{"\xE6\x88\x91\xE8\x83\xBD\xE5\x90\x9E\xE4\xB8\x8B\xE7\x8E\xBB\xE7\x92\x83\xE8\x80\x8C\xE4\xB8\x8D\xE4\xBC\xA4\xE8\xBA\xAB\xE4\xBD\x93\xE3\x80\x82", "Chinese"},
|
||||
{"\xE4\xBD\xA0\xE5\x90\x83\xE4\xBA\x86\xE5\x90\x97\xEF\xBC\x9F", "Chinese"},
|
||||
{"\xE4\xB8\x8D\xE4\xBD\x9C\xE4\xB8\x8D\xE6\xAD\xBB\xE3\x80\x82", "Chinese"},
|
||||
{"\xE6\x9C\x80\xE8\xBF\x91\xE5\xA5\xBD\xE5\x90\x97\xEF\xBC\x9F", "Chinese"},
|
||||
{"\xE5\xA1\x9E\xE7\xBF\x81\xE5\xA4\xB1\xE9\xA9\xAC\xEF\xBC\x8C\xE7\x84\x89\xE7\x9F\xA5\xE9\x9D\x9E\xE7\xA6\x8F\xE3\x80\x82", "Chinese"},
|
||||
{"\xE5\x8D\x83\xE5\x86\x9B\xE6\x98\x93\xE5\xBE\x97\x2C\x20\xE4\xB8\x80\xE5\xB0\x86\xE9\x9A\xBE\xE6\xB1\x82", "Chinese"},
|
||||
{"\xE4\xB8\x87\xE4\xBA\x8B\xE5\xBC\x80\xE5\xA4\xB4\xE9\x9A\xBE\xE3\x80\x82", "Chinese"},
|
||||
{"\xE9\xA3\x8E\xE6\x97\xA0\xE5\xB8\xB8\xE9\xA1\xBA\xEF\xBC\x8C\xE5\x85\xB5\xE6\x97\xA0\xE5\xB8\xB8\xE8\x83\x9C\xE3\x80\x82", "Chinese"},
|
||||
{"\xE6\xB4\xBB\xE5\x88\xB0\xE8\x80\x81\xEF\xBC\x8C\xE5\xAD\xA6\xE5\x88\xB0\xE8\x80\x81\xE3\x80\x82", "Chinese"},
|
||||
{"\xE4\xB8\x80\xE8\xA8\x80\xE6\x97\xA2\xE5\x87\xBA\xEF\xBC\x8C\xE9\xA9\xB7\xE9\xA9\xAC\xE9\x9A\xBE\xE8\xBF\xBD\xE3\x80\x82", "Chinese"},
|
||||
{"\xE8\xB7\xAF\xE9\x81\xA5\xE7\x9F\xA5\xE9\xA9\xAC\xE5\x8A\x9B\xEF\xBC\x8C\xE6\x97\xA5\xE4\xB9\x85\xE8\xA7\x81\xE4\xBA\xBA\xE5\xBF\x83", "Chinese"},
|
||||
{"\xE6\x9C\x89\xE7\x90\x86\xE8\xB5\xB0\xE9\x81\x8D\xE5\xA4\xA9\xE4\xB8\x8B\xEF\xBC\x8C\xE6\x97\xA0\xE7\x90\x86\xE5\xAF\xB8\xE6\xAD\xA5\xE9\x9A\xBE\xE8\xA1\x8C\xE3\x80\x82", "Chinese"},
|
||||
|
||||
{"\xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B", "Japanese"},
|
||||
{"\xE4\xBA\x80\xE3\x81\xAE\xE7\x94\xB2\xE3\x82\x88\xE3\x82\x8A\xE5\xB9\xB4\xE3\x81\xAE\xE5\x8A\x9F", "Japanese"},
|
||||
{"\xE3\x81\x86\xE3\x82\x89\xE3\x82\x84\xE3\x81\xBE\xE3\x81\x97\x20\x20\xE6\x80\x9D\xE3\x81\xB2\xE5\x88\x87\xE3\x82\x8B\xE6\x99\x82\x20\x20\xE7\x8C\xAB\xE3\x81\xAE\xE6\x81\x8B", "Japanese"},
|
||||
{"\xE8\x99\x8E\xE7\xA9\xB4\xE3\x81\xAB\xE5\x85\xA5\xE3\x82\x89\xE3\x81\x9A\xE3\x82\x93\xE3\x81\xB0\xE8\x99\x8E\xE5\xAD\x90\xE3\x82\x92\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"},
|
||||
{"\xE4\xBA\x8C\xE5\x85\x8E\xE3\x82\x92\xE8\xBF\xBD\xE3\x81\x86\xE8\x80\x85\xE3\x81\xAF\xE4\xB8\x80\xE5\x85\x8E\xE3\x82\x92\xE3\x82\x82\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"},
|
||||
{"\xE9\xA6\xAC\xE9\xB9\xBF\xE3\x81\xAF\xE6\xAD\xBB\xE3\x81\xAA\xE3\x81\xAA\xE3\x81\x8D\xE3\x82\x83\xE6\xB2\xBB\xE3\x82\x89\xE3\x81\xAA\xE3\x81\x84\xE3\x80\x82", "Japanese"},
|
||||
{"\xE6\x9E\xAF\xE9\x87\x8E\xE8\xB7\xAF\xE3\x81\xAB\xE3\x80\x80\xE5\xBD\xB1\xE3\x81\x8B\xE3\x81\x95\xE3\x81\xAA\xE3\x82\x8A\xE3\x81\xA6\xE3\x80\x80\xE3\x82\x8F\xE3\x81\x8B\xE3\x82\x8C\xE3\x81\x91\xE3\x82\x8A", "Japanese"},
|
||||
{"\xE7\xB9\xB0\xE3\x82\x8A\xE8\xBF\x94\xE3\x81\x97\xE9\xBA\xA6\xE3\x81\xAE\xE7\x95\x9D\xE7\xB8\xAB\xE3\x81\xB5\xE8\x83\xA1\xE8\x9D\xB6\xE5\x93\x89", "Japanese"},
|
||||
|
||||
{"\xEC\x95\x84\xEB\x93\x9D\xED\x95\x9C\x20\xEB\xB0\x94\xEB\x8B\xA4\x20\xEC\x9C\x84\xEC\x97\x90\x20\xEA\xB0\x88\xEB\xA7\xA4\xEA\xB8\xB0\x20\xEB\x91\x90\xEC\x97\x87\x20"
|
||||
"\xEB\x82\xA0\xEC\x95\x84\x20\xEB\x8F\x88\xEB\x8B\xA4\x2E\x0A\xEB\x84\x88\xED\x9B\x8C\xEB\x84\x88\xED\x9B\x8C\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E"
|
||||
"\x20\xEB\xAA\xA8\xEB\xA5\xB4\xEB\x8A\x94\x20\xEB\x82\x98\xEB\x9D\xBC\x20\xEA\xB8\x80\xEC\x9E\x90\xEB\x8B\xA4\x2E\x0A\xEB\x84\x90\xEB\x94\xB0\xEB\x9E\x80\x20\xED\x95\x98"
|
||||
"\xEB\x8A\x98\x20\xEB\xB3\xB5\xED\x8C\x90\xEC\x97\x90\x20\xEB\x82\x98\xEB\x8F\x84\x20\xEA\xB0\x99\xEC\x9D\xB4\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E", "Korean"},
|
||||
{"\xEC\xA0\x9C\x20\xEB\x88\x88\xEC\x97\x90\x20\xEC\x95\x88\xEA\xB2\xBD\xEC\x9D\xB4\xEB\x8B\xA4", "Korean"},
|
||||
{"\xEA\xBF\xA9\x20\xEB\xA8\xB9\xEA\xB3\xA0\x20\xEC\x95\x8C\x20\xEB\xA8\xB9\xEB\x8A\x94\xEB\x8B\xA4", "Korean"},
|
||||
{"\xEB\xA1\x9C\xEB\xA7\x88\xEB\x8A\x94\x20\xED\x95\x98\xEB\xA3\xA8\xEC\x95\x84\xEC\xB9\xA8\xEC\x97\x90\x20\xEC\x9D\xB4\xEB\xA3\xA8\xEC\x96\xB4\xEC\xA7\x84\x20\xEA\xB2\x83\xEC\x9D\xB4"
|
||||
"\x20\xEC\x95\x84\xEB\x8B\x88\xEB\x8B\xA4", "Korean"},
|
||||
{"\xEA\xB3\xA0\xEC\x83\x9D\x20\xEB\x81\x9D\xEC\x97\x90\x20\xEB\x82\x99\xEC\x9D\xB4\x20\xEC\x98\xA8\xEB\x8B\xA4", "Korean"},
|
||||
{"\xEA\xB0\x9C\xEC\xB2\x9C\xEC\x97\x90\xEC\x84\x9C\x20\xEC\x9A\xA9\x20\xEB\x82\x9C\xEB\x8B\xA4", "Korean"},
|
||||
{"\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"},
|
||||
{"\xEB\xA7\x8C\xEB\x82\x98\xEC\x84\x9C\x20\xEB\xB0\x98\xEA\xB0\x91\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4", "Korean"},
|
||||
{"\xED\x95\x9C\xEA\xB5\xAD\xEB\xA7\x90\x20\xED\x95\x98\xEC\x8B\xA4\x20\xEC\xA4\x84\x20\xEC\x95\x84\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"},
|
||||
// Array containing all of the emojis messages
|
||||
static Message[] messages = new Message[]
|
||||
{
|
||||
new Message("\x46\x61\x6C\x73\x63\x68\x65\x73\x20\xC3\x9C\x62\x65\x6E\x20\x76\x6F\x6E\x20\x58\x79\x6C\x6F\x70\x68\x6F\x6E\x6D\x75\x73\x69\x6B\x20\x71\x75\xC3\xA4\x6C\x74\x20\x6A\x65\x64\x65\x6E\x20\x67\x72\xC3\xB6\xC3\x9F\x65\x72\x65\x6E\x20\x5A\x77\x65\x72\x67", "German"),
|
||||
new Message("\x42\x65\x69\xC3\x9F\x20\x6E\x69\x63\x68\x74\x20\x69\x6E\x20\x64\x69\x65\x20\x48\x61\x6E\x64\x2C\x20\x64\x69\x65\x20\x64\x69\x63\x68\x20\x66\xC3\xBC\x74\x74\x65\x72\x74\x2E", "German"),
|
||||
new Message("\x41\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\xC3\x9C\x62\x65\x6C\x20\x65\x72\x66\x6F\x72\x64\x65\x72\x6E\x20\x61\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\x4D\x69\x74\x74\x65\x6C\x2E", "German"),
|
||||
new Message("\xD4\xBF\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB4\x20\xD5\xA1\xD5\xBA\xD5\xA1\xD5\xAF\xD5\xAB\x20\xD5\xB8\xD6\x82\xD5\xBF\xD5\xA5\xD5\xAC\x20\xD6\x87\x20\xD5\xAB\xD5\xB6\xD5\xAE\xD5\xAB\x20\xD5\xA1\xD5\xB6\xD5\xB0\xD5\xA1\xD5\xB6\xD5\xA3\xD5\xAB\xD5\xBD\xD5\xBF\x20\xD5\xB9\xD5\xA8\xD5\xB6\xD5\xA5\xD6\x80", "Armenian"),
|
||||
new Message("\xD4\xB5\xD6\x80\xD5\xA2\x20\xD5\xB8\xD6\x80\x20\xD5\xAF\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\xD5\xA8\x20\xD5\xA5\xD5\xAF\xD5\xA1\xD6\x82\x20\xD5\xA1\xD5\xB6\xD5\xBF\xD5\xA1\xD5\xBC\x2C\x20\xD5\xAE\xD5\xA1\xD5\xBC\xD5\xA5\xD6\x80\xD5\xA8\x20\xD5\xA1\xD5\xBD\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\x2E\x2E\x2E\x20\xC2\xAB\xD4\xBF\xD5\xB8\xD5\xBF\xD5\xA8\x20\xD5\xB4\xD5\xA5\xD6\x80\xD5\xB8\xD5\xB6\xD6\x81\xD5\xAB\xD6\x81\x20\xD5\xA7\x3A\xC2\xBB", "Armenian"),
|
||||
new Message("\xD4\xB3\xD5\xA1\xD5\xBC\xD5\xA8\xD5\x9D\x20\xD5\xA3\xD5\xA1\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB6\x2C\x20\xD5\xB1\xD5\xAB\xD6\x82\xD5\xB6\xD5\xA8\xD5\x9D\x20\xD5\xB1\xD5\xB4\xD5\xBC\xD5\xA1\xD5\xB6", "Armenian"),
|
||||
new Message("\x4A\x65\xC5\xBC\x75\x20\x6B\x6C\xC4\x85\x74\x77\x2C\x20\x73\x70\xC5\x82\xC3\xB3\x64\xC5\xBA\x20\x46\x69\x6E\x6F\x6D\x20\x63\x7A\xC4\x99\xC5\x9B\xC4\x87\x20\x67\x72\x79\x20\x68\x61\xC5\x84\x62\x21", "Polish"),
|
||||
new Message("\x44\x6F\x62\x72\x79\x6D\x69\x20\x63\x68\xC4\x99\x63\x69\x61\x6D\x69\x20\x6A\x65\x73\x74\x20\x70\x69\x65\x6B\xC5\x82\x6F\x20\x77\x79\x62\x72\x75\x6B\x6F\x77\x61\x6E\x65\x2E", "Polish"),
|
||||
new Message("\xC3\x8E\xC8\x9B\x69\x20\x6D\x75\x6C\xC8\x9B\x75\x6D\x65\x73\x63\x20\x63\xC4\x83\x20\x61\x69\x20\x61\x6C\x65\x73\x20\x72\x61\x79\x6C\x69\x62\x2E\x0A\xC8\x98\x69\x20\x73\x70\x65\x72\x20\x73\xC4\x83\x20\x61\x69\x20\x6F\x20\x7A\x69\x20\x62\x75\x6E\xC4\x83\x21", "Romanian"),
|
||||
new Message("\xD0\xAD\xD1\x85\x2C\x20\xD1\x87\xD1\x83\xD0\xB6\xD0\xB0\xD0\xBA\x2C\x20\xD0\xBE\xD0\xB1\xD1\x89\xD0\xB8\xD0\xB9\x20\xD1\x81\xD1\x8A\xD1\x91\xD0\xBC\x20\xD1\x86\xD0\xB5\xD0\xBD\x20\xD1\x88\xD0\xBB\xD1\x8F\xD0\xBF\x20\x28\xD1\x8E\xD1\x84\xD1\x82\xD1\x8C\x29\x20\xD0\xB2\xD0\xB4\xD1\x80\xD1\x8B\xD0\xB7\xD0\xB3\x21", "Russian"),
|
||||
new Message("\xD0\xAF\x20\xD0\xBB\xD1\x8E\xD0\xB1\xD0\xBB\xD1\x8E\x20\x72\x61\x79\x6C\x69\x62\x21", "Russian"),
|
||||
new Message("\xD0\x9C\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2C\x20\xD1\x81\xD0\xBA\xD1\x80\xD1\x8B\xD0\xB2\xD0\xB0\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\x20\xD1\x82\xD0\xB0\xD0\xB8\x0A\xD0\x98\x20\xD1\x87\xD1\x83\xD0\xB2\xD1\x81\xD1\x82\xD0\xB2\xD0\xB0\x20\xD0\xB8\x20\xD0\xBC\xD0\xB5\xD1\x87\xD1\x82\xD1\x8B\x20\xD1\x81\xD0\xB2\xD0\xBE\xD0\xB8\x20\xE2\x80\x93\x0A\xD0\x9F\xD1\x83\xD1\x81\xD0\xBA\xD0\xB0\xD0\xB9\x20\xD0\xB2\x20\xD0\xB4\xD1\x83\xD1\x88\xD0\xB5\xD0\xB2\xD0\xBD\xD0\xBE\xD0\xB9\x20\xD0\xB3\xD0\xBB\xD1\x83\xD0\xB1\xD0\xB8\xD0\xBD\xD0\xB5\x0A\xD0\x98\x20\xD0\xB2\xD1\x81\xD1\x85\xD0\xBE\xD0\xB4\xD1\x8F\xD1\x82\x20\xD0\xB8\x20\xD0\xB7\xD0\xB0\xD0\xB9\xD0\xB4\xD1\x83\xD1\x82\x20\xD0\xBE\xD0\xBD\xD0\xB5\x0A\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB7\xD0\xB2\xD0\xB5\xD0\xB7\xD0\xB4\xD1\x8B\x20\xD1\x8F\xD1\x81\xD0\xBD\xD1\x8B\xD0\xB5\x20\xD0\xB2\x20\xD0\xBD\xD0\xBE\xD1\x87\xD0\xB8\x2D\x0A\xD0\x9B\xD1\x8E\xD0\xB1\xD1\x83\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\xD0\xBC\xD0\xB8\x20\xE2\x80\x93\x20\xD0\xB8\x20\xD0\xBC\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2E", "Russian"),
|
||||
new Message("\x56\x6F\x69\x78\x20\x61\x6D\x62\x69\x67\x75\xC3\xAB\x20\x64\xE2\x80\x99\x75\x6E\x20\x63\xC5\x93\x75\x72\x20\x71\x75\x69\x20\x61\x75\x20\x7A\xC3\xA9\x70\x68\x79\x72\x20\x70\x72\xC3\xA9\x66\xC3\xA8\x72\x65\x20\x6C\x65\x73\x20\x6A\x61\x74\x74\x65\x73\x20\x64\x65\x20\x6B\x69\x77\x69", "French"),
|
||||
new Message("\x42\x65\x6E\x6A\x61\x6D\xC3\xAD\x6E\x20\x70\x69\x64\x69\xC3\xB3\x20\x75\x6E\x61\x20\x62\x65\x62\x69\x64\x61\x20\x64\x65\x20\x6B\x69\x77\x69\x20\x79\x20\x66\x72\x65\x73\x61\x3B\x20\x4E\x6F\xC3\xA9\x2C\x20\x73\x69\x6E\x20\x76\x65\x72\x67\xC3\xBC\x65\x6E\x7A\x61\x2C\x20\x6C\x61\x20\x6D\xC3\xA1\x73\x20\x65\x78\x71\x75\x69\x73\x69\x74\x61\x20\x63\x68\x61\x6D\x70\x61\xC3\xB1\x61\x20\x64\x65\x6C\x20\x6D\x65\x6E\xC3\xBA\x2E", "Spanish"),
|
||||
new Message("\xCE\xA4\xCE\xB1\xCF\x87\xCE\xAF\xCF\x83\xCF\x84\xCE\xB7\x20\xCE\xB1\xCE\xBB\xCF\x8E\xCF\x80\xCE\xB7\xCE\xBE\x20\xCE\xB2\xCE\xB1\xCF\x86\xCE\xAE\xCF\x82\x20\xCF\x88\xCE\xB7\xCE\xBC\xCE\xAD\xCE\xBD\xCE\xB7\x20\xCE\xB3\xCE\xB7\x2C\x20\xCE\xB4\xCF\x81\xCE\xB1\xCF\x83\xCE\xBA\xCE\xB5\xCE\xBB\xCE\xAF\xCE\xB6\xCE\xB5\xCE\xB9\x20\xCF\x85\xCF\x80\xCE\xAD\xCF\x81\x20\xCE\xBD\xCF\x89\xCE\xB8\xCF\x81\xCE\xBF\xCF\x8D\x20\xCE\xBA\xCF\x85\xCE\xBD\xCF\x8C\xCF\x82", "Greek"),
|
||||
new Message("\xCE\x97\x20\xCE\xBA\xCE\xB1\xCE\xBB\xCF\x8D\xCF\x84\xCE\xB5\xCF\x81\xCE\xB7\x20\xCE\xAC\xCE\xBC\xCF\x85\xCE\xBD\xCE\xB1\x20\xCE\xB5\xCE\xAF\xCE\xBD\xCE\xB1\xCE\xB9\x20\xCE\xB7\x20\xCE\xB5\xCF\x80\xCE\xAF\xCE\xB8\xCE\xB5\xCF\x83\xCE\xB7\x2E", "Greek"),
|
||||
new Message("\xCE\xA7\xCF\x81\xCF\x8C\xCE\xBD\xCE\xB9\xCE\xB1\x20\xCE\xBA\xCE\xB1\xCE\xB9\x20\xCE\xB6\xCE\xB1\xCE\xBC\xCE\xAC\xCE\xBD\xCE\xB9\xCE\xB1\x21", "Greek"),
|
||||
new Message("\xCE\xA0\xCF\x8E\xCF\x82\x20\xCF\x84\xCE\xB1\x20\xCF\x80\xCE\xB1\xCF\x82\x20\xCF\x83\xCE\xAE\xCE\xBC\xCE\xB5\xCF\x81\xCE\xB1\x3B", "Greek"),
|
||||
new Message("\xE6\x88\x91\xE8\x83\xBD\xE5\x90\x9E\xE4\xB8\x8B\xE7\x8E\xBB\xE7\x92\x83\xE8\x80\x8C\xE4\xB8\x8D\xE4\xBC\xA4\xE8\xBA\xAB\xE4\xBD\x93\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE4\xBD\xA0\xE5\x90\x83\xE4\xBA\x86\xE5\x90\x97\xEF\xBC\x9F", "Chinese"),
|
||||
new Message("\xE4\xB8\x8D\xE4\xBD\x9C\xE4\xB8\x8D\xE6\xAD\xBB\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE6\x9C\x80\xE8\xBF\x91\xE5\xA5\xBD\xE5\x90\x97\xEF\xBC\x9F", "Chinese"),
|
||||
new Message("\xE5\xA1\x9E\xE7\xBF\x81\xE5\xA4\xB1\xE9\xA9\xAC\xEF\xBC\x8C\xE7\x84\x89\xE7\x9F\xA5\xE9\x9D\x9E\xE7\xA6\x8F\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE5\x8D\x83\xE5\x86\x9B\xE6\x98\x93\xE5\xBE\x97\x2C\x20\xE4\xB8\x80\xE5\xB0\x86\xE9\x9A\xBE\xE6\xB1\x82", "Chinese"),
|
||||
new Message("\xE4\xB8\x87\xE4\xBA\x8B\xE5\xBC\x80\xE5\xA4\xB4\xE9\x9A\xBE\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE9\xA3\x8E\xE6\x97\xA0\xE5\xB8\xB8\xE9\xA1\xBA\xEF\xBC\x8C\xE5\x85\xB5\xE6\x97\xA0\xE5\xB8\xB8\xE8\x83\x9C\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE6\xB4\xBB\xE5\x88\xB0\xE8\x80\x81\xEF\xBC\x8C\xE5\xAD\xA6\xE5\x88\xB0\xE8\x80\x81\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE4\xB8\x80\xE8\xA8\x80\xE6\x97\xA2\xE5\x87\xBA\xEF\xBC\x8C\xE9\xA9\xB7\xE9\xA9\xAC\xE9\x9A\xBE\xE8\xBF\xBD\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE8\xB7\xAF\xE9\x81\xA5\xE7\x9F\xA5\xE9\xA9\xAC\xE5\x8A\x9B\xEF\xBC\x8C\xE6\x97\xA5\xE4\xB9\x85\xE8\xA7\x81\xE4\xBA\xBA\xE5\xBF\x83", "Chinese"),
|
||||
new Message("\xE6\x9C\x89\xE7\x90\x86\xE8\xB5\xB0\xE9\x81\x8D\xE5\xA4\xA9\xE4\xB8\x8B\xEF\xBC\x8C\xE6\x97\xA0\xE7\x90\x86\xE5\xAF\xB8\xE6\xAD\xA5\xE9\x9A\xBE\xE8\xA1\x8C\xE3\x80\x82", "Chinese"),
|
||||
new Message("\xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B", "Japanese"),
|
||||
new Message("\xE4\xBA\x80\xE3\x81\xAE\xE7\x94\xB2\xE3\x82\x88\xE3\x82\x8A\xE5\xB9\xB4\xE3\x81\xAE\xE5\x8A\x9F", "Japanese"),
|
||||
new Message("\xE3\x81\x86\xE3\x82\x89\xE3\x82\x84\xE3\x81\xBE\xE3\x81\x97\x20\x20\xE6\x80\x9D\xE3\x81\xB2\xE5\x88\x87\xE3\x82\x8B\xE6\x99\x82\x20\x20\xE7\x8C\xAB\xE3\x81\xAE\xE6\x81\x8B", "Japanese"),
|
||||
new Message("\xE8\x99\x8E\xE7\xA9\xB4\xE3\x81\xAB\xE5\x85\xA5\xE3\x82\x89\xE3\x81\x9A\xE3\x82\x93\xE3\x81\xB0\xE8\x99\x8E\xE5\xAD\x90\xE3\x82\x92\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"),
|
||||
new Message("\xE4\xBA\x8C\xE5\x85\x8E\xE3\x82\x92\xE8\xBF\xBD\xE3\x81\x86\xE8\x80\x85\xE3\x81\xAF\xE4\xB8\x80\xE5\x85\x8E\xE3\x82\x92\xE3\x82\x82\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82", "Japanese"),
|
||||
new Message("\xE9\xA6\xAC\xE9\xB9\xBF\xE3\x81\xAF\xE6\xAD\xBB\xE3\x81\xAA\xE3\x81\xAA\xE3\x81\x8D\xE3\x82\x83\xE6\xB2\xBB\xE3\x82\x89\xE3\x81\xAA\xE3\x81\x84\xE3\x80\x82", "Japanese"),
|
||||
new Message("\xE6\x9E\xAF\xE9\x87\x8E\xE8\xB7\xAF\xE3\x81\xAB\xE3\x80\x80\xE5\xBD\xB1\xE3\x81\x8B\xE3\x81\x95\xE3\x81\xAA\xE3\x82\x8A\xE3\x81\xA6\xE3\x80\x80\xE3\x82\x8F\xE3\x81\x8B\xE3\x82\x8C\xE3\x81\x91\xE3\x82\x8A", "Japanese"),
|
||||
new Message("\xE7\xB9\xB0\xE3\x82\x8A\xE8\xBF\x94\xE3\x81\x97\xE9\xBA\xA6\xE3\x81\xAE\xE7\x95\x9D\xE7\xB8\xAB\xE3\x81\xB5\xE8\x83\xA1\xE8\x9D\xB6\xE5\x93\x89", "Japanese"),
|
||||
new Message("\xEC\x95\x84\xEB\x93\x9D\xED\x95\x9C\x20\xEB\xB0\x94\xEB\x8B\xA4\x20\xEC\x9C\x84\xEC\x97\x90\x20\xEA\xB0\x88\xEB\xA7\xA4\xEA\xB8\xB0\x20\xEB\x91\x90\xEC\x97\x87\x20\xEB\x82\xA0\xEC\x95\x84\x20\xEB\x8F\x88\xEB\x8B\xA4\x2E\x0A\xEB\x84\x88\xED\x9B\x8C\xEB\x84\x88\xED\x9B\x8C\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E\x20\xEB\xAA\xA8\xEB\xA5\xB4\xEB\x8A\x94\x20\xEB\x82\x98\xEB\x9D\xBC\x20\xEA\xB8\x80\xEC\x9E\x90\xEB\x8B\xA4\x2E\x0A\xEB\x84\x90\xEB\x94\xB0\xEB\x9E\x80\x20\xED\x95\x98\xEB\x8A\x98\x20\xEB\xB3\xB5\xED\x8C\x90\xEC\x97\x90\x20\xEB\x82\x98\xEB\x8F\x84\x20\xEA\xB0\x99\xEC\x9D\xB4\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E", "Korean"),
|
||||
new Message("\xEC\xA0\x9C\x20\xEB\x88\x88\xEC\x97\x90\x20\xEC\x95\x88\xEA\xB2\xBD\xEC\x9D\xB4\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xEA\xBF\xA9\x20\xEB\xA8\xB9\xEA\xB3\xA0\x20\xEC\x95\x8C\x20\xEB\xA8\xB9\xEB\x8A\x94\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xEB\xA1\x9C\xEB\xA7\x88\xEB\x8A\x94\x20\xED\x95\x98\xEB\xA3\xA8\xEC\x95\x84\xEC\xB9\xA8\xEC\x97\x90\x20\xEC\x9D\xB4\xEB\xA3\xA8\xEC\x96\xB4\xEC\xA7\x84\x20\xEA\xB2\x83\xEC\x9D\xB4\x20\xEC\x95\x84\xEB\x8B\x88\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xEA\xB3\xA0\xEC\x83\x9D\x20\xEB\x81\x9D\xEC\x97\x90\x20\xEB\x82\x99\xEC\x9D\xB4\x20\xEC\x98\xA8\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xEA\xB0\x9C\xEC\xB2\x9C\xEC\x97\x90\xEC\x84\x9C\x20\xEC\x9A\xA9\x20\xEB\x82\x9C\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"),
|
||||
new Message("\xEB\xA7\x8C\xEB\x82\x98\xEC\x84\x9C\x20\xEB\xB0\x98\xEA\xB0\x91\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4", "Korean"),
|
||||
new Message("\xED\x95\x9C\xEA\xB5\xAD\xEB\xA7\x90\x20\xED\x95\x98\xEC\x8B\xA4\x20\xEC\xA4\x84\x20\xEC\x95\x84\xEC\x84\xB8\xEC\x9A\x94\x3F", "Korean"),
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module functions declaration
|
||||
//--------------------------------------------------------------------------------------
|
||||
static void RandomizeEmoji(void); // Fills the emoji array with random emojis
|
||||
private Font fontDefault;
|
||||
private Font fontAsian;
|
||||
private Font fontEmoji;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global variables
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Arrays that holds the random emojis
|
||||
struct emoji
|
||||
private Vector2 hoveredPos;
|
||||
private Vector2 selectedPos;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
int index; // Index inside `emojiCodepoints`
|
||||
int message; // Message index
|
||||
Color color; // Emoji color
|
||||
emoji = new EmojiInfo[EmojiPerWidth * EmojiPerHeight];
|
||||
|
||||
hovered = -1;
|
||||
selected = -1;
|
||||
|
||||
// Load the font resources
|
||||
// NOTE: fontAsian is for asian languages,
|
||||
// fontEmoji is the emojis and fontDefault is used for everything else
|
||||
fontDefault = LoadFont("resources/fonts/dejavu.fnt"); // Requires "resources/fonts/dejavu.png"
|
||||
fontAsian = LoadFont("resources/fonts/noto_cjk.fnt"); // Requires "resources/fonts/noto_cjk.png"
|
||||
fontEmoji = LoadFont("resources/fonts/symbola.fnt"); // Requires "resources/fonts/symbola.png"
|
||||
|
||||
hoveredPos = new(0.0f, 0.0f);
|
||||
selectedPos = new(0.0f, 0.0f);
|
||||
|
||||
// Set a random set of emojis when starting up
|
||||
RandomizeEmoji();
|
||||
}
|
||||
emoji[EMOJI_PER_WIDTH * EMOJI_PER_HEIGHT] = { 0 };
|
||||
|
||||
static int hovered = -1, selected = -1;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode");
|
||||
|
||||
// Load the font resources
|
||||
// NOTE: fontAsian is for asian languages,
|
||||
// fontEmoji is the emojis and fontDefault is used for everything else
|
||||
Font fontDefault = LoadFont("resources/fonts/dejavu.fnt");
|
||||
Font fontAsian = LoadFont("resources/fonts/notoCJK.fnt");
|
||||
Font fontEmoji = LoadFont("resources/fonts/emoji.fnt");
|
||||
|
||||
Vector2 hoveredPos = new(0.0f, 0.0f);
|
||||
Vector2 selectedPos = new(0.0f, 0.0f);
|
||||
|
||||
// Set a random set of emojis when starting up
|
||||
RandomizeEmoji();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Add a new set of emojis when SPACE is pressed
|
||||
if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji();
|
||||
if (IsKeyPressed(KeyboardKey.Space))
|
||||
{
|
||||
RandomizeEmoji();
|
||||
}
|
||||
|
||||
// Set the selected emoji and copy its text to clipboard
|
||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (hovered != -1) && (hovered != selected))
|
||||
// Set the selected emoji
|
||||
if (IsMouseButtonPressed(MouseButton.Left) && (hovered != -1) && (hovered != selected))
|
||||
{
|
||||
selected = hovered;
|
||||
selectedPos = hoveredPos;
|
||||
SetClipboardText(messages[emoji[selected].message].text);
|
||||
}
|
||||
|
||||
Vector2 mouse = GetMousePosition();
|
||||
Vector2 pos = new(28.8f, 10.0f);
|
||||
Vector2 position = new(28.8f, 10.0f);
|
||||
hovered = -1;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
// Draw random emojis in the background
|
||||
//------------------------------------------------------------------------------
|
||||
for (int i = 0; i < SIZEOF(emoji); ++i)
|
||||
for (int i = 0; i < emoji.Length; i++)
|
||||
{
|
||||
const char* txt = ref[emoji[i].index];
|
||||
Rectangle emojiRect = new(pos.X, pos.Y, fontEmoji.BaseSize, fontEmoji.BaseSize);
|
||||
string txt = GetEmojiAt(emoji[i].Index);
|
||||
Rectangle emojiRect = new(position.X, position.Y, fontEmoji.BaseSize, fontEmoji.BaseSize);
|
||||
|
||||
if (!CheckCollisionPointRec(mouse, emojiRect))
|
||||
{
|
||||
DrawTextEx(fontEmoji, txt, pos, fontEmoji.BaseSize, 1.0, selected == i ? emoji[i].Color : ColorAlpha(LIGHTGRAY, 0.4f));
|
||||
DrawTextEx(fontEmoji, txt, position, fontEmoji.BaseSize, 1.0f, selected == i ? emoji[i].Color : Fade(Color.LightGray, 0.4f));
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextEx(fontEmoji, txt, pos, fontEmoji.BaseSize, 1.0, emoji[i].Color);
|
||||
DrawTextEx(fontEmoji, txt, position, fontEmoji.BaseSize, 1.0f, emoji[i].Color);
|
||||
hovered = i;
|
||||
hoveredPos = pos;
|
||||
hoveredPos = position;
|
||||
}
|
||||
|
||||
if ((i != 0) && (i % EMOJI_PER_WIDTH == 0)) { pos.Y += fontEmoji.BaseSize + 24.25f; pos.X = 28.8f; }
|
||||
else pos.X += fontEmoji.BaseSize + 28.8f;
|
||||
if ((i != 0) && (i % EmojiPerWidth == 0))
|
||||
{
|
||||
position.Y += fontEmoji.BaseSize + 24.25f;
|
||||
position.X = 28.8f;
|
||||
}
|
||||
else
|
||||
{
|
||||
position.X += fontEmoji.BaseSize + 28.8f;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -230,19 +228,30 @@ int main(int argc, char** argv)
|
|||
//------------------------------------------------------------------------------
|
||||
if (selected != -1)
|
||||
{
|
||||
const int message = emoji[selected].message;
|
||||
const int horizontalPadding = 20, verticalPadding = 30;
|
||||
Font* font = ref;
|
||||
int message = emoji[selected].Message;
|
||||
const int horizontalPadding = 20;
|
||||
const int verticalPadding = 30;
|
||||
Font font = fontDefault;
|
||||
|
||||
// Set correct font for asian languages
|
||||
if (TextIsEqual(messages[message].language, "Chinese") ||
|
||||
TextIsEqual(messages[message].language, "Korean") ||
|
||||
TextIsEqual(messages[message].language, "Japanese")) font = ref;
|
||||
if ((messages[message].Language == "Chinese") ||
|
||||
(messages[message].Language == "Korean") ||
|
||||
(messages[message].Language == "Japanese"))
|
||||
{
|
||||
font = fontAsian;
|
||||
}
|
||||
|
||||
// Calculate size for the message box (approximate the height and width)
|
||||
Vector2 sz = MeasureTextEx(*font, messages[message].text, font->baseSize, 1.0f);
|
||||
if (sz.X > 300) { sz.Y *= sz.X / 300; sz.X = 300; }
|
||||
else if (sz.X < 160) sz.X = 160;
|
||||
Vector2 sz = MeasureTextEx(font, messages[message].Text, font.BaseSize, 1.0f);
|
||||
if (sz.X > 300)
|
||||
{
|
||||
sz.Y *= sz.X / 300;
|
||||
sz.X = 300;
|
||||
}
|
||||
else if (sz.X < 160)
|
||||
{
|
||||
sz.X = 160;
|
||||
}
|
||||
|
||||
Rectangle msgRect = new(selectedPos.X - 38.8f, selectedPos.Y, 2 * horizontalPadding + sz.X, 2 * verticalPadding + sz.Y);
|
||||
msgRect.Y -= msgRect.Height;
|
||||
|
|
@ -253,7 +262,11 @@ int main(int argc, char** argv)
|
|||
Vector2 c = new(a.X + 10, a.Y);
|
||||
|
||||
// Don't go outside the screen
|
||||
if (msgRect.X < 10) msgRect.X += 28;
|
||||
if (msgRect.X < 10)
|
||||
{
|
||||
msgRect.X += 28;
|
||||
}
|
||||
|
||||
if (msgRect.Y < 10)
|
||||
{
|
||||
msgRect.Y = selectedPos.Y + 84;
|
||||
|
|
@ -266,65 +279,269 @@ int main(int argc, char** argv)
|
|||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
if (msgRect.X + msgRect.Width > screenWidth) msgRect.X -= (msgRect.X + msgRect.Width) - screenWidth + 10;
|
||||
|
||||
if (msgRect.X + msgRect.Width > screenWidth)
|
||||
{
|
||||
msgRect.X -= (msgRect.X + msgRect.Width) - screenWidth + 10;
|
||||
}
|
||||
|
||||
// Draw chat bubble
|
||||
DrawRectangleRec(msgRect, emoji[selected].Color);
|
||||
DrawTriangle(a, b, c, emoji[selected].Color);
|
||||
|
||||
// Draw the main text message
|
||||
Rectangle textRect = new(msgRect.X + horizontalPadding / 2, msgRect.Y + verticalPadding / 2, msgRect.Width - horizontalPadding, msgRect.Height);
|
||||
DrawTextRec(*font, messages[message].text, textRect, font->baseSize, 1.0f, true, WHITE);
|
||||
Rectangle textRect = new(msgRect.X + (float)horizontalPadding / 2, msgRect.Y + (float)verticalPadding / 2, msgRect.Width - horizontalPadding, msgRect.Height);
|
||||
DrawTextBoxed(font, messages[message].Text, textRect, font.BaseSize, 1.0f, true, Color.White);
|
||||
|
||||
// Draw the info text below the main message
|
||||
int size = strlen(messages[message].text);
|
||||
int len = GetCodepointsCount(messages[message].text);
|
||||
const char* info = TextFormat("%s %u characters %i bytes", messages[message].language, len, size);
|
||||
int size = Encoding.UTF8.GetByteCount(messages[message].Text);
|
||||
int length = GetCodepointCount(messages[message].Text);
|
||||
string info = $"{messages[message].Language} {length} characters {size} bytes";
|
||||
sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f);
|
||||
Vector2 pos = new(textRect.X + textRect.Width - sz.X, msgRect.Y + msgRect.Height - sz.Y - 2);
|
||||
DrawText(info, pos.X, pos.Y, 10, RAYWHITE);
|
||||
|
||||
DrawText(info, (int)(textRect.X + textRect.Width - sz.X), (int)(msgRect.Y + msgRect.Height - sz.Y - 2), 10, Color.RayWhite);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Draw the info text
|
||||
DrawText("These emojis have something to tell you, click each to find out!", (screenWidth - 650) / 2, screenHeight - 40, 20, GRAY);
|
||||
DrawText("Each emoji is a unicode character from a font, not a texture... Press [SPACEBAR] to refresh", (screenWidth - 484) / 2, screenHeight - 16, 10, GRAY);
|
||||
DrawText("These emojis have something to tell you, click each to find out!", (screenWidth - 650) / 2, screenHeight - 40, 20, Color.Gray);
|
||||
DrawText("Each emoji is a unicode character from a font, not a texture... Press [SPACEBAR] to refresh", (screenWidth - 484) / 2, screenHeight - 16, 10, Color.Gray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadFont(fontDefault); // Unload font resource
|
||||
UnloadFont(fontAsian); // Unload font resource
|
||||
UnloadFont(fontEmoji); // Unload font resource
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fills the emoji array with random emoji (only those emojis present in fontEmoji)
|
||||
static void RandomizeEmoji(void)
|
||||
{
|
||||
hovered = selected = -1;
|
||||
int start = GetRandomValue(45, 360);
|
||||
|
||||
for (int i = 0; i < SIZEOF(emoji); ++i)
|
||||
public void Unload()
|
||||
{
|
||||
// 0-179 emoji codepoints (from emoji char array) each 4bytes + null char
|
||||
emoji[i].index = GetRandomValue(0, 179) * 5;
|
||||
UnloadFont(fontDefault); // Unload font resource
|
||||
UnloadFont(fontAsian); // Unload font resource
|
||||
UnloadFont(fontEmoji); // Unload font resource
|
||||
}
|
||||
|
||||
// Generate a random color for this emoji
|
||||
Vector3 hsv = new((start * (i + 1)) % 360, 0.6f, 0.85f);
|
||||
emoji[i].Color = ColorAlpha(ColorFromHSV(hsv), 0.8f);
|
||||
// Fills the emoji array with random emoji (only those emojis present in fontEmoji)
|
||||
void RandomizeEmoji()
|
||||
{
|
||||
hovered = selected = -1;
|
||||
int start = GetRandomValue(45, 360);
|
||||
|
||||
// Set a random message for this emoji
|
||||
emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1);
|
||||
for (int i = 0; i < emoji.Length; i++)
|
||||
{
|
||||
// 0-179 emoji codepoints (from emoji char array) each 4bytes + null char
|
||||
emoji[i].Index = GetRandomValue(0, 179) * 5;
|
||||
|
||||
// Generate a random color for this emoji
|
||||
emoji[i].Color = Fade(ColorFromHSV((start * (i + 1)) % 360, 0.6f, 0.85f), 0.8f);
|
||||
|
||||
// Set a random message for this emoji
|
||||
emoji[i].Message = GetRandomValue(0, messages.Length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the emoji codepoint (4 bytes + null) located at the given byte index inside EmojiCodepoints
|
||||
static string GetEmojiAt(int index)
|
||||
{
|
||||
// Each emoji takes 4 bytes followed by a null separator, codepoints are stored as raw bytes
|
||||
var sb = new StringBuilder();
|
||||
for (int i = index; (i < EmojiCodepoints.Length) && (EmojiCodepoints[i] != '\0'); i++)
|
||||
{
|
||||
sb.Append(EmojiCodepoints[i]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw text using font inside rectangle limits
|
||||
static void DrawTextBoxed(Font font, string text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
|
||||
{
|
||||
DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, Color.White, Color.White);
|
||||
}
|
||||
|
||||
// Draw text using font inside rectangle limits with support for text selection
|
||||
static unsafe void DrawTextBoxedSelectable(Font font, string text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint)
|
||||
{
|
||||
int length = text.Length; // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
|
||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||
|
||||
float scaleFactor = fontSize / (float)font.BaseSize; // Character rectangle scaling factor
|
||||
|
||||
// Word/character wrapping mechanism variables
|
||||
const int MeasureState = 0;
|
||||
const int DrawState = 1;
|
||||
int state = wordWrap ? MeasureState : DrawState;
|
||||
|
||||
int startLine = -1; // Index where to begin drawing (where a line begins)
|
||||
int endLine = -1; // Index where to stop drawing (where a line ends)
|
||||
int lastk = -1; // Holds last value of the character position
|
||||
|
||||
using var textNative = new Utf8Buffer(text);
|
||||
|
||||
for (int i = 0, k = 0; i < length; i++, k++)
|
||||
{
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
int codepointByteCount = 0;
|
||||
int codepoint = GetCodepoint(&textNative.AsPointer()[i], &codepointByteCount);
|
||||
int index = GetGlyphIndex(font, codepoint);
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f)
|
||||
{
|
||||
codepointByteCount = 1;
|
||||
}
|
||||
|
||||
i += (codepointByteCount - 1);
|
||||
|
||||
float glyphWidth = 0;
|
||||
if (codepoint != '\n')
|
||||
{
|
||||
glyphWidth = (font.Glyphs[index].AdvanceX == 0) ?
|
||||
font.Recs[index].Width * scaleFactor :
|
||||
font.Glyphs[index].AdvanceX * scaleFactor;
|
||||
|
||||
if (i + 1 < length)
|
||||
{
|
||||
glyphWidth = glyphWidth + spacing;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
||||
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
||||
// and change states again and again recursively until the end of the text (or until we get outside of the container)
|
||||
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
||||
// and begin drawing on the next line before we can get outside the container
|
||||
if (state == MeasureState)
|
||||
{
|
||||
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
||||
// Ref: http://jkorpela.fi/chars/spaces.html
|
||||
if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n'))
|
||||
{
|
||||
endLine = i;
|
||||
}
|
||||
|
||||
if ((textOffsetX + glyphWidth) > rec.Width)
|
||||
{
|
||||
endLine = (endLine < 1) ? i : endLine;
|
||||
if (i == endLine)
|
||||
{
|
||||
endLine -= codepointByteCount;
|
||||
}
|
||||
if ((startLine + codepointByteCount) == endLine)
|
||||
{
|
||||
endLine = (i - codepointByteCount);
|
||||
}
|
||||
|
||||
state = 1 - state;
|
||||
}
|
||||
else if ((i + 1) == length)
|
||||
{
|
||||
endLine = i;
|
||||
state = 1 - state;
|
||||
}
|
||||
else if (codepoint == '\n')
|
||||
{
|
||||
state = 1 - state;
|
||||
}
|
||||
|
||||
if (state == DrawState)
|
||||
{
|
||||
textOffsetX = 0;
|
||||
i = startLine;
|
||||
glyphWidth = 0;
|
||||
|
||||
// Save character position when we switch states
|
||||
int tmp = lastk;
|
||||
lastk = k - 1;
|
||||
k = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codepoint == '\n')
|
||||
{
|
||||
if (!wordWrap)
|
||||
{
|
||||
textOffsetY += (font.BaseSize + font.BaseSize / 2) * scaleFactor;
|
||||
textOffsetX = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.Width))
|
||||
{
|
||||
textOffsetY += (font.BaseSize + font.BaseSize / 2) * scaleFactor;
|
||||
textOffsetX = 0;
|
||||
}
|
||||
|
||||
// When text overflows rectangle height limit, just stop drawing
|
||||
if ((textOffsetY + font.BaseSize * scaleFactor) > rec.Height)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw selection background
|
||||
bool isGlyphSelected = false;
|
||||
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
|
||||
{
|
||||
DrawRectangleRec(new Rectangle(rec.X + textOffsetX - 1, rec.Y + textOffsetY, glyphWidth, (float)font.BaseSize * scaleFactor), selectBackTint);
|
||||
isGlyphSelected = true;
|
||||
}
|
||||
|
||||
// Draw current character glyph
|
||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||
{
|
||||
DrawTextCodepoint(font, codepoint, new Vector2(rec.X + textOffsetX, rec.Y + textOffsetY), fontSize, isGlyphSelected ? selectTint : tint);
|
||||
}
|
||||
}
|
||||
|
||||
if (wordWrap && (i == endLine))
|
||||
{
|
||||
textOffsetY += (font.BaseSize + font.BaseSize / 2) * scaleFactor;
|
||||
textOffsetX = 0;
|
||||
startLine = endLine;
|
||||
endLine = -1;
|
||||
glyphWidth = 0;
|
||||
selectStart += lastk - k;
|
||||
k = lastk;
|
||||
|
||||
state = 1 - state;
|
||||
}
|
||||
}
|
||||
|
||||
textOffsetX += glyphWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
SetConfigFlags(ConfigFlags.Msaa4xHint | ConfigFlags.VSyncHint);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode emojis");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new Unicode();
|
||||
game.Init();
|
||||
|
||||
// Main loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
225
Examples/Text/UnicodeRanges.cs
Normal file
225
Examples/Text/UnicodeRanges.cs
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - unicode ranges
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Vadim Gunko (@GuvaCode) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 Vadim Gunko (@GuvaCode) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using Raylib_cs;
|
||||
using static Raylib_cs.Raylib;
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class UnicodeRanges : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// path differs from upstream: font lives under resources/fonts/
|
||||
private const string FontPath = "resources/fonts/NotoSansTC-Regular.ttf";
|
||||
|
||||
public string Name => "Text / Unicode Ranges";
|
||||
|
||||
public string Title => "raylib [text] example - unicode ranges";
|
||||
|
||||
private Font font;
|
||||
private int unicodeRange; // Track the ranges of codepoints added to font
|
||||
private int prevUnicodeRange; // Previous Unicode range to avoid reloading every frame
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Load font with default Unicode range: Basic ASCII [32-127]
|
||||
font = LoadFont(FontPath);
|
||||
SetTextureFilter(font.Texture, TextureFilter.Bilinear);
|
||||
|
||||
unicodeRange = 0;
|
||||
prevUnicodeRange = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (unicodeRange != prevUnicodeRange)
|
||||
{
|
||||
UnloadFont(font);
|
||||
|
||||
// Load font with default Unicode range: Basic ASCII [32-127]
|
||||
font = LoadFont(FontPath);
|
||||
|
||||
// Add required ranges to loaded font
|
||||
// NOTE: The upstream switch uses fall-through so range N also loads all lower
|
||||
// ranges, in the same order (4 -> 3 -> 2 -> 1); the descending if-chain preserves that.
|
||||
|
||||
/*
|
||||
if (unicodeRange >= 5)
|
||||
{
|
||||
// Unicode range: Devanari, Arabic, Hebrew
|
||||
// WARNING: Glyphs not available on provided font!
|
||||
AddCodepointRange(ref font, FontPath, 0x900, 0x97f); // Devanagari
|
||||
AddCodepointRange(ref font, FontPath, 0x600, 0x6ff); // Arabic
|
||||
AddCodepointRange(ref font, FontPath, 0x5d0, 0x5ea); // Hebrew
|
||||
}
|
||||
*/
|
||||
if (unicodeRange >= 4)
|
||||
{
|
||||
// Unicode range: CJK (Japanese and Chinese)
|
||||
// WARNING: Loading thousands of codepoints requires lot of time!
|
||||
// A better strategy is prefilter the required codepoints for the text
|
||||
// in the game and just load the required ones
|
||||
AddCodepointRange(ref font, FontPath, 0x4e00, 0x9fff);
|
||||
AddCodepointRange(ref font, FontPath, 0x3400, 0x4dbf);
|
||||
AddCodepointRange(ref font, FontPath, 0x3000, 0x303f);
|
||||
AddCodepointRange(ref font, FontPath, 0x3040, 0x309f);
|
||||
AddCodepointRange(ref font, FontPath, 0x30A0, 0x30ff);
|
||||
AddCodepointRange(ref font, FontPath, 0x31f0, 0x31ff);
|
||||
AddCodepointRange(ref font, FontPath, 0xff00, 0xffef);
|
||||
AddCodepointRange(ref font, FontPath, 0xac00, 0xd7af);
|
||||
AddCodepointRange(ref font, FontPath, 0x1100, 0x11ff);
|
||||
}
|
||||
if (unicodeRange >= 3)
|
||||
{
|
||||
// Unicode range: Cyrillic
|
||||
AddCodepointRange(ref font, FontPath, 0x400, 0x4ff);
|
||||
AddCodepointRange(ref font, FontPath, 0x500, 0x52f);
|
||||
AddCodepointRange(ref font, FontPath, 0x2de0, 0x2Dff);
|
||||
AddCodepointRange(ref font, FontPath, 0xa640, 0xA69f);
|
||||
}
|
||||
if (unicodeRange >= 2)
|
||||
{
|
||||
// Unicode range: Greek
|
||||
AddCodepointRange(ref font, FontPath, 0x370, 0x3ff);
|
||||
AddCodepointRange(ref font, FontPath, 0x1f00, 0x1fff);
|
||||
}
|
||||
if (unicodeRange >= 1)
|
||||
{
|
||||
// Unicode range: European Languages
|
||||
AddCodepointRange(ref font, FontPath, 0xc0, 0x17f);
|
||||
AddCodepointRange(ref font, FontPath, 0x180, 0x24f);
|
||||
//AddCodepointRange(ref font, FontPath, 0x1e00, 0x1eff);
|
||||
//AddCodepointRange(ref font, FontPath, 0x2c60, 0x2c7f);
|
||||
}
|
||||
|
||||
prevUnicodeRange = unicodeRange;
|
||||
SetTextureFilter(font.Texture, TextureFilter.Bilinear); // Set font atlas scale filter
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Zero)) unicodeRange = 0;
|
||||
else if (IsKeyPressed(KeyboardKey.One)) unicodeRange = 1;
|
||||
else if (IsKeyPressed(KeyboardKey.Two)) unicodeRange = 2;
|
||||
else if (IsKeyPressed(KeyboardKey.Three)) unicodeRange = 3;
|
||||
else if (IsKeyPressed(KeyboardKey.Four)) unicodeRange = 4;
|
||||
//else if (IsKeyPressed(KeyboardKey.Five)) unicodeRange = 5;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText("ADD CODEPOINTS: [1][2][3][4]", 20, 20, 20, Color.Maroon);
|
||||
|
||||
// Render test strings in different languages
|
||||
DrawTextEx(font, "> English: Hello World!", new Vector2(50, 70), 32, 1, Color.DarkGray); // English
|
||||
DrawTextEx(font, "> Español: Hola mundo!", new Vector2(50, 120), 32, 1, Color.DarkGray); // Spanish
|
||||
DrawTextEx(font, "> Ελληνικά: Γειά σου κόσμε!", new Vector2(50, 170), 32, 1, Color.DarkGray); // Greek
|
||||
DrawTextEx(font, "> Русский: Привет мир!", new Vector2(50, 220), 32, 0, Color.DarkGray); // Russian
|
||||
DrawTextEx(font, "> 中文: 你好世界!", new Vector2(50, 270), 32, 1, Color.DarkGray); // Chinese
|
||||
DrawTextEx(font, "> 日本語: こんにちは世界!", new Vector2(50, 320), 32, 1, Color.DarkGray); // Japanese
|
||||
//DrawTextEx(font, "देवनागरी: होला मुंडो!", new Vector2(50, 350), 32, 1, Color.DarkGray); // Devanagari (glyphs not available in font)
|
||||
|
||||
// Draw font texture scaled to screen
|
||||
float atlasScale = 380.0f / font.Texture.Width;
|
||||
DrawRectangleRec(new Rectangle(400.0f, 16.0f, font.Texture.Width * atlasScale, font.Texture.Height * atlasScale), Color.Black);
|
||||
DrawTexturePro(font.Texture, new Rectangle(0, 0, font.Texture.Width, font.Texture.Height),
|
||||
new Rectangle(400.0f, 16.0f, font.Texture.Width * atlasScale, font.Texture.Height * atlasScale), new Vector2(0, 0), 0.0f, Color.White);
|
||||
DrawRectangleLines(400, 16, 380, 380, Color.Red);
|
||||
|
||||
DrawText($"ATLAS SIZE: {font.Texture.Width}x{font.Texture.Height} px (x{atlasScale:00.00})", 20, 380, 20, Color.Blue);
|
||||
DrawText($"CODEPOINTS GLYPHS LOADED: {font.GlyphCount}", 20, 410, 20, Color.Lime);
|
||||
|
||||
// Display font attribution
|
||||
DrawText("Font: Noto Sans TC. License: SIL Open Font License 1.1", screenWidth - 300, screenHeight - 20, 10, Color.Gray);
|
||||
|
||||
if (prevUnicodeRange != unicodeRange)
|
||||
{
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, Fade(Color.White, 0.8f));
|
||||
DrawRectangle(0, 125, screenWidth, 200, Color.Gray);
|
||||
DrawText("GENERATING FONT ATLAS...", 120, 210, 40, Color.Black);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
UnloadFont(font); // Unload font resource
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Add codepoint range to existing font
|
||||
private static unsafe void AddCodepointRange(ref Font font, string fontPath, int start, int stop)
|
||||
{
|
||||
int rangeSize = stop - start + 1;
|
||||
int currentRangeSize = font.GlyphCount;
|
||||
|
||||
// TODO: Load glyphs from provided vector font (if available),
|
||||
// add them to existing font, regenerating font image and texture
|
||||
|
||||
int updatedCodepointCount = currentRangeSize + rangeSize;
|
||||
int[] updatedCodepoints = new int[updatedCodepointCount];
|
||||
|
||||
// Get current codepoint list
|
||||
for (int i = 0; i < currentRangeSize; i++) updatedCodepoints[i] = font.Glyphs[i].Value;
|
||||
|
||||
// Add new codepoints to list (provided range)
|
||||
for (int i = currentRangeSize; i < updatedCodepointCount; i++)
|
||||
updatedCodepoints[i] = start + (i - currentRangeSize);
|
||||
|
||||
UnloadFont(font);
|
||||
font = LoadFontEx(fontPath, 32, updatedCodepoints, updatedCodepointCount);
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - unicode ranges");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new UnicodeRanges();
|
||||
game.Init();
|
||||
|
||||
// Main loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
167
Examples/Text/WordsAlignment.cs
Normal file
167
Examples/Text/WordsAlignment.cs
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - words alignment
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 JP Mortiboys (@themushroompirates)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
using System.Numerics;
|
||||
using static Raylib_cs.Raylib;
|
||||
using static Raylib_cs.Raymath; // Required for: Lerp()
|
||||
|
||||
namespace Examples.Text;
|
||||
|
||||
public partial class WordsAlignment : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
// TextAlignment values: Left/Top = 0, Centre/Middle = 1, Right/Bottom = 2
|
||||
|
||||
public string Name => "Text / Words Alignment";
|
||||
|
||||
public string Title => "raylib [text] example - words alignment";
|
||||
|
||||
// Define the rectangle we will draw the text in
|
||||
private Rectangle textContainerRect;
|
||||
|
||||
// Some text to display the current alignment
|
||||
private static readonly string[] textAlignNameH = { "Left", "Centre", "Right" };
|
||||
private static readonly string[] textAlignNameV = { "Top", "Middle", "Bottom" };
|
||||
|
||||
// Define the text we're going to draw in the rectangle
|
||||
private int wordIndex;
|
||||
private int wordCount;
|
||||
private string[] words;
|
||||
|
||||
// Initialize the font size we're going to use
|
||||
private int fontSize;
|
||||
|
||||
// And of course the font...
|
||||
private Font font;
|
||||
|
||||
// Initialize the alignment variables
|
||||
private int hAlign;
|
||||
private int vAlign;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
// Define the rectangle we will draw the text in
|
||||
textContainerRect = new Rectangle((float)screenWidth / 2 - (float)screenWidth / 4, (float)screenHeight / 2 - (float)screenHeight / 3, (float)screenWidth / 2, (float)screenHeight * 2 / 3);
|
||||
|
||||
// Define the text we're going to draw in the rectangle
|
||||
wordIndex = 0;
|
||||
words = "raylib is a simple and easy-to-use library to enjoy videogames programming".Split(' ');
|
||||
wordCount = words.Length;
|
||||
|
||||
// Initialize the font size we're going to use
|
||||
fontSize = 40;
|
||||
|
||||
// And of course the font...
|
||||
font = GetFontDefault();
|
||||
|
||||
// Initialize the alignment variables
|
||||
hAlign = 1; // TEXT_ALIGN_CENTRE
|
||||
vAlign = 1; // TEXT_ALIGN_MIDDLE
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.Left))
|
||||
{
|
||||
if (hAlign > 0) hAlign = hAlign - 1;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Right))
|
||||
{
|
||||
hAlign = hAlign + 1;
|
||||
if (hAlign > 2) hAlign = 2;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Up))
|
||||
{
|
||||
if (vAlign > 0) vAlign = vAlign - 1;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Down))
|
||||
{
|
||||
vAlign = vAlign + 1;
|
||||
if (vAlign > 2) vAlign = 2;
|
||||
}
|
||||
|
||||
// One word per second
|
||||
if (wordCount > 0) wordIndex = (int)GetTime() % wordCount;
|
||||
else wordIndex = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(Color.DarkBlue);
|
||||
|
||||
DrawText("Use Arrow Keys to change the text alignment", 20, 20, 20, Color.LightGray);
|
||||
DrawText($"Alignment: Horizontal = {textAlignNameH[hAlign]}, Vertical = {textAlignNameV[vAlign]}", 20, 40, 20, Color.LightGray);
|
||||
|
||||
DrawRectangleRec(textContainerRect, Color.Blue);
|
||||
|
||||
// Get the size of the text to draw
|
||||
Vector2 textSize = MeasureTextEx(font, words[wordIndex], fontSize, fontSize * .1f);
|
||||
|
||||
// Calculate the top-left text position based on the rectangle and alignment
|
||||
Vector2 textPos = new Vector2(
|
||||
textContainerRect.X + Lerp(0.0f, textContainerRect.Width - textSize.X, hAlign * 0.5f),
|
||||
textContainerRect.Y + Lerp(0.0f, textContainerRect.Height - textSize.Y, vAlign * 0.5f)
|
||||
);
|
||||
|
||||
// Draw the text
|
||||
DrawTextEx(font, words[wordIndex], textPos, fontSize, fontSize * .1f, Color.RayWhite);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WordsAlignment();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [text] example - Text Writing Animation
|
||||
* raylib [text] example - writing anim
|
||||
*
|
||||
* This example has been created using raylib 1.4 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
|
||||
* Example originally created with raylib 1.4, last time updated with raylib 1.4
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2016-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
|
|
@ -13,60 +17,85 @@ using static Raylib_cs.Raylib;
|
|||
|
||||
namespace Examples.Text;
|
||||
|
||||
public class WritingAnim
|
||||
public partial class WritingAnim : IExample
|
||||
{
|
||||
private const int screenWidth = 800;
|
||||
private const int screenHeight = 450;
|
||||
|
||||
public string Name => "Text / Writing Animation";
|
||||
|
||||
public string Title => "raylib [text] example - writing anim";
|
||||
|
||||
private string message;
|
||||
private int framesCounter;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
message = "This sample illustrates a text writing\nanimation effect! Check it out! ;)";
|
||||
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
framesCounter += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesCounter += 1;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText(message.SubText(0, framesCounter / 10), 210, 160, 20, Color.Maroon);
|
||||
|
||||
DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, Color.LightGray);
|
||||
DrawText("HOLD [SPACE] to SPEED UP!", 239, 300, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
}
|
||||
|
||||
public static int Main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - writing anim");
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim");
|
||||
|
||||
string message = "This sample illustrates a text writing\nanimation effect! Check it out! ;)";
|
||||
int framesCounter = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
var game = new WritingAnim();
|
||||
game.Init();
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KeyboardKey.Space))
|
||||
{
|
||||
framesCounter += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
framesCounter += 1;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KeyboardKey.Enter))
|
||||
{
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(Color.RayWhite);
|
||||
|
||||
DrawText(message.SubText(0, framesCounter / 10), 210, 160, 20, Color.Maroon);
|
||||
|
||||
DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, Color.LightGray);
|
||||
DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, Color.LightGray);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
game.Update();
|
||||
}
|
||||
|
||||
game.Unload();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow();
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue