diff options
| author | ilotterytea <iltsu@alright.party> | 2025-01-25 16:30:07 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-01-25 16:30:07 +0500 |
| commit | 9f5b2b1ebd4bb46163b7f00912db0578aca57d25 (patch) | |
| tree | 4147ff7cd7ba74058862bd78cb07154ef314966f /src/editor.c | |
| parent | 8a27da4c34c2a233a5f793893ed778e395a5220d (diff) | |
feat: build tab + tile loading
Diffstat (limited to 'src/editor.c')
| -rw-r--r-- | src/editor.c | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/src/editor.c b/src/editor.c index 65f6a32..118b1f9 100644 --- a/src/editor.c +++ b/src/editor.c @@ -1,8 +1,17 @@ #include "editor.h" +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "raygui.h" #include "raylib.h" #include "xd.h" +const char *EDITOR_MAIN_TABS[] = {"Build"}; +const int EDITOR_MAIN_TABS_SIZE = + sizeof(EDITOR_MAIN_TABS) / sizeof(EDITOR_MAIN_TABS[0]); + void SE_DrawEditor(Editor *editor, Camera2D *camera) { Vector2 mousePos = GetScreenToWorld2D(GetMousePosition(), *camera); float zoom = camera->zoom; @@ -28,3 +37,318 @@ void SE_DrawEditor(Editor *editor, Camera2D *camera) { } } } + +void drawBuildTab(Editor *editor, int x, int y, int width, int height) { + int padding = 20; + GuiPanel((Rectangle){x, y + 24.0f, width, height}, NULL); + + if (IsFileDropped() && editor->state.createBlockState == NULL) { + EditorCreateBlockState *state = malloc(sizeof(EditorCreateBlockState)); + + FilePathList droppedFiles = LoadDroppedFiles(); + + if (!IsFileExtension(droppedFiles.paths[0], ".png")) { + free(state); + UnloadDroppedFiles(droppedFiles); + return; + } + + state->upFilePath = droppedFiles.paths[0]; + UnloadDroppedFiles(droppedFiles); + + // loading textures + Image image = LoadImage(state->upFilePath); + if (image.width != TEXTURE_WIDTH || image.height != TEXTURE_HEIGHT) { + ImageResize(&image, TEXTURE_WIDTH, TEXTURE_HEIGHT); + } + state->upTexture = LoadTextureFromImage(image); + + editor->state.createBlockState = state; + + UnloadImage(image); + } + + // Rendering + Rectangle controlBounds = {x + padding, y + padding + 20.0f, 200, 200}; + Rectangle contentSize = {x + padding, y + padding, 10 * TEXTURE_WIDTH, 1000}; + + GuiScrollPanel(controlBounds, NULL, contentSize, &editor->state.panelScroll, + &editor->state.panelView); + + BeginScissorMode(editor->state.panelView.x, editor->state.panelView.y, + editor->state.panelView.width, + editor->state.panelView.height); + + Vector2 mousePos = GetMousePosition(); + + // rendering floor tiles in grid + int row = 0, column = 0, texturesPerRow = 10; + for (int i = 0; i < sizeof(editor->state.cache.tiles) / + sizeof(editor->state.cache.tiles[0]); + i++) { + EditorTile *tile = editor->state.cache.tiles[i]; + if (tile == NULL) continue; + + row = i / texturesPerRow; + column = i % texturesPerRow; + + int x = controlBounds.x + 5 + TEXTURE_WIDTH * column; + int y = + controlBounds.y + editor->state.panelScroll.y + TEXTURE_HEIGHT * row; + + DrawTexture(tile->texture, x, y, WHITE); + + bool isHovered = (x <= mousePos.x && mousePos.x <= x + TEXTURE_WIDTH) && + (y <= mousePos.y && mousePos.y <= y + TEXTURE_HEIGHT); + + bool sameTile = editor->state.selectedTile != NULL && + editor->state.selectedTile->data.id == tile->data.id; + + // hover event + if (isHovered || sameTile) { + DrawRectangleLines(x, y, TEXTURE_WIDTH, TEXTURE_HEIGHT, YELLOW); + } + + // select tile + if (isHovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { + editor->state.selectedTile = tile; + } + } + + EndScissorMode(); +} + +void drawTextures(EditorCreateBlockState *state, int wx, int wy, int ww, int wh, + int pad) { + if (state->isFloor) { + GuiLabel((Rectangle){wx + pad, wy + pad + 24.0f * 2.0f, ww, 24.0f}, "UP"); + DrawTexture(state->upTexture, wx + pad, wy + pad + 24.0f * 3.0f, WHITE); + } else { + GuiLabel((Rectangle){wx + pad, wy + pad + 24.0f * 2.0f, ww, 24.0f}, + "UP (2D)"); + DrawTexture(state->upTexture, wx + pad, wy + pad + 24.0f * 3.0f, WHITE); + + GuiLabel((Rectangle){wx + pad + 24.0f * 3.0f, wy + pad + 24.0f * 2.0f, ww, + 24.0f}, + "CORNER (2D)"); + DrawTexture(state->cornerTexture, wx + pad + 24.0f * 3.0f, + wy + pad + 24.0f * 3.0f, WHITE); + + GuiLabel((Rectangle){wx + pad + 24.0f * 7.0f, wy + pad + 24.0f * 2.0f, ww, + 24.0f}, + "SIDE (3D)"); + DrawTexture(state->sideTexture, wx + pad + 24.0f * 7.0f, + wy + pad + 24.0f * 3.0f, WHITE); + } +} + +void loadWallTextures(EditorCreateBlockState *state, int wx, int wy, int ww, + int wh, int pad) { + if (state->sideFilePath == NULL) { + int box = GuiMessageBox((Rectangle){wx - 20, wy + 100, ww + 40, 200}, + "Waiting for side texture", + "Drop side texture here", "No"); + + if (box >= 1) { + state->isWall = false; + state->isFloor = true; + } + + if (IsFileDropped()) { + FilePathList droppedFiles = LoadDroppedFiles(); + + if (!IsFileExtension(droppedFiles.paths[0], ".png")) { + UnloadDroppedFiles(droppedFiles); + return; + } + + state->sideFilePath = droppedFiles.paths[0]; + UnloadDroppedFiles(droppedFiles); + + Image image = LoadImage(state->sideFilePath); + if (image.width != TEXTURE_WIDTH || image.height != TEXTURE_HEIGHT) { + ImageResize(&image, TEXTURE_WIDTH, TEXTURE_HEIGHT); + } + state->sideTexture = LoadTextureFromImage(image); + } + + return; + } + + if (state->cornerFilePath == NULL) { + int box = GuiMessageBox((Rectangle){wx - 20, wy + 100, ww + 40, 200}, + "Waiting for corner texture", + "Drop corner texture here", "No"); + + if (box >= 1) { + UnloadTexture(state->sideTexture); + free(state->sideFilePath); + state->sideFilePath = NULL; + state->isWall = false; + state->isFloor = true; + } + + if (IsFileDropped()) { + FilePathList droppedFiles = LoadDroppedFiles(); + + if (!IsFileExtension(droppedFiles.paths[0], ".png")) { + UnloadDroppedFiles(droppedFiles); + return; + } + + state->cornerFilePath = droppedFiles.paths[0]; + UnloadDroppedFiles(droppedFiles); + + Image image = LoadImage(state->cornerFilePath); + if (image.width != TEXTURE_WIDTH || image.height != TEXTURE_HEIGHT) { + ImageResize(&image, TEXTURE_WIDTH, TEXTURE_HEIGHT); + } + state->cornerTexture = LoadTextureFromImage(image); + } + + return; + } +} + +void drawPreview(EditorCreateBlockState *state, int wx, int wy, int ww, int wh, + int pad) { + GuiLabel((Rectangle){wx + pad, wy + pad + 24.0f * 4.0f, ww, 24.0f}, + "2D PREVIEW"); + for (int x = 0; x < 10; x++) { + for (int y = 0; y < 5; y++) { + if (state->isFloor) { + DrawTexture(state->upTexture, wx + pad + x * TEXTURE_WIDTH, + wy + pad + 24.0f * 5.0f + y * TEXTURE_HEIGHT, WHITE); + } else { + Vector2 position = {x * TEXTURE_WIDTH, y * TEXTURE_HEIGHT}; + position.x += wx + pad; + position.y += wy + pad + 24.0f * 5.0f; + + // --- CORNERS --- + // top left + if (x == 0 && y == 0) { + DrawTextureEx(state->cornerTexture, position, 0.0f, 1.0f, WHITE); + } + // top right + else if (x == 9 && y == 0) { + DrawTextureEx(state->cornerTexture, position, 90.0f, 1.0f, WHITE); + } + // bottom left + else if (x == 0 && y == 4) { + DrawTextureEx(state->cornerTexture, position, 270.0f, 1.0f, WHITE); + } + // bottom right + else if (x == 9 && y == 4) { + DrawTextureEx(state->cornerTexture, position, 180.0f, 1.0f, WHITE); + } + + // --- SIDES --- + // top + else if (y == 0) { + DrawTextureEx(state->upTexture, position, 0.0f, 1.0f, WHITE); + } + // left + else if (x == 0 && y > 1) { + DrawTextureEx(state->upTexture, position, 270.0f, 1.0f, WHITE); + } + // right + else if (x == 9) { + DrawTextureEx(state->upTexture, position, 90.0f, 1.0f, WHITE); + } + // bottom + else if (y == 4 && x > 1) { + DrawTextureEx(state->upTexture, position, 180.0f, 1.0f, WHITE); + } + } + } + } +} + +void drawCreatingNewBlock(Editor *editor) { + EditorCreateBlockState *state = editor->state.createBlockState; + + int ww = 300; + int wh = 280; + + int wx = GetScreenWidth() / 2.0f - ww / 2.0f; + int wy = GetScreenHeight() / 2.0f - wh / 2.0f; + int pad = 20; + + int close = GuiWindowBox((Rectangle){wx, wy, ww, wh}, "Creating a new block"); + + // --- Block type --- + GuiLabel((Rectangle){wx + pad, wy + pad, ww - pad * 2, 24.0f}, "Select type"); + + GuiCheckBox((Rectangle){wx + pad, wy + pad + 24.0f, 24.0f, 24.0f}, "Floor", + &state->isFloor); + if (state->isFloor) state->isWall = false; + + GuiCheckBox( + (Rectangle){wx + pad * 4.0f + 24.0f, wy + pad + 24.0f, 24.0f, 24.0f}, + "Wall", &state->isWall); + if (state->isWall) state->isFloor = false; + if (!state->isWall && !state->isFloor) state->isFloor = true; + + // --- Texture loading --- + // Up texture + drawTextures(state, wx, wy, ww, wh, pad); + + // Side texture + if (state->isWall) { + loadWallTextures(state, wx, wy, ww, wh, pad); + } + + drawPreview(state, wx, wy, ww, wh, pad); + + int createButton = GuiButton( + (Rectangle){wx + pad, wy + wh - pad * 2.0f, ww - pad * 2.0f, 32.0f}, + "Create"); + + if (createButton) { + close = true; + + if (state->isFloor) { + int id = editor->state.cache.tileCacheSize; + + EditorTile *tile = malloc(sizeof(EditorTile)); + editor->state.cache.tiles[id] = tile; + + tile->data = (XdTileData){}; + tile->data.id = id; + tile->data.type = TILE_FLOOR; + + tile->texture = state->upTexture; + + editor->state.cache.tileCacheSize++; + } + } + + if (close) { + // free(state); + editor->state.createBlockState = NULL; + } +} + +void SE_DrawEditorToolkit(Editor *editor) { + float width = 400.0f; + float height = GetScreenHeight(); + float x = GetScreenWidth() - width; + float y = 0; + + switch (editor->state.activeMainTab) { + case 0: { + drawBuildTab(editor, x, y, width, height); + break; + } + default: + break; + } + + GuiTabBar((Rectangle){x, y, 100.0, 24.0f}, EDITOR_MAIN_TABS, + EDITOR_MAIN_TABS_SIZE, &editor->state.activeMainTab); + + // Creating new block + if (editor->state.createBlockState != NULL) { + drawCreatingNewBlock(editor); + } +}
\ No newline at end of file |
