unfinished ui textbox
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"activeFile": "overworld.tsx",
|
"activeFile": "map.tmj",
|
||||||
"expandedProjectPaths": [
|
"expandedProjectPaths": [
|
||||||
".",
|
".",
|
||||||
"templates"
|
"templates"
|
||||||
@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"map.tmj": {
|
"map.tmj": {
|
||||||
"scale": 3,
|
"scale": 3,
|
||||||
"selectedLayer": 0,
|
"selectedLayer": 2,
|
||||||
"viewCenter": {
|
"viewCenter": {
|
||||||
"x": 6520.166666666666,
|
"x": 6520.166666666666,
|
||||||
"y": 6836.833333333333
|
"y": 6836.833333333333
|
||||||
@ -35,8 +35,8 @@
|
|||||||
"project": "map project.tiled-project",
|
"project": "map project.tiled-project",
|
||||||
"property.type": "int",
|
"property.type": "int",
|
||||||
"recentFiles": [
|
"recentFiles": [
|
||||||
"map.tmj",
|
|
||||||
"overworld.tsx",
|
"overworld.tsx",
|
||||||
|
"map.tmj",
|
||||||
"entities.tsx"
|
"entities.tsx"
|
||||||
],
|
],
|
||||||
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
|
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
|
||||||
|
@ -425,14 +425,14 @@
|
|||||||
"type":"player_spawn",
|
"type":"player_spawn",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":16,
|
"width":16,
|
||||||
"x":6607.58333333333,
|
"x":6384.58333333333,
|
||||||
"y":6944.25
|
"y":6846.91666666667
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":7,
|
"id":7,
|
||||||
"template":"templates\/NPC.tx",
|
"template":"templates\/NPC.tx",
|
||||||
"x":6700.25,
|
"x":6383.25,
|
||||||
"y":6838.75
|
"y":6880.08333333333
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":8,
|
"id":8,
|
||||||
|
@ -25,6 +25,8 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
add_subdirectory(assert)
|
add_subdirectory(assert)
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
add_subdirectory(entity)
|
add_subdirectory(entity)
|
||||||
|
add_subdirectory(item)
|
||||||
add_subdirectory(physics)
|
add_subdirectory(physics)
|
||||||
|
add_subdirectory(ui)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
add_subdirectory(world)
|
add_subdirectory(world)
|
@ -15,4 +15,5 @@
|
|||||||
|
|
||||||
typedef bool bool_t;
|
typedef bool bool_t;
|
||||||
typedef int int_t;
|
typedef int int_t;
|
||||||
typedef float float_t;
|
typedef float float_t;
|
||||||
|
typedef char char_t;
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
|
|
||||||
|
#include "ui/uitextbox.h"
|
||||||
|
|
||||||
void npcInit(entity_t *entity) {
|
void npcInit(entity_t *entity) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -16,5 +18,5 @@ void npcUpdate(entity_t *entity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void npcInteract(entity_t *player, entity_t *self) {
|
void npcInteract(entity_t *player, entity_t *self) {
|
||||||
printf("I am being interacted with!\n");
|
uiTextboxSetText("Hello World");
|
||||||
}
|
}
|
@ -12,6 +12,10 @@
|
|||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
#include "physics/physics.h"
|
#include "physics/physics.h"
|
||||||
|
|
||||||
|
#include "ui/uitextbox.h"
|
||||||
|
|
||||||
|
inventory_t PLAYER_INVENTORY;
|
||||||
|
|
||||||
void playerInit() {
|
void playerInit() {
|
||||||
entity_t *ent = &ENTITIES[0];
|
entity_t *ent = &ENTITIES[0];
|
||||||
|
|
||||||
@ -20,6 +24,8 @@ void playerInit() {
|
|||||||
|
|
||||||
ent->x = WORLD_PLAYER_SPAWN_X;
|
ent->x = WORLD_PLAYER_SPAWN_X;
|
||||||
ent->y = WORLD_PLAYER_SPAWN_Y;
|
ent->y = WORLD_PLAYER_SPAWN_Y;
|
||||||
|
|
||||||
|
inventoryInit(&PLAYER_INVENTORY, INVENTORY_SIZE_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void playerNPCInit(entity_t *entity) {
|
void playerNPCInit(entity_t *entity) {
|
||||||
@ -31,6 +37,11 @@ void playerNPCUpdate(entity_t *entity) {
|
|||||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||||
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER");
|
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER");
|
||||||
|
|
||||||
|
if(UI_TEXTBOX.visible) {
|
||||||
|
entity->vx = entity->vy = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(inputIsDown(INPUT_BIND_UP)) {
|
if(inputIsDown(INPUT_BIND_UP)) {
|
||||||
if(inputIsDown(INPUT_BIND_LEFT)) {
|
if(inputIsDown(INPUT_BIND_LEFT)) {
|
||||||
entity->vx = -PLAYER_MOVE_SPEED_XY;
|
entity->vx = -PLAYER_MOVE_SPEED_XY;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
#include "util/fixed.h"
|
#include "util/fixed.h"
|
||||||
|
#include "item/inventory.h"
|
||||||
|
|
||||||
typedef struct _entity_t entity_t;
|
typedef struct _entity_t entity_t;
|
||||||
|
|
||||||
@ -23,6 +24,8 @@ typedef struct {
|
|||||||
)
|
)
|
||||||
#define PLAYER_INTERACT_ANGLE ((fixed248_t)175)
|
#define PLAYER_INTERACT_ANGLE ((fixed248_t)175)
|
||||||
|
|
||||||
|
extern inventory_t PLAYER_INVENTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the player and all player-related entities.
|
* Initializes the player and all player-related entities.
|
||||||
*/
|
*/
|
||||||
|
10
src/dusk/item/CMakeLists.txt
Normal file
10
src/dusk/item/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
inventory.c
|
||||||
|
)
|
68
src/dusk/item/inventory.c
Normal file
68
src/dusk/item/inventory.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void inventoryInit(inventory_t *inventory, const uint8_t size) {
|
||||||
|
assertNotNull(inventory, "inventory must not be NULL");
|
||||||
|
assertTrue(size <= INVENTORY_SIZE_MAX, "size exceeding INVENTORY_SIZE_MAX");
|
||||||
|
assertTrue(size > 0, "size must be greater than 0");
|
||||||
|
|
||||||
|
memoryZero(inventory, sizeof(inventory_t));
|
||||||
|
inventory->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inventoryItemIndexByType(
|
||||||
|
const inventory_t *inventory,
|
||||||
|
const itemtype_t type
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "inventory must not be NULL");
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "type must be greater than ITEM_TYPE_NULL");
|
||||||
|
|
||||||
|
uint8_t item = inventory->itemCount;
|
||||||
|
while(item--) {
|
||||||
|
if(inventory->items[item].type == type) return item;
|
||||||
|
}
|
||||||
|
return INVENTORY_SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t inventoryItemCount(
|
||||||
|
const inventory_t *inventory,
|
||||||
|
const itemtype_t type
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "inventory must not be NULL");
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "type must be greater than ITEM_TYPE_NULL");
|
||||||
|
|
||||||
|
const uint8_t index = inventoryItemIndexByType(inventory, type);
|
||||||
|
if(index == INVENTORY_SIZE_MAX) return 0;
|
||||||
|
return inventory->items[index].count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inventoryItemSet(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemtype_t type,
|
||||||
|
const uint8_t count
|
||||||
|
) {
|
||||||
|
assertNotNull(inventory, "inventory must not be NULL");
|
||||||
|
assertTrue(type > ITEM_TYPE_NULL, "type must be greater than ITEM_TYPE_NULL");
|
||||||
|
assertTrue(count > 0, "count must be greater than 0");
|
||||||
|
|
||||||
|
const uint8_t index = inventoryItemIndexByType(inventory, type);
|
||||||
|
|
||||||
|
if(index == INVENTORY_SIZE_MAX) {
|
||||||
|
// Item does not exist, add it
|
||||||
|
assertTrue(inventory->itemCount < inventory->size, "inventory is full");
|
||||||
|
inventory->items[inventory->itemCount].type = type;
|
||||||
|
inventory->items[inventory->itemCount].count = count;
|
||||||
|
inventory->itemCount++;
|
||||||
|
} else {
|
||||||
|
// Item exists, update the count
|
||||||
|
inventory->items[index].count = count;
|
||||||
|
}
|
||||||
|
}
|
63
src/dusk/item/inventory.h
Normal file
63
src/dusk/item/inventory.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "itemstack.h"
|
||||||
|
|
||||||
|
#define INVENTORY_SIZE_MAX UINT8_MAX
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
itemstack_t items[INVENTORY_SIZE_MAX];
|
||||||
|
uint8_t itemCount;
|
||||||
|
uint8_t size;
|
||||||
|
} inventory_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an inventory with a specified size.
|
||||||
|
*
|
||||||
|
* @param inventory Pointer to the inventory to initialize.
|
||||||
|
* @param size The size of the inventory (maximum is INVENTORY_SIZE_MAX).
|
||||||
|
*/
|
||||||
|
void inventoryInit(inventory_t *inventory, const uint8_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the index of the item of a specified type in the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory Pointer to the inventory to search.
|
||||||
|
* @param type The type of item to find.
|
||||||
|
* @return The index of the item, or INVENTORY_SIZE_MAX if not found.
|
||||||
|
*/
|
||||||
|
uint8_t inventoryItemIndexByType(
|
||||||
|
const inventory_t *inventory,
|
||||||
|
const itemtype_t type
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count of items of a specified type in the inventory.
|
||||||
|
*
|
||||||
|
* @param inventory Pointer to the inventory to check.
|
||||||
|
* @param type The type of item to count.
|
||||||
|
* @return The count of items of the specified type.
|
||||||
|
*/
|
||||||
|
uint8_t inventoryItemCount(
|
||||||
|
const inventory_t *inventory,
|
||||||
|
const itemtype_t type
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the count of items of a specified type in the inventory.
|
||||||
|
* If the item does not exist, it will be added.
|
||||||
|
*
|
||||||
|
* @param inventory Pointer to the inventory to modify.
|
||||||
|
* @param type The type of item to set.
|
||||||
|
* @param count The count of items to set.
|
||||||
|
*/
|
||||||
|
void inventoryItemSet(
|
||||||
|
inventory_t *inventory,
|
||||||
|
const itemtype_t type,
|
||||||
|
const uint8_t count
|
||||||
|
);
|
14
src/dusk/item/itemstack.h
Normal file
14
src/dusk/item/itemstack.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "itemtype.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
itemtype_t type;
|
||||||
|
uint8_t count;
|
||||||
|
} itemstack_t;
|
24
src/dusk/item/itemtype.h
Normal file
24
src/dusk/item/itemtype.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ITEM_TYPE_NULL = 0,
|
||||||
|
|
||||||
|
// MEDICINE
|
||||||
|
ITEM_TYPE_POTION,
|
||||||
|
|
||||||
|
// INGREDIENTS
|
||||||
|
ITEM_TYPE_ONION,
|
||||||
|
ITEM_TYPE_SWEET_POTATO,
|
||||||
|
ITEM_TYPE_CARROT,
|
||||||
|
|
||||||
|
// COOKED FOOD
|
||||||
|
ITEM_TYPE_BAKED_SWEET_POTATO,
|
||||||
|
} itemtype_t;
|
@ -12,10 +12,13 @@
|
|||||||
#include "world/overworld.h"
|
#include "world/overworld.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
|
#include "ui/uitextbox.h"
|
||||||
|
|
||||||
// Press F5 to compile and run the compiled game.gb in the Emulicous Emulator/Debugger
|
// Press F5 to compile and run the compiled game.gb in the Emulicous Emulator/Debugger
|
||||||
void main(void) {
|
void main(void) {
|
||||||
renderInit();
|
renderInit();
|
||||||
inputInit();
|
inputInit();
|
||||||
|
uiTextboxInit();
|
||||||
|
|
||||||
overworldInit();
|
overworldInit();
|
||||||
|
|
||||||
@ -27,6 +30,8 @@ void main(void) {
|
|||||||
|
|
||||||
overworldUpdate();
|
overworldUpdate();
|
||||||
|
|
||||||
|
uiTextboxUpdate();
|
||||||
|
|
||||||
// Update input for next frame.
|
// Update input for next frame.
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
}
|
}
|
||||||
|
10
src/dusk/ui/CMakeLists.txt
Normal file
10
src/dusk/ui/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Copyright (c) 2025 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
uitextbox.c
|
||||||
|
)
|
18
src/dusk/ui/font.h
Normal file
18
src/dusk/ui/font.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
#define FONT_HEIGHT 8
|
||||||
|
#define FONT_LINE_SPACING 1
|
||||||
|
|
||||||
|
#define FONT_LINE_HEIGHT ( \
|
||||||
|
FONT_HEIGHT + FONT_LINE_SPACING \
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
128
src/dusk/ui/uitextbox.c
Normal file
128
src/dusk/ui/uitextbox.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uitextbox.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
uitextbox_t UI_TEXTBOX;
|
||||||
|
|
||||||
|
void uiTextboxInit() {
|
||||||
|
memoryZero(&UI_TEXTBOX, sizeof(uitextbox_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiTextboxUpdate() {
|
||||||
|
if(UI_TEXTBOX.visible == false) return;
|
||||||
|
|
||||||
|
if(UI_TEXTBOX.charsRevealed < UI_TEXTBOX.pageChars[UI_TEXTBOX.page]) {
|
||||||
|
if((RENDER_FRAME % 4) == 0) {
|
||||||
|
// printf("Revealing char\n");
|
||||||
|
UI_TEXTBOX.charsRevealed++;
|
||||||
|
} else if(inputIsDown(INPUT_BIND_ACTION)) {
|
||||||
|
UI_TEXTBOX.charsRevealed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(inputPressed(INPUT_BIND_ACTION)) {
|
||||||
|
if(UI_TEXTBOX.page <= UI_TEXTBOX.pageCount - 1) {
|
||||||
|
uitextbox_t *textbox = &UI_TEXTBOX;
|
||||||
|
printf("next page?\n");
|
||||||
|
UI_TEXTBOX.page++;
|
||||||
|
UI_TEXTBOX.charsRevealed = 0;
|
||||||
|
} else {
|
||||||
|
printf("Closing textbox\n");
|
||||||
|
// Close the textbox
|
||||||
|
UI_TEXTBOX.visible = false;
|
||||||
|
UI_TEXTBOX.page = 0;
|
||||||
|
UI_TEXTBOX.charsRevealed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiTextboxSetText(const char_t *text) {
|
||||||
|
assertNotNull(text, "Text pointer cannot be NULL, call uiTextboxClose()");
|
||||||
|
|
||||||
|
memoryZero(UI_TEXTBOX.text, sizeof(UI_TEXTBOX.text));
|
||||||
|
memoryZero(UI_TEXTBOX.lineLengths, sizeof(UI_TEXTBOX.lineLengths));
|
||||||
|
memoryZero(UI_TEXTBOX.pageChars, sizeof(UI_TEXTBOX.pageChars));
|
||||||
|
UI_TEXTBOX.pageCount = 0;
|
||||||
|
UI_TEXTBOX.totalChars = 0;
|
||||||
|
UI_TEXTBOX.page = 0;
|
||||||
|
UI_TEXTBOX.charsRevealed = 0;
|
||||||
|
UI_TEXTBOX.visible = true;
|
||||||
|
|
||||||
|
char_t c;
|
||||||
|
uint16_t i = 0;
|
||||||
|
uint16_t j = 0;
|
||||||
|
uint8_t line = 0;
|
||||||
|
while((c = text[i++]) != '\0') {
|
||||||
|
assertTrue(c != '\r', "Carriage return characters not allowed.");
|
||||||
|
assertTrue(c != '\t', "Tab characters not allowed.");
|
||||||
|
|
||||||
|
if(c == '\n') {
|
||||||
|
goto newline;
|
||||||
|
} else {
|
||||||
|
goto character;
|
||||||
|
}
|
||||||
|
|
||||||
|
newline: {
|
||||||
|
line++;
|
||||||
|
if(line >= UI_TEXTBOX_LINE_COUNT) {
|
||||||
|
goto newPage;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
character: {
|
||||||
|
UI_TEXTBOX.text[j] = c;
|
||||||
|
UI_TEXTBOX.totalChars++;
|
||||||
|
UI_TEXTBOX.lineLengths[line]++;
|
||||||
|
UI_TEXTBOX.pageChars[UI_TEXTBOX.pageCount]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
newPage: {
|
||||||
|
assertTrue(
|
||||||
|
UI_TEXTBOX.pageCount < UI_TEXTBOX_PAGE_COUNT_MAX,
|
||||||
|
"Exceeded maximum number of pages in textbox."
|
||||||
|
);
|
||||||
|
UI_TEXTBOX.pageCount++;
|
||||||
|
line = 0;
|
||||||
|
continue;
|
||||||
|
// j = 0; // Reset character index for new page
|
||||||
|
}
|
||||||
|
|
||||||
|
assertUnreachable("Code should not reach here, all cases handled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Hard coded testing values
|
||||||
|
// char_t buffer[UI_TEXTBOX_CHARS_PER_LINE];
|
||||||
|
// uint8_t line;
|
||||||
|
|
||||||
|
// for(line = 0; line < UI_TEXTBOX_LINE_COUNT; line++) {
|
||||||
|
// // Set the text for each line
|
||||||
|
// sprintf(buffer, "HC Line %d", line);
|
||||||
|
// UI_TEXTBOX.lineLengths[line] = strlen(text); // Set line length for each line
|
||||||
|
// UI_TEXTBOX.totalChars += UI_TEXTBOX.lineLengths[line];
|
||||||
|
// UI_TEXTBOX.pageChars[UI_TEXTBOX.pageCount] += UI_TEXTBOX.lineLengths[line];
|
||||||
|
|
||||||
|
// memoryCopy(
|
||||||
|
// UI_TEXTBOX.text + line * (UI_TEXTBOX_CHARS_PER_LINE),
|
||||||
|
// buffer,
|
||||||
|
// UI_TEXTBOX.lineLengths[line]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if(line == 3 || line == 7 || line == 11 || line == 15) {
|
||||||
|
// // Increment page count every 4 lines
|
||||||
|
// UI_TEXTBOX.pageCount++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
70
src/dusk/ui/uitextbox.h
Normal file
70
src/dusk/ui/uitextbox.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "display/renderbase.h"
|
||||||
|
#include "ui/font.h"
|
||||||
|
|
||||||
|
#define UI_TEXTBOX_LINES_PER_PAGE 4
|
||||||
|
#define UI_TEXTBOX_WIDTH RENDER_WIDTH
|
||||||
|
#define UI_TEXTBOX_HEIGHT_INNER ( \
|
||||||
|
FONT_LINE_HEIGHT * UI_TEXTBOX_LINES_PER_PAGE \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define UI_TEXTBOX_BORDER_WIDTH 1
|
||||||
|
#define UI_TEXTBOX_BORDER_HEIGHT 1
|
||||||
|
#define UI_TEXTBOX_PADDING_X 1
|
||||||
|
#define UI_TEXTBOX_PADDING_Y 1
|
||||||
|
#define UI_TEXTBOX_WIDTH_INNER ( \
|
||||||
|
UI_TEXTBOX_WIDTH - (UI_TEXTBOX_BORDER_WIDTH * 2) - \
|
||||||
|
(UI_TEXTBOX_PADDING_X * 2) \
|
||||||
|
)
|
||||||
|
#define UI_TEXTBOX_HEIGHT ( \
|
||||||
|
UI_TEXTBOX_HEIGHT_INNER + (UI_TEXTBOX_BORDER_HEIGHT * 2) + \
|
||||||
|
(UI_TEXTBOX_PADDING_Y * 2) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define UI_TEXTBOX_CHARS_PER_LINE UI_TEXTBOX_WIDTH_INNER
|
||||||
|
#define UI_TEXTBOX_PAGE_CHARS ( \
|
||||||
|
UI_TEXTBOX_CHARS_PER_LINE * UI_TEXTBOX_LINES_PER_PAGE \
|
||||||
|
)
|
||||||
|
#define UI_TEXTBOX_PAGE_COUNT_MAX 6
|
||||||
|
#define UI_TEXTBOX_LINE_COUNT ( \
|
||||||
|
UI_TEXTBOX_LINES_PER_PAGE * UI_TEXTBOX_PAGE_COUNT_MAX \
|
||||||
|
)
|
||||||
|
#define UI_TEXTBOX_CHARS_MAX ( \
|
||||||
|
UI_TEXTBOX_PAGE_CHARS * UI_TEXTBOX_PAGE_COUNT_MAX \
|
||||||
|
)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char_t text[UI_TEXTBOX_CHARS_MAX];
|
||||||
|
uint8_t lineLengths[UI_TEXTBOX_LINE_COUNT];
|
||||||
|
uint8_t pageCount;
|
||||||
|
uint8_t pageChars[UI_TEXTBOX_PAGE_COUNT_MAX];
|
||||||
|
uint16_t totalChars;
|
||||||
|
|
||||||
|
uint8_t page;
|
||||||
|
uint8_t charsRevealed;
|
||||||
|
|
||||||
|
bool_t visible;
|
||||||
|
} uitextbox_t;
|
||||||
|
|
||||||
|
extern uitextbox_t UI_TEXTBOX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the UI textbox.
|
||||||
|
*/
|
||||||
|
void uiTextboxInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the UI textbox, handling text input and scrolling.
|
||||||
|
*/
|
||||||
|
void uiTextboxUpdate(void);
|
||||||
|
|
||||||
|
void uiTextboxSetText(
|
||||||
|
const char_t *text
|
||||||
|
);
|
@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
drawscene.c
|
drawscene.c
|
||||||
drawoverworld.c
|
drawoverworld.c
|
||||||
|
drawui.c
|
||||||
)
|
)
|
@ -47,7 +47,6 @@ void drawOverworldDraw(void) {
|
|||||||
};
|
};
|
||||||
uint8_t colorCount = sizeof(colors) / sizeof(Color);
|
uint8_t colorCount = sizeof(colors) / sizeof(Color);
|
||||||
|
|
||||||
BeginBlendMode(BLEND_ALPHA_PREMULTIPLY);
|
|
||||||
do {
|
do {
|
||||||
// Base layer
|
// Base layer
|
||||||
for(uint8_t i = 0; i < CHUNK_TILE_COUNT; i++) {
|
for(uint8_t i = 0; i < CHUNK_TILE_COUNT; i++) {
|
||||||
@ -99,7 +98,6 @@ void drawOverworldDraw(void) {
|
|||||||
|
|
||||||
chunk++;
|
chunk++;
|
||||||
} while(chunk < CHUNK_MAP.chunks + CHUNK_MAP_COUNT);
|
} while(chunk < CHUNK_MAP.chunks + CHUNK_MAP_COUNT);
|
||||||
EndBlendMode();
|
|
||||||
|
|
||||||
// Entities
|
// Entities
|
||||||
entity_t *entity = ENTITIES;
|
entity_t *entity = ENTITIES;
|
||||||
|
83
src/duskraylib/display/draw/drawui.c
Normal file
83
src/duskraylib/display/draw/drawui.c
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drawui.h"
|
||||||
|
#include "ui/uitextbox.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
void drawUIInit(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawUI() {
|
||||||
|
drawUITextbox();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawUITextbox() {
|
||||||
|
if(!UI_TEXTBOX.visible) return;
|
||||||
|
|
||||||
|
// Semi-transparent dark blue
|
||||||
|
Color background = (Color){ 0, 0, 128, 128 };
|
||||||
|
DrawRectangle(
|
||||||
|
0, RENDER_HEIGHT - UI_TEXTBOX_HEIGHT,
|
||||||
|
UI_TEXTBOX_WIDTH, UI_TEXTBOX_HEIGHT,
|
||||||
|
background
|
||||||
|
);
|
||||||
|
|
||||||
|
BeginBlendMode(BLEND_ALPHA);
|
||||||
|
|
||||||
|
if(UI_TEXTBOX.charsRevealed > 0) {
|
||||||
|
char_t buffer[UI_TEXTBOX_CHARS_PER_LINE + 1];// +1 for null term
|
||||||
|
uint8_t charsRendered = 0;
|
||||||
|
|
||||||
|
// For each line
|
||||||
|
for(uint8_t i = 0; i < UI_TEXTBOX_LINES_PER_PAGE; i++) {
|
||||||
|
// Get count of chars in the line
|
||||||
|
uint8_t lineLength = UI_TEXTBOX.lineLengths[i];
|
||||||
|
if(lineLength == 0) continue;
|
||||||
|
|
||||||
|
// Determine how many chars left to render
|
||||||
|
uint8_t lineChars = UI_TEXTBOX.charsRevealed - charsRendered;
|
||||||
|
|
||||||
|
// Don't render more than in line
|
||||||
|
if(lineChars > lineLength) lineChars = lineLength;
|
||||||
|
assertTrue(lineChars > 0, "Line chars must be greater than 0");
|
||||||
|
|
||||||
|
// Update how many rendered
|
||||||
|
charsRendered += lineChars;
|
||||||
|
|
||||||
|
|
||||||
|
// Copy string from VN Textbox...
|
||||||
|
memoryCopy(
|
||||||
|
buffer,
|
||||||
|
UI_TEXTBOX.text + (UI_TEXTBOX.page * UI_TEXTBOX_PAGE_CHARS) +
|
||||||
|
(i * UI_TEXTBOX_CHARS_PER_LINE),
|
||||||
|
lineChars
|
||||||
|
);
|
||||||
|
// Null term string
|
||||||
|
buffer[lineChars] = '\0'; // Null-terminate the string
|
||||||
|
|
||||||
|
// Render the text
|
||||||
|
DrawText(
|
||||||
|
buffer,
|
||||||
|
UI_TEXTBOX_PADDING_X + UI_TEXTBOX_BORDER_WIDTH,
|
||||||
|
(
|
||||||
|
(RENDER_HEIGHT - UI_TEXTBOX_HEIGHT) +
|
||||||
|
UI_TEXTBOX_PADDING_Y + UI_TEXTBOX_BORDER_HEIGHT +
|
||||||
|
(i * FONT_LINE_HEIGHT)
|
||||||
|
),
|
||||||
|
FONT_HEIGHT,
|
||||||
|
WHITE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if we're done rendering text
|
||||||
|
if(UI_TEXTBOX.charsRevealed - charsRendered == 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EndBlendMode();
|
||||||
|
}
|
24
src/duskraylib/display/draw/drawui.h
Normal file
24
src/duskraylib/display/draw/drawui.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "duskraylib.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the UI drawing system.
|
||||||
|
*/
|
||||||
|
void drawUIInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws all the UI elements to the screen in the correct order.
|
||||||
|
*/
|
||||||
|
void drawUI(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the UI textbox to the screen.
|
||||||
|
*/
|
||||||
|
void drawUITextbox(void);
|
@ -8,6 +8,7 @@
|
|||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "display/draw/drawscene.h"
|
#include "display/draw/drawscene.h"
|
||||||
#include "display/draw/drawoverworld.h"
|
#include "display/draw/drawoverworld.h"
|
||||||
|
#include "display/draw/drawui.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
RenderTexture2D RENDER_SCREEN_TEXTURE;
|
RenderTexture2D RENDER_SCREEN_TEXTURE;
|
||||||
@ -32,14 +33,17 @@ void renderInit(void) {
|
|||||||
RENDER_ENTITIES_TEXTURE = LoadTexture("../data/entities.png");
|
RENDER_ENTITIES_TEXTURE = LoadTexture("../data/entities.png");
|
||||||
|
|
||||||
drawOverworldInit();
|
drawOverworldInit();
|
||||||
|
drawUIInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderDraw(void) {
|
void renderDraw(void) {
|
||||||
// Draw the actual game.
|
// Draw the actual game.
|
||||||
|
BeginBlendMode(BLEND_ALPHA_PREMULTIPLY);
|
||||||
BeginTextureMode(RENDER_SCREEN_TEXTURE);
|
BeginTextureMode(RENDER_SCREEN_TEXTURE);
|
||||||
ClearBackground(BLACK);
|
ClearBackground(BLACK);
|
||||||
|
|
||||||
drawScene();
|
drawScene();
|
||||||
|
drawUI();
|
||||||
|
|
||||||
EndTextureMode();
|
EndTextureMode();
|
||||||
|
|
||||||
@ -69,7 +73,10 @@ void renderDraw(void) {
|
|||||||
0.0f,
|
0.0f,
|
||||||
WHITE
|
WHITE
|
||||||
);
|
);
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
EndBlendMode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderDispose(void) {
|
void renderDispose(void) {
|
||||||
|
Reference in New Issue
Block a user