From 19a28025eaccaec36a87e3c028edad227e719925 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 11:46:04 +0100 Subject: [PATCH 01/19] cmake: Add cimgui and glad dependencies --- .gitmodules | 6 ++++++ CMakeLists.txt | 2 ++ cmake/cimgui.cmake | 43 +++++++++++++++++++++++++++++++++++++++++++ cmake/glad.cmake | 14 ++++++++++++++ external/cimgui | 1 + external/glad | 1 + 6 files changed, 67 insertions(+) create mode 100644 cmake/cimgui.cmake create mode 100644 cmake/glad.cmake create mode 160000 external/cimgui create mode 160000 external/glad diff --git a/.gitmodules b/.gitmodules index ad1bdcf..7b7510e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "external/stb"] path = external/stb url = https://github.com/nothings/stb.git +[submodule "external/cimgui"] + path = external/cimgui + url = https://github.com/cimgui/cimgui.git +[submodule "external/glad"] + path = external/glad + url = https://github.com/Dav1dde/glad.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 927f21d..8e6b940 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,8 @@ include(CTest) include(GoogleTest) include("${CMAKE_SOURCE_DIR}/cmake/GTest.cmake") include("${CMAKE_SOURCE_DIR}/cmake/stb.cmake") +include("${CMAKE_SOURCE_DIR}/cmake/glad.cmake") +include("${CMAKE_SOURCE_DIR}/cmake/cimgui.cmake") if (MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC") message(FATAL_ERROR " Microsoft C Compiler is not supported, please use GCC or Clang") diff --git a/cmake/cimgui.cmake b/cmake/cimgui.cmake new file mode 100644 index 0000000..04a0e1c --- /dev/null +++ b/cmake/cimgui.cmake @@ -0,0 +1,43 @@ +# Configures cimgui for use in PebbleOfDoom + +set(CIMGUI_DIR "${CMAKE_SOURCE_DIR}/external/cimgui/") +set(IMGUI_DIR "${CIMGUI_DIR}/imgui/") +if (NOT EXISTS "${CIMGUI_DIR}/cimgui.h") + message(FATAL_ERROR "Could not find cimgui, did you clone the submodules?") +endif() +if (NOT EXISTS "${IMGUI_DIR}/imgui.h") + message(FATAL_ERROR "Could not find imgui, did you clone the submodules *recursively*?") +endif() + +set(sources_cimgui + ${CIMGUI_DIR}/cimgui.h + ${CIMGUI_DIR}/cimgui.cpp + + ${IMGUI_DIR}/imgui.h + ${IMGUI_DIR}/imgui.cpp + ${IMGUI_DIR}/imgui_draw.cpp + ${IMGUI_DIR}/imgui_demo.cpp + ${IMGUI_DIR}/imgui_widgets.cpp + + ${IMGUI_DIR}/examples/imgui_impl_sdl.h + ${IMGUI_DIR}/examples/imgui_impl_sdl.cpp + ${IMGUI_DIR}/examples/imgui_impl_opengl3.h + ${IMGUI_DIR}/examples/imgui_impl_opengl3.cpp +) + +add_library(cimgui ${sources_cimgui}) +target_include_directories(cimgui + PRIVATE ${IMGUI_DIR} + PRIVATE ${SDL2_INCLUDE_DIR} + INTERFACE ${CIMGUI_DIR} + INTERFACE ${IMGUI_DIR}/examples +) +target_link_libraries(cimgui + PUBLIC ${SDL2_LIBRARY} + PUBLIC glad +) +target_compile_definitions(cimgui + PRIVATE "-DIMGUI_IMPL_API=extern \"C\"" + PRIVATE IMGUI_IMPL_OPENGL_LOADER_GLAD + INTERFACE CIMGUI_DEFINE_ENUMS_AND_STRUCTS +) diff --git a/cmake/glad.cmake b/cmake/glad.cmake new file mode 100644 index 0000000..1e5ec89 --- /dev/null +++ b/cmake/glad.cmake @@ -0,0 +1,14 @@ +# Configures glad for use in PebbleOfDoom + +set(GLAD_DIR "${CMAKE_SOURCE_DIR}/external/glad") +if (NOT EXISTS "${GLAD_DIR}/CMakeLists.txt") + message(FATAL_ERROR "Could not find glad, did you clone the submodules?") +endif() + +set(GLAD_PROFILE "core" CACHE STRING "" FORCE) +set(GLAD_API "gl=3.0" CACHE STRING "" FORCE) +set(GLAD_GENERATOR "c" CACHE STRING "" FORCE) +set(GLAD_EXTENSIONS "" CACHE STRING "" FORCE) +set(GLAD_SPEC "gl" CACHE STRING "" FORCE) +option(GLAD_NO_LOADER "" ON) +add_subdirectory(${GLAD_DIR}) diff --git a/external/cimgui b/external/cimgui new file mode 160000 index 0000000..8911a5a --- /dev/null +++ b/external/cimgui @@ -0,0 +1 @@ +Subproject commit 8911a5a9921ec6f8e10b32d592dc43b80d053549 diff --git a/external/glad b/external/glad new file mode 160000 index 0000000..ea33861 --- /dev/null +++ b/external/glad @@ -0,0 +1 @@ +Subproject commit ea33861340d2407a4f5939f9c3166a97a5069ef1 From 444d6dd3f4683c308231bd384bfe1ae5659905e9 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 13:46:25 +0100 Subject: [PATCH 02/19] pcmockup: Add imgui WindowContainer --- pcmockup/CMakeLists.txt | 3 +- pcmockup/pcmockup.c | 40 +++++++++++ pcmockup/pcmockup.h | 8 +++ pcmockup/windowcontainer.c | 137 +++++++++++++++++++++++++++++++++++++ renderer/CMakeLists.txt | 3 + 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 pcmockup/windowcontainer.c diff --git a/pcmockup/CMakeLists.txt b/pcmockup/CMakeLists.txt index e753ffc..57524d5 100644 --- a/pcmockup/CMakeLists.txt +++ b/pcmockup/CMakeLists.txt @@ -15,13 +15,14 @@ set(sources_pcmockup safeframebuffer.c rendererinterface.c texturemanager.c + windowcontainer.c ) assign_source_group(${sources_pcmockup}) add_executable(pcmockup ${sources_pcmockup}) target_link_libraries(pcmockup ${SDL2_LIBRARY} - ${STB_LIBRARY} + stb podrenderer ) target_include_directories(pcmockup diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index 018b4df..86d1faf 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -12,6 +12,7 @@ struct PCMockup TextureManager* textureManager; PebbleWindow *pebbleWindow; DebugWindowSet *debugWindowSet; + WindowContainer* windowContainer; bool_t isRunning; }; @@ -79,6 +80,13 @@ PCMockup *pcmockup_init() return NULL; } + me->windowContainer = windowContainer_init(GSize(1024, 768)); + if (me->windowContainer == NULL) + { + pcmockup_free(me); + return NULL; + } + me->isRunning = true; return me; } @@ -87,6 +95,8 @@ void pcmockup_free(PCMockup *me) { if (me == NULL) return; + if (me->windowContainer != NULL) + windowContainer_free(me->windowContainer); if (me->debugWindowSet != NULL) debugWindowSet_free(me->debugWindowSet); if (me->pebbleWindow != NULL) @@ -102,11 +112,13 @@ void pcmockup_free(PCMockup *me) void pcmockup_update(PCMockup *me) { + windowContainer_startUpdate(me->windowContainer); GColor *framebuffer = pebbleWindow_getPebbleFramebuffer(me->pebbleWindow); pebbleWindow_startUpdate(me->pebbleWindow); renderer_render(me->renderer, framebuffer); pebbleWindow_endUpdate(me->pebbleWindow); debugWindowSet_update(me->debugWindowSet); + windowContainer_endUpdate(me->windowContainer); SDL_Event event; while (SDL_PollEvent(&event)) @@ -175,6 +187,7 @@ void pcmockup_update(PCMockup *me) } } debugWindowSet_handleEvent(me->debugWindowSet, &event); + windowContainer_handleEvent(me->windowContainer, &event); } } @@ -202,6 +215,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); return -1; } + if (SDL_GL_LoadLibrary(NULL) < 0) + { + fprintf(stderr, "SDL_GL_LoadLibrary: %s\n", SDL_GetError()); + return -1; + } PCMockup* pcmockup = pcmockup_init(); if (pcmockup == NULL) return -1; @@ -243,3 +261,25 @@ SDL_Rect padRect(SDL_Rect rect, GSize amount) rect.h - amount.h }; } + +Uint32 getWindowIDByEvent(const SDL_Event* ev) +{ + switch (ev->type) + { + case (SDL_KEYDOWN): + case (SDL_KEYUP): + return ev->key.windowID; + case (SDL_MOUSEBUTTONDOWN): + case (SDL_MOUSEBUTTONUP): + return ev->button.windowID; + case (SDL_MOUSEMOTION): + return ev->motion.windowID; + case (SDL_MOUSEWHEEL): + return ev->wheel.windowID; + case (SDL_WINDOWEVENT): + return ev->window.windowID; + case (SDL_TEXTINPUT): + return ev->text.windowID; + } + return UINT32_MAX; +} diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index fbd844c..2bf665a 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -6,6 +6,14 @@ SDL_Rect findBestFit(SDL_Rect target, float aspect); SDL_Rect padRect(SDL_Rect rect, GSize amount); +Uint32 getWindowIDByEvent(const SDL_Event* ev); + +typedef struct WindowContainer WindowContainer; +WindowContainer* windowContainer_init(GSize windowSize); +void windowContainer_free(WindowContainer* me); +void windowContainer_startUpdate(WindowContainer* me); +void windowContainer_endUpdate(WindowContainer* me); +void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev); typedef struct WindowGrid { diff --git a/pcmockup/windowcontainer.c b/pcmockup/windowcontainer.c new file mode 100644 index 0000000..47253b7 --- /dev/null +++ b/pcmockup/windowcontainer.c @@ -0,0 +1,137 @@ +#include "pcmockup.h" +#include +#include + +#define IMGUI_IMPL_API +#include + +// glsl_version is default-defined in the header file, so we have to +// declare them ourself without this default value +extern int ImGui_ImplOpenGL3_Init(const char* glsl_version); +extern void ImGui_ImplOpenGL3_Shutdown(); +extern void ImGui_ImplOpenGL3_NewFrame(); +extern void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); + +struct WindowContainer +{ + SDL_Window* window; + SDL_GLContext glContext; + ImGuiContext* imGuiContext; +}; + +WindowContainer* windowContainer_init(GSize windowSize) +{ + WindowContainer* me = (WindowContainer*)malloc(sizeof(WindowContainer)); + if (me == NULL) + return NULL; + memset(me, 0, sizeof(WindowContainer)); + + me->window = SDL_CreateWindow("PebbleOfDoom", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + windowSize.w, windowSize.h, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); + if (me->window == NULL) + { + fprintf(stderr, "SDL_CreateWindow: %s\n", SDL_GetError()); + windowContainer_free(me); + return NULL; + } + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetSwapInterval(0); + me->glContext = SDL_GL_CreateContext(me->window); + if (me->glContext == NULL) + { + fprintf(stderr, "SDL_GL_CreateContext: %s\n", SDL_GetError()); + windowContainer_free(me); + return NULL; + } + + SDL_GL_MakeCurrent(me->window, me->glContext); + if (!gladLoadGLLoader(SDL_GL_GetProcAddress)) + { + fprintf(stderr, "gladLoadGLLoader: %s\n", SDL_GetError()); + windowContainer_free(me); + return NULL; + } + + me->imGuiContext = igCreateContext(NULL); + if (me->imGuiContext == NULL) + { + fprintf(stderr, "igCreateContext: failure\n"); + windowContainer_free(me); + return NULL; + } + ImGuiIO* io = igGetIO(); + io->IniFilename = NULL; + + if (!ImGui_ImplOpenGL3_Init(NULL)) + { + fprintf(stderr, "ImGui_ImplOpenGL3_Init: failure\n"); + windowContainer_free(me); + return NULL; + } + + if (!ImGui_ImplSDL2_InitForOpenGL(me->window, me->glContext)) + { + fprintf(stderr, "ImGui_ImplSDL2_InitForOpenGL: failure\n"); + windowContainer_free(me); + return NULL; + } + + glClearColor(0.45f, 0.55f, 0.60f, 1.00f); + return me; +} + +void windowContainer_free(WindowContainer* me) +{ + if (me == NULL) + return; + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + if (me->imGuiContext != NULL) + igDestroyContext(me->imGuiContext); + if (me->glContext) + SDL_GL_DeleteContext(me->glContext); + if (me->window) + SDL_DestroyWindow(me->window); + free(me); +} + +void windowContainer_startUpdate(WindowContainer* me) +{ + bool open = true; + SDL_GL_MakeCurrent(me->window, me->glContext); + igSetCurrentContext(me->imGuiContext); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(me->window); + igNewFrame(); + igShowDemoWindow(&open); +} + +void windowContainer_endUpdate(WindowContainer* me) +{ + SDL_GL_MakeCurrent(me->window, me->glContext); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + igRender(); + ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData()); + glFlush(); + SDL_GL_SwapWindow(me->window); +} + +void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev) +{ + // the ImGui SDL2 implementation does not filter the events by window ID + Uint32 windowID = SDL_GetWindowID(me->window); + if (getWindowIDByEvent(ev) == windowID) + ImGui_ImplSDL2_ProcessEvent((SDL_Event*)ev); + // TODO: Remove const-removing-cast as soon as (https://github.com/ocornut/imgui/issues/2187) is resolved! +} diff --git a/renderer/CMakeLists.txt b/renderer/CMakeLists.txt index e7e9c93..671f5cf 100644 --- a/renderer/CMakeLists.txt +++ b/renderer/CMakeLists.txt @@ -33,4 +33,7 @@ target_compile_definitions(podrenderer PUBLIC REAL_USE_FLOAT PUBLIC DEBUG_WINDOWS ) +target_link_libraries(podrenderer + PUBLIC cimgui +) enable_warnings(podrenderer) From 3823558598d73f4cbce4e19edfc58a6f19376b7a Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 14:09:08 +0100 Subject: [PATCH 03/19] pcmockup: Add imgui ImageWindow --- pcmockup/imagewindow.c | 145 +++++++++++++++++++++++++++++++++++++++++ pcmockup/pcmockup.c | 14 ++-- pcmockup/pcmockup.h | 10 +++ 3 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 pcmockup/imagewindow.c diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c new file mode 100644 index 0000000..f431311 --- /dev/null +++ b/pcmockup/imagewindow.c @@ -0,0 +1,145 @@ +#define _CRT_NONSTDC_NO_DEPRECATE +#include "pcmockup.h" +#include +#include + +struct ImageWindow +{ + char* title; + GLuint textureID; + GSize windowSize; + float aspect; + SDL_Rect lastContentPos; + bool isOpen, isEssential; + ImVec2 initialPosition; +}; + +ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential) +{ + ImageWindow* me = (ImageWindow*)malloc(sizeof(ImageWindow)); + if (me == NULL) + return NULL; + memset(me, 0, sizeof(ImageWindow)); + + me->title = strdup(title); + if (me->title == NULL) + { + fprintf(stderr, "strdup: failure\n"); + imageWindow_free(me); + return NULL; + } + + glGenTextures(1, &me->textureID); + if (me->textureID == 0) + { + fprintf(stderr, "glGenTextures: %d\n", glGetError()); + imageWindow_free(me); + return NULL; + } + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, me->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + const SDL_Color black = { 255, 255, 255, 255 }; + imageWindow_setImageData(me, GSize(1, 1), &black); + + me->isOpen = true; + me->isEssential = isEssential; + me->windowSize = initialSize; + me->aspect = (float)initialSize.w / initialSize.h; + me->initialPosition.x = -1; // undefined initial position + return me; +} + +void imageWindow_free(ImageWindow* me) +{ + if (me == NULL) + return; + if (me->textureID != 0) + glDeleteTextures(1, &me->textureID); + if (me->title != NULL) + free(me->title); + free(me); +} + +void imageWindow_setImageData(ImageWindow* me, GSize size, const SDL_Color* data) +{ + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, me->textureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.w, size.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + me->windowSize.w = max(me->windowSize.w, size.w); + me->windowSize.h = max(me->windowSize.h, size.h); +} + +SDL_Rect imageWindow_getContentPos(ImageWindow* me) +{ + return me->lastContentPos; +} + +void imageWindow_update(ImageWindow* me) +{ + if (!me->isOpen) + return; + const SDL_Rect windowRect = { 0, 0, me->windowSize.w, me->windowSize.h }; + const SDL_Rect imageRect = findBestFit(windowRect, me->aspect); + const ImVec2 + offset = { (float)imageRect.x, (float)imageRect.y }, + size = { (float)imageRect.w, (float)imageRect.h }, + zero = { 0, 0 }, + uv1 = { 1, 1 }; + ImVec2 toolbarSize, windowPos; + const ImVec4 + tintColor = { 1, 1, 1, 1 }, + borderColor = { 0, 0, 0, 0 }; + bool* isOpenPtr = me->isEssential + ? NULL // essential windows don't get a close button + : &me->isOpen; + + if (me->initialPosition.x >= 0 && me->initialPosition.y >= 0) + igSetNextWindowPos(me->initialPosition, ImGuiCond_Once, zero); + igSetNextWindowContentSize(size); + igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, zero); // space between image and window border + igPushStyleVarVec2(ImGuiStyleVar_ItemSpacing, zero); // space between vertical centering dummy and image + igPushStyleVarFloat(ImGuiStyleVar_IndentSpacing, 0.0f); // space between horizontal centering indent and image + igBegin(me->title, isOpenPtr, + ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoCollapse); + igGetItemRectSize_nonUDT(&toolbarSize); + igGetWindowPos_nonUDT(&windowPos); + igDummy(offset); // center vertically + igIndent(offset.x); // center horizontally + igImage((ImTextureID)(intptr_t)me->textureID, size, zero, uv1, tintColor, borderColor); + igPopStyleVar(3); + + me->windowSize.w = (int16_t)igGetWindowWidth(); + me->windowSize.h = (int16_t)(igGetWindowHeight() - toolbarSize.y); + igEnd(); + + me->lastContentPos = (SDL_Rect) { + (int)(windowPos.x + imageRect.x), + (int)(windowPos.y + toolbarSize.y + imageRect.y), + (int)imageRect.w, + (int)imageRect.h + }; +} + +void imageWindow_setInitialPosition(ImageWindow* me, GPoint initialPosition) +{ + me->initialPosition = (ImVec2) { + (float)initialPosition.x, + (float)initialPosition.y + }; +} + +void imageWindow_toggle(ImageWindow* me, bool_t isOpen) +{ + me->isOpen = isOpen; +} + +bool_t imageWindow_isOpen(ImageWindow* me) +{ + return me->isOpen; +} diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index 86d1faf..5135c83 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -54,6 +54,13 @@ PCMockup *pcmockup_init() return NULL; } + me->windowContainer = windowContainer_init(GSize(1024, 768)); + if (me->windowContainer == NULL) + { + pcmockup_free(me); + return NULL; + } + SDL_DisplayMode displayMode; SDL_GetCurrentDisplayMode(0, &displayMode); WindowGrid windowGrid; @@ -80,13 +87,6 @@ PCMockup *pcmockup_init() return NULL; } - me->windowContainer = windowContainer_init(GSize(1024, 768)); - if (me->windowContainer == NULL) - { - pcmockup_free(me); - return NULL; - } - me->isRunning = true; return me; } diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 2bf665a..d1b0557 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -15,6 +15,16 @@ void windowContainer_startUpdate(WindowContainer* me); void windowContainer_endUpdate(WindowContainer* me); void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev); +typedef struct ImageWindow ImageWindow; +ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential); +void imageWindow_free(ImageWindow* me); +void imageWindow_setImageData(ImageWindow* me, GSize size, const SDL_Color* data); +SDL_Rect imageWindow_getContentPos(ImageWindow* me); // in screen coordinates +void imageWindow_update(ImageWindow* me); +void imageWindow_setInitialPosition(ImageWindow* me, GPoint initialPosition); +void imageWindow_toggle(ImageWindow* me, bool_t isOpen); +bool_t imageWindow_isOpen(ImageWindow* me); + typedef struct WindowGrid { int windowCount; From fe21c969eae4dc7913f069980eb35f8591a4bc69 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 14:29:12 +0100 Subject: [PATCH 04/19] pcmockup: Migrate PebbleWindow to imgui --- pcmockup/CMakeLists.txt | 1 + pcmockup/imagewindow.c | 2 ++ pcmockup/pcmockup.h | 2 ++ pcmockup/pebblewindow.c | 72 +++++++++++------------------------------ 4 files changed, 24 insertions(+), 53 deletions(-) diff --git a/pcmockup/CMakeLists.txt b/pcmockup/CMakeLists.txt index 57524d5..d8da2a5 100644 --- a/pcmockup/CMakeLists.txt +++ b/pcmockup/CMakeLists.txt @@ -16,6 +16,7 @@ set(sources_pcmockup rendererinterface.c texturemanager.c windowcontainer.c + imagewindow.c ) assign_source_group(${sources_pcmockup}) diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index f431311..d3b52cf 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -14,6 +14,8 @@ struct ImageWindow ImVec2 initialPosition; }; +const Uint32 imageWindow_SDLPixelFormat = SDL_PIXELFORMAT_ABGR8888; + ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential) { ImageWindow* me = (ImageWindow*)malloc(sizeof(ImageWindow)); diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index d1b0557..f045257 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -15,6 +15,7 @@ void windowContainer_startUpdate(WindowContainer* me); void windowContainer_endUpdate(WindowContainer* me); void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev); +extern const Uint32 imageWindow_SDLPixelFormat; typedef struct ImageWindow ImageWindow; ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential); void imageWindow_free(ImageWindow* me); @@ -47,6 +48,7 @@ void pebbleWindow_startUpdate(PebbleWindow* window); void pebbleWindow_endUpdate(PebbleWindow* window); SDL_Rect pebbleWindow_getBounds(PebbleWindow* window); GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window); +ImageWindow* pebbleWindow_asImageWindow(PebbleWindow* window); typedef struct DebugWindow DebugWindow; DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* debugView, Renderer* renderer); diff --git a/pcmockup/pebblewindow.c b/pcmockup/pebblewindow.c index 98d8be7..bf94d38 100644 --- a/pcmockup/pebblewindow.c +++ b/pcmockup/pebblewindow.c @@ -6,9 +6,8 @@ struct PebbleWindow { - SDL_Window* window; - SDL_Renderer* renderer; - SDL_Texture* pebbleTexture; + ImageWindow* window; + SDL_Color* textureData; SDL_PixelFormat* texturePixelFormat; SafeFramebuffer* framebuffer; GSize pebbleSize; @@ -21,37 +20,23 @@ PebbleWindow* pebbleWindow_init(SDL_Rect initialBounds, GSize pebbleSize) return NULL; memset(me, 0, sizeof(PebbleWindow)); - me->window = SDL_CreateWindow("PebbleOfDoom - PCMockup", - initialBounds.x, initialBounds.y, - initialBounds.w, initialBounds.h, - SDL_WINDOW_RESIZABLE); + me->window = imageWindow_init("Pebble screen", (GSize) { initialBounds.w, initialBounds.h }, true); if (me->window == NULL) { - fprintf(stderr, "SDL_CreateWindow: %s\n", SDL_GetError()); pebbleWindow_free(me); return NULL; } + imageWindow_setInitialPosition(me->window, (GPoint) { initialBounds.x, initialBounds.y }); - me->renderer = SDL_CreateRenderer(me->window, -1, 0); - if (me->renderer == NULL) + me->textureData = (SDL_Color*)malloc(sizeof(SDL_Color) * pebbleSize.w * pebbleSize.h); + if (me->textureData == NULL) { - fprintf(stderr, "SDL_CreateRenderer: %s\n", SDL_GetError()); + fprintf(stderr, "Could not allocate pebble texture!\n"); pebbleWindow_free(me); return NULL; } - me->pebbleTexture = SDL_CreateTexture(me->renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - pebbleSize.w, pebbleSize.h); - if (me->pebbleTexture == NULL) - { - fprintf(stderr, "SDL_CreateTexture: %s\n", SDL_GetError()); - pebbleWindow_free(me); - return NULL; - } - - me->texturePixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888); + me->texturePixelFormat = SDL_AllocFormat(imageWindow_SDLPixelFormat); if (me->texturePixelFormat == NULL) { fprintf(stderr, "SDL_AllocFormat: %s\n", SDL_GetError()); @@ -75,27 +60,17 @@ void pebbleWindow_free(PebbleWindow* me) { if (me == NULL) return; + if (me->window != NULL) + imageWindow_free(me->window); + if (me->textureData != NULL) + free(me->textureData); if (me->framebuffer != NULL) safeFramebuffer_free(me->framebuffer); if (me->texturePixelFormat != NULL) SDL_FreeFormat(me->texturePixelFormat); - if (me->pebbleTexture != NULL) - SDL_DestroyTexture(me->pebbleTexture); - if (me->renderer != NULL) - SDL_DestroyRenderer(me->renderer); - if (me->window != NULL) - SDL_DestroyWindow(me->window); free(me); } -static SDL_Rect prv_pebbleWindow_fitPebbleScreen(const PebbleWindow* me) -{ - SDL_Rect src; - SDL_GetWindowSize(me->window, &src.w, &src.h); - const float pebbleAspect = (float)me->pebbleSize.w / me->pebbleSize.h; - return findBestFit(src, pebbleAspect); -} - static inline SDL_Color prv_convertGColorTo32Bit(GColor pebbleColor) { SDL_Color color; @@ -129,10 +104,8 @@ static void prv_pebbleWindow_convertPebbleToTexture(PebbleWindow* me) } // Advance to next line - texPixels += texPitch; + texPixels += me->pebbleSize.w; } - - SDL_UnlockTexture(me->pebbleTexture); } void pebbleWindow_startUpdate(PebbleWindow* me) @@ -144,23 +117,16 @@ void pebbleWindow_endUpdate(PebbleWindow* me) { safeFramebuffer_check(me->framebuffer); prv_pebbleWindow_convertPebbleToTexture(me); - - SDL_SetRenderDrawColor(me->renderer, 255, 0, 255, 255); - SDL_RenderClear(me->renderer); - const SDL_Rect dst = prv_pebbleWindow_fitPebbleScreen(me); - SDL_RenderCopy(me->renderer, me->pebbleTexture, NULL, &dst); - SDL_RenderPresent(me->renderer); + imageWindow_setImageData(me->window, me->pebbleSize, me->textureData); + imageWindow_update(me->window); } -SDL_Rect pebbleWindow_getBounds(PebbleWindow* me) +GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window) { - SDL_Rect bounds; - SDL_GetWindowPosition(me->window, &bounds.x, &bounds.y); - SDL_GetWindowSize(me->window, &bounds.w, &bounds.h); - return bounds; + return safeFramebuffer_getScreenBuffer(window->framebuffer); } -GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window) +ImageWindow* pebbleWindow_asImageWindow(PebbleWindow* me) { - return safeFramebuffer_getScreenBuffer(window->framebuffer); + return me->window; } From b18c0dc2945c4ec509b779837fe48a4b2b7b6787 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 14:51:52 +0100 Subject: [PATCH 05/19] pcmockup: Migrate debugWindow to imgui --- pcmockup/debugwindow.c | 95 ++++++++++++++++++++---------------------- pcmockup/pcmockup.c | 7 ++-- pcmockup/pcmockup.h | 2 + 3 files changed, 50 insertions(+), 54 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index 1211bd5..744759a 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -5,16 +5,28 @@ struct DebugWindow { - SDL_Window* window; + ImageWindow* window; SDL_Renderer* renderer; - SDL_Texture* texture; - SDL_Rect texturePos; + SDL_Surface* surface; Renderer* podRenderer; const DebugView* view; xz_t position, offset; real_t zoom; }; +SDL_Surface* createSDLSurface(int w, int h, Uint32 format) +{ + SDL_PixelFormat* formatInfo = SDL_AllocFormat(format); + if (formatInfo == NULL) + return NULL; + SDL_Surface* surface = SDL_CreateRGBSurface( + SDL_SWSURFACE, w, h, formatInfo->BitsPerPixel, + formatInfo->Rmask, formatInfo->Gmask, formatInfo->Bmask, formatInfo->Amask + ); + SDL_FreeFormat(formatInfo); + return surface; +} + DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) { DebugWindow* me = (DebugWindow*)malloc(sizeof(DebugWindow)); @@ -22,21 +34,25 @@ DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* view, Renderer* return NULL; memset(me, 0, sizeof(DebugWindow)); - me->window = SDL_CreateWindow(view->name, - bounds.x, bounds.y, - bounds.w, bounds.h, - SDL_WINDOW_RESIZABLE); + me->window = imageWindow_init(view->name, (GSize) { bounds.w, bounds.h }, false); if (me->window == NULL) { - fprintf(stderr, "SDL_CreateWindow: %s\n", SDL_GetError()); debugWindow_free(me); return NULL; } + imageWindow_setInitialPosition(me->window, (GPoint) { bounds.x, bounds.y }); - me->renderer = SDL_CreateRenderer(me->window, -1, SDL_RENDERER_TARGETTEXTURE); + me->surface = createSDLSurface(bounds.w, bounds.h, SDL_PIXELFORMAT_ABGR8888); + if (me->surface == NULL) + { + fprintf(stderr, "createSDLSurface: %s\n", SDL_GetError()); + debugWindow_free(me); + return NULL; + } + + me->renderer = SDL_CreateSoftwareRenderer(me->surface); if (me->renderer == NULL) { - fprintf(stderr, "SDL_CreateRenderer: %s\n", SDL_GetError()); debugWindow_free(me); return NULL; } @@ -53,56 +69,27 @@ void debugWindow_free(DebugWindow* me) { if (me == NULL) return; - if (me->texture != NULL) - SDL_DestroyTexture(me->texture); + if (me->window != NULL) + imageWindow_free(me->window); + if (me->surface != NULL) + SDL_FreeSurface(me->surface); if (me->renderer != NULL) SDL_DestroyRenderer(me->renderer); - if (me->window != NULL) - SDL_DestroyWindow(me->window); free(me); } void debugWindow_startUpdate(DebugWindow* me) { - SDL_Rect src; - int textureW = -1, textureH = -1; - SDL_GetWindowSize(me->window, &src.w, &src.h); - if (me->texture != NULL) - SDL_QueryTexture(me->texture, NULL, NULL, &textureW, &textureH); - me->texturePos = findBestFit(src, 1.0f); - - if (me->texturePos.w != textureW || me->texturePos.h != textureH) - { - if (me->texture != NULL) - SDL_DestroyTexture(me->texture); - me->texture = SDL_CreateTexture(me->renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_TARGET, - me->texturePos.w, me->texturePos.h); - if (me->texture == NULL) - { - fprintf(stderr, "SDL_CreateTexture: %s\n", SDL_GetError()); - exit(-1); - } - } - - SDL_SetRenderTarget(me->renderer, me->texture); + float scale = real_to_float(me->zoom); SDL_SetRenderDrawColor(me->renderer, 0, 0, 0, 255); SDL_RenderClear(me->renderer); - - float scale = real_to_float(me->zoom); SDL_RenderSetScale(me->renderer, scale, scale); } void debugWindow_endUpdate(DebugWindow* me) { - SDL_RenderSetScale(me->renderer, 1.0f, 1.0f); - SDL_SetRenderTarget(me->renderer, NULL); - SDL_SetRenderDrawColor(me->renderer, 255, 0, 255, 255); - SDL_RenderClear(me->renderer); - SDL_SetRenderDrawColor(me->renderer, 255, 255, 255, 255); - SDL_RenderCopy(me->renderer, me->texture, NULL, &me->texturePos); - SDL_RenderPresent(me->renderer); + imageWindow_setImageData(me->window, GSize(me->surface->w, me->surface->h), (SDL_Color*)me->surface->pixels); + imageWindow_update(me->window); } void debugWindow_update(DebugWindow* me) @@ -114,7 +101,7 @@ void debugWindow_update(DebugWindow* me) void debugWindow_handleEvent(DebugWindow* me, const SDL_Event* ev) { - Uint32 windowID = SDL_GetWindowID(me->window); + Uint32 windowID = 1234; if (ev->type == SDL_MOUSEMOTION && ev->motion.windowID == windowID && (ev->motion.state & SDL_BUTTON_LMASK) > 0) { xz_t move = xz(real_from_int(ev->motion.xrel), real_from_int(ev->motion.yrel)); @@ -133,11 +120,19 @@ void debugWindow_handleEvent(DebugWindow* me, const SDL_Event* ev) } // update render offset - int textureW, textureH; - SDL_QueryTexture(me->texture, NULL, NULL, &textureW, &textureH); - xz_t halfSize = xz(real_from_int(textureW / 2), real_from_int(textureH / 2)); + xz_t halfSize = xz(real_from_int(me->surface->w / 2), real_from_int(me->surface->h / 2)); me->offset = xz_sub( xz_invScale(halfSize, me->zoom), me->position ); } + +const DebugView* debugWindow_getDebugView(const DebugWindow* me) +{ + return me->view; +} + +ImageWindow* debugWindow_asImageWindow(DebugWindow* me) +{ + return me->window; +} diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index 5135c83..ecef47d 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -3,6 +3,7 @@ #include "renderer.h" #include "platform.h" +static const GSize WINDOW_START_SIZE = { 1024, 768 }; static const int MAX_FRAMERATE = 60; struct PCMockup @@ -54,18 +55,16 @@ PCMockup *pcmockup_init() return NULL; } - me->windowContainer = windowContainer_init(GSize(1024, 768)); + me->windowContainer = windowContainer_init(WINDOW_START_SIZE); if (me->windowContainer == NULL) { pcmockup_free(me); return NULL; } - SDL_DisplayMode displayMode; - SDL_GetCurrentDisplayMode(0, &displayMode); WindowGrid windowGrid; windowGrid.windowCount = 1 + renderer_getDebugCount(me->renderer); - windowGrid.totalSize = GSize(displayMode.w, displayMode.h); + windowGrid.totalSize = WINDOW_START_SIZE; me->pebbleWindow = pebbleWindow_init( windowGrid_getSingleBounds(&windowGrid, 0), diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index f045257..499d015 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -55,6 +55,8 @@ DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* debugView, Rende void debugWindow_free(DebugWindow* window); void debugWindow_update(DebugWindow* window); void debugWindow_handleEvent(DebugWindow* window, const SDL_Event* ev); +const DebugView* debugWindow_getDebugView(const DebugWindow* window); +ImageWindow* debugWindow_asImageWindow(DebugWindow* window); typedef struct DebugWindowSet DebugWindowSet; DebugWindowSet* debugWindowSet_init(const WindowGrid* grid, Renderer* renderer); From 9dbaddb4e98c849e094196b106f8e9a646a22c11 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 15:00:22 +0100 Subject: [PATCH 06/19] pcmockup: add initial menubar --- pcmockup/debugwindowset.c | 18 ++++++++++++++++++ pcmockup/pcmockup.c | 18 ++++++++++++++++++ pcmockup/pcmockup.h | 1 + 3 files changed, 37 insertions(+) diff --git a/pcmockup/debugwindowset.c b/pcmockup/debugwindowset.c index 6ce4bb0..ad6b5da 100644 --- a/pcmockup/debugwindowset.c +++ b/pcmockup/debugwindowset.c @@ -1,4 +1,5 @@ #include "pcmockup.h" +#include #define WINDOW_GAP 64 @@ -73,6 +74,23 @@ void debugWindowSet_update(DebugWindowSet* me) #endif } +void debugWindowSet_updateMenubar(DebugWindowSet* me) +{ +#ifdef DEBUG_WINDOWS + if (!igBeginMenu("Debug windows", true)) + return; + for (int i = 0; i < me->count; i++) + { + ImageWindow* window = debugWindow_asImageWindow(me->windows[i]); + const DebugView* view = debugWindow_getDebugView(me->windows[i]); + bool isOpen = imageWindow_isOpen(window); + igMenuItemBoolPtr(view->name, NULL, &isOpen, true); + imageWindow_toggle(window, isOpen); + } + igEndMenu(); +#endif +} + void debugWindowSet_handleEvent(DebugWindowSet* me, const SDL_Event* ev) { for (int i = 0; i < me->count; i++) diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index ecef47d..a40639f 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -1,4 +1,5 @@ #include +#include #include "pcmockup.h" #include "renderer.h" #include "platform.h" @@ -109,6 +110,22 @@ void pcmockup_free(PCMockup *me) free(me); } +void pcmockup_updateMainMenubar(PCMockup* me) +{ + if (!igBeginMainMenuBar()) + return; + + if (igBeginMenu("PCMockup", true)) + { + if (igMenuItemBool("Exit", NULL, false, true)) + me->isRunning = false; + igEndMenu(); + } + debugWindowSet_updateMenubar(me->debugWindowSet); + + igEndMainMenuBar(); +} + void pcmockup_update(PCMockup *me) { windowContainer_startUpdate(me->windowContainer); @@ -117,6 +134,7 @@ void pcmockup_update(PCMockup *me) renderer_render(me->renderer, framebuffer); pebbleWindow_endUpdate(me->pebbleWindow); debugWindowSet_update(me->debugWindowSet); + pcmockup_updateMainMenubar(me); windowContainer_endUpdate(me->windowContainer); SDL_Event event; diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 499d015..2cae7ac 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -62,6 +62,7 @@ typedef struct DebugWindowSet DebugWindowSet; DebugWindowSet* debugWindowSet_init(const WindowGrid* grid, Renderer* renderer); void debugWindowSet_free(DebugWindowSet* set); void debugWindowSet_update(DebugWindowSet* set); +void debugWindowSet_updateMenubar(DebugWindowSet* me); void debugWindowSet_handleEvent(DebugWindowSet* set, const SDL_Event* ev); typedef struct PCMockup PCMockup; From a74c9c827cfe69f8bcdd7363904e8ecdfe4067cb Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 16:15:16 +0100 Subject: [PATCH 07/19] pcmockup: Improve ImageWindow content alignment --- pcmockup/imagewindow.c | 52 ++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index d3b52cf..16e2e1b 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -7,11 +7,12 @@ struct ImageWindow { char* title; GLuint textureID; - GSize windowSize; + GSize windowSize, imageSize; float aspect; SDL_Rect lastContentPos; bool isOpen, isEssential; ImVec2 initialPosition; + float toolbarHeight; }; const Uint32 imageWindow_SDLPixelFormat = SDL_PIXELFORMAT_ABGR8888; @@ -71,6 +72,8 @@ void imageWindow_setImageData(ImageWindow* me, GSize size, const SDL_Color* data glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, me->textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.w, size.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + me->imageSize = size; + me->aspect = (float)size.w / (float)size.h; me->windowSize.w = max(me->windowSize.w, size.w); me->windowSize.h = max(me->windowSize.h, size.h); } @@ -80,17 +83,35 @@ SDL_Rect imageWindow_getContentPos(ImageWindow* me) return me->lastContentPos; } +void imageWindow_constrainWindowSize(ImGuiSizeCallbackData* data) +{ + ImageWindow* me = (ImageWindow*)data->UserData; + data->DesiredSize.y -= me->toolbarHeight; + + ImVec2 byWidth = { + floorf(data->DesiredSize.x), + floorf(data->DesiredSize.x / me->aspect + me->toolbarHeight) + }; + float byWidthArea = byWidth.x * byWidth.y; + ImVec2 byHeight = { + floorf(data->DesiredSize.y * me->aspect), + floorf(data->DesiredSize.y + me->toolbarHeight) + }; + float byHeightArea = byHeight.x * byHeight.y; + + data->DesiredSize = byWidthArea > byHeightArea ? byWidth : byHeight; +} + void imageWindow_update(ImageWindow* me) { if (!me->isOpen) return; - const SDL_Rect windowRect = { 0, 0, me->windowSize.w, me->windowSize.h }; - const SDL_Rect imageRect = findBestFit(windowRect, me->aspect); const ImVec2 - offset = { (float)imageRect.x, (float)imageRect.y }, - size = { (float)imageRect.w, (float)imageRect.h }, + size = { (float)me->windowSize.w, (float)me->windowSize.h }, + minSize = { (float)me->imageSize.w, (float)me->imageSize.h }, + maxSize = { FLT_MAX, FLT_MAX }, zero = { 0, 0 }, - uv1 = { 1, 1 }; + one = { 1 + FLT_EPSILON, 1 + FLT_EPSILON }; ImVec2 toolbarSize, windowPos; const ImVec4 tintColor = { 1, 1, 1, 1 }, @@ -101,30 +122,27 @@ void imageWindow_update(ImageWindow* me) if (me->initialPosition.x >= 0 && me->initialPosition.y >= 0) igSetNextWindowPos(me->initialPosition, ImGuiCond_Once, zero); - igSetNextWindowContentSize(size); + igSetNextWindowSizeConstraints(minSize, maxSize, imageWindow_constrainWindowSize, me); igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, zero); // space between image and window border - igPushStyleVarVec2(ImGuiStyleVar_ItemSpacing, zero); // space between vertical centering dummy and image - igPushStyleVarFloat(ImGuiStyleVar_IndentSpacing, 0.0f); // space between horizontal centering indent and image igBegin(me->title, isOpenPtr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse); igGetItemRectSize_nonUDT(&toolbarSize); igGetWindowPos_nonUDT(&windowPos); - igDummy(offset); // center vertically - igIndent(offset.x); // center horizontally - igImage((ImTextureID)(intptr_t)me->textureID, size, zero, uv1, tintColor, borderColor); - igPopStyleVar(3); + igImageButton((ImTextureID)(intptr_t)me->textureID, size, zero, one, 0, borderColor, tintColor); + igPopStyleVar(1); me->windowSize.w = (int16_t)igGetWindowWidth(); me->windowSize.h = (int16_t)(igGetWindowHeight() - toolbarSize.y); + me->toolbarHeight = toolbarSize.y; igEnd(); me->lastContentPos = (SDL_Rect) { - (int)(windowPos.x + imageRect.x), - (int)(windowPos.y + toolbarSize.y + imageRect.y), - (int)imageRect.w, - (int)imageRect.h + (int)(windowPos.x), + (int)(windowPos.y), + (int)me->windowSize.w, + (int)me->windowSize.h }; } From 529bbc6fa36b6fa0e5322538a04ac69a11fa2711 Mon Sep 17 00:00:00 2001 From: Helco Date: Sun, 25 Nov 2018 17:18:53 +0100 Subject: [PATCH 08/19] pcmockup: add extra include for travis --- pcmockup/imagewindow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index 16e2e1b..f32023e 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -2,6 +2,7 @@ #include "pcmockup.h" #include #include +#include struct ImageWindow { From d5b4e4df818e4ca8a6a51f4066567470b83c5e9c Mon Sep 17 00:00:00 2001 From: Helco Date: Mon, 26 Nov 2018 15:33:52 +0100 Subject: [PATCH 09/19] pcmockup: work around missing header guard --- pcmockup/CMakeLists.txt | 5 +++++ pcmockup/cimgui.include.h | 12 ++++++++++++ pcmockup/debugwindowset.c | 2 +- pcmockup/imagewindow.c | 2 +- pcmockup/pcmockup.c | 2 +- pcmockup/windowcontainer.c | 2 +- 6 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 pcmockup/cimgui.include.h diff --git a/pcmockup/CMakeLists.txt b/pcmockup/CMakeLists.txt index d8da2a5..ce36fa5 100644 --- a/pcmockup/CMakeLists.txt +++ b/pcmockup/CMakeLists.txt @@ -6,6 +6,11 @@ set(sources_pcmockup pebble.h sdl.include.h stb.include.h + cimgui.include.h + + window.h + windowcontainer.c + pcmockup.h pcmockup.c pebblewindow.c diff --git a/pcmockup/cimgui.include.h b/pcmockup/cimgui.include.h new file mode 100644 index 0000000..8a09090 --- /dev/null +++ b/pcmockup/cimgui.include.h @@ -0,0 +1,12 @@ +#ifndef CIMGUI_INCLUDE_H +#define CIMGUI_INCLUDE_H + +#pragma GCC diagnostic push +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wpragma-pack" +#pragma GCC diagnostic ignored "-Wmacro-redefined" +#endif +#include +#pragma GCC diagnostic pop + +#endif diff --git a/pcmockup/debugwindowset.c b/pcmockup/debugwindowset.c index ad6b5da..65c9630 100644 --- a/pcmockup/debugwindowset.c +++ b/pcmockup/debugwindowset.c @@ -1,5 +1,5 @@ #include "pcmockup.h" -#include +#include "cimgui.include.h" #define WINDOW_GAP 64 diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index f32023e..929c42c 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -1,7 +1,7 @@ #define _CRT_NONSTDC_NO_DEPRECATE #include "pcmockup.h" #include -#include +#include "cimgui.include.h" #include struct ImageWindow diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index a40639f..fbda727 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -1,5 +1,5 @@ #include -#include +#include "cimgui.include.h" #include "pcmockup.h" #include "renderer.h" #include "platform.h" diff --git a/pcmockup/windowcontainer.c b/pcmockup/windowcontainer.c index 47253b7..04fd2a7 100644 --- a/pcmockup/windowcontainer.c +++ b/pcmockup/windowcontainer.c @@ -1,6 +1,6 @@ #include "pcmockup.h" #include -#include +#include "cimgui.include.h" #define IMGUI_IMPL_API #include From 81ea2671b31172646ad88b327216349a8267dc10 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 14:32:29 +0100 Subject: [PATCH 10/19] cmake: Update cimgui and ignore warnings --- cmake/cimgui.cmake | 6 ++++++ external/cimgui | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/cimgui.cmake b/cmake/cimgui.cmake index 04a0e1c..5a1c748 100644 --- a/cmake/cimgui.cmake +++ b/cmake/cimgui.cmake @@ -41,3 +41,9 @@ target_compile_definitions(cimgui PRIVATE IMGUI_IMPL_OPENGL_LOADER_GLAD INTERFACE CIMGUI_DEFINE_ENUMS_AND_STRUCTS ) +target_compile_options(cimgui PRIVATE + "-Wno-pragma-pack" + "-Wno-return-type-c-linkage" + "-Wno-unused-const-variable" + "-Wno-macro-redefined" +) diff --git a/external/cimgui b/external/cimgui index 8911a5a..204f282 160000 --- a/external/cimgui +++ b/external/cimgui @@ -1 +1 @@ -Subproject commit 8911a5a9921ec6f8e10b32d592dc43b80d053549 +Subproject commit 204f2828bb81857ffa4b9e2dbc360eabbb7cbd25 From ca3108c12225c614ca95cf4eff2db926962feb9d Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 14:32:50 +0100 Subject: [PATCH 11/19] PCMockup: Add Window module --- pcmockup/CMakeLists.txt | 2 + pcmockup/pcmockup.h | 9 +-- pcmockup/window.c | 162 +++++++++++++++++++++++++++++++++++++ pcmockup/window.h | 58 +++++++++++++ pcmockup/window_internal.h | 11 +++ pcmockup/windowcontainer.c | 54 ++++++++++++- 6 files changed, 285 insertions(+), 11 deletions(-) create mode 100644 pcmockup/window.c create mode 100644 pcmockup/window.h create mode 100644 pcmockup/window_internal.h diff --git a/pcmockup/CMakeLists.txt b/pcmockup/CMakeLists.txt index ce36fa5..cd242a3 100644 --- a/pcmockup/CMakeLists.txt +++ b/pcmockup/CMakeLists.txt @@ -9,6 +9,8 @@ set(sources_pcmockup cimgui.include.h window.h + window_internal.h + window.c windowcontainer.c pcmockup.h diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 2cae7ac..7c27dd4 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -3,17 +3,10 @@ #include "sdl.include.h" #include "pebble.h" #include "renderer.h" +#include "window.h" SDL_Rect findBestFit(SDL_Rect target, float aspect); SDL_Rect padRect(SDL_Rect rect, GSize amount); -Uint32 getWindowIDByEvent(const SDL_Event* ev); - -typedef struct WindowContainer WindowContainer; -WindowContainer* windowContainer_init(GSize windowSize); -void windowContainer_free(WindowContainer* me); -void windowContainer_startUpdate(WindowContainer* me); -void windowContainer_endUpdate(WindowContainer* me); -void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev); extern const Uint32 imageWindow_SDLPixelFormat; typedef struct ImageWindow ImageWindow; diff --git a/pcmockup/window.c b/pcmockup/window.c new file mode 100644 index 0000000..4f59193 --- /dev/null +++ b/pcmockup/window.c @@ -0,0 +1,162 @@ +#define _CRT_NONSTDC_NO_DEPRECATE +#include "window_internal.h" + +#define MOUSE_BUTTON_COUNT 5 // even imgui uses this "magic" number + +struct Window +{ + char* title; + ImVec2 currentPos, currentSize; + ImVec2 initialPos, initialSize; + bool isFocused; + ImGuiWindowFlags flags; + WindowOpenState openState; + bool wasDragging[MOUSE_BUTTON_COUNT]; + GPoint draggingOrigin[MOUSE_BUTTON_COUNT]; + + void* userdata; + WindowUpdateCallbacks onUpdate; + WindowDragCallback onDrag; + WindowKeyCallbacks onKey; +}; + +Window* window_init() +{ + Window* me = (Window*)malloc(sizeof(Window)); + if (me == NULL) + return NULL; + memset(me, 0, sizeof(Window)); + + me->initialPos = me->currentPos = (ImVec2) { -1, -1 }; + me->initialSize = me->currentSize = (ImVec2) { -1, -1 }; + window_setTitle(me, ""); + return me; +} + +void window_free(Window* me) +{ + if (me == NULL) + return; + if (me->title != NULL) + free(me->title); + free(me); +} + +void window_update(Window* me) +{ + if (me->openState == WindowOpenState_Closed) + return; + if (me->onUpdate.before != NULL) + me->onUpdate.before(me); + + bool isOpen = (me->openState == WindowOpenState_Open); + bool* isOpenPtr = me->openState == WindowOpenState_Unclosable ? NULL : &isOpen; + if (me->initialPos.x >= 0 && me->initialPos.y >= 0) + igSetNextWindowPos(me->initialPos, ImGuiCond_Once, (ImVec2) { 0, 0 }); + if (me->initialSize.x > 0 && me->initialSize.y > 0) + igSetNextWindowSize(me->initialSize, ImGuiCond_Once); + igBegin(me->title, isOpenPtr, me->flags); + igGetCursorScreenPos_nonUDT(&me->currentPos); // handles toolbar height + igGetWindowSize_nonUDT(&me->currentSize); + me->isFocused = igIsWindowFocused(ImGuiFocusedFlags_AnyWindow); + + if (me->onUpdate.content != NULL) + me->onUpdate.content(me); + + igEnd(); + if (isOpenPtr != NULL) + me->openState = isOpen ? WindowOpenState_Open : WindowOpenState_Closed; + + if (me->onUpdate.after != NULL) + me->onUpdate.after(me); +} + +void window_handleDragEvent(Window* me) +{ + for (int button = 0; button < 4; button++) + { + if (!igIsMouseDragging(button, -1.0f) || me->onDrag == NULL) + continue; + ImVec2 delta; + igGetMouseDragDelta_nonUDT(&delta, button, -1.0f); + me->onDrag(me, button, delta); + } +} + +void window_handleKeyEvent(Window* me, SDL_Keysym sym, bool isDown) +{ + if (isDown && me->onKey.down != NULL) + me->onKey.down(me, sym); + if (!isDown && me->onKey.up != NULL) + me->onKey.up(me, sym); +} + +GRect window_getBounds(const Window* me) +{ + return (GRect) { + (GPoint) { (int)me->currentPos.x, (int)me->currentPos.y }, + (GSize) { (int)me->currentSize.x, (int)me->currentSize.y } + }; +} + +WindowOpenState window_getOpenState(const Window* me) +{ + return me->openState; +} + +bool window_isFocused(const Window* me) +{ + return me->isFocused; +} + +void* window_getUserdata(const Window* me) +{ + return me->userdata; +} + +void window_setUserdata(Window* me, void* userdata) +{ + me->userdata = userdata; +} + +void window_setTitle(Window* me, const char* title) +{ + if (me->title != NULL) + free(me->title); + me->title = strdup(title); +} + +void window_setFlags(Window* me, ImGuiWindowFlags flags) +{ + me->flags = flags; +} + +void window_setOpenState(Window* me, WindowOpenState state) +{ + me->openState = state; +} + +void window_setInitialBounds(Window* me, GRect bounds) +{ + me->initialPos = (ImVec2) { (float)bounds.origin.x, (float)bounds.origin.y }; + me->initialSize = (ImVec2) { (float)bounds.size.w, (float)bounds.size.h }; + if (me->initialPos.x < 0 && me->initialPos.y < 0) + me->currentPos = me->initialPos; + if (me->initialSize.x < 0 && me->initialSize.y < 0) + me->currentSize = me->initialSize; +} + +void window_setUpdateCallbacks(Window* me, WindowUpdateCallbacks callbacks) +{ + me->onUpdate = callbacks; +} + +void window_setDragCallback(Window* me, WindowDragCallback callback) +{ + me->onDrag = callback; +} + +void window_setKeyCallbacks(Window* me, WindowKeyCallbacks callbacks) +{ + me->onKey = callbacks; +} diff --git a/pcmockup/window.h b/pcmockup/window.h new file mode 100644 index 0000000..4d6881f --- /dev/null +++ b/pcmockup/window.h @@ -0,0 +1,58 @@ +#ifndef WINDOW_H +#define WINDOW_H +#include +#include +#include +#include "cimgui.include.h" +#include "sdl.include.h" + +typedef struct Window Window; +typedef void (*WindowUpdateCallback)(Window* window); +typedef struct WindowUpdateCallbacks +{ + WindowUpdateCallback + before, + content, + after; +} WindowUpdateCallbacks; +typedef void (*WindowDragCallback)(Window* window, int mouseKey, ImVec2 delta); +typedef void (*WindowKeyCallback)(Window* window, SDL_Keysym sym); +typedef struct WindowKeyCallbacks +{ + WindowKeyCallback + down, + up; +} WindowKeyCallbacks; + +typedef enum WindowOpenState +{ + WindowOpenState_Open, + WindowOpenState_Closed, + WindowOpenState_Unclosable +} WindowOpenState; + +Uint32 getWindowIDByEvent(const SDL_Event* ev); + +GRect window_getBounds(const Window* window); +bool window_isFocused(const Window* window); +WindowOpenState window_getOpenState(const Window* window); +void* window_getUserdata(const Window* window); +void window_setUserdata(Window* window, void* userdata); +void window_setTitle(Window* window, const char* title); +void window_setFlags(Window* window, ImGuiWindowFlags flags); +void window_setOpenState(Window* window, WindowOpenState state); +void window_setInitialBounds(Window* window, GRect bounds); +void window_setUpdateCallbacks(Window* window, WindowUpdateCallbacks callbacks); +void window_setDragCallback(Window* window, WindowDragCallback callback); +void window_setKeyCallbacks(Window* window, WindowKeyCallbacks callbacks); + +typedef struct WindowContainer WindowContainer; +WindowContainer* windowContainer_init(GSize windowSize); +void windowContainer_free(WindowContainer* me); +void windowContainer_startUpdate(WindowContainer* me); +void windowContainer_endUpdate(WindowContainer* me); +Window* windowContainer_newWindow(WindowContainer* me, const char* title); +Window* windowContainer_getFocusedWindow(WindowContainer* me); +void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev); + +#endif diff --git a/pcmockup/window_internal.h b/pcmockup/window_internal.h new file mode 100644 index 0000000..fd11c46 --- /dev/null +++ b/pcmockup/window_internal.h @@ -0,0 +1,11 @@ +#ifndef WINDOW_INTERNAL_H +#define WINDOW_INTERNAL_H +#include "window.h" + +Window* window_init(); +void window_free(Window* window); +void window_update(Window* window); +void window_handleDragEvent(Window* window); +void window_handleKeyEvent(Window* window, SDL_Keysym sym, bool isDown); + +#endif diff --git a/pcmockup/windowcontainer.c b/pcmockup/windowcontainer.c index 04fd2a7..21013e8 100644 --- a/pcmockup/windowcontainer.c +++ b/pcmockup/windowcontainer.c @@ -1,6 +1,8 @@ -#include "pcmockup.h" +#include "window_internal.h" +#include #include #include "cimgui.include.h" +#include "sdl.include.h" #define IMGUI_IMPL_API #include @@ -12,11 +14,16 @@ extern void ImGui_ImplOpenGL3_Shutdown(); extern void ImGui_ImplOpenGL3_NewFrame(); extern void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); +#define WINDOW_CONTAINER_CHUNK 16 + struct WindowContainer { SDL_Window* window; SDL_GLContext glContext; ImGuiContext* imGuiContext; + Window** windows; + Window* focusedWindow; + int windowCount, windowCapacity; }; WindowContainer* windowContainer_init(GSize windowSize) @@ -103,6 +110,12 @@ void windowContainer_free(WindowContainer* me) SDL_GL_DeleteContext(me->glContext); if (me->window) SDL_DestroyWindow(me->window); + if (me->windows != NULL) + { + for (int i = 0; i < me->windowCount; i++) + window_free(me->windows[i]); + free(me->windows); + } free(me); } @@ -115,6 +128,14 @@ void windowContainer_startUpdate(WindowContainer* me) ImGui_ImplSDL2_NewFrame(me->window); igNewFrame(); igShowDemoWindow(&open); + + me->focusedWindow = NULL; + for (int i = 0; i < me->windowCount; i++) + { + window_update(me->windows[i]); + if (window_isFocused(me->windows[i])) + me->focusedWindow = me->windows[i]; + } } void windowContainer_endUpdate(WindowContainer* me) @@ -127,11 +148,38 @@ void windowContainer_endUpdate(WindowContainer* me) SDL_GL_SwapWindow(me->window); } +Window* windowContainer_newWindow(WindowContainer* me, const char* title) +{ + if (me->windowCount == me->windowCapacity) + { + me->windowCapacity += WINDOW_CONTAINER_CHUNK; + me->windows = (Window**)realloc(me->windows, sizeof(Window*) * me->windowCapacity); + assert(me->windows != NULL); + } + Window* newWindow = window_init(); + window_setTitle(newWindow, title); + me->windows[me->windowCount++] = newWindow; + return newWindow; +} + +Window* windowContainer_getFocusedWindow(WindowContainer* me) +{ + return me->focusedWindow; +} + void windowContainer_handleEvent(WindowContainer* me, const SDL_Event* ev) { // the ImGui SDL2 implementation does not filter the events by window ID Uint32 windowID = SDL_GetWindowID(me->window); - if (getWindowIDByEvent(ev) == windowID) - ImGui_ImplSDL2_ProcessEvent((SDL_Event*)ev); + if (getWindowIDByEvent(ev) != windowID) + return; + ImGui_ImplSDL2_ProcessEvent((SDL_Event*)ev); // TODO: Remove const-removing-cast as soon as (https://github.com/ocornut/imgui/issues/2187) is resolved! + + if (me->focusedWindow == NULL) + return; + const ImGuiIO* io = igGetIO(); + if ((ev->type == SDL_KEYDOWN || ev->type == SDL_KEYUP) && !io->WantCaptureKeyboard) + window_handleKeyEvent(me->focusedWindow, ev->key.keysym, (ev->type == SDL_KEYDOWN)); + window_handleDragEvent(me->focusedWindow); } From 0fbb7b93a2117324b441facc755a5a005c4b6054 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 15:25:45 +0100 Subject: [PATCH 12/19] pcmockup: Migrate ImageWindow and consumers to Window --- pcmockup/debugwindow.c | 7 ++- pcmockup/debugwindowset.c | 3 +- pcmockup/imagewindow.c | 107 ++++++++++++++++---------------------- pcmockup/pcmockup.c | 2 + pcmockup/pcmockup.h | 16 +++--- pcmockup/pebblewindow.c | 7 ++- 6 files changed, 60 insertions(+), 82 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index 744759a..f17094b 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -27,20 +27,20 @@ SDL_Surface* createSDLSurface(int w, int h, Uint32 format) return surface; } -DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) +DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) { DebugWindow* me = (DebugWindow*)malloc(sizeof(DebugWindow)); if (me == NULL) return NULL; memset(me, 0, sizeof(DebugWindow)); - me->window = imageWindow_init(view->name, (GSize) { bounds.w, bounds.h }, false); + GRect b = { { bounds.x, bounds.y }, { bounds.w, bounds.h} }; + me->window = imageWindow_init(parent, view->name, b, false); if (me->window == NULL) { debugWindow_free(me); return NULL; } - imageWindow_setInitialPosition(me->window, (GPoint) { bounds.x, bounds.y }); me->surface = createSDLSurface(bounds.w, bounds.h, SDL_PIXELFORMAT_ABGR8888); if (me->surface == NULL) @@ -89,7 +89,6 @@ void debugWindow_startUpdate(DebugWindow* me) void debugWindow_endUpdate(DebugWindow* me) { imageWindow_setImageData(me->window, GSize(me->surface->w, me->surface->h), (SDL_Color*)me->surface->pixels); - imageWindow_update(me->window); } void debugWindow_update(DebugWindow* me) diff --git a/pcmockup/debugwindowset.c b/pcmockup/debugwindowset.c index 65c9630..6495cc7 100644 --- a/pcmockup/debugwindowset.c +++ b/pcmockup/debugwindowset.c @@ -10,7 +10,7 @@ struct DebugWindowSet Renderer* renderer; }; -DebugWindowSet* debugWindowSet_init(const WindowGrid* grid, Renderer* renderer) +DebugWindowSet* debugWindowSet_init(WindowContainer* parent, const WindowGrid* grid, Renderer* renderer) { DebugWindowSet* me = (DebugWindowSet*)malloc(sizeof(DebugWindowSet)); if (me == NULL) @@ -32,6 +32,7 @@ DebugWindowSet* debugWindowSet_init(const WindowGrid* grid, Renderer* renderer) for (int i = 0; i < me->count; i++) { me->windows[i] = debugWindow_init( + parent, windowGrid_getSingleBounds(grid, -1 - i), &renderer_getDebugViews(renderer)[i], renderer diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index 929c42c..735d327 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -1,4 +1,3 @@ -#define _CRT_NONSTDC_NO_DEPRECATE #include "pcmockup.h" #include #include "cimgui.include.h" @@ -6,32 +5,44 @@ struct ImageWindow { - char* title; + Window* window; GLuint textureID; - GSize windowSize, imageSize; + GSize imageSize; float aspect; - SDL_Rect lastContentPos; - bool isOpen, isEssential; - ImVec2 initialPosition; + bool isEssential; float toolbarHeight; }; const Uint32 imageWindow_SDLPixelFormat = SDL_PIXELFORMAT_ABGR8888; -ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential) +void imageWindow_beforeUpdate(Window* me); +void imageWindow_contentUpdate(Window* me); + +ImageWindow* imageWindow_init(WindowContainer* parent, const char* title, GRect initialBounds, bool_t isEssential) { ImageWindow* me = (ImageWindow*)malloc(sizeof(ImageWindow)); if (me == NULL) return NULL; memset(me, 0, sizeof(ImageWindow)); - me->title = strdup(title); - if (me->title == NULL) + me->window = windowContainer_newWindow(parent, title); + if (me->window == NULL) { - fprintf(stderr, "strdup: failure\n"); + fprintf(stderr, "Could not allocate new window\n"); imageWindow_free(me); return NULL; } + window_setUserdata(me->window, me); + window_setInitialBounds(me->window, initialBounds); + window_setOpenState(me->window, isEssential ? WindowOpenState_Unclosable : WindowOpenState_Open); + window_setFlags(me->window, + ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoCollapse); + window_setUpdateCallbacks(me->window, (WindowUpdateCallbacks) { + .before = imageWindow_beforeUpdate, + .content = imageWindow_contentUpdate + }); glGenTextures(1, &me->textureID); if (me->textureID == 0) @@ -49,11 +60,8 @@ ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEss const SDL_Color black = { 255, 255, 255, 255 }; imageWindow_setImageData(me, GSize(1, 1), &black); - me->isOpen = true; me->isEssential = isEssential; - me->windowSize = initialSize; - me->aspect = (float)initialSize.w / initialSize.h; - me->initialPosition.x = -1; // undefined initial position + me->aspect = (float)initialBounds.size.w / initialBounds.size.h; return me; } @@ -63,8 +71,6 @@ void imageWindow_free(ImageWindow* me) return; if (me->textureID != 0) glDeleteTextures(1, &me->textureID); - if (me->title != NULL) - free(me->title); free(me); } @@ -75,13 +81,6 @@ void imageWindow_setImageData(ImageWindow* me, GSize size, const SDL_Color* data glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.w, size.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); me->imageSize = size; me->aspect = (float)size.w / (float)size.h; - me->windowSize.w = max(me->windowSize.w, size.w); - me->windowSize.h = max(me->windowSize.h, size.h); -} - -SDL_Rect imageWindow_getContentPos(ImageWindow* me) -{ - return me->lastContentPos; } void imageWindow_constrainWindowSize(ImGuiSizeCallbackData* data) @@ -103,64 +102,46 @@ void imageWindow_constrainWindowSize(ImGuiSizeCallbackData* data) data->DesiredSize = byWidthArea > byHeightArea ? byWidth : byHeight; } -void imageWindow_update(ImageWindow* me) +void imageWindow_beforeUpdate(Window* window) { - if (!me->isOpen) - return; + ImageWindow* me = (ImageWindow*)window_getUserdata(window); const ImVec2 - size = { (float)me->windowSize.w, (float)me->windowSize.h }, + zero = { 0, 0 }, minSize = { (float)me->imageSize.w, (float)me->imageSize.h }, - maxSize = { FLT_MAX, FLT_MAX }, + maxSize = { FLT_MAX, FLT_MAX }; + igSetNextWindowSizeConstraints(minSize, maxSize, imageWindow_constrainWindowSize, me); + igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, zero); // space between image and window border +} + +void imageWindow_contentUpdate(Window* window) +{ + const ImageWindow* me = (const ImageWindow*)window_getUserdata(window); + const GSize windowSize = window_getBounds(window).size; + const ImVec2 zero = { 0, 0 }, - one = { 1 + FLT_EPSILON, 1 + FLT_EPSILON }; - ImVec2 toolbarSize, windowPos; + one = { 1 + FLT_EPSILON, 1 + FLT_EPSILON }, + size = { (float)windowSize.w, (float)windowSize.h }; const ImVec4 tintColor = { 1, 1, 1, 1 }, borderColor = { 0, 0, 0, 0 }; - bool* isOpenPtr = me->isEssential - ? NULL // essential windows don't get a close button - : &me->isOpen; + ImVec2 toolbarSize; - if (me->initialPosition.x >= 0 && me->initialPosition.y >= 0) - igSetNextWindowPos(me->initialPosition, ImGuiCond_Once, zero); - igSetNextWindowSizeConstraints(minSize, maxSize, imageWindow_constrainWindowSize, me); - igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, zero); // space between image and window border - igBegin(me->title, isOpenPtr, - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse | - ImGuiWindowFlags_NoCollapse); igGetItemRectSize_nonUDT(&toolbarSize); - igGetWindowPos_nonUDT(&windowPos); igImageButton((ImTextureID)(intptr_t)me->textureID, size, zero, one, 0, borderColor, tintColor); igPopStyleVar(1); - - me->windowSize.w = (int16_t)igGetWindowWidth(); - me->windowSize.h = (int16_t)(igGetWindowHeight() - toolbarSize.y); - me->toolbarHeight = toolbarSize.y; - igEnd(); - - me->lastContentPos = (SDL_Rect) { - (int)(windowPos.x), - (int)(windowPos.y), - (int)me->windowSize.w, - (int)me->windowSize.h - }; } -void imageWindow_setInitialPosition(ImageWindow* me, GPoint initialPosition) +void imageWindow_toggle(ImageWindow* me, bool_t isOpen) { - me->initialPosition = (ImVec2) { - (float)initialPosition.x, - (float)initialPosition.y - }; + window_setOpenState(me->window, isOpen ? WindowOpenState_Open : WindowOpenState_Closed); } -void imageWindow_toggle(ImageWindow* me, bool_t isOpen) +bool_t imageWindow_isOpen(ImageWindow* me) { - me->isOpen = isOpen; + return window_getOpenState(me->window) == WindowOpenState_Open; } -bool_t imageWindow_isOpen(ImageWindow* me) +Window* imageWindow_asWindow(ImageWindow* me) { - return me->isOpen; + return me->window; } diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index fbda727..c275ae7 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -68,6 +68,7 @@ PCMockup *pcmockup_init() windowGrid.totalSize = WINDOW_START_SIZE; me->pebbleWindow = pebbleWindow_init( + me->windowContainer, windowGrid_getSingleBounds(&windowGrid, 0), GSize(RENDERER_WIDTH, RENDERER_HEIGHT) ); @@ -78,6 +79,7 @@ PCMockup *pcmockup_init() } me->debugWindowSet = debugWindowSet_init( + me->windowContainer, &windowGrid, me->renderer ); diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 7c27dd4..f1ba0b8 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -10,14 +10,12 @@ SDL_Rect padRect(SDL_Rect rect, GSize amount); extern const Uint32 imageWindow_SDLPixelFormat; typedef struct ImageWindow ImageWindow; -ImageWindow* imageWindow_init(const char* title, GSize initialSize, bool_t isEssential); +ImageWindow* imageWindow_init(WindowContainer* parent, const char* title, GRect initialBounds, bool_t isEssential); void imageWindow_free(ImageWindow* me); void imageWindow_setImageData(ImageWindow* me, GSize size, const SDL_Color* data); -SDL_Rect imageWindow_getContentPos(ImageWindow* me); // in screen coordinates -void imageWindow_update(ImageWindow* me); -void imageWindow_setInitialPosition(ImageWindow* me, GPoint initialPosition); void imageWindow_toggle(ImageWindow* me, bool_t isOpen); bool_t imageWindow_isOpen(ImageWindow* me); +Window* imageWindow_asWindow(ImageWindow* me); typedef struct WindowGrid { @@ -35,16 +33,14 @@ void safeFramebuffer_prepare(SafeFramebuffer* me); void safeFramebuffer_check(SafeFramebuffer* me); typedef struct PebbleWindow PebbleWindow; -PebbleWindow* pebbleWindow_init(SDL_Rect initialBounds, GSize pebbleSize); +PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize); void pebbleWindow_free(PebbleWindow* window); -void pebbleWindow_startUpdate(PebbleWindow* window); -void pebbleWindow_endUpdate(PebbleWindow* window); -SDL_Rect pebbleWindow_getBounds(PebbleWindow* window); +void pebbleWindow_update(PebbleWindow* me); GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window); ImageWindow* pebbleWindow_asImageWindow(PebbleWindow* window); typedef struct DebugWindow DebugWindow; -DebugWindow* debugWindow_init(SDL_Rect bounds, const DebugView* debugView, Renderer* renderer); +DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* debugView, Renderer* renderer); void debugWindow_free(DebugWindow* window); void debugWindow_update(DebugWindow* window); void debugWindow_handleEvent(DebugWindow* window, const SDL_Event* ev); @@ -52,7 +48,7 @@ const DebugView* debugWindow_getDebugView(const DebugWindow* window); ImageWindow* debugWindow_asImageWindow(DebugWindow* window); typedef struct DebugWindowSet DebugWindowSet; -DebugWindowSet* debugWindowSet_init(const WindowGrid* grid, Renderer* renderer); +DebugWindowSet* debugWindowSet_init(WindowContainer* parent, const WindowGrid* grid, Renderer* renderer); void debugWindowSet_free(DebugWindowSet* set); void debugWindowSet_update(DebugWindowSet* set); void debugWindowSet_updateMenubar(DebugWindowSet* me); diff --git a/pcmockup/pebblewindow.c b/pcmockup/pebblewindow.c index bf94d38..fc10580 100644 --- a/pcmockup/pebblewindow.c +++ b/pcmockup/pebblewindow.c @@ -13,20 +13,20 @@ struct PebbleWindow GSize pebbleSize; }; -PebbleWindow* pebbleWindow_init(SDL_Rect initialBounds, GSize pebbleSize) +PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize) { PebbleWindow* me = (PebbleWindow*)malloc(sizeof(PebbleWindow)); if (me == NULL) return NULL; memset(me, 0, sizeof(PebbleWindow)); - me->window = imageWindow_init("Pebble screen", (GSize) { initialBounds.w, initialBounds.h }, true); + GRect b = { { initialBounds.x, initialBounds.y }, { initialBounds.w, initialBounds.h } }; + me->window = imageWindow_init(parent, "Pebble screen", b, true); if (me->window == NULL) { pebbleWindow_free(me); return NULL; } - imageWindow_setInitialPosition(me->window, (GPoint) { initialBounds.x, initialBounds.y }); me->textureData = (SDL_Color*)malloc(sizeof(SDL_Color) * pebbleSize.w * pebbleSize.h); if (me->textureData == NULL) @@ -118,7 +118,6 @@ void pebbleWindow_endUpdate(PebbleWindow* me) safeFramebuffer_check(me->framebuffer); prv_pebbleWindow_convertPebbleToTexture(me); imageWindow_setImageData(me->window, me->pebbleSize, me->textureData); - imageWindow_update(me->window); } GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window) From c0acc799795a65ae4151b4b7cd56ef0957bf658c Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 18:36:45 +0100 Subject: [PATCH 13/19] pcmockup: Readd debug dragging --- pcmockup/debugwindow.c | 30 +++++++++++------------------ pcmockup/debugwindowset.c | 6 ------ pcmockup/imagewindow.c | 18 ++++++++++-------- pcmockup/pcmockup.c | 1 - pcmockup/pcmockup.h | 2 -- pcmockup/window.c | 40 ++++++++++++++++++--------------------- pcmockup/window.h | 12 ++++++------ 7 files changed, 45 insertions(+), 64 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index f17094b..ae599b3 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -1,5 +1,6 @@ #include "pcmockup.h" #include "renderer.h" +#include "platform.h" #include @@ -27,6 +28,8 @@ SDL_Surface* createSDLSurface(int w, int h, Uint32 format) return surface; } +void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata); + DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) { DebugWindow* me = (DebugWindow*)malloc(sizeof(DebugWindow)); @@ -41,6 +44,7 @@ DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const De debugWindow_free(me); return NULL; } + window_setDragCallback(imageWindow_asWindow(me->window), debugWindow_onDrag, me); me->surface = createSDLSurface(bounds.w, bounds.h, SDL_PIXELFORMAT_ABGR8888); if (me->surface == NULL) @@ -98,27 +102,15 @@ void debugWindow_update(DebugWindow* me) debugWindow_endUpdate(me); } -void debugWindow_handleEvent(DebugWindow* me, const SDL_Event* ev) +void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata) { - Uint32 windowID = 1234; - if (ev->type == SDL_MOUSEMOTION && ev->motion.windowID == windowID && (ev->motion.state & SDL_BUTTON_LMASK) > 0) - { - xz_t move = xz(real_from_int(ev->motion.xrel), real_from_int(ev->motion.yrel)); - move = xz_invScale(move, me->zoom); - me->position = xz_sub(me->position, move); - } - if (ev->type == SDL_MOUSEWHEEL && ev->wheel.windowID == windowID) - { - real_t zoom = real_from_int(ev->wheel.y); - zoom = real_mul(real_div(zoom, real_from_int(10)), me->zoom); - me->zoom = real_add(me->zoom, zoom); - } - if (ev->type == SDL_KEYDOWN && ev->key.windowID == windowID && ev->key.keysym.sym == SDLK_r) - { - me->position = xz(real_zero, real_zero); - } + UNUSED(window); + if (button != 0) + return; + DebugWindow* me = (DebugWindow*)userdata; + xz_t move = xz_invScale((xz_t) { real_from_int(delta.x), real_from_int(delta.y) }, me->zoom); + me->position = xz_sub(me->position, move); - // update render offset xz_t halfSize = xz(real_from_int(me->surface->w / 2), real_from_int(me->surface->h / 2)); me->offset = xz_sub( xz_invScale(halfSize, me->zoom), diff --git a/pcmockup/debugwindowset.c b/pcmockup/debugwindowset.c index 6495cc7..57e7e33 100644 --- a/pcmockup/debugwindowset.c +++ b/pcmockup/debugwindowset.c @@ -91,9 +91,3 @@ void debugWindowSet_updateMenubar(DebugWindowSet* me) igEndMenu(); #endif } - -void debugWindowSet_handleEvent(DebugWindowSet* me, const SDL_Event* ev) -{ - for (int i = 0; i < me->count; i++) - debugWindow_handleEvent(me->windows[i], ev); -} diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index 735d327..96963ae 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -2,6 +2,7 @@ #include #include "cimgui.include.h" #include +#include "platform.h" struct ImageWindow { @@ -15,8 +16,8 @@ struct ImageWindow const Uint32 imageWindow_SDLPixelFormat = SDL_PIXELFORMAT_ABGR8888; -void imageWindow_beforeUpdate(Window* me); -void imageWindow_contentUpdate(Window* me); +void imageWindow_beforeUpdate(Window* me, void* userdata); +void imageWindow_contentUpdate(Window* me, void* userdata); ImageWindow* imageWindow_init(WindowContainer* parent, const char* title, GRect initialBounds, bool_t isEssential) { @@ -32,7 +33,6 @@ ImageWindow* imageWindow_init(WindowContainer* parent, const char* title, GRect imageWindow_free(me); return NULL; } - window_setUserdata(me->window, me); window_setInitialBounds(me->window, initialBounds); window_setOpenState(me->window, isEssential ? WindowOpenState_Unclosable : WindowOpenState_Open); window_setFlags(me->window, @@ -41,7 +41,8 @@ ImageWindow* imageWindow_init(WindowContainer* parent, const char* title, GRect ImGuiWindowFlags_NoCollapse); window_setUpdateCallbacks(me->window, (WindowUpdateCallbacks) { .before = imageWindow_beforeUpdate, - .content = imageWindow_contentUpdate + .content = imageWindow_contentUpdate, + .userdata = me }); glGenTextures(1, &me->textureID); @@ -102,9 +103,10 @@ void imageWindow_constrainWindowSize(ImGuiSizeCallbackData* data) data->DesiredSize = byWidthArea > byHeightArea ? byWidth : byHeight; } -void imageWindow_beforeUpdate(Window* window) +void imageWindow_beforeUpdate(Window* window, void* userdata) { - ImageWindow* me = (ImageWindow*)window_getUserdata(window); + UNUSED(window); + ImageWindow* me = (ImageWindow*)userdata; const ImVec2 zero = { 0, 0 }, minSize = { (float)me->imageSize.w, (float)me->imageSize.h }, @@ -113,9 +115,9 @@ void imageWindow_beforeUpdate(Window* window) igPushStyleVarVec2(ImGuiStyleVar_WindowPadding, zero); // space between image and window border } -void imageWindow_contentUpdate(Window* window) +void imageWindow_contentUpdate(Window* window, void* userdata) { - const ImageWindow* me = (const ImageWindow*)window_getUserdata(window); + const ImageWindow* me = (const ImageWindow*)userdata; const GSize windowSize = window_getBounds(window).size; const ImVec2 zero = { 0, 0 }, diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index c275ae7..b31c663 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -205,7 +205,6 @@ void pcmockup_update(PCMockup *me) break; } } - debugWindowSet_handleEvent(me->debugWindowSet, &event); windowContainer_handleEvent(me->windowContainer, &event); } } diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index f1ba0b8..017d585 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -43,7 +43,6 @@ typedef struct DebugWindow DebugWindow; DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* debugView, Renderer* renderer); void debugWindow_free(DebugWindow* window); void debugWindow_update(DebugWindow* window); -void debugWindow_handleEvent(DebugWindow* window, const SDL_Event* ev); const DebugView* debugWindow_getDebugView(const DebugWindow* window); ImageWindow* debugWindow_asImageWindow(DebugWindow* window); @@ -52,7 +51,6 @@ DebugWindowSet* debugWindowSet_init(WindowContainer* parent, const WindowGrid* g void debugWindowSet_free(DebugWindowSet* set); void debugWindowSet_update(DebugWindowSet* set); void debugWindowSet_updateMenubar(DebugWindowSet* me); -void debugWindowSet_handleEvent(DebugWindowSet* set, const SDL_Event* ev); typedef struct PCMockup PCMockup; PCMockup* pcmockup_init(); diff --git a/pcmockup/window.c b/pcmockup/window.c index 4f59193..c043ce6 100644 --- a/pcmockup/window.c +++ b/pcmockup/window.c @@ -11,10 +11,9 @@ struct Window bool isFocused; ImGuiWindowFlags flags; WindowOpenState openState; - bool wasDragging[MOUSE_BUTTON_COUNT]; - GPoint draggingOrigin[MOUSE_BUTTON_COUNT]; + ImVec2 lastDragDelta[MOUSE_BUTTON_COUNT]; - void* userdata; + void* onDragUserdata; WindowUpdateCallbacks onUpdate; WindowDragCallback onDrag; WindowKeyCallbacks onKey; @@ -47,7 +46,7 @@ void window_update(Window* me) if (me->openState == WindowOpenState_Closed) return; if (me->onUpdate.before != NULL) - me->onUpdate.before(me); + me->onUpdate.before(me, me->onUpdate.userdata); bool isOpen = (me->openState == WindowOpenState_Open); bool* isOpenPtr = me->openState == WindowOpenState_Unclosable ? NULL : &isOpen; @@ -58,17 +57,17 @@ void window_update(Window* me) igBegin(me->title, isOpenPtr, me->flags); igGetCursorScreenPos_nonUDT(&me->currentPos); // handles toolbar height igGetWindowSize_nonUDT(&me->currentSize); - me->isFocused = igIsWindowFocused(ImGuiFocusedFlags_AnyWindow); + me->isFocused = igIsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); if (me->onUpdate.content != NULL) - me->onUpdate.content(me); + me->onUpdate.content(me, me->onUpdate.userdata); igEnd(); if (isOpenPtr != NULL) me->openState = isOpen ? WindowOpenState_Open : WindowOpenState_Closed; if (me->onUpdate.after != NULL) - me->onUpdate.after(me); + me->onUpdate.after(me, me->onUpdate.userdata); } void window_handleDragEvent(Window* me) @@ -76,19 +75,25 @@ void window_handleDragEvent(Window* me) for (int button = 0; button < 4; button++) { if (!igIsMouseDragging(button, -1.0f) || me->onDrag == NULL) + { + me->lastDragDelta[button] = (ImVec2) { 0, 0 }; continue; - ImVec2 delta; + } + ImVec2 lastDelta = me->lastDragDelta[button], delta; igGetMouseDragDelta_nonUDT(&delta, button, -1.0f); - me->onDrag(me, button, delta); + + ImVec2 deltaDelta = { delta.x - lastDelta.x, delta.y - lastDelta.y }; + me->onDrag(me, button, deltaDelta, me->onDragUserdata); + me->lastDragDelta[button] = delta; } } void window_handleKeyEvent(Window* me, SDL_Keysym sym, bool isDown) { if (isDown && me->onKey.down != NULL) - me->onKey.down(me, sym); + me->onKey.down(me, sym, me->onKey.userdata); if (!isDown && me->onKey.up != NULL) - me->onKey.up(me, sym); + me->onKey.up(me, sym, me->onKey.userdata); } GRect window_getBounds(const Window* me) @@ -109,16 +114,6 @@ bool window_isFocused(const Window* me) return me->isFocused; } -void* window_getUserdata(const Window* me) -{ - return me->userdata; -} - -void window_setUserdata(Window* me, void* userdata) -{ - me->userdata = userdata; -} - void window_setTitle(Window* me, const char* title) { if (me->title != NULL) @@ -151,9 +146,10 @@ void window_setUpdateCallbacks(Window* me, WindowUpdateCallbacks callbacks) me->onUpdate = callbacks; } -void window_setDragCallback(Window* me, WindowDragCallback callback) +void window_setDragCallback(Window* me, WindowDragCallback callback, void* userdata) { me->onDrag = callback; + me->onDragUserdata = userdata; } void window_setKeyCallbacks(Window* me, WindowKeyCallbacks callbacks) diff --git a/pcmockup/window.h b/pcmockup/window.h index 4d6881f..19af4fb 100644 --- a/pcmockup/window.h +++ b/pcmockup/window.h @@ -7,21 +7,23 @@ #include "sdl.include.h" typedef struct Window Window; -typedef void (*WindowUpdateCallback)(Window* window); +typedef void (*WindowUpdateCallback)(Window* window, void* userdata); typedef struct WindowUpdateCallbacks { WindowUpdateCallback before, content, after; + void* userdata; } WindowUpdateCallbacks; -typedef void (*WindowDragCallback)(Window* window, int mouseKey, ImVec2 delta); -typedef void (*WindowKeyCallback)(Window* window, SDL_Keysym sym); +typedef void (*WindowDragCallback)(Window* window, int mouseKey, ImVec2 delta, void* userdata); +typedef void (*WindowKeyCallback)(Window* window, SDL_Keysym sym, void* userdata); typedef struct WindowKeyCallbacks { WindowKeyCallback down, up; + void* userdata; } WindowKeyCallbacks; typedef enum WindowOpenState @@ -36,14 +38,12 @@ Uint32 getWindowIDByEvent(const SDL_Event* ev); GRect window_getBounds(const Window* window); bool window_isFocused(const Window* window); WindowOpenState window_getOpenState(const Window* window); -void* window_getUserdata(const Window* window); -void window_setUserdata(Window* window, void* userdata); void window_setTitle(Window* window, const char* title); void window_setFlags(Window* window, ImGuiWindowFlags flags); void window_setOpenState(Window* window, WindowOpenState state); void window_setInitialBounds(Window* window, GRect bounds); void window_setUpdateCallbacks(Window* window, WindowUpdateCallbacks callbacks); -void window_setDragCallback(Window* window, WindowDragCallback callback); +void window_setDragCallback(Window* window, WindowDragCallback callback, void* userdata); void window_setKeyCallbacks(Window* window, WindowKeyCallbacks callbacks); typedef struct WindowContainer WindowContainer; From d5583a3e63b2ba2b92f19951448a878186f72c34 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 18:51:24 +0100 Subject: [PATCH 14/19] pcmockup: Readd debug zooming --- pcmockup/debugwindow.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index ae599b3..ded9bf6 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -29,6 +29,7 @@ SDL_Surface* createSDLSurface(int w, int h, Uint32 format) } void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata); +void debugWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata); DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) { @@ -45,6 +46,10 @@ DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const De return NULL; } window_setDragCallback(imageWindow_asWindow(me->window), debugWindow_onDrag, me); + window_setKeyCallbacks(imageWindow_asWindow(me->window), (WindowKeyCallbacks) { + .down = debugWindow_onKeyDown, + .userdata = me + }); me->surface = createSDLSurface(bounds.w, bounds.h, SDL_PIXELFORMAT_ABGR8888); if (me->surface == NULL) @@ -102,6 +107,15 @@ void debugWindow_update(DebugWindow* me) debugWindow_endUpdate(me); } +void debugWindow_updateOffset(DebugWindow* me) +{ + xz_t halfSize = xz(real_from_int(me->surface->w / 2), real_from_int(me->surface->h / 2)); + me->offset = xz_sub( + xz_invScale(halfSize, me->zoom), + me->position + ); +} + void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata) { UNUSED(window); @@ -110,12 +124,24 @@ void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata DebugWindow* me = (DebugWindow*)userdata; xz_t move = xz_invScale((xz_t) { real_from_int(delta.x), real_from_int(delta.y) }, me->zoom); me->position = xz_sub(me->position, move); + debugWindow_updateOffset(me); +} - xz_t halfSize = xz(real_from_int(me->surface->w / 2), real_from_int(me->surface->h / 2)); - me->offset = xz_sub( - xz_invScale(halfSize, me->zoom), - me->position - ); +void debugWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata) +{ + UNUSED(window); + real_t delta = real_zero; + switch (sym.sym) + { + case (SDLK_PLUS): + case (SDLK_KP_PLUS): delta = real_from_float(0.1f); break; + case (SDLK_MINUS): + case (SDLK_KP_MINUS): delta = real_from_float(-0.1f); break; + default: return; + } + DebugWindow* me = (DebugWindow*)userdata; + me->zoom = real_add(me->zoom, real_mul(me->zoom, delta)); + debugWindow_updateOffset(me); } const DebugView* debugWindow_getDebugView(const DebugWindow* me) From 6d2905632654771e110418c8dae34b3673d1d61c Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 19:16:10 +0100 Subject: [PATCH 15/19] pcmockup: fix slight misalignment --- pcmockup/imagewindow.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pcmockup/imagewindow.c b/pcmockup/imagewindow.c index 96963ae..570014d 100644 --- a/pcmockup/imagewindow.c +++ b/pcmockup/imagewindow.c @@ -117,18 +117,19 @@ void imageWindow_beforeUpdate(Window* window, void* userdata) void imageWindow_contentUpdate(Window* window, void* userdata) { - const ImageWindow* me = (const ImageWindow*)userdata; + ImageWindow* me = (ImageWindow*)userdata; const GSize windowSize = window_getBounds(window).size; const ImVec2 zero = { 0, 0 }, - one = { 1 + FLT_EPSILON, 1 + FLT_EPSILON }, - size = { (float)windowSize.w, (float)windowSize.h }; + one = { 1, 1 }, + size = { (float)windowSize.w, (float)windowSize.h - me->toolbarHeight }; const ImVec4 tintColor = { 1, 1, 1, 1 }, borderColor = { 0, 0, 0, 0 }; ImVec2 toolbarSize; igGetItemRectSize_nonUDT(&toolbarSize); + me->toolbarHeight = toolbarSize.y; igImageButton((ImTextureID)(intptr_t)me->textureID, size, zero, one, 0, borderColor, tintColor); igPopStyleVar(1); } From 341a266ffd17cdf16a578c9d0336b52cb1a891ff Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 27 Nov 2018 19:34:50 +0100 Subject: [PATCH 16/19] pcmockup: fix logical merge conflict --- pcmockup/pcmockup.h | 3 ++- pcmockup/pebblewindow.c | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 017d585..96bf863 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -35,7 +35,8 @@ void safeFramebuffer_check(SafeFramebuffer* me); typedef struct PebbleWindow PebbleWindow; PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize); void pebbleWindow_free(PebbleWindow* window); -void pebbleWindow_update(PebbleWindow* me); +void pebbleWindow_startUpdate(PebbleWindow* me); +void pebbleWindow_endUpdate(PebbleWindow* me); GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window); ImageWindow* pebbleWindow_asImageWindow(PebbleWindow* window); diff --git a/pcmockup/pebblewindow.c b/pcmockup/pebblewindow.c index fc10580..0d25f21 100644 --- a/pcmockup/pebblewindow.c +++ b/pcmockup/pebblewindow.c @@ -84,9 +84,7 @@ static inline SDL_Color prv_convertGColorTo32Bit(GColor pebbleColor) static void prv_pebbleWindow_convertPebbleToTexture(PebbleWindow* me) { const GColor* pebblePixels = pebbleWindow_getPebbleFramebuffer(me); - char* texPixels; - int texPitch; - SDL_LockTexture(me->pebbleTexture, NULL, (void**)&texPixels, &texPitch); + SDL_Color* texPixels = me->textureData; uint32_t* itTexPixel; const GColor* itPebblePixel; From 1f9ba448b0eb31cdd1567dbc752d972e8131bdeb Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 4 Dec 2018 12:08:28 +0100 Subject: [PATCH 17/19] pcmockup: replace dragging with key controls because imgui really does not like other people knowing what it does --- pcmockup/debugwindow.c | 22 +++++++++++----- pcmockup/pcmockup.c | 56 +++-------------------------------------- pcmockup/pcmockup.h | 2 +- pcmockup/pebblewindow.c | 38 ++++++++++++++++++++++++++-- 4 files changed, 56 insertions(+), 62 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index ded9bf6..cec8b09 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -28,7 +28,6 @@ SDL_Surface* createSDLSurface(int w, int h, Uint32 format) return surface; } -void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata); void debugWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata); DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) @@ -45,7 +44,6 @@ DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const De debugWindow_free(me); return NULL; } - window_setDragCallback(imageWindow_asWindow(me->window), debugWindow_onDrag, me); window_setKeyCallbacks(imageWindow_asWindow(me->window), (WindowKeyCallbacks) { .down = debugWindow_onKeyDown, .userdata = me @@ -130,17 +128,29 @@ void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata void debugWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata) { UNUSED(window); - real_t delta = real_zero; + static const float zoomSpeed = 0.1f; + static const float moveSpeed = 8.0f; + real_t zoomDelta = real_zero; + xz_t moveDelta = xz_zero; switch (sym.sym) { case (SDLK_PLUS): - case (SDLK_KP_PLUS): delta = real_from_float(0.1f); break; + case (SDLK_KP_PLUS): zoomDelta = real_from_float(zoomSpeed); break; case (SDLK_MINUS): - case (SDLK_KP_MINUS): delta = real_from_float(-0.1f); break; + case (SDLK_KP_MINUS): zoomDelta = real_from_float(-zoomSpeed); break; + case (SDLK_w): + case (SDLK_UP): moveDelta = xz(real_zero, real_from_float(-moveSpeed)); break; + case (SDLK_s): + case (SDLK_DOWN): moveDelta = xz(real_zero, real_from_float(moveSpeed)); break; + case (SDLK_a): + case (SDLK_LEFT): moveDelta = xz(real_from_float(-moveSpeed), real_zero); break; + case (SDLK_d): + case (SDLK_RIGHT): moveDelta = xz(real_from_float(moveSpeed), real_zero); break; default: return; } DebugWindow* me = (DebugWindow*)userdata; - me->zoom = real_add(me->zoom, real_mul(me->zoom, delta)); + me->position = xz_sub(me->position, xz_invScale(moveDelta, me->zoom)); + me->zoom = real_add(me->zoom, real_mul(me->zoom, zoomDelta)); debugWindow_updateOffset(me); } diff --git a/pcmockup/pcmockup.c b/pcmockup/pcmockup.c index b31c663..1a94929 100644 --- a/pcmockup/pcmockup.c +++ b/pcmockup/pcmockup.c @@ -70,7 +70,8 @@ PCMockup *pcmockup_init() me->pebbleWindow = pebbleWindow_init( me->windowContainer, windowGrid_getSingleBounds(&windowGrid, 0), - GSize(RENDERER_WIDTH, RENDERER_HEIGHT) + GSize(RENDERER_WIDTH, RENDERER_HEIGHT), + me->renderer ); if (me->pebbleWindow == NULL) { @@ -151,58 +152,7 @@ void pcmockup_update(PCMockup *me) case (SDLK_ESCAPE): { me->isRunning = 0; - } - break; - case (SDLK_w): - { - renderer_moveForward(me->renderer); - } - break; - case (SDLK_s): - { - renderer_moveBackwards(me->renderer); - } - break; - case (SDLK_a): - { - renderer_moveLeft(me->renderer); - } - break; - case (SDLK_d): - { - renderer_moveRight(me->renderer); - } - break; - case (SDLK_RIGHT): - { - renderer_rotateRight(me->renderer); - } - break; - case (SDLK_LEFT): - { - renderer_rotateLeft(me->renderer); - } - break; - case (SDLK_UP): - { - renderer_moveUp(me->renderer); - } - break; - case (SDLK_DOWN): - { - renderer_moveDown(me->renderer); - } - break; - case (SDLK_SPACE): - { - Location playerLocation; - playerLocation.angle = real_degToRad(real_from_int(0)); - playerLocation.height = real_zero; - playerLocation.position = xz(real_from_int(20), real_from_int(20)); - - renderer_moveTo(me->renderer, playerLocation); - } - break; + }break; } } windowContainer_handleEvent(me->windowContainer, &event); diff --git a/pcmockup/pcmockup.h b/pcmockup/pcmockup.h index 96bf863..9781c06 100644 --- a/pcmockup/pcmockup.h +++ b/pcmockup/pcmockup.h @@ -33,7 +33,7 @@ void safeFramebuffer_prepare(SafeFramebuffer* me); void safeFramebuffer_check(SafeFramebuffer* me); typedef struct PebbleWindow PebbleWindow; -PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize); +PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize, Renderer* renderer); void pebbleWindow_free(PebbleWindow* window); void pebbleWindow_startUpdate(PebbleWindow* me); void pebbleWindow_endUpdate(PebbleWindow* me); diff --git a/pcmockup/pebblewindow.c b/pcmockup/pebblewindow.c index 0d25f21..05e40e0 100644 --- a/pcmockup/pebblewindow.c +++ b/pcmockup/pebblewindow.c @@ -1,4 +1,5 @@ #include "pcmockup.h" +#include "platform.h" #include #include @@ -10,10 +11,13 @@ struct PebbleWindow SDL_Color* textureData; SDL_PixelFormat* texturePixelFormat; SafeFramebuffer* framebuffer; + Renderer* renderer; GSize pebbleSize; }; -PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize) +void pebbleWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata); + +PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, GSize pebbleSize, Renderer* renderer) { PebbleWindow* me = (PebbleWindow*)malloc(sizeof(PebbleWindow)); if (me == NULL) @@ -27,6 +31,10 @@ PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, pebbleWindow_free(me); return NULL; } + window_setKeyCallbacks(imageWindow_asWindow(me->window), (WindowKeyCallbacks) { + .down = pebbleWindow_onKeyDown, + .userdata = me + }); me->textureData = (SDL_Color*)malloc(sizeof(SDL_Color) * pebbleSize.w * pebbleSize.h); if (me->textureData == NULL) @@ -52,7 +60,7 @@ PebbleWindow* pebbleWindow_init(WindowContainer* parent, SDL_Rect initialBounds, } me->pebbleSize = pebbleSize; - + me->renderer = renderer; return me; } @@ -118,6 +126,32 @@ void pebbleWindow_endUpdate(PebbleWindow* me) imageWindow_setImageData(me->window, me->pebbleSize, me->textureData); } +void pebbleWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata) +{ + UNUSED(window); + PebbleWindow* me = (PebbleWindow*)userdata; + switch(sym.sym) + { + case (SDLK_w): renderer_moveForward(me->renderer); break; + case (SDLK_s): renderer_moveBackwards(me->renderer); break; + case (SDLK_a): renderer_moveLeft(me->renderer); break; + case (SDLK_d): renderer_moveRight(me->renderer); break; + case (SDLK_UP): renderer_moveUp(me->renderer); break; + case (SDLK_DOWN): renderer_moveDown(me->renderer); break; + case (SDLK_LEFT): renderer_rotateLeft(me->renderer); break; + case (SDLK_RIGHT): renderer_rotateRight(me->renderer); break; + case(SDLK_SPACE): + { + Location playerLocation; + playerLocation.angle = real_degToRad(real_from_int(0)); + playerLocation.height = real_zero; + playerLocation.position = xz(real_from_int(20), real_from_int(20)); + + renderer_moveTo(me->renderer, playerLocation); + }break; + } +} + GColor* pebbleWindow_getPebbleFramebuffer(PebbleWindow* window) { return safeFramebuffer_getScreenBuffer(window->framebuffer); From 05aaf486edb8903e50001b18eef65e8731348370 Mon Sep 17 00:00:00 2001 From: Helco Date: Tue, 4 Dec 2018 16:08:08 +0100 Subject: [PATCH 18/19] pcmockup: reintroduce dragging with MMB --- pcmockup/debugwindow.c | 4 +++- pcmockup/window.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pcmockup/debugwindow.c b/pcmockup/debugwindow.c index cec8b09..2884c56 100644 --- a/pcmockup/debugwindow.c +++ b/pcmockup/debugwindow.c @@ -28,6 +28,7 @@ SDL_Surface* createSDLSurface(int w, int h, Uint32 format) return surface; } +void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata); void debugWindow_onKeyDown(Window* window, SDL_Keysym sym, void* userdata); DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const DebugView* view, Renderer* podRenderer) @@ -44,6 +45,7 @@ DebugWindow* debugWindow_init(WindowContainer* parent, SDL_Rect bounds, const De debugWindow_free(me); return NULL; } + window_setDragCallback(imageWindow_asWindow(me->window), debugWindow_onDrag, me); window_setKeyCallbacks(imageWindow_asWindow(me->window), (WindowKeyCallbacks) { .down = debugWindow_onKeyDown, .userdata = me @@ -117,7 +119,7 @@ void debugWindow_updateOffset(DebugWindow* me) void debugWindow_onDrag(Window* window, int button, ImVec2 delta, void* userdata) { UNUSED(window); - if (button != 0) + if (button != 2) // middle mouse button return; DebugWindow* me = (DebugWindow*)userdata; xz_t move = xz_invScale((xz_t) { real_from_int(delta.x), real_from_int(delta.y) }, me->zoom); diff --git a/pcmockup/window.c b/pcmockup/window.c index c043ce6..e12f0dd 100644 --- a/pcmockup/window.c +++ b/pcmockup/window.c @@ -70,11 +70,21 @@ void window_update(Window* me) me->onUpdate.after(me, me->onUpdate.userdata); } +static bool window_shouldHandleDrag(const Window* me, int button) +{ + if (!igIsMouseDragging(button, -1.0f) || me->onDrag == NULL) + return false; + const ImVec2 dragSource = igGetIO()->MouseClickedPos[button]; + return + dragSource.x >= me->currentPos.x && dragSource.x < me->currentPos.x + me->currentSize.x && + dragSource.y >= me->currentPos.y && dragSource.y < me->currentPos.y + me->currentSize.y; +} + void window_handleDragEvent(Window* me) { for (int button = 0; button < 4; button++) { - if (!igIsMouseDragging(button, -1.0f) || me->onDrag == NULL) + if (!window_shouldHandleDrag(me, button)) { me->lastDragDelta[button] = (ImVec2) { 0, 0 }; continue; From 1fad7ca618408814deb8fcfffef9170a6de9ddfe Mon Sep 17 00:00:00 2001 From: Helco Date: Fri, 7 Dec 2018 13:59:06 +0100 Subject: [PATCH 19/19] pcmockup: tweaks --- pcmockup/window.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pcmockup/window.c b/pcmockup/window.c index e12f0dd..74c345a 100644 --- a/pcmockup/window.c +++ b/pcmockup/window.c @@ -2,6 +2,7 @@ #include "window_internal.h" #define MOUSE_BUTTON_COUNT 5 // even imgui uses this "magic" number +#define DEFAULT_MOUSE_THRESHOLD -1.0f struct Window { @@ -72,7 +73,7 @@ void window_update(Window* me) static bool window_shouldHandleDrag(const Window* me, int button) { - if (!igIsMouseDragging(button, -1.0f) || me->onDrag == NULL) + if (!igIsMouseDragging(button, DEFAULT_MOUSE_THRESHOLD) || me->onDrag == NULL) return false; const ImVec2 dragSource = igGetIO()->MouseClickedPos[button]; return @@ -82,7 +83,7 @@ static bool window_shouldHandleDrag(const Window* me, int button) void window_handleDragEvent(Window* me) { - for (int button = 0; button < 4; button++) + for (int button = 0; button < MOUSE_BUTTON_COUNT; button++) { if (!window_shouldHandleDrag(me, button)) { @@ -90,7 +91,7 @@ void window_handleDragEvent(Window* me) continue; } ImVec2 lastDelta = me->lastDragDelta[button], delta; - igGetMouseDragDelta_nonUDT(&delta, button, -1.0f); + igGetMouseDragDelta_nonUDT(&delta, button, DEFAULT_MOUSE_THRESHOLD); ImVec2 deltaDelta = { delta.x - lastDelta.x, delta.y - lastDelta.y }; me->onDrag(me, button, deltaDelta, me->onDragUserdata);