Fixed CSV Parsing on tools

This commit is contained in:
2023-01-28 21:01:30 -08:00
parent fcaeebd316
commit d14e063ba6
17 changed files with 347 additions and 19 deletions

View File

@ -29,4 +29,5 @@ scene.22.1,"King Fight"
scene.23.1,"Post King Fight, angry he leaves, town rallies around you" scene.23.1,"Post King Fight, angry he leaves, town rallies around you"
scene.24.1,"Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on." scene.24.1,"Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on."
unknown3,"Something here has to bring the big bad to town." unknown3,"Something here has to bring the big bad to town."
test.1,"Test" test.1,"Test "
test.2,"Test*"
1 undefined UNDEFINED
29 scene.23.1 Post King Fight, angry he leaves, town rallies around you
30 scene.24.1 Go to one of the kingsmen who's working with the big bad, he's worried that the townspeople know more than they let on.
31 unknown3 Something here has to bring the big bad to town.
32 test.1 Test Test
33 test.2 Test*

View File

@ -7,6 +7,7 @@
#include "scene/Scene.hpp" #include "scene/Scene.hpp"
#include "ui/UIComponent.hpp" #include "ui/UIComponent.hpp"
#include "game/DawnGame.hpp" #include "game/DawnGame.hpp"
#include "ui/UIMenu.hpp"
using namespace Dawn; using namespace Dawn;
@ -26,6 +27,12 @@ void UICanvas::onRenderTargetResize(float_t w, float_t h){
} }
} }
void UICanvas::onSceneUpdate() {
if(this->currentMenu != nullptr) {
this->currentMenu->onTick();
}
}
void UICanvas::setCamera(Camera *camera) { void UICanvas::setCamera(Camera *camera) {
assertTrue(camera != this->camera); assertTrue(camera != this->camera);
@ -58,11 +65,23 @@ float_t UICanvas::getHeight() {
return this->camera->getRenderTarget()->getHeight(); return this->camera->getRenderTarget()->getHeight();
} }
struct UIMenu * UICanvas::getCurrentMenu() {
return this->currentMenu;
}
void UICanvas::setCurrentMenu(struct UIMenu *menu) {
if(this->currentMenu != nullptr) this->currentMenu->onInactive();
this->currentMenu = menu;
if(menu != nullptr) menu->onActive();
}
void UICanvas::onStart() { void UICanvas::onStart() {
if(this->camera == nullptr) { if(this->camera == nullptr) {
auto camera = this->getScene()->findComponent<Camera>(); auto camera = this->getScene()->findComponent<Camera>();
this->setCamera(camera); this->setCamera(camera);
} }
this->getScene()->eventSceneUpdate.addListener(this, &UICanvas::onSceneUpdate);
} }
void UICanvas::onDispose() { void UICanvas::onDispose() {
@ -71,6 +90,8 @@ void UICanvas::onDispose() {
this, &UICanvas::onRenderTargetResize this, &UICanvas::onRenderTargetResize
); );
} }
this->getScene()->eventSceneUpdate.removeListener(this, &UICanvas::onSceneUpdate);
auto it = this->children.begin(); auto it = this->children.begin();
while(it != this->children.end()) { while(it != this->children.end()) {

View File

@ -16,12 +16,15 @@ namespace Dawn {
}; };
class UIComponent; class UIComponent;
struct UIMenu;
class UICanvas : public SceneItemComponent { class UICanvas : public SceneItemComponent {
protected: protected:
Camera *camera = nullptr; Camera *camera = nullptr;
struct UIMenu *currentMenu = nullptr;
void onRenderTargetResize(float_t w, float_t h); void onRenderTargetResize(float_t w, float_t h);
void onSceneUpdate();
public: public:
/** /**
@ -33,7 +36,7 @@ namespace Dawn {
*/ */
static UICanvas * create(Scene *scene); static UICanvas * create(Scene *scene);
// //======================================================================//
std::vector<UIComponent*> children; std::vector<UIComponent*> children;
UIDrawType drawType = UI_DRAW_TYPE_WORLD_CAMERA_RELATIVE; UIDrawType drawType = UI_DRAW_TYPE_WORLD_CAMERA_RELATIVE;
@ -64,6 +67,12 @@ namespace Dawn {
return item; return item;
} }
/**
* Find a UI Element attached to this canvas.
*
* @tparam Type of the UI item to find.
* @return Pointer to first matching element of type T.
*/
template<class T> template<class T>
T * findElement() { T * findElement() {
auto it = this->children.begin(); auto it = this->children.begin();
@ -90,6 +99,20 @@ namespace Dawn {
*/ */
float_t getHeight(); float_t getHeight();
/**
* Returns the currently active menu for this UI Canvas.
*
* @return The currently active menu, or nullptr if there is none.
*/
struct UIMenu * getCurrentMenu();
/**
* Sets the currently active menu, and ticks it appropriately.
*
* @param menu Menu to set as the current active menu.
*/
void setCurrentMenu(struct UIMenu *menu);
void onStart() override; void onStart() override;
void onDispose() override; void onDispose() override;
}; };

View File

@ -12,4 +12,5 @@ target_sources(${DAWN_TARGET_NAME}
UISprite.cpp UISprite.cpp
UIEmpty.cpp UIEmpty.cpp
UIGrid.cpp UIGrid.cpp
UIMenu.cpp
) )

View File

@ -91,9 +91,7 @@ void UIComponent::updatePositions() {
} }
// Fire event // Fire event
eventAlignmentUpdated.invoke( eventAlignmentUpdated.invoke(this);
this->width, this->height, this->relativeX, this->relativeY
);
} }
float_t UIComponent::getWidth() { float_t UIComponent::getWidth() {

View File

@ -38,7 +38,7 @@ namespace Dawn {
UIComponent *parent = nullptr; UIComponent *parent = nullptr;
// Events // Events
Event<float_t, float_t, float_t, float_t> eventAlignmentUpdated; Event<UIComponent*> eventAlignmentUpdated;
// I currently don't support rotation or scale. Not because I can't but // I currently don't support rotation or scale. Not because I can't but
// because it's basically un-necessary. Unity does support rotation but // because it's basically un-necessary. Unity does support rotation but

View File

@ -36,7 +36,18 @@ std::vector<struct ShaderPassItem> UIGrid::getSelfPassItems(
return std::vector<struct ShaderPassItem>(); return std::vector<struct ShaderPassItem>();
} }
void UIGrid::onChildAligned(UIComponent *child) {
assertNotNull(child);
assertMapHasKey(this->gridChildren, child);
this->alignChild(child, this->gridChildren[child]);
}
void UIGrid::alignChild(UIComponent *child, struct UIGridPosition pos) { void UIGrid::alignChild(UIComponent *child, struct UIGridPosition pos) {
assertNotNull(child);
// Remove event listener
child->eventAlignmentUpdated.addListener(this, &UIGrid::onChildAligned);
float_t gridX = (this->sizeCol * pos.x) + (this->gutterX * pos.x); float_t gridX = (this->sizeCol * pos.x) + (this->gutterX * pos.x);
float_t gridY = (this->sizeRow * pos.y) + (this->gutterY * pos.y); float_t gridY = (this->sizeRow * pos.y) + (this->gutterY * pos.y);
@ -68,6 +79,9 @@ void UIGrid::alignChild(UIComponent *child, struct UIGridPosition pos) {
glm::vec4(gridX + x, gridY + y, sizeX, sizeY), glm::vec4(gridX + x, gridY + y, sizeX, sizeY),
0.0f 0.0f
); );
// Re-Add event listener
child->eventAlignmentUpdated.addListener(this, &UIGrid::onChildAligned);
} }
void UIGrid::setGridSize( void UIGrid::setGridSize(
@ -79,6 +93,8 @@ void UIGrid::setGridSize(
this->gutterX = gutterX; this->gutterX = gutterX;
this->gutterY = gutterY; this->gutterY = gutterY;
// TODO: Need to fix children here.
this->gridChildren.clear(); this->gridChildren.clear();
this->updatePositions(); this->updatePositions();
} }

View File

@ -33,6 +33,8 @@ namespace Dawn {
*/ */
void alignChild(UIComponent *child, struct UIGridPosition pos); void alignChild(UIComponent *child, struct UIGridPosition pos);
void onChildAligned(UIComponent *child);
protected: protected:
void updatePositions() override; void updatePositions() override;
std::vector<struct ShaderPassItem> getSelfPassItems( std::vector<struct ShaderPassItem> getSelfPassItems(

96
src/dawn/ui/UIMenu.cpp Normal file
View File

@ -0,0 +1,96 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "UIMenu.hpp"
using namespace Dawn;
UIMenu::UIMenu(UICanvas *canvas, int32_t columns, int32_t rows) {
assertNotNull(canvas);
assertTrue(columns > 0);
assertTrue(rows > 0);
this->canvas = canvas;
this->rows = rows;
this->columns = columns;
this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
}
void UIMenu::setSize(int32_t cols, int32_t rows) {
assertNotNull(this->items);
assertTrue(columns > 0);
assertTrue(rows > 0);
assertTrue(columns != this->columns);
assertTrue(rows != this->rows);
memoryFree(this->items);
this->items = (UIMenuItem**)memoryFillWithZero(sizeof(UIMenuItem*)*columns*rows);
}
UIMenuItem * UIMenu::getItem(int32_t x, int32_t y) {
return this->items[x * this->columns + y];
}
void UIMenu::setPosition(int32_t x, int32_t y) {
assertTrue(x >= 0 && x < this->columns);
assertTrue(y >= 0 && y < this->rows);
UIMenuItem *item;
if(this->x != -1) {
assertTrue(this->y != -1);
item = this->getItem(this->x, this->y);
if(item != nullptr) {
item->onItemOff();
}
}
this->eventCursorChange.invoke(this->x, this->y, x, y);
this->x = x;
this->y = y;
item = this->getItem(x, y);
if(item != nullptr && item->canBeOvered()) {
item->onItemOver();
}
}
void UIMenu::moveRelative(int32_t x, int32_t y) {
int32_t x2 = this->x + x;
if(x2 < 0 || x2 >= this->columns) return;
int32_t y2 = this->y + y;
if(y2 < 0 || y2 >= this->rows) return;
this->setPosition(x2, y2);
}
void UIMenu::setItem(int32_t x, int32_t y, UIMenuItem *item) {
assertTrue(x >= 0);
assertTrue(y >= 0);
assertTrue(x < this->columns);
assertTrue(y < this->rows);
assertNotNull(item);
assertNotNull(this->items);
assertNull(this->getItem(x, y));
this->items[x * this->columns + y] = item;
}
void UIMenu::onInactive() {
this->eventMenuInactive.invoke();
}
void UIMenu::onActive() {
this->eventMenuActive.invoke();
}
void UIMenu::onTick() {
std::cout << "Tick menu" << std::endl;
}
UIMenu::~UIMenu() {
if(this->canvas->getCurrentMenu() == this) {
this->canvas->setCurrentMenu(nullptr);
}
memoryFree(this->items);
}

125
src/dawn/ui/UIMenu.hpp Normal file
View File

@ -0,0 +1,125 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "event/Event.hpp"
#include "ui/UIComponent.hpp"
#include "util/memory.hpp"
namespace Dawn {
class UIMenuItem {
public:
/**
* Called when the item is selected (Accepted) on.
*/
virtual void onItemSelected() = 0;
/**
* Called when either the mouse or the user controller input is removed
* off this item.
*/
virtual void onItemOver() = 0;
/**
* Called when either the mouth or the user controller input is put over
* this item.
*/
virtual void onItemOff() = 0;
/**
* Returns whether the UI item can be hovered overed or not.
* @return Whether it can be overed or not.
*/
virtual bool_t canBeOvered() = 0;
/**
* Returns whether or not the item can be selected or not.
* @return Whether it can be selected or not.
*/
virtual bool_t canBeSelected() = 0;
};
struct UIMenu {
private:
UICanvas *canvas;
int32_t x = -1;
int32_t y = -1;
int32_t rows = 1;
int32_t columns = 1;
UIMenuItem **items = nullptr;
protected:
/** Invoked by UICanvas when this menu has been made inactive. */
void onInactive();
/** Invoked by UICanvas when this menu has been made active. */
void onActive();
/** Invoked by UICanvas every tick this menu is active. */
void onTick();
public:
Event<> eventMenuActive;
Event<> eventMenuInactive;
Event<int32_t, int32_t, int32_t, int32_t> eventCursorChange;
Event<UIMenuItem*> eventItemSelected;
/**
* Construct a new UI Menu Host.
*
* @param canvas Canvas that this menu belongs to.
* @param columns Iniitial size of the menu X axis.
* @param rows Initial size of the menu Y axis.
*/
UIMenu(UICanvas *canvas, int32_t columns, int32_t rows);
/**
* Sets the size of the UI Menu.
*
* @param columns How many columns in the menu.
* @param rows How many rows in the menu.
*/
void setSize(int32_t columns, int32_t rows);
/**
* Returns the UI Item at the given position.
*
* @param x X coordinate of the item to get.
* @param y Y coordinate of the item to get.
* @return The pointer to the menu item, or null if invalid.
*/
UIMenuItem * getItem(int32_t x, int32_t y);
/**
* Sets the position of the cursor in the grid.
*
* @param x X position of the cursor.
* @param y Y position of the cursor.
*/
void setPosition(int32_t x, int32_t y);
/**
* Move the cursor relative to the current position.
*
* @param x X position to move relative.
* @param y Y position to move relative.
*/
void moveRelative(int32_t x, int32_t y);
/**
* Adds/Sets an item onto the menu.
*
* @param x X coordinate to set the item.
* @param y Y coordinate to set the item.
* @param item Item to set.
*/
void setItem(int32_t x, int32_t y, UIMenuItem *item);
/**
* Cleans up the menu items, doesn't free the children themselves.
*/
~UIMenu();
friend class UICanvas;
};
}

View File

@ -20,6 +20,17 @@ static inline void * memoryAllocate(const size_t size) {
return (void *)malloc(size); return (void *)malloc(size);
} }
/**
* Allocate space in memory, where all values are set to 0 (in binary space).
*
* @param size Size of the array.
* @return Pointer to the space in memory to use.
*/
static inline void * memoryFillWithZero(const size_t size) {
return (void *)calloc(1, size);
}
/** /**
* Free some previously allocated memory space. * Free some previously allocated memory space.
* @param pointer Pointer in memory to free. * @param pointer Pointer in memory to free.

View File

@ -30,7 +30,6 @@ set(DIR_GAME_ASSETS games/pokergame)
tool_texture(texture_test texture_test.png) tool_texture(texture_test texture_test.png)
tool_language(language_en ${DIR_GAME_ASSETS}/locale/en.csv) tool_language(language_en ${DIR_GAME_ASSETS}/locale/en.csv)
tool_language(language_jp ${DIR_GAME_ASSETS}/locale/jp.csv)
tool_tileset(tileset_death texture_death ${DIR_GAME_ASSETS}/characters/death/sheet.png 1 3) tool_tileset(tileset_death texture_death ${DIR_GAME_ASSETS}/characters/death/sheet.png 1 3)
@ -40,7 +39,6 @@ tool_audio(audio_test borrowed/sample_short.wav)
add_dependencies(${DAWN_TARGET_NAME} add_dependencies(${DAWN_TARGET_NAME}
language_en language_en
language_jp
tileset_death tileset_death

View File

@ -46,6 +46,8 @@ void TestUIScene::stage() {
auto grid = this->canvas->addElement<UIGrid>(); auto grid = this->canvas->addElement<UIGrid>();
grid->setTransform(UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, glm::vec4(0, 0, 0, 0), 0); grid->setTransform(UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, glm::vec4(0, 0, 0, 0), 0);
grid->setGridSize(4, 4, 8, 8); grid->setGridSize(4, 4, 8, 8);
auto menu = new UIMenu(this->canvas, grid->getColumns(), grid->getRows());
for(int32_t x = 0; x < grid->getColumns(); x++) { for(int32_t x = 0; x < grid->getColumns(); x++) {
for(int32_t y = 0; y < grid->getRows(); y++) { for(int32_t y = 0; y < grid->getRows(); y++) {
@ -54,6 +56,15 @@ void TestUIScene::stage() {
label->setText("test.1"); label->setText("test.1");
label->setFontSize(24); label->setFontSize(24);
grid->addToGrid(label, x, y, UI_COMPONENT_ALIGN_END, UI_COMPONENT_ALIGN_END); grid->addToGrid(label, x, y, UI_COMPONENT_ALIGN_END, UI_COMPONENT_ALIGN_END);
auto menuItem = new TestMenuItem;
menuItem->label = label;
menu->setItem(x, y, menuItem);
} }
menu->setPosition(0, 0);
this->canvas->setCurrentMenu(menu);
} }
this->canvas->setCurrentMenu(menu);
} }

View File

@ -12,8 +12,33 @@
#include "ui/UIGrid.hpp" #include "ui/UIGrid.hpp"
#include "ui/UISprite.hpp" #include "ui/UISprite.hpp"
#include "prefabs/SimpleSpinningCubePrefab.hpp" #include "prefabs/SimpleSpinningCubePrefab.hpp"
#include "ui/UIMenu.hpp"
namespace Dawn { namespace Dawn {
class TestMenuItem : public UIMenuItem {
public:
UILabel *label;
void onItemSelected() {
}
void onItemOver() {
this->label->setText("test.2");
}
void onItemOff() {
this->label->setText("test.1");
}
bool_t canBeOvered() {
return true;
}
bool_t canBeSelected() {
return true;
}
};
class TestUIScene : public Scene { class TestUIScene : public Scene {
private: private:
Camera *camera = nullptr; Camera *camera = nullptr;

View File

@ -56,23 +56,22 @@ int main(int argc, char *argv[]) {
size_t readSize = fread(buffer, 1, fileSize, file); size_t readSize = fread(buffer, 1, fileSize, file);
fclose(file); fclose(file);
if(readSize < fileSize) { if(readSize < fileSize) {
free(buffer);
printf("Failed to read all data from CSV\n"); printf("Failed to read all data from CSV\n");
free(buffer);
return 1; return 1;
} }
buffer[fileSize] = '\0'; buffer[fileSize] = '\0';
csvParse(buffer, &csv); csvParse(buffer, &csv);
free(buffer); free(buffer);
printf("Parsed\n");
// Prepare output file for writing. // Prepare output file for writing.
sprintf(path, "%s.language", out); sprintf(path, "%s.language", out);
fileMkdirp(path); fileMkdirp(path);
file = fopen(path, "wb"); file = fopen(path, "wb");
if(file == NULL) { if(file == NULL) {
csvDispose(&csv);
printf("Failed to create output language file\n"); printf("Failed to create output language file\n");
csvDispose(&csv);
return 1; return 1;
} }
@ -85,14 +84,13 @@ int main(int argc, char *argv[]) {
csvDispose(&csv); csvDispose(&csv);
return 1; return 1;
} }
char *key = csvGetCell(&csv, y, 0); char *key = csvGetCell(&csv, y, 0);
char *value = csvGetCell(&csv, y, 1); char *value = csvGetCell(&csv, y, 1);
// 23/01/14 - Replace \r in CSV. // 23/01/14 - Replace \r in CSV.
stringRemoveAll(key, '\r'); stringRemoveAll(key, '\r');
stringRemoveAll(value, '\r'); stringRemoveAll(value, '\r');
if(strlen(key) <= 0 || strlen(value) <= 0) { if(strlen(key) <= 0 || strlen(value) <= 0) {
printf("Failed to parse language. Line %i has an invalid string\n", y); printf("Failed to parse language. Line %i has an invalid string\n", y);
fclose(file); fclose(file);

View File

@ -8,7 +8,7 @@
#include "csv.h" #include "csv.h"
char * csvGetCell(csv_t *csv, int32_t row, int32_t cell) { char * csvGetCell(csv_t *csv, int32_t row, int32_t cell) {
return csv->rows[(row * CSV_ROW_COUNT_MAX) + cell]; return csv->rows[(row * CSV_COLUMN_COUNT_MAX) + cell];
} }
void csvParse(char *string, csv_t *csv) { void csvParse(char *string, csv_t *csv) {
@ -18,9 +18,9 @@ void csvParse(char *string, csv_t *csv) {
int32_t rowCellCount; int32_t rowCellCount;
length = strlen(string); length = strlen(string);
csv->buffer = malloc(sizeof(char) * length * 2); csv->buffer = malloc(sizeof(char) * (length+1) * CSV_COLUMN_COUNT_MAX * CSV_ROW_COUNT_MAX);
csv->cellCounts = malloc(sizeof(int32_t) * CSV_ROW_COUNT_MAX); csv->cellCounts = malloc(sizeof(int32_t) * CSV_ROW_COUNT_MAX);
csv->rows = malloc(sizeof(char *) * 32 * CSV_ROW_COUNT_MAX); csv->rows = malloc(sizeof(char*) * CSV_ROW_COUNT_MAX * CSV_COLUMN_COUNT_MAX);
i = 0; i = 0;
j = 0; j = 0;
@ -35,7 +35,7 @@ void csvParse(char *string, csv_t *csv) {
case CSV_PARSE_STATE_FIND_CELL: case CSV_PARSE_STATE_FIND_CELL:
if(c == '"') { if(c == '"') {
state = CSV_PARSE_STATE_PARSE_CELL_WITH_QUOTES; state = CSV_PARSE_STATE_PARSE_CELL_WITH_QUOTES;
csv->rows[(csv->rowCount * CSV_ROW_COUNT_MAX) + rowCellCount] = csv->buffer + j; csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
rowCellCount++; rowCellCount++;
continue; continue;
} else if(c == '\r' || c == '\n') { } else if(c == '\r' || c == '\n') {
@ -43,13 +43,13 @@ void csvParse(char *string, csv_t *csv) {
state = CSV_PARSE_STATE_LINE_END; state = CSV_PARSE_STATE_LINE_END;
continue; continue;
} else if(c == ',') { } else if(c == ',') {
csv->rows[(csv->rowCount * CSV_ROW_COUNT_MAX) + rowCellCount] = csv->buffer + j; csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
csv->buffer[j++] = '\0'; csv->buffer[j++] = '\0';
rowCellCount++; rowCellCount++;
continue; continue;
} else { } else {
state = CSV_PARSE_STATE_PARSE_CELL; state = CSV_PARSE_STATE_PARSE_CELL;
csv->rows[(csv->rowCount * CSV_ROW_COUNT_MAX) + rowCellCount] = csv->buffer + j; csv->rows[(csv->rowCount * CSV_COLUMN_COUNT_MAX) + rowCellCount] = csv->buffer + j;
csv->buffer[j++] = c; csv->buffer[j++] = c;
rowCellCount++; rowCellCount++;
continue; continue;
@ -104,6 +104,7 @@ void csvParse(char *string, csv_t *csv) {
free(NULL); free(NULL);
} }
} }
csv->buffer[j++] = '\0'; csv->buffer[j++] = '\0';
if(rowCellCount != 0) { if(rowCellCount != 0) {

View File

@ -10,6 +10,7 @@
#include "string.h" #include "string.h"
#define CSV_ROW_COUNT_MAX 128 #define CSV_ROW_COUNT_MAX 128
#define CSV_COLUMN_COUNT_MAX 16
typedef enum { typedef enum {
CSV_PARSE_STATE_FIND_CELL,//0 CSV_PARSE_STATE_FIND_CELL,//0