Add string length in pixel func, add button label
This commit is contained in:
parent
c33b37b0ea
commit
90068d2c64
@ -455,6 +455,10 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
||||
font->tex = &assetManager->textures[texlist_font];
|
||||
font->atlas = &assetManager->texAtlas[texlist_font];
|
||||
|
||||
// NOTE(doyle): Formula derived from STB Font
|
||||
font->verticalSpacing =
|
||||
font->metrics.ascent - font->metrics.descent + font->metrics.lineGap;
|
||||
|
||||
for (i32 i = 0; i < numGlyphs; i++)
|
||||
{
|
||||
i32 glyphBitmapSizeInBytes = CAST(i32) glyphBitmaps[i].dimensions.w *
|
||||
@ -489,3 +493,25 @@ void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||
|
||||
assetManager->anims[animId] = anim;
|
||||
}
|
||||
|
||||
v2 asset_stringDimInPixels(const Font *const font, const char *const string)
|
||||
{
|
||||
v2 stringDim = V2(0, 0);
|
||||
for (i32 i = 0; i < common_strlen(string); i++)
|
||||
{
|
||||
i32 codepoint = string[i];
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(codepoint >= font->codepointRange.x &&
|
||||
codepoint <= font->codepointRange.y)
|
||||
#endif
|
||||
|
||||
i32 relativeIndex = CAST(i32)(codepoint - font->codepointRange.x);
|
||||
|
||||
v2 charDim = font->charMetrics[relativeIndex].trueSize;
|
||||
stringDim.x += charDim.x;
|
||||
stringDim.y = (charDim.y > stringDim.y) ? charDim.y : stringDim.y;
|
||||
}
|
||||
|
||||
return stringDim;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void debug_init(MemoryArena *arena, v2 windowSize, Font font)
|
||||
{
|
||||
GLOBAL_debug.font = font;
|
||||
GLOBAL_debug.callCount = PLATFORM_MEM_ALLOC(arena, debugcallcount_num, i32);
|
||||
GLOBAL_debug.stringLineGap = 1.1f * asset_getVFontSpacing(font.metrics);
|
||||
GLOBAL_debug.stringLineGap = CAST(f32)font.verticalSpacing;
|
||||
|
||||
/* Init debug string stack */
|
||||
GLOBAL_debug.numDebugStrings = 0;
|
||||
@ -357,7 +357,7 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
renderer_string(&state->renderer, &state->arena, camera, font,
|
||||
debugString, strPos, V2(0, 0), 0, color);
|
||||
|
||||
f32 stringLineGap = 1.1f * asset_getVFontSpacing(font->metrics);
|
||||
f32 stringLineGap = 1.1f * font->verticalSpacing;
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
|
||||
char entityPosStr[128];
|
||||
|
@ -211,7 +211,9 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
|
||||
v2 posInCameraSpace = v2_sub(pos, camera.pos);
|
||||
|
||||
pos = posInCameraSpace;
|
||||
f32 baseline = pos.y;
|
||||
|
||||
// TODO(doyle): Find why font is 1px off, might be arial font semantics
|
||||
f32 baseline = pos.y - font->verticalSpacing + 1;
|
||||
for (i32 i = 0; i < strLen; i++)
|
||||
{
|
||||
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
|
||||
|
@ -1,11 +1,16 @@
|
||||
#include "Dengine/UserInterface.h"
|
||||
#include "Dengine/AssetManager.h"
|
||||
#include "Dengine/Assets.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
#include "Dengine/Debug.h"
|
||||
|
||||
i32 userInterface_button(UiState *const uiState,
|
||||
MemoryArena *const arena,
|
||||
AssetManager *const assetManager,
|
||||
Renderer *const renderer, const KeyInput input,
|
||||
const i32 id, const Rect rect)
|
||||
Renderer *const renderer,
|
||||
Font *const font,
|
||||
const KeyInput input,
|
||||
const i32 id, const Rect rect, const char *const label)
|
||||
{
|
||||
if (math_pointInRect(rect, input.mouseP))
|
||||
{
|
||||
@ -33,25 +38,60 @@ i32 userInterface_button(UiState *const uiState,
|
||||
renderer_staticRect(renderer, v2_add(V2(8, 8), rect.pos), rect.size,
|
||||
V2(0, 0), 0, renderTex, V4(0, 0, 0, 1));
|
||||
|
||||
v2 buttonOffset = V2(0, 0);
|
||||
if (uiState->hotItem == id)
|
||||
{
|
||||
if (uiState->activeItem == id)
|
||||
{
|
||||
renderer_staticRect(renderer, v2_add(V2(2, 2), rect.pos), rect.size,
|
||||
V2(0, 0), 0, renderTex, V4(1, 1, 1, 1));
|
||||
buttonOffset = V2(2, 2);
|
||||
renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos),
|
||||
rect.size, V2(0, 0), 0, renderTex,
|
||||
V4(1, 1, 1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer_staticRect(renderer, v2_add(V2(0, 0), rect.pos), rect.size,
|
||||
V2(0, 0), 0, renderTex, V4(1, 1, 1, 1));
|
||||
renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos),
|
||||
rect.size, V2(0, 0), 0, renderTex,
|
||||
V4(1, 1, 1, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer_staticRect(renderer, v2_add(V2(0, 0), rect.pos), rect.size,
|
||||
renderer_staticRect(renderer, v2_add(buttonOffset, rect.pos), rect.size,
|
||||
V2(0, 0), 0, renderTex, V4(0.5f, 0.5f, 0.5f, 1));
|
||||
}
|
||||
|
||||
if (label)
|
||||
{
|
||||
v2 labelDim = asset_stringDimInPixels(font, label);
|
||||
DEBUG_PUSH_VAR("label dim: %4.2f, %4.2f", labelDim, "v2");
|
||||
v2 labelPos = rect.pos;
|
||||
if (labelDim.w < rect.size.w)
|
||||
{
|
||||
// Initially position the label to half the width of the button
|
||||
labelPos.x += (rect.size.w * 0.5f);
|
||||
|
||||
// Move the label pos back half the length of the string (i.e.
|
||||
// center it)
|
||||
labelPos.x -= (CAST(f32)labelDim.w * 0.5f);
|
||||
}
|
||||
|
||||
if (labelDim.h < rect.size.h)
|
||||
{
|
||||
labelPos.y += (rect.size.h * 0.5f);
|
||||
labelPos.y -= (CAST(f32)labelDim.h * 0.5f);
|
||||
}
|
||||
|
||||
labelPos = v2_add(labelPos, buttonOffset);
|
||||
renderer_staticString(renderer, arena, font, label, labelPos, V2(0, 0),
|
||||
0, V4(0, 0, 0, 1));
|
||||
|
||||
v2 rulerPos = rect.pos;
|
||||
rulerPos.y -= 10;
|
||||
renderer_staticRect(renderer, rulerPos, V2(10, 10), V2(0, 0), 0,
|
||||
renderTex, V4(0.5f, 0.1f, 0.7f, 1));
|
||||
}
|
||||
|
||||
// After renderering before click check, see if we need to process keys
|
||||
if (uiState->kbdItem == id)
|
||||
{
|
||||
@ -194,7 +234,7 @@ i32 userInterface_scrollBar(UiState *const uiState,
|
||||
return 0;
|
||||
}
|
||||
|
||||
i32 userInterface_textField(UiState *const uiState, MemoryArena *arena,
|
||||
i32 userInterface_textField(UiState *const uiState, MemoryArena *const arena,
|
||||
AssetManager *const assetManager,
|
||||
Renderer *const renderer, Font *const font,
|
||||
KeyInput input, const i32 id, v2 pos,
|
||||
@ -244,8 +284,7 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena *arena,
|
||||
renderTex, V4(0.5f, 0.5f, 0.5f, 1));
|
||||
}
|
||||
|
||||
// TODO(doyle): Figure out why we need to offset text ..
|
||||
v2 strPos = v2_add(textRect.pos, V2(0, -font->maxSize.h));
|
||||
v2 strPos = textRect.pos;
|
||||
|
||||
renderer_staticString(renderer, arena, font, string, strPos, V2(0, 0), 0,
|
||||
V4(0, 0, 0, 1));
|
||||
|
@ -1305,16 +1305,16 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
||||
|
||||
/* Draw ui */
|
||||
Rect buttonRectA = {V2(300, 500), V2(100, 50)};
|
||||
userInterface_button(&state->uiState, assetManager, renderer, state->input,
|
||||
1, buttonRectA);
|
||||
userInterface_button(&state->uiState, &state->arena, assetManager, renderer,
|
||||
font, state->input, 1, buttonRectA, "HELLO WORLD");
|
||||
|
||||
Rect buttonRectB = {V2(500, 500), V2(100, 50)};
|
||||
userInterface_button(&state->uiState, assetManager, renderer, state->input,
|
||||
2, buttonRectB);
|
||||
userInterface_button(&state->uiState, &state->arena, assetManager, renderer,
|
||||
font, state->input, 2, buttonRectB, "button2");
|
||||
|
||||
Rect buttonRectC = {V2(700, 500), V2(100, 50)};
|
||||
userInterface_button(&state->uiState, assetManager, renderer, state->input,
|
||||
3, buttonRectC);
|
||||
userInterface_button(&state->uiState, &state->arena, assetManager, renderer,
|
||||
font, state->input, 3, buttonRectC, "button3");
|
||||
|
||||
LOCAL_PERSIST i32 scrollValue = 30;
|
||||
Rect scrollRectA = {V2(900, 500), V2(16, 255)};
|
||||
@ -1356,6 +1356,9 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
||||
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
|
||||
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));
|
||||
|
||||
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
|
||||
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));
|
||||
|
||||
for (i32 i = 0; i < world->maxEntities; i++)
|
||||
{
|
||||
Entity *entity = &world->entities[i];
|
||||
|
@ -43,14 +43,10 @@ const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena,
|
||||
const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
||||
const char *filePath);
|
||||
|
||||
inline i32 asset_getVFontSpacing(FontMetrics metrics)
|
||||
{
|
||||
i32 result = metrics.ascent - metrics.descent + metrics.lineGap;
|
||||
return result;
|
||||
}
|
||||
|
||||
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||
i32 texId, i32 animId, i32 *atlasIndexes, i32 numFrames,
|
||||
f32 frameDuration);
|
||||
|
||||
v2 asset_stringDimInPixels(const Font *const font, const char *const string);
|
||||
|
||||
#endif
|
||||
|
@ -118,8 +118,13 @@ typedef struct Font
|
||||
Texture *tex;
|
||||
|
||||
FontMetrics metrics;
|
||||
|
||||
// NOTE(doyle): Array of character's by ASCII value starting from
|
||||
// codepointRange and their metrics
|
||||
CharMetrics *charMetrics;
|
||||
|
||||
i32 verticalSpacing;
|
||||
|
||||
v2 codepointRange;
|
||||
v2 maxSize;
|
||||
|
||||
|
@ -43,11 +43,16 @@ typedef struct UiState
|
||||
} UiState;
|
||||
|
||||
i32 userInterface_button(UiState *const uiState,
|
||||
MemoryArena *const arena,
|
||||
AssetManager *const assetManager,
|
||||
Renderer *const renderer, const KeyInput input,
|
||||
const i32 id, const Rect rect);
|
||||
Renderer *const renderer,
|
||||
Font *const font,
|
||||
const KeyInput input,
|
||||
const i32 id, const Rect rect,
|
||||
const char *const label);
|
||||
|
||||
i32 userInterface_textField(UiState *const uiState, MemoryArena *arena,
|
||||
i32 userInterface_textField(UiState *const uiState,
|
||||
MemoryArena *const arena,
|
||||
AssetManager *const assetManager,
|
||||
Renderer *const renderer, Font *const font,
|
||||
KeyInput input, const i32 id, v2 pos,
|
||||
|
@ -16,6 +16,11 @@
|
||||
/* Forward declaration */
|
||||
typedef struct Entity Entity;
|
||||
|
||||
typedef struct Config
|
||||
{
|
||||
b32 playWorldAudio;
|
||||
} Config;
|
||||
|
||||
typedef struct World
|
||||
{
|
||||
Entity *entities;
|
||||
@ -49,6 +54,7 @@ typedef struct GameState
|
||||
|
||||
AssetManager assetManager;
|
||||
AudioManager audioManager;
|
||||
Config config;
|
||||
MemoryArena arena;
|
||||
UiState uiState;
|
||||
} GameState;
|
||||
|
Loading…
Reference in New Issue
Block a user