2
0
mirror of https://github.com/raylib-cs/raylib-cs synced 2025-06-30 19:03:42 -04:00

Update/merge examples back into main repo (#192)

This commit is contained in:
2023-08-25 08:08:32 +01:00
committed by GitHub
parent fa682b00ac
commit bcdf8cec5b
320 changed files with 57965 additions and 1 deletions

View File

@ -0,0 +1,132 @@
/*******************************************************************************************
*
* raylib [text] example - Codepoints loading
*
* Example originally created with raylib 4.2, last time updated with raylib 2.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) 2022-2023 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
using static Raylib_cs.Raylib;
namespace Examples.Text;
class CodepointsLoading
{
public unsafe static int Main()
{
// 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);
// Remove duplicate codepoints to generate smaller font atlas
int[] codepointsNoDuplicates = codepoints.Distinct().ToArray();
// Load font containing all the provided codepoint glyphs
// A texture font atlas is automatically generated
Font font = LoadFontEx(
"resources/DotGothic16-Regular.ttf",
36,
codepointsNoDuplicates,
codepointsNoDuplicates.Length
);
// Set bilinear scale filter for better font scaling
SetTextureFilter(font.Texture, TextureFilter.TEXTURE_FILTER_BILINEAR);
bool showFontAtlas = false;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KeyboardKey.KEY_SPACE))
{
showFontAtlas = !showFontAtlas;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
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
);
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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(font);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
private static List<int> GetCodePoints(string text)
{
List<int> codePoints = new();
StringInfo stringInfo = new(text);
TextElementEnumerator enumerator = StringInfo.GetTextElementEnumerator(text);
while (enumerator.MoveNext())
{
int codePoint = char.ConvertToUtf32(enumerator.Current.ToString(), 0);
codePoints.Add(codePoint);
}
return codePoints;
}
}

View File

@ -0,0 +1,146 @@
/*******************************************************************************************
*
* raylib [text] example - Font filters
*
* 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)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class FontFilters
{
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters");
string 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);
// Generate mipmap levels to use trilinear filtering
// NOTE: On 2D drawing it won't be noticeable, it looks like TEXTURE_FILTER_BILINEAR
GenTextureMipmaps(ref font.Texture);
float fontSize = font.BaseSize;
Vector2 fontPosition = new(40, screenHeight / 2 - 80);
Vector2 textSize = new(0.0f, 0.0f);
// Setup texture scaling filter
SetTextureFilter(font.Texture, TextureFilter.TEXTURE_FILTER_POINT);
TextureFilter currentFontFilter = TextureFilter.TEXTURE_FILTER_POINT;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
fontSize += GetMouseWheelMove() * 4.0f;
// Choose font texture filter method
if (IsKeyPressed(KeyboardKey.KEY_ONE))
{
SetTextureFilter(font.Texture, TextureFilter.TEXTURE_FILTER_POINT);
currentFontFilter = TextureFilter.TEXTURE_FILTER_POINT;
}
else if (IsKeyPressed(KeyboardKey.KEY_TWO))
{
SetTextureFilter(font.Texture, TextureFilter.TEXTURE_FILTER_BILINEAR);
currentFontFilter = TextureFilter.TEXTURE_FILTER_BILINEAR;
}
else if (IsKeyPressed(KeyboardKey.KEY_THREE))
{
// NOTE: Trilinear filter won't be noticed on 2D drawing
SetTextureFilter(font.Texture, TextureFilter.TEXTURE_FILTER_TRILINEAR);
currentFontFilter = TextureFilter.TEXTURE_FILTER_TRILINEAR;
}
textSize = MeasureTextEx(font, msg, fontSize, 0);
if (IsKeyDown(KeyboardKey.KEY_LEFT))
{
fontPosition.X -= 10;
}
else if (IsKeyDown(KeyboardKey.KEY_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.TEXTURE_FILTER_POINT)
{
DrawText("POINT", 570, 400, 20, Color.BLACK);
}
else if (currentFontFilter == TextureFilter.TEXTURE_FILTER_POINT)
{
DrawText("BILINEAR", 570, 400, 20, Color.BLACK);
}
else if (currentFontFilter == TextureFilter.TEXTURE_FILTER_TRILINEAR)
{
DrawText("TRILINEAR", 570, 400, 20, Color.BLACK);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(font);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,102 @@
/*******************************************************************************************
*
* raylib [text] example - Font loading
*
* raylib can load fonts from multiple 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
* - 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)
*
* Copyright (c) 2016-2019 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class FontLoading
{
public static int Main()
{
// 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øùúûüýþÿ";
// 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");
// 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);
bool useTtf = false;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KeyboardKey.KEY_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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(fontBm);
UnloadFont(fontTtf);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

162
Examples/Text/FontSdf.cs Normal file
View File

@ -0,0 +1,162 @@
/*******************************************************************************************
*
* raylib [text] example - TTF loading and usage
*
* 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)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System;
using System.Numerics;
using System.Runtime.InteropServices;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class FontSdf
{
public unsafe static int Main()
{
// 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";
// Loading file to memory
uint fileSize = 0;
byte* fileData = LoadFileData("resources/fonts/anonymous_pro_bold.ttf", ref fileSize);
// Default font generation from TTF font
Font fontDefault = new();
fontDefault.BaseSize = 16;
fontDefault.GlyphCount = 95;
// Loading font data from memory data
// Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array)
fontDefault.Glyphs = LoadFontData(fileData, (int)fileSize, 16, null, 95, FontType.FONT_DEFAULT);
// 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);
fontDefault.Texture = LoadTextureFromImage(atlas);
UnloadImage(atlas);
// 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.FONT_SDF);
// Parameters > chars count: 95, font size: 16, chars 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);
// Free memory from loaded file
UnloadFileData(fileData);
// 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.TEXTURE_FILTER_BILINEAR);
Vector2 fontPosition = new(40, screenHeight / 2 - 50);
Vector2 textSize = new(0.0f);
float fontSize = 16.0f;
// 0 - fontDefault, 1 - fontSDF
int currentFont = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
fontSize += GetMouseWheelMove() * 8.0f;
if (fontSize < 6)
{
fontSize = 6;
}
if (IsKeyDown(KeyboardKey.KEY_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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(fontDefault);
UnloadFont(fontSDF);
UnloadShader(shader);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,96 @@
/*******************************************************************************************
*
* raylib [text] example - Sprite font loading
*
* 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
*
* 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).
*
* 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)
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class FontSpritefont
{
public static int Main()
{
// 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";
// 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");
Vector2 fontPosition1 = new(
screenWidth / 2 - MeasureTextEx(font1, msg1, font1.BaseSize, -3).X / 2,
screenHeight / 2 - font1.BaseSize / 2 - 80
);
Vector2 fontPosition2 = new(
screenWidth / 2 - MeasureTextEx(font2, msg2, font2.BaseSize, -2).X / 2,
screenHeight / 2 - font2.BaseSize / 2 - 10
);
Vector2 fontPosition3 = new(
screenWidth / 2 - MeasureTextEx(font3, msg3, font3.BaseSize, 2).X / 2,
screenHeight / 2 - font3.BaseSize / 2 + 50
);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// 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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadFont(font1);
UnloadFont(font2);
UnloadFont(font3);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,63 @@
/*******************************************************************************************
*
* raylib [text] example - Text formatting
*
* 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)
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class FormatText
{
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - text formatting");
int score = 100020;
int hiscore = 200450;
int lives = 5;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// 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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

166
Examples/Text/InputBox.cs Normal file
View File

@ -0,0 +1,166 @@
/*******************************************************************************************
*
* 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)
*
* Copyright (c) 2017 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class InputBox
{
public const int MaxInputChars = 9;
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);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
if (CheckCollisionPointRec(GetMousePosition(), textBox))
{
mouseOnText = true;
}
else
{
mouseOnText = false;
}
if (mouseOnText)
{
// Set the window's cursor to the I-Beam
SetMouseCursor(MouseCursor.MOUSE_CURSOR_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.KEY_BACKSPACE))
{
letterCount -= 1;
if (letterCount < 0)
{
letterCount = 0;
}
name[letterCount] = '\0';
}
}
else
{
SetMouseCursor(MouseCursor.MOUSE_CURSOR_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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,121 @@
/*******************************************************************************************
*
* raylib [text] example - raylib font loading and usage
*
* 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)
*
* Copyright (c) 2017 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class RaylibFonts
{
public const int MaxFonts = 8;
public static int Main()
{
// 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[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");
string[] messages = new string[MaxFonts] {
"ALAGARD FONT designed by Hewett Tsoi",
"PIXELPLAY FONT designed by Aleksander Shevchuk",
"MECHA FONT designed by Captain Falcon",
"SETBACK FONT designed by Brian Kent (AEnigma)",
"ROMULUS FONT designed by Hewett Tsoi",
"PIXANTIQUA FONT designed by Gerhard Grossmann",
"ALPHA_BETA FONT designed by Brian Kent (AEnigma)",
"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];
for (int i = 0; i < MaxFonts; i++)
{
float 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;
}
// Small Y position corrections
positions[3].Y += 8;
positions[4].Y += 2;
positions[7].Y -= 8;
Color[] colors = new Color[MaxFonts] {
Color.MAROON,
Color.ORANGE,
Color.DARKGREEN,
Color.DARKBLUE,
Color.DARKPURPLE,
Color.LIME,
Color.GOLD,
Color.RED
};
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// 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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < MaxFonts; i++)
{
UnloadFont(fonts[i]);
}
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,357 @@
using System.Numerics;
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class RectangleBounds
{
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle");
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.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;
Vector2 lastMouse = new(0.0f, 0.0f);
Color borderColor = Color.MAROON;
Font font = GetFontDefault();
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KeyboardKey.KEY_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.MOUSE_LEFT_BUTTON))
{
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.MOUSE_LEFT_BUTTON) && 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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
// 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;
// Offset between lines (on line break '\n')
float textOffsetY = 0;
// Offset X to next character to draw
float textOffsetX = 0.0f;
// Character rectangle scaling factor
float scaleFactor = fontSize / (float)font.BaseSize;
// Word/character wrapping mechanism variables
bool shouldMeasure = wordWrap;
// Index where to begin drawing (where a line begins)
int startLine = -1;
// Index where to stop drawing (where a line ends)
int endLine = -1;
// Holds last value of the character position
int 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);
// 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 (shouldMeasure)
{
// 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);
}
shouldMeasure = !shouldMeasure;
}
else if ((i + 1) == length)
{
endLine = i;
shouldMeasure = !shouldMeasure;
}
else if (codepoint == '\n')
{
shouldMeasure = !shouldMeasure;
}
if (!shouldMeasure)
{
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;
shouldMeasure = !shouldMeasure;
}
}
if ((textOffsetX != 0) || (codepoint != ' '))
{
// avoid leading spaces
textOffsetX += glyphWidth;
}
}
}
}

330
Examples/Text/Unicode.cs Normal file
View File

@ -0,0 +1,330 @@
/*******************************************************************************************
*
* raylib [text] example - Using unicode with raylib
*
* 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 contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
*
* Copyright (c) 2019 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using Raylib_cs;
using static Raylib_cs.Raylib;
using static Raylib_cs.Color;
namespace Examples.Text
{
public class Unicode
{
const int EMOJI_PER_WIDTH = 8;
const int EMOJI_PER_HEIGHT = 4;
// 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"
"\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"},
};
//--------------------------------------------------------------------------------------
// Module functions declaration
//--------------------------------------------------------------------------------------
static void RandomizeEmoji(void); // Fills the emoji array with random emojis
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
// Arrays that holds the random emojis
struct emoji
{
int index; // Index inside `emojiCodepoints`
int message; // Message index
Color color; // Emoji color
}
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
{
// Update
//----------------------------------------------------------------------------------
// Add a new set of emojis when SPACE is pressed
if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji();
// Set the selected emoji and copy its text to clipboard
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && (hovered != -1) && (hovered != selected))
{
selected = hovered;
selectedPos = hoveredPos;
SetClipboardText(messages[emoji[selected].message].text);
}
Vector2 mouse = GetMousePosition();
Vector2 pos = new(28.8f, 10.0f);
hovered = -1;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw random emojis in the background
//------------------------------------------------------------------------------
for (int i = 0; i < SIZEOF(emoji); ++i)
{
const char* txt = ref[emoji[i].index];
Rectangle emojiRect = new(pos.X, pos.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));
}
else
{
DrawTextEx(fontEmoji, txt, pos, fontEmoji.BaseSize, 1.0, emoji[i].Color);
hovered = i;
hoveredPos = pos;
}
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;
}
//------------------------------------------------------------------------------
// Draw the message when a emoji is selected
//------------------------------------------------------------------------------
if (selected != -1)
{
const int message = emoji[selected].message;
const int horizontalPadding = 20, verticalPadding = 30;
Font* font = ref;
// Set correct font for asian languages
if (TextIsEqual(messages[message].language, "Chinese") ||
TextIsEqual(messages[message].language, "Korean") ||
TextIsEqual(messages[message].language, "Japanese")) font = ref;
// 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;
Rectangle msgRect = new(selectedPos.X - 38.8f, selectedPos.Y, 2 * horizontalPadding + sz.X, 2 * verticalPadding + sz.Y);
msgRect.Y -= msgRect.Height;
// Coordinates for the chat bubble triangle
Vector2 a = new(selectedPos.X, msgRect.Y + msgRect.Height);
Vector2 b = new(a.X + 8, a.Y + 10);
Vector2 c = new(a.X + 10, a.Y);
// Don't go outside the screen
if (msgRect.X < 10) msgRect.X += 28;
if (msgRect.Y < 10)
{
msgRect.Y = selectedPos.Y + 84;
a.Y = msgRect.Y;
c.Y = a.Y;
b.Y = a.Y - 10;
// Swap values so we can actually render the triangle :(
Vector2 tmp = a;
a = b;
b = tmp;
}
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);
// 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);
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);
}
//------------------------------------------------------------------------------
// 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);
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)
{
// 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
Vector3 hsv = new((start * (i + 1)) % 360, 0.6f, 0.85f);
emoji[i].Color = ColorAlpha(ColorFromHSV(hsv), 0.8f);
// Set a random message for this emoji
emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1);
}
}
}
}

View File

@ -0,0 +1,74 @@
/*******************************************************************************************
*
* raylib [text] example - Text Writing Animation
*
* 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)
*
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
using static Raylib_cs.Raylib;
namespace Examples.Text;
public class WritingAnim
{
public static int Main()
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
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);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KeyboardKey.KEY_SPACE))
{
framesCounter += 8;
}
else
{
framesCounter += 1;
}
if (IsKeyPressed(KeyboardKey.KEY_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();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
}