summaryrefslogtreecommitdiff
path: root/src/editor.c
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-01-25 16:30:07 +0500
committerilotterytea <iltsu@alright.party>2025-01-25 16:30:07 +0500
commit9f5b2b1ebd4bb46163b7f00912db0578aca57d25 (patch)
tree4147ff7cd7ba74058862bd78cb07154ef314966f /src/editor.c
parent8a27da4c34c2a233a5f793893ed778e395a5220d (diff)
feat: build tab + tile loading
Diffstat (limited to 'src/editor.c')
-rw-r--r--src/editor.c324
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