#include "cad.h" #include "cad/debug.h" #define CIMGUI_DEFINE_ENUMS_AND_STRUCTS #include "cimgui/cimgui.h" #include "cimgui/cimgui_impl.h" #include #include #include #define igGetIO igGetIO_Nil SDL_Window *window = NULL; struct smooth_line { struct component l1; struct component l2; struct component corner; struct component corner_center; struct component end; struct component start; struct component perp1; struct component perp2; struct component corner_start; struct component corner_end; }; struct smooth_line a_smooth_line() { return (struct smooth_line){ .l1 = {.type = COM_LINE}, .l2 = {.type = COM_LINE}, .corner = {.type = COM_POINT}, .corner_center = {.type = COM_POINT}, .end = {.type = COM_POINT}, .start = {.type = COM_POINT}, .perp1 = {.type = COM_LINE}, .perp2 = {.type = COM_LINE}, .corner_start = {.type = COM_POINT}, .corner_end = {.type = COM_POINT}, }; } struct box { struct component corner[4]; struct component side[4]; }; void a_box(struct box *box, struct topology *topo, struct constraints *constr) { assert(box != NULL); *box = (struct box){ .corner = { {.type = COM_POINT}, {.type = COM_POINT}, {.type = COM_POINT}, {.type = COM_POINT}, }, .side = { {.type = COM_LINE}, {.type = COM_LINE}, {.type = COM_LINE}, {.type = COM_LINE}, }, }; if(topo != NULL) { add_fragment(topo, (struct topology_elem[]){ TOPO_MOVETO(&box->corner[0]), TOPO_LINETO(&box->corner[1]), TOPO_LINETO(&box->corner[2]), TOPO_LINETO(&box->corner[3]), TOPO_LINETO(&box->corner[0]), TOPO_END(), }); } if(constr != NULL) { add_constraint(constr, (struct constraint[]){ POINT_ON_LINE(&box->corner[0], &box->side[0]), POINT_ON_LINE(&box->corner[1], &box->side[0]), POINT_ON_LINE(&box->corner[1], &box->side[1]), POINT_ON_LINE(&box->corner[2], &box->side[1]), POINT_ON_LINE(&box->corner[2], &box->side[2]), POINT_ON_LINE(&box->corner[3], &box->side[2]), POINT_ON_LINE(&box->corner[0], &box->side[3]), POINT_ON_LINE(&box->corner[3], &box->side[3]), LL_ANGLE(&box->side[3], &box->side[0], DEG(90)), LL_ANGLE(&box->side[1], &box->side[2], DEG(90)), LL_ANGLE(&box->side[2], &box->side[3], DEG(90)), CEND(), }); } } struct mid { struct component l1; struct component l2; struct component x1; struct component p1; struct component p; }; struct mid a_midpoint() { return (struct mid) { .l1 = {.type = COM_LINE}, .l2 = {.type = COM_LINE}, .x1 = {.type = COM_POINT}, .p1 = {.type = COM_LINE}, .p = {.type = COM_POINT}, }; } void draw_from_constraints(struct constraints *c, struct topology *t, struct canvas *cv) { struct drawing drawing = {}; struct subassembly assemblies[16] = {}; size_t assembly_num; solve_constraints(c, &drawing, assemblies, &assembly_num); // Copy over all the parameter values to a new array // @PERF: Maybe we should just store them in a separate array to start with double *params = malloc(sizeof(double) * (c->length)); for(size_t i = 0; i < c->length; i++) { params[i] = c->elements[i].v; } place_points(&drawing, params); free(params); print_subassemblies(c, assemblies, assembly_num); begin_drawing(cv); // for(struct command *current = drawing.root; current != NULL && current != drawing.error; current = current->next) { // if(current->hidden) continue; // plot_generic(current->result); // } // if(drawing.error != NULL) { // plot_generic(*drawing.error->arg1); // plot_generic(*drawing.error->arg2); // fprintf(stderr, "Solver error detected. Drawing will be incomplete\n"); // } draw_topology(cv, t); draw_constraints(cv, c); end_drawing(cv); free_drawing(&drawing); } int main2(int argc, char *argv[]) { struct constraints constraints = {}; struct topology topo = {}; struct component components[] = { {.type = COM_POINT}, {.type = COM_POINT}, {.type = COM_POINT}, {.type = COM_LINE}, {.type = COM_LINE}, {.type = COM_POINT}, }; add_fragment(&topo, (struct topology_elem[]){ TOPO_MOVETO(&components[1]), TOPO_LINETO(&components[5]), TOPO_LINETO(&components[0]), TOPO_LINETO(&components[2]), TOPO_LINETO(&components[1]), TOPO_END(), }); add_constraint(&constraints, (struct constraint[]){ PP_DISTANCE(&components[0], &components[1], 13), PP_DISTANCE(&components[1], &components[2], 7), PP_DISTANCE(&components[2], &components[0], 7), POINT_ON_LINE(&components[0], &components[3]), POINT_ON_LINE(&components[1], &components[3]), LL_ANGLE(&components[3], &components[4], M_PI/1.7), POINT_ON_LINE(&components[4], &components[1]), POINT_ON_LINE(&components[4], &components[5]), PP_DISTANCE(&components[0], &components[5], 12.8), CEND(), }); struct smooth_line line = a_smooth_line(); add_fragment(&topo, (struct topology_elem[]){ TOPO_MOVETO(&line.start), TOPO_LINETO(&line.corner_start), TOPO_ARCTO(&line.corner_center, &line.corner_end), TOPO_LINETO(&line.end), TOPO_END(), }); add_constraint(&constraints, (struct constraint[]){ PP_SAME(&line.start, &components[5]), LL_ANGLE(&components[3], &line.l1, DEG(90)), POINT_ON_LINE(&line.start, &line.l1), LL_ANGLE(&line.l2, &line.l1, DEG(90)), POINT_ON_LINE(&line.corner, &line.l1), POINT_ON_LINE(&line.corner, &line.l2), POINT_ON_LINE(&line.end, &line.l2), PL_DISTANCE(&line.end, &line.l1, 10), PL_DISTANCE(&line.end, &components[4], 5), PL_DISTANCE(&line.corner_center, &line.l1, 2), PL_DISTANCE(&line.corner_center, &line.l2, -2), LL_ANGLE(&line.l1, &line.perp1, DEG(90)), POINT_ON_LINE(&line.corner_center, &line.perp1), POINT_ON_LINE(&line.corner_start, &line.perp1), POINT_ON_LINE(&line.corner_start, &line.l1), LL_ANGLE(&line.l2, &line.perp2, DEG(90)), POINT_ON_LINE(&line.corner_center, &line.perp2), POINT_ON_LINE(&line.corner_end, &line.perp2), POINT_ON_LINE(&line.corner_end, &line.l2), CEND(), }); struct box box; a_box(&box, &topo, &constraints); add_constraint(&constraints, (struct constraint[]){ PP_DISTANCE(&box.corner[0], &box.corner[1], 8), PP_DISTANCE(&box.corner[1], &box.corner[2], 4), PP_DISTANCE(&line.corner_end, &box.corner[0], 9.5), PL_DISTANCE(&box.corner[0], &components[3], 20), CEND(), }); add_constraint(&constraints, (struct constraint[]){ LL_ANGLE(&components[3], &box.side[1], DEG(90)), CEND(), }); // struct mid box_enter = a_midpoint(); // add_constraint(&constraints, (struct constraint[]){ // LL_ANGLE(&box.side[3], &box_enter.l1, DEG(-30)), // POINT_ON_LINE(&box.corner[0], &box_enter.l1), // LL_ANGLE(&box.side[3], &box_enter.l2, DEG(30)), // POINT_ON_LINE(&box.corner[3], &box_enter.l2), // POINT_ON_LINE(&box_enter.l1, &box_enter.x1), // POINT_ON_LINE(&box_enter.l2, &box_enter.x1), // LL_ANGLE(&box.side[3], &box_enter.p1, DEG(90)), // POINT_ON_LINE(&box_enter.x1, &box_enter.p1), // POINT_ON_LINE(&box_enter.p, &box.side[3]), // POINT_ON_LINE(&box_enter.p1, &box_enter.p), // PP_DISTANCE(&box_enter.p, &box.corner[0], 5), // CEND(), // }); struct canvas canvas = { .state = CANVAS_INIT, .f = stdout, }; draw_from_constraints(&constraints, &topo, &canvas); free_constraints(&constraints); free_topology(&topo); return 0; } int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { SDL_Log("failed to init: %s", SDL_GetError()); return -1; } // GL 3.0 + GLSL 130 const char* glsl_version = "#version 130"; SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); // and prepare OpenGL stuff SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_DisplayMode current; SDL_GetCurrentDisplayMode(0, ¤t); float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(720 * main_scale), window_flags); if (window == NULL) { SDL_Log("Failed to create window: %s", SDL_GetError()); return -1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); // enable vsync // check opengl version sdl uses SDL_Log("opengl version: %s", (char*)glGetString(GL_VERSION)); // setup imgui igCreateContext(NULL); //set docking ImGuiIO* ioptr = igGetIO(); ioptr->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ioptr->ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Setup scaling ImGuiStyle* style = igGetStyle(); ImGuiStyle_ScaleAllSizes(style, main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) style->FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) ioptr->ConfigDpiScaleFonts = true; // [Experimental] Automatically overwrite style.FontScaleDpi in Begin() when Monitor DPI changes. This will scale fonts but _NOT_ scale sizes/padding for now. ioptr->ConfigDpiScaleViewports = true; // [Experimental] Scale Dear ImGui and Platform Windows when Monitor DPI changes. ImGui_ImplSDL2_InitForOpenGL(window, gl_context); ImGui_ImplOpenGL3_Init(glsl_version); igStyleColorsDark(NULL); //ImFontAtlas_AddFontDefault(io.Fonts, NULL); bool showDemoWindow = true; bool showAnotherWindow = false; ImVec4 clearColor; clearColor.x = 0.45f; clearColor.y = 0.55f; clearColor.z = 0.60f; clearColor.w = 1.00f; bool quit = false; while (!quit) { SDL_Event e; // we need to call SDL_PollEvent to let window rendered, otherwise // no window will be shown while (SDL_PollEvent(&e) != 0) { ImGui_ImplSDL2_ProcessEvent(&e); if (e.type == SDL_QUIT) quit = true; if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_CLOSE && e.window.windowID == SDL_GetWindowID(window)) quit = true; } // start imgui frame ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL2_NewFrame(); igNewFrame(); if (showDemoWindow) igShowDemoWindow(&showDemoWindow); // show a simple window that we created ourselves. { static float f = 0.0f; static int counter = 0; igBegin("Hello, world!", NULL, 0); igText("This is some useful text"); igCheckbox("Demo window", &showDemoWindow); igCheckbox("Another window", &showAnotherWindow); igSliderFloat("Float", &f, 0.0f, 1.0f, "%.3f", 0); igColorEdit3("clear color", (float*)&clearColor, 0); ImVec2 buttonSize; buttonSize.x = 0; buttonSize.y = 0; if (igButton("Button", buttonSize)) counter++; igSameLine(0.0f, -1.0f); igText("counter = %d", counter); igText("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / igGetIO()->Framerate, igGetIO()->Framerate); igEnd(); } if (showAnotherWindow) { igBegin("imgui Another Window", &showAnotherWindow, 0); igText("Hello from imgui"); ImVec2 buttonSize; buttonSize.x = 0; buttonSize.y = 0; if (igButton("Close me", buttonSize)) { showAnotherWindow = false; } igEnd(); } // render igRender(); SDL_GL_MakeCurrent(window, gl_context); glViewport(0, 0, (int)ioptr->DisplaySize.x, (int)ioptr->DisplaySize.y); glClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData()); if (ioptr->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow(); SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext(); igUpdatePlatformWindows(); igRenderPlatformWindowsDefault(NULL,NULL); SDL_GL_MakeCurrent(backup_current_window, backup_current_context); } SDL_GL_SwapWindow(window); } // clean up ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL2_Shutdown(); igDestroyContext(NULL); SDL_GL_DeleteContext(gl_context); if (window != NULL) { SDL_DestroyWindow(window); window = NULL; } SDL_Quit(); return 0; }