From fa2749ece720ddab81bc75a64c51ee1b0fdfc00b Mon Sep 17 00:00:00 2001 From: erysdren Date: Fri, 19 Sep 2025 21:40:39 -0500 Subject: [PATCH 1/8] editor: wip --- CMakeLists.txt | 14 ++ editor/main.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+) create mode 100644 editor/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 18851a2..1be7810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ project(plush # options option(PLUSH_BUILD_EXAMPLES "Build Plush Examples" ON) +option(PLUSH_BUILD_EDITOR "Build Plush Editor" ON) option(PLUSH_USE_ASAN "Use Address Sanitizer" OFF) set(PLUSH_MAX_LIGHTS "32" CACHE STRING "Maximum number of lights in a single render pass") set(PLUSH_MAX_TRIANGLES "16384" CACHE STRING "Maximum number of triangles in a single render pass") @@ -77,6 +78,19 @@ endif() target_link_libraries(plush PUBLIC $<$:ASAN::ASAN>) +# editor + +if(PLUSH_BUILD_EDITOR) + find_package(SDL3 CONFIG COMPONENTS SDL3) + if (SDL3_FOUND) + add_executable(plush-editor) + target_sources(plush-editor PRIVATE + ${PROJECT_SOURCE_DIR}/editor/main.c + ) + target_link_libraries(plush-editor PUBLIC plush SDL3::SDL3) + endif() +endif() + # examples if(PLUSH_BUILD_EXAMPLES) diff --git a/editor/main.c b/editor/main.c new file mode 100644 index 0000000..a9cb7f0 --- /dev/null +++ b/editor/main.c @@ -0,0 +1,339 @@ + +#include +#include + +#define SDL_MAIN_USE_CALLBACKS 1 +#include + +#define log_error(...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) +#define log_warning(...) SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) + +#define WINDOW_TITLE "Plush Editor" +#define WINDOW_WIDTH (800) +#define WINDOW_HEIGHT (600) + +#define FRAMEBUFFER_SIZE (WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(uint8_t)) +#define ZBUFFER_SIZE (WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)) + +#define DEFAULT_FOV (90) +#define DEFAULT_SENSITIVITY (8) +#define DEFAULT_MOVESPEED (32) +#define DEFAULT_STRAFESPEED (32) + +#define MAX_MATERIALS (256) +#define MAX_VELOCITY (128) + +/* + * + * this holds all the editor state + * + */ + +typedef struct app { + /* sdl video state */ + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + SDL_Surface *surface; + SDL_Surface *surface8; + SDL_Palette *palette; + + /* plush video state */ + uint8_t *framebuffer; + float *zbuffer; + pl_Cam *camera; + pl_Light *headlight; + + /* camera state */ + float velocity[3]; + float movespeed; + float strafespeed; + + /* assets */ + pl_Mat *fallback_material; + + /* timer state */ + uint64_t ticks; + uint64_t deltaticks; + float time; + float deltatime; +} app_t; + +/* + * + * utility functions + * + */ + +static SDL_AppResult die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, fmt, ap); + va_end(ap); + + SDL_Event event; + event.quit.type = SDL_EVENT_QUIT; + event.quit.timestamp = SDL_GetTicksNS(); + SDL_PushEvent(&event); + + return SDL_APP_FAILURE; +} + +/* + * + * sdl callbacks + * + */ + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppInit(SDL_UNUSED void **appstate, SDL_UNUSED int argc, SDL_UNUSED char *argv[]) +{ + uint8_t pal[768]; + app_t *app; + + if (!SDL_Init(SDL_INIT_VIDEO)) + return die("%s", SDL_GetError()); + + /* allocate app state */ + app = SDL_malloc(sizeof(app_t)); + if (!app) + return die("%s", SDL_GetError()); + + /* create window and renderer */ + SDL_CreateWindowAndRenderer(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &app->window, &app->renderer); + SDL_SetWindowMinimumSize(app->window, WINDOW_WIDTH, WINDOW_HEIGHT); + SDL_SetWindowRelativeMouseMode(app->window, true); + SDL_SetRenderLogicalPresentation(app->renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); + + /* create render texture */ + app->texture = SDL_CreateTexture(app->renderer, SDL_GetWindowPixelFormat(app->window), SDL_TEXTUREACCESS_STREAMING, WINDOW_WIDTH, WINDOW_HEIGHT); + SDL_SetTextureScaleMode(app->texture, SDL_SCALEMODE_NEAREST); + + /* allocate plush buffers */ + app->framebuffer = plMalloc(WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(uint8_t)); + app->zbuffer = plMalloc(WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)); + + /* create render surfaces */ + app->surface = SDL_CreateSurfaceFrom(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_GetWindowPixelFormat(app->window), NULL, 0); + app->surface8 = SDL_CreateSurfaceFrom(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_PIXELFORMAT_INDEX8, app->framebuffer, WINDOW_WIDTH); + + /* create camera */ + app->camera = plCamCreate(WINDOW_WIDTH, WINDOW_HEIGHT, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, DEFAULT_FOV, app->framebuffer, app->zbuffer); + app->movespeed = DEFAULT_MOVESPEED; + app->strafespeed = DEFAULT_STRAFESPEED; + + /* create light */ + app->headlight = plLightSet(plLightCreate(), PL_LIGHT_POINT, 0, 0, 0, 0.5, 256); + + app->fallback_material = plMatCreate(); + app->fallback_material->ShadeType = PL_SHADE_FLAT; + app->fallback_material->Ambient[0] = 0.1745 * 255; + app->fallback_material->Ambient[1] = 0.03175 * 255; + app->fallback_material->Ambient[2] = 0.03175 * 255; + app->fallback_material->Diffuse[0] = 0.61424 * 255; + app->fallback_material->Diffuse[1] = 0.10136 * 255; + app->fallback_material->Diffuse[2] = 0.10136 * 255; + app->fallback_material->Specular[0] = 0.727811 * 255; + app->fallback_material->Specular[1] = 0.626959 * 255; + app->fallback_material->Specular[2] = 0.626959 * 255; + plMatInit(app->fallback_material); + + /* generate palette from fallback material */ + /* first color in the palette is always black and the second color is always white */ + plMatMakeOptPal(pal, 2, 255, &app->fallback_material, 1); + pal[0] = pal[1] = pal[2] = 0; + pal[3] = pal[4] = pal[5] = 255; + + /* map fallback material to generated palette */ + plMatMapToPal(app->fallback_material, pal, 0, 255); + + /* convert generated palette to sdl palette */ + app->palette = SDL_CreateSurfacePalette(app->surface8); + for (int i = 0; i < app->palette->ncolors; i++) + { + app->palette->colors[i].r = pal[i * 3 + 0]; + app->palette->colors[i].g = pal[i * 3 + 1]; + app->palette->colors[i].b = pal[i * 3 + 2]; + app->palette->colors[i].a = SDL_ALPHA_OPAQUE; + } + + /* start timer */ + app->ticks = SDL_GetTicks(); + app->deltaticks = 0; + app->time = (float)app->ticks / 1000.0f; + app->deltatime = (float)app->deltaticks / 1000.0f; + + /* return app state */ + *appstate = app; + + return SDL_APP_CONTINUE; +} + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppIterate(SDL_UNUSED void *appstate) +{ + const bool *keys = SDL_GetKeyboardState(NULL); + float look[3]; + float strafe[2]; + app_t *app = (app_t *)appstate; + + /* tick world state */ + uint64_t now = SDL_GetTicks(); + app->deltaticks = now - app->ticks; + app->ticks = now; + app->time = (float)app->ticks / 1000.0f; + app->deltatime = (float)app->deltaticks / 1000.0f; + + /* clear screen */ + SDL_memset(app->zbuffer, 0, WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)); + SDL_FillSurfaceRect(app->surface8, NULL, 0); + + /* handle movement */ + look[0] = plCos(plDegToRad(app->camera->Pan + 90)) * plCos(plDegToRad(app->camera->Pitch)); + look[1] = plSin(plDegToRad(app->camera->Pitch)); + look[2] = plSin(plDegToRad(app->camera->Pan + 90)) * plCos(plDegToRad(app->camera->Pitch)); + + strafe[0] = plCos(plDegToRad(app->camera->Pan)); + strafe[1] = plSin(plDegToRad(app->camera->Pan)); + + if (keys[SDL_SCANCODE_LSHIFT]) + { + app->movespeed = DEFAULT_MOVESPEED * 2; + app->strafespeed = DEFAULT_STRAFESPEED * 2; + } + else + { + app->movespeed = DEFAULT_MOVESPEED; + app->strafespeed = DEFAULT_STRAFESPEED; + } + + if (keys[SDL_SCANCODE_W]) + { + app->velocity[0] += look[0] * app->movespeed * app->deltatime; + app->velocity[1] += look[1] * app->movespeed * app->deltatime; + app->velocity[2] += look[2] * app->movespeed * app->deltatime; + } + + if (keys[SDL_SCANCODE_S]) + { + app->velocity[0] -= look[0] * app->movespeed * app->deltatime; + app->velocity[1] -= look[1] * app->movespeed * app->deltatime; + app->velocity[2] -= look[2] * app->movespeed * app->deltatime; + } + + if (keys[SDL_SCANCODE_A]) + { + app->velocity[0] -= strafe[0] * app->strafespeed * app->deltatime; + app->velocity[2] -= strafe[1] * app->strafespeed * app->deltatime; + } + + if (keys[SDL_SCANCODE_D]) + { + app->velocity[0] += strafe[0] * app->strafespeed * app->deltatime; + app->velocity[2] += strafe[1] * app->strafespeed * app->deltatime; + } + + /* cap velocity */ + if (app->velocity[0] < -MAX_VELOCITY) app->velocity[0] = -MAX_VELOCITY; + if (app->velocity[0] > MAX_VELOCITY) app->velocity[0] = MAX_VELOCITY; + if (app->velocity[1] < -MAX_VELOCITY) app->velocity[1] = -MAX_VELOCITY; + if (app->velocity[1] > MAX_VELOCITY) app->velocity[1] = MAX_VELOCITY; + if (app->velocity[2] < -MAX_VELOCITY) app->velocity[2] = -MAX_VELOCITY; + if (app->velocity[2] > MAX_VELOCITY) app->velocity[2] = MAX_VELOCITY; + + /* apply velocity */ + app->camera->X += app->velocity[0] * app->deltatime; + app->camera->Y += app->velocity[1] * app->deltatime; + app->camera->Z += app->velocity[2] * app->deltatime; + + /* keep headlight on camera */ + app->headlight->Xp = app->camera->X; + app->headlight->Yp = app->camera->Y; + app->headlight->Zp = app->camera->Z; + + /* render something */ + plRenderBegin(app->camera); + plRenderLight(app->headlight); + plRenderEnd(); + plTextPutStr(app->camera, 0, 0, 0, 1, "press escape to exit\npress space to release mouse"); + + /* sync to screen */ + SDL_SetRenderDrawColor(app->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + SDL_RenderClear(app->renderer); + if (SDL_LockTexture(app->texture, NULL, &app->surface->pixels, &app->surface->pitch)) + { + SDL_BlitSurface(app->surface8, NULL, app->surface, NULL); + SDL_UnlockTexture(app->texture); + } + SDL_RenderTexture(app->renderer, app->texture, NULL, NULL); + SDL_RenderPresent(app->renderer); + + return SDL_APP_CONTINUE; +} + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(SDL_UNUSED void *appstate, SDL_Event *event) +{ + app_t *app = (app_t *)appstate; + + if (event->type == SDL_EVENT_QUIT) + return SDL_APP_SUCCESS; + + switch (event->type) + { + case SDL_EVENT_KEY_DOWN: + { + if (event->key.scancode == SDL_SCANCODE_ESCAPE) + { + return SDL_APP_SUCCESS; + } + else if (event->key.scancode == SDL_SCANCODE_SPACE) + { + if (SDL_GetWindowRelativeMouseMode(app->window)) + { + int w, h; + SDL_GetWindowSize(app->window, &w, &h); + SDL_WarpMouseInWindow(app->window, w/2.0f, h/2.0f); + SDL_SetWindowRelativeMouseMode(app->window, false); + } + else + { + SDL_SetWindowRelativeMouseMode(app->window, true); + } + } + break; + } + + case SDL_EVENT_MOUSE_MOTION: + { + if (SDL_GetWindowRelativeMouseMode(app->window)) + { + app->camera->Pitch -= event->motion.yrel * app->deltatime * DEFAULT_SENSITIVITY; + app->camera->Pan -= event->motion.xrel * app->deltatime * DEFAULT_SENSITIVITY; + } + break; + } + } + + return SDL_APP_CONTINUE; +} + +SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(SDL_UNUSED void *appstate, SDL_UNUSED SDL_AppResult result) +{ + app_t *app = (app_t *)appstate; + + if (app) + { + if (app->headlight) plLightDelete(app->headlight); + if (app->fallback_material) plMatDelete(app->fallback_material); + if (app->surface) SDL_DestroySurface(app->surface); + if (app->surface8) SDL_DestroySurface(app->surface8); + if (app->texture) SDL_DestroyTexture(app->texture); + if (app->renderer) SDL_DestroyRenderer(app->renderer); + if (app->window) SDL_DestroyWindow(app->window); + if (app->camera) plCamDelete(app->camera); + if (app->framebuffer) plFree(app->framebuffer); + if (app->zbuffer) plFree(app->zbuffer); + SDL_free(app); + } + + SDL_Quit(); +} From 4cce3312734d902d7cd873186530d79092877c5e Mon Sep 17 00:00:00 2001 From: erysdren Date: Sat, 20 Sep 2025 00:53:12 -0500 Subject: [PATCH 2/8] editor: add scenefmt.txt concept for format --- editor/scenefmt.txt | 72 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 editor/scenefmt.txt diff --git a/editor/scenefmt.txt b/editor/scenefmt.txt new file mode 100644 index 0000000..bea2e32 --- /dev/null +++ b/editor/scenefmt.txt @@ -0,0 +1,72 @@ +Namespace = "Plush"; +Name = "Test Scene"; +DefaultCamera = 0; + +// palette 0 +palette +{ + 000000,FFFFFF,2B0707,330909,3B0A0A,430B0B,4B0D0D,530E0E,5C1010,641212,6D1515,771818,811C1C,8D2121,982727,A52D2D, + B23434,C13D3D,D04545,DF4F4F,EF5959,FF6464,FF6F6F,FF7A7A,FF8585,FF9090,FF9A9A,FFA3A3,FFABAB,FFB2B2,FFB8B8,FFBCBC, + FFBFBF,FFC0C0,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,00A01D,A9DF09,7F0000,20828E,DBCBAB,0000F0,22A9DF,097F00,00003E,A8DF09,7F0000, + 020000,000000,00000E,000000,000000,800000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,000200,000000,000000,0E0000,000000,008000,000000,000000,000000,000000,000000, + 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000080,030000,800300,008003,000080,030000, + 800300,008003,000080,030000,800300,008003,000080,030000,800300,008003,000080,030000,800300,008003,000080,030000, + FFB5F0,000000,0000C5,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,00D8D6,A6DF09,7F0000, + 000000,000000,000000,000000,0000C3,000000,800000,000000,160000,000300,000008,000000,000000,01F922,000000,000000, + 010000,000000,000002,000000,000000,004000,000000,000000,D0CF1D,50FE7F,000010,D01D50,FE7F00,0058E5,A6DF09,7F0000, + 020000,002903,8C0004,000000,000000,004000,000000,000000,831B24,DF097F,0000FF,FFFFFF,FFFFFF,FF0000,000000,000000, + 18D11D,50FE7F,000001,000000,000000,000010,A9DF09,7F0000,B80D8D,1FB255,0000A0,CF1D50,FE7F00,00CFAB,64DF09,7F0000 +} + +// camera 0 +camera +{ + Width = 640; + Height = 480; + Fov = 90; + zBuffer = true; + + Origin = "64 64 -384"; + Angles = "15 10 0"; + + Palette = 0; +} + +// material 0 +material +{ + Name = "Fallback Material"; + Fallback = true; + + Ambient = "0.1745 0.03175 0.03175"; + AmbientScale = 255; + + Diffuse = "0.61424 0.10136 0.10136"; + DiffuseScale = 255; + + Specular = "0.727811 0.626959 0.626959"; + SpecularScale = 255; +} + +// mesh 0 +mesh +{ + Name = "Polyrobo"; + + File = "polyrobo.obj"; + + Material = 0; +} + +// object 0 +object +{ + Name = "Polyrobo"; + + Mesh = 0; +} From 9c46342887c32ea14a6c63da86574ffba1ebd60e Mon Sep 17 00:00:00 2001 From: erysdren Date: Sat, 20 Sep 2025 13:46:08 -0500 Subject: [PATCH 3/8] editor: scenefmt.txt: palette updates --- editor/scenefmt.txt | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/editor/scenefmt.txt b/editor/scenefmt.txt index bea2e32..8c7f87e 100644 --- a/editor/scenefmt.txt +++ b/editor/scenefmt.txt @@ -5,22 +5,9 @@ DefaultCamera = 0; // palette 0 palette { - 000000,FFFFFF,2B0707,330909,3B0A0A,430B0B,4B0D0D,530E0E,5C1010,641212,6D1515,771818,811C1C,8D2121,982727,A52D2D, - B23434,C13D3D,D04545,DF4F4F,EF5959,FF6464,FF6F6F,FF7A7A,FF8585,FF9090,FF9A9A,FFA3A3,FFABAB,FFB2B2,FFB8B8,FFBCBC, - FFBFBF,FFC0C0,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,00A01D,A9DF09,7F0000,20828E,DBCBAB,0000F0,22A9DF,097F00,00003E,A8DF09,7F0000, - 020000,000000,00000E,000000,000000,800000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,000200,000000,000000,0E0000,000000,008000,000000,000000,000000,000000,000000, - 000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,000080,030000,800300,008003,000080,030000, - 800300,008003,000080,030000,800300,008003,000080,030000,800300,008003,000080,030000,800300,008003,000080,030000, - FFB5F0,000000,0000C5,000000,000000,000000,000000,000000,000000,000000,000000,000000,000000,00D8D6,A6DF09,7F0000, - 000000,000000,000000,000000,0000C3,000000,800000,000000,160000,000300,000008,000000,000000,01F922,000000,000000, - 010000,000000,000002,000000,000000,004000,000000,000000,D0CF1D,50FE7F,000010,D01D50,FE7F00,0058E5,A6DF09,7F0000, - 020000,002903,8C0004,000000,000000,004000,000000,000000,831B24,DF097F,0000FF,FFFFFF,FFFFFF,FF0000,000000,000000, - 18D11D,50FE7F,000001,000000,000000,000010,A9DF09,7F0000,B80D8D,1FB255,0000A0,CF1D50,FE7F00,00CFAB,64DF09,7F0000 + FirstColor = 0; + LastColor = 255; + File = "palette.pcx"; } // camera 0 From c65df4079c11060078b652a8d79c28f316a0cc75 Mon Sep 17 00:00:00 2001 From: erysdren Date: Sat, 20 Sep 2025 14:21:56 -0500 Subject: [PATCH 4/8] editor: switch to C++, use Dear ImGui --- CMakeLists.txt | 28 +++- editor/main.c | 339 ------------------------------------------------ editor/main.cpp | 149 +++++++++++++++++++++ 3 files changed, 174 insertions(+), 342 deletions(-) delete mode 100644 editor/main.c create mode 100644 editor/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1be7810..49ea0e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.28) project(plush DESCRIPTION "A neat, portable, realtime 3D rendering library." HOMEPAGE_URL "https://github.com/erysdren/plush" - LANGUAGES C + LANGUAGES C CXX VERSION 1.2.0 ) @@ -83,11 +83,33 @@ target_link_libraries(plush PUBLIC $<$:ASAN::ASAN>) if(PLUSH_BUILD_EDITOR) find_package(SDL3 CONFIG COMPONENTS SDL3) if (SDL3_FOUND) + include(FetchContent) + FetchContent_Declare( + imgui + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_TAG v1.92.3 + ) + FetchContent_MakeAvailable(imgui) + add_library(imgui STATIC + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp + ) + target_include_directories(imgui PUBLIC + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends + ) add_executable(plush-editor) target_sources(plush-editor PRIVATE - ${PROJECT_SOURCE_DIR}/editor/main.c + ${PROJECT_SOURCE_DIR}/editor/main.cpp ) - target_link_libraries(plush-editor PUBLIC plush SDL3::SDL3) + target_link_libraries(plush-editor PUBLIC plush SDL3::SDL3 imgui) + else() + message(WARNING "SDL3 not found, cannot build editor") endif() endif() diff --git a/editor/main.c b/editor/main.c deleted file mode 100644 index a9cb7f0..0000000 --- a/editor/main.c +++ /dev/null @@ -1,339 +0,0 @@ - -#include -#include - -#define SDL_MAIN_USE_CALLBACKS 1 -#include - -#define log_error(...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) -#define log_warning(...) SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__) - -#define WINDOW_TITLE "Plush Editor" -#define WINDOW_WIDTH (800) -#define WINDOW_HEIGHT (600) - -#define FRAMEBUFFER_SIZE (WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(uint8_t)) -#define ZBUFFER_SIZE (WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)) - -#define DEFAULT_FOV (90) -#define DEFAULT_SENSITIVITY (8) -#define DEFAULT_MOVESPEED (32) -#define DEFAULT_STRAFESPEED (32) - -#define MAX_MATERIALS (256) -#define MAX_VELOCITY (128) - -/* - * - * this holds all the editor state - * - */ - -typedef struct app { - /* sdl video state */ - SDL_Window *window; - SDL_Renderer *renderer; - SDL_Texture *texture; - SDL_Surface *surface; - SDL_Surface *surface8; - SDL_Palette *palette; - - /* plush video state */ - uint8_t *framebuffer; - float *zbuffer; - pl_Cam *camera; - pl_Light *headlight; - - /* camera state */ - float velocity[3]; - float movespeed; - float strafespeed; - - /* assets */ - pl_Mat *fallback_material; - - /* timer state */ - uint64_t ticks; - uint64_t deltaticks; - float time; - float deltatime; -} app_t; - -/* - * - * utility functions - * - */ - -static SDL_AppResult die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, fmt, ap); - va_end(ap); - - SDL_Event event; - event.quit.type = SDL_EVENT_QUIT; - event.quit.timestamp = SDL_GetTicksNS(); - SDL_PushEvent(&event); - - return SDL_APP_FAILURE; -} - -/* - * - * sdl callbacks - * - */ - -SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppInit(SDL_UNUSED void **appstate, SDL_UNUSED int argc, SDL_UNUSED char *argv[]) -{ - uint8_t pal[768]; - app_t *app; - - if (!SDL_Init(SDL_INIT_VIDEO)) - return die("%s", SDL_GetError()); - - /* allocate app state */ - app = SDL_malloc(sizeof(app_t)); - if (!app) - return die("%s", SDL_GetError()); - - /* create window and renderer */ - SDL_CreateWindowAndRenderer(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE, &app->window, &app->renderer); - SDL_SetWindowMinimumSize(app->window, WINDOW_WIDTH, WINDOW_HEIGHT); - SDL_SetWindowRelativeMouseMode(app->window, true); - SDL_SetRenderLogicalPresentation(app->renderer, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_LOGICAL_PRESENTATION_LETTERBOX); - - /* create render texture */ - app->texture = SDL_CreateTexture(app->renderer, SDL_GetWindowPixelFormat(app->window), SDL_TEXTUREACCESS_STREAMING, WINDOW_WIDTH, WINDOW_HEIGHT); - SDL_SetTextureScaleMode(app->texture, SDL_SCALEMODE_NEAREST); - - /* allocate plush buffers */ - app->framebuffer = plMalloc(WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(uint8_t)); - app->zbuffer = plMalloc(WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)); - - /* create render surfaces */ - app->surface = SDL_CreateSurfaceFrom(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_GetWindowPixelFormat(app->window), NULL, 0); - app->surface8 = SDL_CreateSurfaceFrom(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_PIXELFORMAT_INDEX8, app->framebuffer, WINDOW_WIDTH); - - /* create camera */ - app->camera = plCamCreate(WINDOW_WIDTH, WINDOW_HEIGHT, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, DEFAULT_FOV, app->framebuffer, app->zbuffer); - app->movespeed = DEFAULT_MOVESPEED; - app->strafespeed = DEFAULT_STRAFESPEED; - - /* create light */ - app->headlight = plLightSet(plLightCreate(), PL_LIGHT_POINT, 0, 0, 0, 0.5, 256); - - app->fallback_material = plMatCreate(); - app->fallback_material->ShadeType = PL_SHADE_FLAT; - app->fallback_material->Ambient[0] = 0.1745 * 255; - app->fallback_material->Ambient[1] = 0.03175 * 255; - app->fallback_material->Ambient[2] = 0.03175 * 255; - app->fallback_material->Diffuse[0] = 0.61424 * 255; - app->fallback_material->Diffuse[1] = 0.10136 * 255; - app->fallback_material->Diffuse[2] = 0.10136 * 255; - app->fallback_material->Specular[0] = 0.727811 * 255; - app->fallback_material->Specular[1] = 0.626959 * 255; - app->fallback_material->Specular[2] = 0.626959 * 255; - plMatInit(app->fallback_material); - - /* generate palette from fallback material */ - /* first color in the palette is always black and the second color is always white */ - plMatMakeOptPal(pal, 2, 255, &app->fallback_material, 1); - pal[0] = pal[1] = pal[2] = 0; - pal[3] = pal[4] = pal[5] = 255; - - /* map fallback material to generated palette */ - plMatMapToPal(app->fallback_material, pal, 0, 255); - - /* convert generated palette to sdl palette */ - app->palette = SDL_CreateSurfacePalette(app->surface8); - for (int i = 0; i < app->palette->ncolors; i++) - { - app->palette->colors[i].r = pal[i * 3 + 0]; - app->palette->colors[i].g = pal[i * 3 + 1]; - app->palette->colors[i].b = pal[i * 3 + 2]; - app->palette->colors[i].a = SDL_ALPHA_OPAQUE; - } - - /* start timer */ - app->ticks = SDL_GetTicks(); - app->deltaticks = 0; - app->time = (float)app->ticks / 1000.0f; - app->deltatime = (float)app->deltaticks / 1000.0f; - - /* return app state */ - *appstate = app; - - return SDL_APP_CONTINUE; -} - -SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppIterate(SDL_UNUSED void *appstate) -{ - const bool *keys = SDL_GetKeyboardState(NULL); - float look[3]; - float strafe[2]; - app_t *app = (app_t *)appstate; - - /* tick world state */ - uint64_t now = SDL_GetTicks(); - app->deltaticks = now - app->ticks; - app->ticks = now; - app->time = (float)app->ticks / 1000.0f; - app->deltatime = (float)app->deltaticks / 1000.0f; - - /* clear screen */ - SDL_memset(app->zbuffer, 0, WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(float)); - SDL_FillSurfaceRect(app->surface8, NULL, 0); - - /* handle movement */ - look[0] = plCos(plDegToRad(app->camera->Pan + 90)) * plCos(plDegToRad(app->camera->Pitch)); - look[1] = plSin(plDegToRad(app->camera->Pitch)); - look[2] = plSin(plDegToRad(app->camera->Pan + 90)) * plCos(plDegToRad(app->camera->Pitch)); - - strafe[0] = plCos(plDegToRad(app->camera->Pan)); - strafe[1] = plSin(plDegToRad(app->camera->Pan)); - - if (keys[SDL_SCANCODE_LSHIFT]) - { - app->movespeed = DEFAULT_MOVESPEED * 2; - app->strafespeed = DEFAULT_STRAFESPEED * 2; - } - else - { - app->movespeed = DEFAULT_MOVESPEED; - app->strafespeed = DEFAULT_STRAFESPEED; - } - - if (keys[SDL_SCANCODE_W]) - { - app->velocity[0] += look[0] * app->movespeed * app->deltatime; - app->velocity[1] += look[1] * app->movespeed * app->deltatime; - app->velocity[2] += look[2] * app->movespeed * app->deltatime; - } - - if (keys[SDL_SCANCODE_S]) - { - app->velocity[0] -= look[0] * app->movespeed * app->deltatime; - app->velocity[1] -= look[1] * app->movespeed * app->deltatime; - app->velocity[2] -= look[2] * app->movespeed * app->deltatime; - } - - if (keys[SDL_SCANCODE_A]) - { - app->velocity[0] -= strafe[0] * app->strafespeed * app->deltatime; - app->velocity[2] -= strafe[1] * app->strafespeed * app->deltatime; - } - - if (keys[SDL_SCANCODE_D]) - { - app->velocity[0] += strafe[0] * app->strafespeed * app->deltatime; - app->velocity[2] += strafe[1] * app->strafespeed * app->deltatime; - } - - /* cap velocity */ - if (app->velocity[0] < -MAX_VELOCITY) app->velocity[0] = -MAX_VELOCITY; - if (app->velocity[0] > MAX_VELOCITY) app->velocity[0] = MAX_VELOCITY; - if (app->velocity[1] < -MAX_VELOCITY) app->velocity[1] = -MAX_VELOCITY; - if (app->velocity[1] > MAX_VELOCITY) app->velocity[1] = MAX_VELOCITY; - if (app->velocity[2] < -MAX_VELOCITY) app->velocity[2] = -MAX_VELOCITY; - if (app->velocity[2] > MAX_VELOCITY) app->velocity[2] = MAX_VELOCITY; - - /* apply velocity */ - app->camera->X += app->velocity[0] * app->deltatime; - app->camera->Y += app->velocity[1] * app->deltatime; - app->camera->Z += app->velocity[2] * app->deltatime; - - /* keep headlight on camera */ - app->headlight->Xp = app->camera->X; - app->headlight->Yp = app->camera->Y; - app->headlight->Zp = app->camera->Z; - - /* render something */ - plRenderBegin(app->camera); - plRenderLight(app->headlight); - plRenderEnd(); - plTextPutStr(app->camera, 0, 0, 0, 1, "press escape to exit\npress space to release mouse"); - - /* sync to screen */ - SDL_SetRenderDrawColor(app->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderClear(app->renderer); - if (SDL_LockTexture(app->texture, NULL, &app->surface->pixels, &app->surface->pitch)) - { - SDL_BlitSurface(app->surface8, NULL, app->surface, NULL); - SDL_UnlockTexture(app->texture); - } - SDL_RenderTexture(app->renderer, app->texture, NULL, NULL); - SDL_RenderPresent(app->renderer); - - return SDL_APP_CONTINUE; -} - -SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(SDL_UNUSED void *appstate, SDL_Event *event) -{ - app_t *app = (app_t *)appstate; - - if (event->type == SDL_EVENT_QUIT) - return SDL_APP_SUCCESS; - - switch (event->type) - { - case SDL_EVENT_KEY_DOWN: - { - if (event->key.scancode == SDL_SCANCODE_ESCAPE) - { - return SDL_APP_SUCCESS; - } - else if (event->key.scancode == SDL_SCANCODE_SPACE) - { - if (SDL_GetWindowRelativeMouseMode(app->window)) - { - int w, h; - SDL_GetWindowSize(app->window, &w, &h); - SDL_WarpMouseInWindow(app->window, w/2.0f, h/2.0f); - SDL_SetWindowRelativeMouseMode(app->window, false); - } - else - { - SDL_SetWindowRelativeMouseMode(app->window, true); - } - } - break; - } - - case SDL_EVENT_MOUSE_MOTION: - { - if (SDL_GetWindowRelativeMouseMode(app->window)) - { - app->camera->Pitch -= event->motion.yrel * app->deltatime * DEFAULT_SENSITIVITY; - app->camera->Pan -= event->motion.xrel * app->deltatime * DEFAULT_SENSITIVITY; - } - break; - } - } - - return SDL_APP_CONTINUE; -} - -SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(SDL_UNUSED void *appstate, SDL_UNUSED SDL_AppResult result) -{ - app_t *app = (app_t *)appstate; - - if (app) - { - if (app->headlight) plLightDelete(app->headlight); - if (app->fallback_material) plMatDelete(app->fallback_material); - if (app->surface) SDL_DestroySurface(app->surface); - if (app->surface8) SDL_DestroySurface(app->surface8); - if (app->texture) SDL_DestroyTexture(app->texture); - if (app->renderer) SDL_DestroyRenderer(app->renderer); - if (app->window) SDL_DestroyWindow(app->window); - if (app->camera) plCamDelete(app->camera); - if (app->framebuffer) plFree(app->framebuffer); - if (app->zbuffer) plFree(app->zbuffer); - SDL_free(app); - } - - SDL_Quit(); -} diff --git a/editor/main.cpp b/editor/main.cpp new file mode 100644 index 0000000..4c3ca0f --- /dev/null +++ b/editor/main.cpp @@ -0,0 +1,149 @@ + +#include +#include +#include +#include + +#include +#include + +#include "imgui.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_sdlrenderer3.h" + +#define SDL_MAIN_USE_CALLBACKS 1 +#include + +static SDL_AppResult die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, fmt, ap); + va_end(ap); + + SDL_Event event; + event.quit.type = SDL_EVENT_QUIT; + event.quit.timestamp = SDL_GetTicksNS(); + SDL_PushEvent(&event); + + return SDL_APP_FAILURE; +} + +class app_t { +public: + void EditorMain() + { + ImGui::ShowDemoWindow(nullptr); + } + + SDL_AppResult Iterate() + { + ImGui_ImplSDLRenderer3_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + EditorMain(); + + ImGui::Render(); + ImGuiIO &io = ImGui::GetIO(); + SDL_SetRenderScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); + SDL_SetRenderDrawColorFloat(renderer, clear_color.x, clear_color.y, clear_color.z, clear_color.w); + SDL_RenderClear(renderer); + ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer); + SDL_RenderPresent(renderer); + + return SDL_APP_CONTINUE; + } + + SDL_AppResult Event(SDL_Event *event) + { + if ((event->type == SDL_EVENT_QUIT) || (event->type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event->window.windowID == SDL_GetWindowID(window))) + return SDL_APP_SUCCESS; + + ImGui_ImplSDL3_ProcessEvent(event); + + return SDL_APP_CONTINUE; + } + + app_t(const char *title, int w=1280, int h=720) : windowTitle(title), windowWidth(w), windowHeight(h) + { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) + throw std::runtime_error(SDL_GetError()); + + if (!SDL_CreateWindowAndRenderer(windowTitle.c_str(), windowWidth, windowHeight, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_MAXIMIZED, &window, &renderer)) + throw std::runtime_error(SDL_GetError()); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO &io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + io.IniFilename = nullptr; + io.LogFilename = nullptr; + + ImGui::StyleColorsDark(); + + ImGui_ImplSDL3_InitForSDLRenderer(window, renderer); + ImGui_ImplSDLRenderer3_Init(renderer); + + SDL_ShowWindow(window); + } + + ~app_t() + { + ImGui_ImplSDLRenderer3_Shutdown(); + ImGui_ImplSDL3_Shutdown(); + ImGui::DestroyContext(); + + if (renderer) SDL_DestroyRenderer(renderer); + if (window) SDL_DestroyWindow(window); + + SDL_Quit(); + } +private: + // SDL video state + SDL_Window *window; + SDL_Renderer *renderer; + + int windowWidth; + int windowHeight; + std::string windowTitle; + + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); +}; + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppInit(void **appstate, SDL_UNUSED int argc, SDL_UNUSED char *argv[]) +{ + app_t *app = NULL; + + try { + app = new app_t("Plush Scene Editor"); + } catch (const std::runtime_error &error) { + return die("%s", error.what()); + } + + *appstate = reinterpret_cast(app); + + return SDL_APP_CONTINUE; +} + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppIterate(void *appstate) +{ + app_t *app = reinterpret_cast(appstate); + + return app->Iterate(); +} + +SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_Event *event) +{ + app_t *app = reinterpret_cast(appstate); + + return app->Event(event); +} + +SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate, SDL_UNUSED SDL_AppResult result) +{ + app_t *app = reinterpret_cast(appstate); + + delete app; +} From ae88cd4f4decad81388ef581c369b2c4b5eb62b0 Mon Sep 17 00:00:00 2001 From: erysdren Date: Sat, 20 Sep 2025 16:03:56 -0500 Subject: [PATCH 5/8] editor: start adding UI elements --- editor/main.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/editor/main.cpp b/editor/main.cpp index 4c3ca0f..eef0616 100644 --- a/editor/main.cpp +++ b/editor/main.cpp @@ -14,6 +14,14 @@ #define SDL_MAIN_USE_CALLBACKS 1 #include +static void quit() +{ + SDL_Event event; + event.quit.type = SDL_EVENT_QUIT; + event.quit.timestamp = SDL_GetTicksNS(); + SDL_PushEvent(&event); +} + static SDL_AppResult die(const char *fmt, ...) { va_list ap; @@ -33,6 +41,45 @@ class app_t { public: void EditorMain() { + // setup flags + ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + + // setup size + int screen_w, screen_h; + SDL_GetRenderOutputSize(renderer, &screen_w, &screen_h); + ImGui::SetNextWindowSize(ImVec2(screen_w, screen_h), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); + + // do it + if (ImGui::Begin("Main Menu", nullptr, window_flags)) + { + // main menu bar + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Load")) + ; + + if (ImGui::MenuItem("Save", "Ctrl+S")) + ; + + if (ImGui::MenuItem("Save As")) + ; + + if (ImGui::MenuItem("Quit", "Alt+F4")) + quit(); + + ImGui::EndMenu(); + } + + ImGui::EndMenuBar(); + } + + ImGui::End(); + } + ImGui::ShowDemoWindow(nullptr); } From b35c6a3241d014cdb75258b6a60002ebf8965d60 Mon Sep 17 00:00:00 2001 From: erysdren Date: Sun, 21 Sep 2025 07:52:02 -0500 Subject: [PATCH 6/8] editor: update how Ambient/Diffuse/Specular is stored --- editor/scenefmt.txt | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/editor/scenefmt.txt b/editor/scenefmt.txt index 8c7f87e..462c29a 100644 --- a/editor/scenefmt.txt +++ b/editor/scenefmt.txt @@ -30,14 +30,9 @@ material Name = "Fallback Material"; Fallback = true; - Ambient = "0.1745 0.03175 0.03175"; - AmbientScale = 255; - - Diffuse = "0.61424 0.10136 0.10136"; - DiffuseScale = 255; - - Specular = "0.727811 0.626959 0.626959"; - SpecularScale = 255; + Ambient = "44 8 8"; + Diffuse = "156 25 25"; + Specular = "185 159 159"; } // mesh 0 From ebf2184bad09696f93ae15169f6dd76a5da3d59c Mon Sep 17 00:00:00 2001 From: erysdren Date: Sun, 21 Sep 2025 08:07:41 -0500 Subject: [PATCH 7/8] editor: move editor CMake stuff into its own CMakeLists.txt --- CMakeLists.txt | 30 +++--------------------------- editor/CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 27 deletions(-) create mode 100644 editor/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 49ea0e6..ef48dee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.28) project(plush DESCRIPTION "A neat, portable, realtime 3D rendering library." HOMEPAGE_URL "https://github.com/erysdren/plush" - LANGUAGES C CXX + LANGUAGES C VERSION 1.2.0 ) @@ -82,32 +82,8 @@ target_link_libraries(plush PUBLIC $<$:ASAN::ASAN>) if(PLUSH_BUILD_EDITOR) find_package(SDL3 CONFIG COMPONENTS SDL3) - if (SDL3_FOUND) - include(FetchContent) - FetchContent_Declare( - imgui - GIT_REPOSITORY https://github.com/ocornut/imgui.git - GIT_TAG v1.92.3 - ) - FetchContent_MakeAvailable(imgui) - add_library(imgui STATIC - ${imgui_SOURCE_DIR}/imgui_demo.cpp - ${imgui_SOURCE_DIR}/imgui_draw.cpp - ${imgui_SOURCE_DIR}/imgui_tables.cpp - ${imgui_SOURCE_DIR}/imgui_widgets.cpp - ${imgui_SOURCE_DIR}/imgui.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp - ${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp - ) - target_include_directories(imgui PUBLIC - ${imgui_SOURCE_DIR} - ${imgui_SOURCE_DIR}/backends - ) - add_executable(plush-editor) - target_sources(plush-editor PRIVATE - ${PROJECT_SOURCE_DIR}/editor/main.cpp - ) - target_link_libraries(plush-editor PUBLIC plush SDL3::SDL3 imgui) + if(SDL3_FOUND) + add_subdirectory(editor) else() message(WARNING "SDL3 not found, cannot build editor") endif() diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt new file mode 100644 index 0000000..20a8408 --- /dev/null +++ b/editor/CMakeLists.txt @@ -0,0 +1,33 @@ +project(plush-editor LANGUAGES C CXX) + +include(FetchContent) + +FetchContent_Declare( + imgui + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_TAG v1.92.3 +) + +FetchContent_MakeAvailable(imgui) + +add_library(imgui STATIC + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp +) + +target_include_directories(imgui PUBLIC + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends +) + +add_executable(plush-editor) +target_sources(plush-editor PRIVATE + ${PROJECT_SOURCE_DIR}/main.cpp +) + +target_link_libraries(plush-editor PUBLIC plush SDL3::SDL3 imgui) From 95f52f501290be8b434e68c6b32009c3c08bb3d6 Mon Sep 17 00:00:00 2001 From: erysdren Date: Sun, 21 Sep 2025 08:18:08 -0500 Subject: [PATCH 8/8] editor: update how vectors are stored in the scene format --- editor/scenefmt.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/editor/scenefmt.txt b/editor/scenefmt.txt index 462c29a..b2a612a 100644 --- a/editor/scenefmt.txt +++ b/editor/scenefmt.txt @@ -18,8 +18,8 @@ camera Fov = 90; zBuffer = true; - Origin = "64 64 -384"; - Angles = "15 10 0"; + Origin = [64, 64, -384]; + Angles = [15, 10, 0]; Palette = 0; } @@ -30,9 +30,9 @@ material Name = "Fallback Material"; Fallback = true; - Ambient = "44 8 8"; - Diffuse = "156 25 25"; - Specular = "185 159 159"; + Ambient = [44, 8, 8]; + Diffuse = [156, 25, 25]; + Specular = [185, 159, 159]; } // mesh 0