mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-27 05:29:53 +03:00
Added text drawing.
This commit is contained in:
parent
a665a51b95
commit
ec41da4952
4 changed files with 142 additions and 125 deletions
|
@ -8,9 +8,10 @@ The game engine is currently under development and is not yet ready for use.
|
||||||
import popka.basic;
|
import popka.basic;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
openWindow(800, 600);
|
openWindow(640, 480);
|
||||||
while (isWindowOpen) {
|
while (isWindowOpen) {
|
||||||
if (Keyboard.q.isPressed) {
|
drawDebugText("Hello world!");
|
||||||
|
if (Keyboard.esc.isPressed) {
|
||||||
closeWindow();
|
closeWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
TODO.md
6
TODO.md
|
@ -1,11 +1,15 @@
|
||||||
# NOW
|
# NOW
|
||||||
|
|
||||||
* Work on text rendering.
|
|
||||||
* Work on dialogue system.
|
* Work on dialogue system.
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
* Dialogue functionality in dialogue.d must be implemented.
|
* Dialogue functionality in dialogue.d must be implemented.
|
||||||
|
* UI functionality must be implemented.
|
||||||
* Collision functionality must be implemented.
|
* Collision functionality must be implemented.
|
||||||
* Add more parsing options for fmt.d and strconv.d.
|
* Add more parsing options for fmt.d and strconv.d.
|
||||||
* Write tests.
|
* Write tests.
|
||||||
|
|
||||||
|
# DONE
|
||||||
|
|
||||||
|
* Work on text rendering.
|
||||||
|
|
|
@ -9,7 +9,7 @@ module popka.core.color;
|
||||||
enum {
|
enum {
|
||||||
blank = Color(),
|
blank = Color(),
|
||||||
black = Color(0),
|
black = Color(0),
|
||||||
gray = Color(100),
|
gray = Color(220),
|
||||||
white = Color(255),
|
white = Color(255),
|
||||||
red = Color(255, 0, 0),
|
red = Color(255, 0, 0),
|
||||||
green = Color(0, 255, 0),
|
green = Color(0, 255, 0),
|
||||||
|
|
220
game/engine.d
220
game/engine.d
|
@ -10,20 +10,25 @@ import ray = popka.vendor.ray.raylib;
|
||||||
import raygl = popka.vendor.ray.rlgl;
|
import raygl = popka.vendor.ray.rlgl;
|
||||||
import popka.core.basic;
|
import popka.core.basic;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
popkaDefaultFPS = 60,
|
||||||
|
popkaDefaultBackgroundColor = Color(0x2A, 0x36, 0x3A),
|
||||||
|
popkaFullscreenWaitTime = 0.125f,
|
||||||
|
rayFontSpacing = Vec2(1.0f, 14.0f),
|
||||||
|
}
|
||||||
|
|
||||||
bool popkaState;
|
bool popkaState;
|
||||||
enum popkaDefaultBackgroundColor = Color(0x2A, 0x36, 0x3A);
|
Color popkaBackgroundColor;
|
||||||
Color popkaBackgroundColor = popkaDefaultBackgroundColor;
|
|
||||||
|
|
||||||
View popkaView;
|
View popkaView;
|
||||||
float popkaViewWidth = 320.0f;
|
float popkaViewWidth = 32.0f;
|
||||||
float popkaViewHeight = 180.0f;
|
float popkaViewHeight = 32.0f;
|
||||||
bool popkaViewLockFlag;
|
bool popkaViewLockFlag;
|
||||||
bool popkaViewUnlockFlag;
|
bool popkaViewUnlockFlag;
|
||||||
|
|
||||||
bool popkaFullscreenFlag;
|
|
||||||
Vec2 popkaFullscreenLastWindowSize;
|
Vec2 popkaFullscreenLastWindowSize;
|
||||||
float popkaFullscreenTime = 0.0f;
|
float popkaFullscreenTime = 0.0f;
|
||||||
enum popkaFullscreenWaitTime = 0.175f;
|
bool popkaFullscreenFlag;
|
||||||
|
|
||||||
struct Sprite {
|
struct Sprite {
|
||||||
ray.Texture2D data;
|
ray.Texture2D data;
|
||||||
|
@ -67,7 +72,6 @@ struct Sprite {
|
||||||
|
|
||||||
struct Font {
|
struct Font {
|
||||||
ray.Font data;
|
ray.Font data;
|
||||||
Vec2 spacing;
|
|
||||||
|
|
||||||
this(const(char)[] path, uint size) {
|
this(const(char)[] path, uint size) {
|
||||||
load(path, size);
|
load(path, size);
|
||||||
|
@ -222,7 +226,7 @@ struct Camera {
|
||||||
void attach() {
|
void attach() {
|
||||||
if (!isAttached) {
|
if (!isAttached) {
|
||||||
isAttached = true;
|
isAttached = true;
|
||||||
auto temp = this.toRay();
|
auto temp = toRay(this);
|
||||||
temp.target.x = floor(temp.target.x);
|
temp.target.x = floor(temp.target.x);
|
||||||
temp.target.y = floor(temp.target.y);
|
temp.target.y = floor(temp.target.y);
|
||||||
temp.offset.x = floor(temp.offset.x);
|
temp.offset.x = floor(temp.offset.x);
|
||||||
|
@ -284,6 +288,16 @@ enum Keyboard {
|
||||||
n7 = ray.KEY_SEVEN,
|
n7 = ray.KEY_SEVEN,
|
||||||
n8 = ray.KEY_EIGHT,
|
n8 = ray.KEY_EIGHT,
|
||||||
n9 = ray.KEY_NINE,
|
n9 = ray.KEY_NINE,
|
||||||
|
n00 = ray.KEY_KP_0,
|
||||||
|
n11 = ray.KEY_KP_1,
|
||||||
|
n22 = ray.KEY_KP_2,
|
||||||
|
n33 = ray.KEY_KP_3,
|
||||||
|
n44 = ray.KEY_KP_4,
|
||||||
|
n55 = ray.KEY_KP_5,
|
||||||
|
n66 = ray.KEY_KP_6,
|
||||||
|
n77 = ray.KEY_KP_7,
|
||||||
|
n88 = ray.KEY_KP_8,
|
||||||
|
n99 = ray.KEY_KP_9,
|
||||||
f1 = ray.KEY_F1,
|
f1 = ray.KEY_F1,
|
||||||
f2 = ray.KEY_F2,
|
f2 = ray.KEY_F2,
|
||||||
f3 = ray.KEY_F3,
|
f3 = ray.KEY_F3,
|
||||||
|
@ -337,8 +351,6 @@ enum Gamepad {
|
||||||
center = ray.GAMEPAD_BUTTON_MIDDLE,
|
center = ray.GAMEPAD_BUTTON_MIDDLE,
|
||||||
}
|
}
|
||||||
|
|
||||||
// # Converters
|
|
||||||
|
|
||||||
Color toPopka(ray.Color from) {
|
Color toPopka(ray.Color from) {
|
||||||
return Color(from.r, from.g, from.b, from.a);
|
return Color(from.r, from.g, from.b, from.a);
|
||||||
}
|
}
|
||||||
|
@ -379,7 +391,7 @@ View toPopka(ray.RenderTexture2D from) {
|
||||||
|
|
||||||
Camera toPopka(ray.Camera2D from) {
|
Camera toPopka(ray.Camera2D from) {
|
||||||
Camera result;
|
Camera result;
|
||||||
result.position = from.target.toPopka();
|
result.position = toPopka(from.target);
|
||||||
result.rotation = from.rotation;
|
result.rotation = from.rotation;
|
||||||
result.scale = from.zoom;
|
result.scale = from.zoom;
|
||||||
return result;
|
return result;
|
||||||
|
@ -418,51 +430,7 @@ ray.RenderTexture2D toRay(View from) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ray.Camera2D toRay(Camera from) {
|
ray.Camera2D toRay(Camera from) {
|
||||||
return ray.Camera2D(from.origin.toRay(), from.position.toRay(), from.rotation, from.scale);
|
return ray.Camera2D(toRay(from.origin), toRay(from.position), from.rotation, from.scale);
|
||||||
}
|
|
||||||
|
|
||||||
void gprintf(size_t line = __LINE__, A...)(const(char)[] str, A args) {
|
|
||||||
static auto timer = 0.0f;
|
|
||||||
enum waitTime = 0.5f;
|
|
||||||
|
|
||||||
timer += deltaTime;
|
|
||||||
if (timer > waitTime) {
|
|
||||||
timer -= waitTime;
|
|
||||||
printf(str, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprintfln(size_t line = __LINE__, A...)(const(char)[] str, A args) {
|
|
||||||
static auto timer = 0.0f;
|
|
||||||
enum waitTime = 0.5f;
|
|
||||||
|
|
||||||
timer += deltaTime;
|
|
||||||
if (timer > waitTime) {
|
|
||||||
timer -= waitTime;
|
|
||||||
printfln(str, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprint(size_t line = __LINE__, A...)(A args) {
|
|
||||||
static auto timer = 0.0f;
|
|
||||||
enum waitTime = 0.5f;
|
|
||||||
|
|
||||||
timer += deltaTime;
|
|
||||||
if (timer > waitTime) {
|
|
||||||
timer -= waitTime;
|
|
||||||
print(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprintln(size_t line = __LINE__, A...)(A args) {
|
|
||||||
static auto timer = 0.0f;
|
|
||||||
enum waitTime = 0.5f;
|
|
||||||
|
|
||||||
timer += deltaTime;
|
|
||||||
if (timer > waitTime) {
|
|
||||||
timer -= waitTime;
|
|
||||||
println(args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int randi() {
|
int randi() {
|
||||||
|
@ -481,16 +449,16 @@ void randomize() {
|
||||||
randomize(randi);
|
randomize(randi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void openWindow(float width, float height, const(char)[] title = "Popka", Color backgroundColor = popkaDefaultBackgroundColor) {
|
void openWindow(float width, float height, const(char)[] title = "Popka", Color color = popkaDefaultBackgroundColor) {
|
||||||
ray.SetConfigFlags(ray.FLAG_VSYNC_HINT | ray.FLAG_WINDOW_RESIZABLE);
|
ray.SetConfigFlags(ray.FLAG_VSYNC_HINT | ray.FLAG_WINDOW_RESIZABLE);
|
||||||
ray.SetTraceLogLevel(ray.LOG_ERROR);
|
ray.SetTraceLogLevel(ray.LOG_ERROR);
|
||||||
ray.InitWindow(cast(int) width, cast(int) height, toStrz(title));
|
ray.InitWindow(cast(int) width, cast(int) height, toStrz(title));
|
||||||
ray.SetWindowMinSize(cast(int) (width * 0.2f), cast(int) (height * 0.2f));
|
ray.SetWindowMinSize(cast(int) (width * 0.25f), cast(int) (height * 0.25f));
|
||||||
ray.SetExitKey(ray.KEY_NULL);
|
ray.SetExitKey(ray.KEY_NULL);
|
||||||
ray.SetTargetFPS(60);
|
ray.SetTargetFPS(popkaDefaultFPS);
|
||||||
popkaState = true;
|
popkaState = true;
|
||||||
|
popkaBackgroundColor = color;
|
||||||
popkaFullscreenLastWindowSize = Vec2(width, height);
|
popkaFullscreenLastWindowSize = Vec2(width, height);
|
||||||
popkaBackgroundColor = backgroundColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeWindow() {
|
void closeWindow() {
|
||||||
|
@ -498,6 +466,7 @@ void closeWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeWindow() {
|
void freeWindow() {
|
||||||
|
popkaView.free();
|
||||||
ray.CloseWindow();
|
ray.CloseWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +482,7 @@ bool isWindowOpen() {
|
||||||
} else {
|
} else {
|
||||||
ray.BeginDrawing();
|
ray.BeginDrawing();
|
||||||
}
|
}
|
||||||
ray.ClearBackground(popkaBackgroundColor.toRay());
|
ray.ClearBackground(toRay(popkaBackgroundColor));
|
||||||
isFirstCall = false;
|
isFirstCall = false;
|
||||||
} else {
|
} else {
|
||||||
// End drawing.
|
// End drawing.
|
||||||
|
@ -559,7 +528,7 @@ bool isWindowOpen() {
|
||||||
} else {
|
} else {
|
||||||
ray.BeginDrawing();
|
ray.BeginDrawing();
|
||||||
}
|
}
|
||||||
ray.ClearBackground(popkaBackgroundColor.toRay());
|
ray.ClearBackground(toRay(popkaBackgroundColor));
|
||||||
// Fullscreen code to fix a bug on KDE.
|
// Fullscreen code to fix a bug on KDE.
|
||||||
if (popkaFullscreenFlag) {
|
if (popkaFullscreenFlag) {
|
||||||
popkaFullscreenTime += deltaTime;
|
popkaFullscreenTime += deltaTime;
|
||||||
|
@ -692,7 +661,7 @@ Font rayFont() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawRect(Rect rect, Color color = white) {
|
void drawRect(Rect rect, Color color = white) {
|
||||||
ray.DrawRectanglePro(rect.floor.toRay(), ray.Vector2(0.0f, 0.0f), 0.0f, color.toRay());
|
ray.DrawRectanglePro(toRay(rect.floor()), ray.Vector2(0.0f, 0.0f), 0.0f, toRay(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawSprite(Sprite sprite, Rect region, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft, Flip flip = Flip.none) {
|
void drawSprite(Sprite sprite, Rect region, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft, Flip flip = Flip.none) {
|
||||||
|
@ -716,11 +685,11 @@ void drawSprite(Sprite sprite, Rect region, Vec2 position = Vec2(), float rotati
|
||||||
}
|
}
|
||||||
ray.DrawTexturePro(
|
ray.DrawTexturePro(
|
||||||
sprite.data,
|
sprite.data,
|
||||||
source.floor().toRay(),
|
toRay(source.floor()),
|
||||||
target.floor().toRay(),
|
toRay(target.floor()),
|
||||||
target.origin(hook).floor().toRay(),
|
toRay(target.origin(hook).floor()),
|
||||||
rotation,
|
rotation,
|
||||||
color.toRay(),
|
toRay(color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,63 +741,106 @@ void drawTileMap(Sprite sprite, TileMap map, Camera camera, Vec2 position = Vec2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec2 measureText(Font font, Vec2 spacing, const(char)[] text, Vec2 scale = Vec2(1.0f)) {
|
||||||
|
if (font.isEmpty || text.length == 0) {
|
||||||
|
return Vec2();
|
||||||
|
}
|
||||||
|
auto result = Vec2();
|
||||||
|
auto tempByteCounter = 0; // Used to count longer text line num chars.
|
||||||
|
auto byteCounter = 0;
|
||||||
|
auto textWidth = 0.0f;
|
||||||
|
auto tempTextWidth = 0.0f; // Used to count longer text line width.
|
||||||
|
auto textHeight = font.size;
|
||||||
|
|
||||||
|
int letter = 0; // Current character.
|
||||||
|
int index = 0; // Index position in sprite font.
|
||||||
|
auto i = 0;
|
||||||
|
while (i < text.length) {
|
||||||
|
byteCounter += 1;
|
||||||
|
|
||||||
|
auto next = 0;
|
||||||
|
letter = ray.GetCodepointNext(&text[i], &next);
|
||||||
|
index = ray.GetGlyphIndex(font.data, letter);
|
||||||
|
i += next;
|
||||||
|
if (letter != '\n') {
|
||||||
|
if (font.data.glyphs[index].advanceX != 0) {
|
||||||
|
textWidth += font.data.glyphs[index].advanceX;
|
||||||
|
} else {
|
||||||
|
textWidth += font.data.recs[index].width + font.data.glyphs[index].offsetX;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tempTextWidth < textWidth) {
|
||||||
|
tempTextWidth = textWidth;
|
||||||
|
}
|
||||||
|
byteCounter = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
textHeight += spacing.y;
|
||||||
|
}
|
||||||
|
if (tempByteCounter < byteCounter) {
|
||||||
|
tempByteCounter = byteCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tempTextWidth < textWidth) {
|
||||||
|
tempTextWidth = textWidth;
|
||||||
|
}
|
||||||
|
result.x = floor(tempTextWidth * scale.x + ((tempByteCounter - 1) * spacing.x * scale.x));
|
||||||
|
result.y = floor(textHeight * scale.y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void drawRune(Font font, dchar rune, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft) {
|
void drawRune(Font font, dchar rune, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft) {
|
||||||
auto origin = toPopka(ray.GetGlyphAtlasRec(toRay(font), rune)).origin(hook);
|
if (font.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto origin = toPopka(ray.GetGlyphAtlasRec(font.data, rune)).origin(hook).floor();
|
||||||
raygl.rlPushMatrix();
|
raygl.rlPushMatrix();
|
||||||
raygl.rlTranslatef(floor(position.x), floor(position.y), 0.0f);
|
raygl.rlTranslatef(floor(position.x), floor(position.y), 0.0f);
|
||||||
raygl.rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
raygl.rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
||||||
raygl.rlScalef (scale.x, scale.y, 1.0f);
|
raygl.rlScalef (scale.x, scale.y, 1.0f);
|
||||||
raygl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
raygl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||||
ray.DrawTextCodepoint(toRay(font), rune, ray.Vector2(0.0f, 0.0f), font.size, toRay(color));
|
ray.DrawTextCodepoint(font.data, rune, ray.Vector2(0.0f, 0.0f), font.size, toRay(color));
|
||||||
raygl.rlPopMatrix();
|
raygl.rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Just copy pasted the raylib one. Fix it later.
|
void drawText(Font font, Vec2 spacing, const(char)[] text, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft) {
|
||||||
void drawText(Font font, const(char)[] text, Vec2 position = Vec2(), float rotation = 0.0f, Vec2 scale = Vec2(1.0f), Color color = white, Hook hook = Hook.topLeft) {
|
if (font.isEmpty || text.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto origin = Rect(measureText(font, spacing, text, Vec2(1.0f))).origin(hook);
|
||||||
raygl.rlPushMatrix();
|
raygl.rlPushMatrix();
|
||||||
raygl.rlTranslatef(floor(position.x), floor(position.y), 0.0f);
|
raygl.rlTranslatef(floor(position.x), floor(position.y), 0.0f);
|
||||||
raygl.rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
raygl.rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
||||||
raygl.rlScalef (scale.x, scale.y, 1.0f);
|
raygl.rlScalef (scale.x, scale.y, 1.0f);
|
||||||
raygl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
raygl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||||
|
auto textOffsetY = 0.0f; // Offset between lines (on linebreak '\n').
|
||||||
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
|
auto textOffsetX = 0.0f; // Offset X to next character to draw.
|
||||||
|
auto i = 0;
|
||||||
int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
|
while (i < text.length) {
|
||||||
|
// Get next codepoint from byte string and glyph index in font.
|
||||||
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
|
auto codepointByteCount = 0;
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
auto codepoint = ray.GetCodepointNext(&text[i], &codepointByteCount);
|
||||||
|
auto index = ray.GetGlyphIndex(font.data, codepoint);
|
||||||
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
|
if (codepoint == '\n') {
|
||||||
|
textOffsetY += spacing.y;
|
||||||
for (int i = 0; i < size;)
|
|
||||||
{
|
|
||||||
// Get next codepoint from byte string and glyph index in font
|
|
||||||
int codepointByteCount = 0;
|
|
||||||
int codepoint = GetCodepointNext(&text[i], &codepointByteCount);
|
|
||||||
int index = GetGlyphIndex(font, codepoint);
|
|
||||||
|
|
||||||
if (codepoint == '\n')
|
|
||||||
{
|
|
||||||
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
|
||||||
textOffsetY += textLineSpacing;
|
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
|
} else {
|
||||||
|
if (codepoint != ' ' && codepoint != '\t') {
|
||||||
|
drawRune(font, codepoint, Vec2(textOffsetX, textOffsetY), 0.0f, Vec2(1.0f), color);
|
||||||
}
|
}
|
||||||
else
|
if (font.data.glyphs[index].advanceX == 0) {
|
||||||
{
|
textOffsetX += font.data.recs[index].width + spacing.x;
|
||||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
} else {
|
||||||
{
|
textOffsetX += font.data.glyphs[index].advanceX + spacing.x;
|
||||||
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
|
|
||||||
else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
|
|
||||||
}
|
}
|
||||||
|
// Move text bytes counter to next codepoint.
|
||||||
i += codepointByteCount; // Move text bytes counter to next codepoint
|
i += codepointByteCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
raygl.rlPopMatrix();
|
raygl.rlPopMatrix();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
void drawDebugText(const(char)[] text, Vec2 position = Vec2(8.0f), float rotation = 0.0f, Vec2 scale = Vec2(2.0f), Color color = gray, Hook hook = Hook.topLeft) {
|
||||||
|
drawText(rayFont, rayFontSpacing, text, position, rotation, scale, color, hook);
|
||||||
|
}
|
||||||
|
|
||||||
unittest {}
|
unittest {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue