diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 581504b..a2b164c 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -120,7 +120,8 @@ void DrawingProgram::send_transforms_for(const std::vector(t.io->theme->padding1 / 2)), @@ -131,7 +132,7 @@ void DrawingProgram::toolbar_gui() { .backgroundColor = convert_vec4(t.io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1) }) { - t.gui.obstructing_window(); + t.gui.obstructing_window(localID); if(t.gui.svg_icon_button_transparent("Brush Toolbar Button", "data/icons/brush.svg", drawTool->get_type() == DrawingProgramToolType::BRUSH)) { switch_to_tool(DrawingProgramToolType::BRUSH); } if(t.gui.svg_icon_button_transparent("Eraser Toolbar Button", "data/icons/eraser.svg", drawTool->get_type() == DrawingProgramToolType::ERASER)) { switch_to_tool(DrawingProgramToolType::ERASER); } if(t.gui.svg_icon_button_transparent("Line Toolbar Button", "data/icons/line.svg", drawTool->get_type() == DrawingProgramToolType::LINE)) { switch_to_tool(DrawingProgramToolType::LINE); } @@ -214,7 +215,8 @@ bool DrawingProgram::right_click_popup_gui(Vector2f popupPos) { void DrawingProgram::tool_options_gui() { Toolbar& t = world.main.toolbar; float minGUIWidth = drawTool->get_type() == DrawingProgramToolType::SCREENSHOT ? 300 : 200; - CLAY_AUTO_ID({ + Clay_ElementId localID = CLAY_ID_LOCAL("Drawing program tool options gui"); + CLAY(localID, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(minGUIWidth), .height = CLAY_SIZING_FIT(0)}, .padding = CLAY_PADDING_ALL(t.io->theme->padding1), @@ -225,7 +227,7 @@ void DrawingProgram::tool_options_gui() { .backgroundColor = convert_vec4(t.io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(t.io->theme->windowCorners1) }) { - t.gui.obstructing_window(); + t.gui.obstructing_window(localID); drawTool->gui_toolbox(); } } @@ -239,7 +241,14 @@ void DrawingProgram::modify_grid(const NetworkingObjects::NetObjWeakPtrhoverObstructed; + { + controls.cursorHoveringOverCanvas = true; + Vector2f mousePosGUI = world.main.input.mouse.pos / world.main.toolbar.final_gui_scale(); + for(auto& aabb : world.main.toolbar.io->hoverObstructingAABBs) + controls.cursorHoveringOverCanvas &= !SCollision::collide(mousePosGUI, aabb); + for(auto& circle : world.main.toolbar.io->hoverObstructingCircles) + controls.cursorHoveringOverCanvas &= !SCollision::collide(mousePosGUI, circle); + } controls.middleClick = controls.cursorHoveringOverCanvas && (world.main.input.mouse.middleClicks || world.main.input.pen.buttons[world.main.toolbar.tabletOptions.middleClickButton].pressed); bool middleHeld = world.main.input.mouse.middleDown || world.main.input.pen.buttons[world.main.toolbar.tabletOptions.middleClickButton].held; diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index a984348..46cb474 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -191,7 +191,7 @@ bool BrushTool::prevent_undo_or_redo() { } void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) { - if(!drawData.main->toolbar.io->hoverObstructed) { + if(drawData.main->world->drawProg.controls.cursorHoveringOverCanvas) { auto relativeWidthResult = drawP.world.main.toolConfig.get_relative_width_stroke_size(drawP, drawP.world.drawData.cam.c.inverseScale); if(relativeWidthResult.first.has_value()) { SkPaint linePaint; diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 4e0b068..374ba6e 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -96,7 +96,7 @@ bool EraserTool::prevent_undo_or_redo() { } void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { - if(!drawData.main->toolbar.io->hoverObstructed) { + if(drawData.main->world->drawProg.controls.cursorHoveringOverCanvas) { auto relativeWidthResult = drawP.world.main.toolConfig.get_relative_width_stroke_size(drawP, drawP.world.drawData.cam.c.inverseScale); if(relativeWidthResult.first.has_value()) { float width = relativeWidthResult.first.value() * 0.5f; diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index f30fcfb..5647604 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -102,6 +102,8 @@ struct UpdateInputData { std::string textInput; bool hoverObstructed = false; + std::vector> hoverObstructingAABBs; + std::vector> hoverObstructingCircles; bool acceptingTextInput = false; float deltaTime = 0.0f; diff --git a/src/GUIStuff/Elements/FontPicker.cpp b/src/GUIStuff/Elements/FontPicker.cpp index a0089ac..23863b3 100644 --- a/src/GUIStuff/Elements/FontPicker.cpp +++ b/src/GUIStuff/Elements/FontPicker.cpp @@ -78,7 +78,8 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU clickedOut = false; } if(dropdownOpen) { - CLAY_AUTO_ID({ + Clay_ElementId localID = CLAY_ID_LOCAL("Font picker floating element"); + CLAY(localID, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(250), .height = CLAY_SIZING_FIT(0, 300)}, .layoutDirection = CLAY_TOP_TO_BOTTOM @@ -100,7 +101,7 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU .width = CLAY_BORDER_OUTSIDE(1) } }) { - gui->obstructing_window(); + gui->obstructing_window(localID); if(Clay_Hovered()) clickedOut = false; gui->scroll_bar_many_entries_area("Font Selector", ENTRY_HEIGHT, sortedFontList.size(), true, [fontName, gui, &fontChangedFromSelection, &sortedFontList = sortedFontList, val, &io = io](size_t i, bool listHovered) { diff --git a/src/GUIStuff/Elements/PaintCircleMenu.cpp b/src/GUIStuff/Elements/PaintCircleMenu.cpp index 6fde436..65b8d9b 100644 --- a/src/GUIStuff/Elements/PaintCircleMenu.cpp +++ b/src/GUIStuff/Elements/PaintCircleMenu.cpp @@ -1,6 +1,7 @@ #include "PaintCircleMenu.hpp" #include "Helpers/ConvertVec.hpp" #include +#include "../GUIManager.hpp" namespace GUIStuff { @@ -10,7 +11,8 @@ constexpr float CIRCLE_END = 150.0f; constexpr double ROTATE_BAR_SNAP_DISTANCE = 0.2; constexpr double ROTATE_BAR_SNAP_DISTRIBUTION = std::numbers::pi * 0.25; -void PaintCircleMenu::update(UpdateInputData& io, const Data& data, const std::function& elemUpdate) { +void PaintCircleMenu::update(GUIManager& gui, const Data& data, const std::function& elemUpdate) { + auto& io = *gui.io; CLAY_AUTO_ID({.layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)} }, @@ -19,7 +21,6 @@ void PaintCircleMenu::update(UpdateInputData& io, const Data& data, const std::f bool isHoveredNoObstruction = Clay_Hovered() && !io.hoverObstructed; Vector2f vecFromCenter = (io.mouse.pos - bb.center()).normalized(); float distFromCenter = vec_distance(io.mouse.pos, bb.center()); - bool rotateHovered = false; if(data.newRotationAngle) { rotateBarSelect.update(isHoveredNoObstruction && distFromCenter > ROTATE_START && distFromCenter < CIRCLE_END, io.mouse.leftClick, io.mouse.leftHeld); if(rotateBarSelect.held) { @@ -38,9 +39,7 @@ void PaintCircleMenu::update(UpdateInputData& io, const Data& data, const std::f } else *data.newRotationAngle = data.currentRotationAngle; - rotateHovered = rotateBarSelect.hovered; } - bool colorHovered = false; if(!data.palette.empty() && data.selectedColor) { colorBarSelect.update(isHoveredNoObstruction && distFromCenter > PALETTE_START && distFromCenter < ROTATE_START, io.mouse.leftClick, io.mouse.leftHeld); if(colorBarSelect.hovered) { @@ -54,9 +53,9 @@ void PaintCircleMenu::update(UpdateInputData& io, const Data& data, const std::f selectedColor.z() = data.palette[colorSelectionIndex].z(); } } - colorHovered = colorBarSelect.hovered; } - if(rotateHovered || colorHovered) + io.hoverObstructingCircles.emplace_back(bb.center() + gui.windowPos, CIRCLE_END); + if(SCollision::collide(io.hoverObstructingCircles.back(), io.mouse.pos)) io.hoverObstructed = true; if(elemUpdate) elemUpdate(); @@ -72,6 +71,9 @@ void PaintCircleMenu::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_Rend draw_rotate_bar(canvas, io); draw_palette_bar(canvas, io); + SkPaint p; + p.setColor4f(color_mul_alpha(io.theme->backColor1, 0.5f)); + canvas->drawCircle(0.0f, 0.0f, PALETTE_START, p); canvas->restore(); } diff --git a/src/GUIStuff/Elements/PaintCircleMenu.hpp b/src/GUIStuff/Elements/PaintCircleMenu.hpp index ea241cc..1bb6a77 100644 --- a/src/GUIStuff/Elements/PaintCircleMenu.hpp +++ b/src/GUIStuff/Elements/PaintCircleMenu.hpp @@ -3,6 +3,8 @@ namespace GUIStuff { + class GUIManager; + class PaintCircleMenu : public Element { public: struct Data { @@ -11,7 +13,7 @@ class PaintCircleMenu : public Element { Vector4f* selectedColor = nullptr; std::vector palette; }; - void update(UpdateInputData& io, const Data& data, const std::function& elemUpdate); + void update(GUIManager& gui, const Data& data, const std::function& elemUpdate); virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; private: void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io); diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index 067b2c5..790449e 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -246,8 +246,8 @@ void GUIManager::draw(SkCanvas* canvas) { canvas->restore(); } -void GUIManager::top_to_bottom_window_popup_layout(Clay_SizingAxis x, Clay_SizingAxis y, const std::function& elemUpdate) { - CLAY_AUTO_ID({.layout = { +void GUIManager::top_to_bottom_window_popup_layout(const Clay_ElementId& windowLocalID, Clay_SizingAxis x, Clay_SizingAxis y, const std::function& elemUpdate) { + CLAY(windowLocalID, {.layout = { .sizing = {.width = x, .height = y }, .padding = CLAY_PADDING_ALL(io->theme->padding1), .childGap = io->theme->childGap1, @@ -258,8 +258,7 @@ void GUIManager::top_to_bottom_window_popup_layout(Clay_SizingAxis x, Clay_Sizin .floating = { .attachTo = CLAY_ATTACH_TO_PARENT }, .border = {.color = convert_vec4(io->theme->fillColor2), .width = CLAY_BORDER_OUTSIDE(1)} }) { - if(Clay_Hovered()) - io->hoverObstructed = true; + obstructing_window(windowLocalID); elemUpdate(); } } @@ -623,7 +622,7 @@ void GUIManager::dropdown_select(const char* id, size_t* val, const std::vector< .width = CLAY_BORDER_OUTSIDE(1) } }) { - obstructing_window(); + obstructing_window(localID); scroll_bar_many_entries_area("dropdown scroll area", 18.0f, selections.size(), true, [&](size_t i, bool) { bool selectedEntry = *val == i; @@ -851,7 +850,7 @@ void GUIManager::paint_circle_popup_menu(const char* id, const Vector2f& centerP } }) { PaintCircleMenu* e = insert_element(); - e->update(*io, val, elemUpdate); + e->update(*this, val, elemUpdate); } pop_id(); } @@ -890,7 +889,7 @@ void GUIManager::list_popup_menu(const char* id, Vector2f popupPos, const std::f .attachTo = CLAY_ATTACH_TO_ROOT } }) { - obstructing_window(); + obstructing_window(localID); push_id(1); elemUpdate(); pop_id(); @@ -905,9 +904,11 @@ void GUIManager::tree_listing(const char* id, NetworkingObjects::NetObjID rootOb pop_id(); } -void GUIManager::obstructing_window() { +void GUIManager::obstructing_window(const Clay_ElementId& elementID) { if(Clay_Hovered()) io->hoverObstructed = true; + const Clay_ElementData& elemData = Clay_GetElementData(elementID); + io->hoverObstructingAABBs.emplace_back(SCollision::AABB{Vector2f{elemData.boundingBox.x, elemData.boundingBox.y} + windowPos, Vector2f{elemData.boundingBox.x + elemData.boundingBox.width, elemData.boundingBox.y + elemData.boundingBox.height} + windowPos}); } void GUIManager::clay_error_handler(Clay_ErrorData errorData) { diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index abe8fe2..4beb21e 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -69,7 +69,7 @@ class GUIManager { bool rotate_wheel(const char* id, double* angle, float size = BIG_BUTTON_SIZE, const std::function& elemUpdate = nullptr); - void top_to_bottom_window_popup_layout(Clay_SizingAxis x, Clay_SizingAxis y, const std::function& elemUpdate); + void top_to_bottom_window_popup_layout(const Clay_ElementId& localID, Clay_SizingAxis x, Clay_SizingAxis y, const std::function& elemUpdate); void left_to_right_layout(Clay_SizingAxis x, Clay_SizingAxis y, const std::function& elemUpdate); void left_to_right_line_layout(const std::function& elemUpdate); void left_to_right_line_centered_layout(const std::function& elemUpdate); @@ -104,7 +104,7 @@ class GUIManager { void tree_listing(const char* id, NetworkingObjects::NetObjID rootObjID, const TreeListing::DisplayData& displayData, TreeListing::SelectionData& selectionData); - void obstructing_window(); + void obstructing_window(const Clay_ElementId& elementID); template NewElement* insert_element() { auto [it, inserted] = elements.emplace(idStack, ElementContainer()); @@ -317,7 +317,7 @@ class GUIManager { if(clicked) isOpen = true; if(isOpen) { - top_to_bottom_window_popup_layout(CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&]() { + top_to_bottom_window_popup_layout(CLAY_ID_LOCAL("COLOR PICKER"), CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&]() { isUpdating = color_picker_items("c", val, selectAlpha); if(io->mouse.leftClick && !Clay_Hovered() && !clicked) isOpen = false; diff --git a/src/InputManager.hpp b/src/InputManager.hpp index b7b918b..18c42b1 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -72,6 +72,12 @@ struct InputManager { friend struct InputManager; } mouse; + struct Touch { + bool isDown = false; + int leftClicksSaved = 0; + std::chrono::steady_clock::time_point lastLeftClickTime; + } touch; + struct Pen { bool inProximity = false; bool isDown = false; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 5e1d7ca..4992cae 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -33,6 +33,7 @@ #endif #include +#include "DrawCollision.hpp" MainProgram::MainProgram(): fonts(std::make_shared()), diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 36cb0e5..eeb4dfb 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -494,7 +494,8 @@ void Toolbar::close_popup_gui() { std::erase_if(closePopupData.worldsToClose, [](auto& wPair) { return wPair.w.expired(); }); - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT CLOSE POPUP"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0, 600) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -506,7 +507,7 @@ void Toolbar::close_popup_gui() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.zIndex = 1, .attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("Close single file popup gui"); gui.text_label("Files may contain unsaved changes"); gui.scroll_bar_area("close file popup gui scroll area", false, [&](float, float, float &) { @@ -614,7 +615,8 @@ void Toolbar::paint_popup(Vector2f popupPos) { } void Toolbar::top_toolbar() { - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT TOP TOOLBAR"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(static_cast(io->theme->padding1 / 2)), @@ -625,7 +627,7 @@ void Toolbar::top_toolbar() { .backgroundColor = convert_vec4(io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1) }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("menu top toolbar"); global_log(); bool menuPopUpJustOpen = false; @@ -701,7 +703,8 @@ void Toolbar::top_toolbar() { layer_menu(layerMenuPopUpJustOpen); } if(menuPopUpOpen) { - CLAY_AUTO_ID({ + Clay_ElementId menuPopupId = CLAY_ID_LOCAL("Menu Popup"); + CLAY(menuPopupId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(100), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -713,7 +716,7 @@ void Toolbar::top_toolbar() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_TOP, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(menuPopupId); if(gui.text_button_left_transparent("new file local", "New File")) { main.new_tab({ .isClient = false @@ -796,7 +799,8 @@ void Toolbar::top_toolbar() { } void Toolbar::web_version_welcome() { - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("Web version welcome"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(700), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -808,7 +812,7 @@ void Toolbar::web_version_welcome() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("web version welcome gui"); gui.text_label_centered("Welcome to the web version of InfiniPaint!"); gui.text_label( @@ -905,7 +909,8 @@ void Toolbar::update_notification_check() { } void Toolbar::update_notification_gui() { - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("UPDATE NOTIFICATION GUI"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(700), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -917,7 +922,7 @@ void Toolbar::update_notification_gui() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("update notification gui"); gui.text_label_centered("Update v" + updateCheckerData.newVersionStr + " available!"); if(gui.text_button_wide("download", "Open download page in web browser")) { @@ -938,7 +943,8 @@ void Toolbar::update_notification_gui() { void Toolbar::grid_menu(bool justOpened) { if(main.world->gridMan.grids) { gui.push_id("grid menu"); - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT GRID MENU"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -950,7 +956,7 @@ void Toolbar::grid_menu(bool justOpened) { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.text_label_centered("Grids"); float entryHeight = 25.0f; if(main.world->gridMan.grids->empty()) @@ -1032,7 +1038,8 @@ void Toolbar::stop_displaying_grid_menu() { void Toolbar::bookmark_menu(bool justOpened) { gui.push_id("bookmark menu"); - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT BOOKMARK MENU"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1044,7 +1051,7 @@ void Toolbar::bookmark_menu(bool justOpened) { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.text_label_centered("Bookmarks"); main.world->bMan.setup_list_gui("bookmark menu list"); if(io->mouse.leftClick && !Clay_Hovered() && !justOpened) { @@ -1057,7 +1064,8 @@ void Toolbar::bookmark_menu(bool justOpened) { void Toolbar::layer_menu(bool justOpened) { gui.push_id("layer menu"); - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT LAYER MENU"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0, 600) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1069,7 +1077,7 @@ void Toolbar::layer_menu(bool justOpened) { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.text_label_centered("Layers"); bool hoveringOverDropdown = false; main.world->drawProg.layerMan.listGUI.setup_list_gui("layer menu list", hoveringOverDropdown); @@ -1111,13 +1119,14 @@ std::unique_ptr Toolbar::build_paragraph_from_chat_ void Toolbar::chat_box() { constexpr float CHATBOX_WIDTH = 700; if(main.world->netObjMan.is_connected()) { - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT CHAT BOX OPEN BUTTON"); + CLAY(localId, { .layout = { .layoutDirection = CLAY_LEFT_TO_RIGHT }, .floating = {.offset = {static_cast(io->theme->padding1), -static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("chat box open button"); if(gui.svg_icon_button("Chat Open Button", "data/icons/chat.svg", chatBoxState != CHATBOXSTATE_CLOSE)) { if(chatBoxState == CHATBOXSTATE_CLOSE) @@ -1128,7 +1137,8 @@ void Toolbar::chat_box() { gui.pop_id(); } } - CLAY_AUTO_ID({ + Clay_ElementId localId = CLAY_ID_LOCAL("INFINIPAINT CHAT BOX OPEN"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(CHATBOX_WIDTH), .height = CLAY_SIZING_FIT(0) }, .childGap = 0, @@ -1137,7 +1147,7 @@ void Toolbar::chat_box() { }, .floating = {.offset = {60 + static_cast(io->theme->padding1), -static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_LEFT_BOTTOM, .parent = CLAY_ATTACH_POINT_LEFT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(localId); gui.push_id("chat box"); if(chatBoxState == CHATBOXSTATE_JUSTOPEN || chatBoxState == CHATBOXSTATE_OPEN) { gui.push_id("messages"); @@ -1196,7 +1206,8 @@ void Toolbar::chat_box() { chatMessage.time.update_time_since(); if(chatMessage.time < DISPLAY_TIME) { float a = 1.0f - lerp_time(chatMessage.time, DISPLAY_TIME, FADE_START_TIME); - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_IDI_LOCAL("CHAT MESSAGE ID", id); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(0), @@ -1207,7 +1218,7 @@ void Toolbar::chat_box() { .backgroundColor = convert_vec4(color_mul_alpha(io->theme->backColor1, a)), }) { gui.push_id(id); - gui.obstructing_window(); + gui.obstructing_window(elemId); gui.text_paragraph("text", build_paragraph_from_chat_message(chatMessage, a), CHATBOX_WIDTH); gui.pop_id(); } @@ -1236,7 +1247,8 @@ void Toolbar::global_log() { logM.time.update_time_since(); if(logM.time < DISPLAY_TIME) { float a = 1.0f - lerp_time(logM.time, DISPLAY_TIME, FADE_START_TIME); - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("GLOBAL LOG"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1247,7 +1259,7 @@ void Toolbar::global_log() { .backgroundColor = convert_vec4(color_mul_alpha(io->theme->backColor1, a)), .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1) }) { - gui.obstructing_window(); + gui.obstructing_window(elemId); SkColor4f c{0, 0, 0, 0}; switch(logM.color) { case LogMessage::COLOR_NORMAL: @@ -1283,7 +1295,8 @@ void Toolbar::drawing_program_gui() { .padding = {.top = 40, .bottom = 40} } }) { - CLAY_AUTO_ID({ + auto localId = CLAY_ID_LOCAL("Drawing program gui color picker left"); + CLAY(localId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0)}, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1294,7 +1307,7 @@ void Toolbar::drawing_program_gui() { .backgroundColor = convert_vec4(io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1) }) { - gui.obstructing_window(); + gui.obstructing_window(localId); isUpdatingColorLeft |= gui.color_picker_items("colorpickerleft", colorLeft, true, 300.0f - io->theme->padding1 * 2.0f); bool hoveringOnDropdown = false; isUpdatingColorLeft |= color_palette("colorpickerleftpalette", colorLeft, hoveringOnDropdown); @@ -1314,7 +1327,8 @@ void Toolbar::drawing_program_gui() { .padding = {.top = 40, .bottom = 40} } }) { - CLAY_AUTO_ID({ + auto localID = CLAY_ID_LOCAL("Drawing program gui color picker right"); + CLAY(localID, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(300), .height = CLAY_SIZING_FIT(0)}, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1325,7 +1339,7 @@ void Toolbar::drawing_program_gui() { .backgroundColor = convert_vec4(io->theme->backColor1), .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1) }) { - gui.obstructing_window(); + gui.obstructing_window(localID); isUpdatingColorRight |= gui.color_picker_items("colorpickerright", colorRight, true, 300.0f - io->theme->padding1 * 2.0f); bool hoveringOnDropdown = false; isUpdatingColorRight |= color_palette("colorpickerrightpalette", colorRight, hoveringOnDropdown); @@ -1506,7 +1520,8 @@ void Toolbar::performance_metrics() { } void Toolbar::player_list() { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT PLAYER LIST"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(500), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1518,7 +1533,7 @@ void Toolbar::player_list() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(elemId); gui.push_id("client list"); gui.text_label_centered("Player List"); if(!main.world->clientStillConnecting) { @@ -1599,7 +1614,8 @@ void Toolbar::options_menu() { switch(optionsMenuType) { case HOST_MENU: case CONNECT_MENU: { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT CONNECT MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(650), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1611,7 +1627,7 @@ void Toolbar::options_menu() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(elemId); if(optionsMenuType == HOST_MENU) { gui.push_id("host menu"); std::string oldS = serverToConnectTo; @@ -1666,7 +1682,8 @@ void Toolbar::options_menu() { .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.push_id("gsettings"); - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT GENERAL SETTINGS MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1675,7 +1692,7 @@ void Toolbar::options_menu() { .layoutDirection = CLAY_LEFT_TO_RIGHT } }) { - gui.obstructing_window(); + gui.obstructing_window(elemId); CLAY_AUTO_ID({ .layout = { .sizing = {.width = CLAY_SIZING_FIT(150), .height = CLAY_SIZING_GROW(0) }, @@ -1913,7 +1930,8 @@ void Toolbar::options_menu() { break; } case LOBBY_INFO_MENU: { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT LOBBY INFO MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(650), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1926,7 +1944,7 @@ void Toolbar::options_menu() { .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.push_id("lobby info menu"); - gui.obstructing_window(); + gui.obstructing_window(elemId); if(!main.world || !main.world->netObjMan.is_connected()) optionsMenuOpen = false; else { @@ -1945,7 +1963,8 @@ void Toolbar::options_menu() { break; } case CANVAS_SETTINGS_MENU: { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT CANVAS SETTINGS MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(500), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1958,7 +1977,7 @@ void Toolbar::options_menu() { .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.push_id("canvas settings menu"); - gui.obstructing_window(); + gui.obstructing_window(elemId); SkColor4f newColorToSet = main.world->canvasTheme.get_back_color(); gui.color_picker_button_field("canvasColor", "Canvas Color", &newColorToSet, false); main.world->canvasTheme.set_back_color(convert_vec3(newColorToSet)); @@ -1969,7 +1988,8 @@ void Toolbar::options_menu() { break; } case SET_DOWNLOAD_NAME: { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT DOWNLOAD NAME MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIT(500), .height = CLAY_SIZING_FIT(0) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -1982,7 +2002,7 @@ void Toolbar::options_menu() { .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.push_id("set download name menu"); - gui.obstructing_window(); + gui.obstructing_window(elemId); if(!main.world) optionsMenuOpen = false; gui.input_text_field("file name", "File Name", &downloadNameSet); @@ -2006,7 +2026,8 @@ void Toolbar::options_menu() { } void Toolbar::about_menu_gui() { - CLAY_AUTO_ID({ + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT ABOUT MENU"); + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(700), .height = CLAY_SIZING_FIXED(600) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -2019,7 +2040,7 @@ void Toolbar::about_menu_gui() { .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.push_id("about menu popup"); - gui.obstructing_window(); + gui.obstructing_window(elemId); gui.left_to_right_line_layout([&]() { gui.push_id("Menu Selector"); CLAY_AUTO_ID({ @@ -2088,8 +2109,9 @@ void Toolbar::reload_theme_list() { void Toolbar::file_picker_gui() { gui.push_id("filepicker"); + Clay_ElementId elemId = CLAY_ID_LOCAL("INFINIPAINT FILE PICKER MENU"); bool isDoneByDoubleClick = false; - CLAY_AUTO_ID({ + CLAY(elemId, { .layout = { .sizing = {.width = CLAY_SIZING_FIXED(700), .height = CLAY_SIZING_FIXED(500) }, .padding = CLAY_PADDING_ALL(io->theme->padding1), @@ -2101,7 +2123,7 @@ void Toolbar::file_picker_gui() { .cornerRadius = CLAY_CORNER_RADIUS(io->theme->windowCorners1), .floating = {.attachPoints = {.element = CLAY_ATTACH_POINT_CENTER_CENTER, .parent = CLAY_ATTACH_POINT_CENTER_CENTER}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { - gui.obstructing_window(); + gui.obstructing_window(elemId); gui.text_label_centered(filePicker.filePickerWindowName); gui.left_to_right_line_layout([&]() { if(gui.svg_icon_button("file picker back button", "data/icons/backarrow.svg", false, 30.0f)) { @@ -2274,6 +2296,8 @@ void Toolbar::start_gui() { } gui.io = io; io->hoverObstructed = false; + io->hoverObstructingAABBs.clear(); + io->hoverObstructingCircles.clear(); gui.begin(); } diff --git a/src/World.cpp b/src/World.cpp index 3cc37e6..4c15b0a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -165,6 +165,9 @@ void World::init_client(const std::string& serverFullID) { } void World::focus_update() { + mousePreviousWorldVec = drawData.cam.c.from_space(main.input.mouse.pos); + mouseWorldMove = drawData.cam.c.from_space(main.input.mouse.move); + connection_update(); if(setToDestroy) return; @@ -189,9 +192,6 @@ void World::focus_update() { rMan.update(); - mousePreviousWorldVec = drawData.cam.c.from_space(main.input.mouse.pos); - mouseWorldMove = drawData.cam.c.from_space(main.input.mouse.move); - if(main.input.key(InputManager::KEY_UNDO).repeat) undo_with_checks(); else if(main.input.key(InputManager::KEY_REDO).repeat) diff --git a/src/main.cpp b/src/main.cpp index 33a93dc..422f2a0 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -197,6 +197,8 @@ void get_refresh_rate(MainStruct& mS) { void initialize_sdl(MainStruct& mS, int wWidth, int wHeight) { SDL_SetHint(SDL_HINT_APP_NAME, "InfiniPaint"); SDL_SetHint(SDL_HINT_PEN_MOUSE_EVENTS, "0"); + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); SDL_SetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT, "#canvas"); // Ensures that SDL only grabs input when browser is focused on canvas if(!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) @@ -602,6 +604,24 @@ void attempt_redraw_and_swap_buffers(MainStruct& mS) { } } +void regular_draw(MainStruct& mS) { + mS.lastRenderTimePoint = std::chrono::steady_clock::now(); + + mS.intermediateCanvas->save(); + mS.m->draw(mS.intermediateCanvas, mS.m->world, mS.m->world->drawData); + mS.intermediateCanvas->restore(); + + #ifdef USE_BACKEND_VULKAN + mS.vulkanWindowContext->getBackbufferSurface()->getCanvas()->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); + mS.ctx->flushAndSubmit(); + mS.vulkanWindowContext->swapBuffers(); + #elif USE_BACKEND_OPENGL + mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); + mS.ctx->flushAndSubmit(); + SDL_GL_SwapWindow(mS.window); + #endif +} + SDL_AppResult SDL_AppIterate(void *appstate) { std::chrono::steady_clock::time_point frameTimeStart = std::chrono::steady_clock::now(); @@ -645,8 +665,9 @@ SDL_AppResult SDL_AppIterate(void *appstate) { SDL_StopTextInput(mS.window); mS.m->input.text.lastAcceptingTextInputVal = mS.m->input.text.get_accepting_input(); - cpu_save_sleep(mS); - attempt_redraw_and_swap_buffers(mS); + //cpu_save_sleep(mS); + //attempt_redraw_and_swap_buffers(mS); + regular_draw(mS); mS.m->input.frame_reset(mS.m->window.size); #ifdef NDEBUG @@ -815,6 +836,32 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { //mS.m->input.mouse.set_pos({event->pbutton.x, event->pbutton.y}); break; } + case SDL_EVENT_FINGER_DOWN: { + mS.m->update_scale_and_density(); + mS.m->input.touch.isDown = true; + mS.m->input.mouse.leftDown = true; + if((std::chrono::steady_clock::now() - mS.m->input.touch.lastLeftClickTime) > std::chrono::milliseconds(300)) + mS.m->input.touch.leftClicksSaved = 0; + mS.m->input.touch.leftClicksSaved++; + mS.m->input.mouse.leftClicks = mS.m->input.touch.leftClicksSaved; + mS.m->input.touch.lastLeftClickTime = std::chrono::steady_clock::now(); + mS.m->input.mouse.set_pos({event->tfinger.x * mS.m->window.size.x() * mS.m->window.density, event->tfinger.y * mS.m->window.size.y() * mS.m->window.density}); + mS.m->input.mouse.move = Vector2f{0.0f, 0.0f}; + break; + } + case SDL_EVENT_FINGER_UP: { + mS.m->update_scale_and_density(); + mS.m->input.touch.isDown = false; + mS.m->input.mouse.leftDown = false; + mS.m->input.mouse.set_pos({-1.0f, -1.0f}); + mS.m->input.mouse.move = Vector2f{0.0f, 0.0f}; + break; + } + case SDL_EVENT_FINGER_MOTION: { + mS.m->update_scale_and_density(); + mS.m->input.mouse.set_pos({event->tfinger.x * mS.m->window.size.x() * mS.m->window.density, event->tfinger.y * mS.m->window.size.y() * mS.m->window.density}); + break; + } case SDL_EVENT_DISPLAY_ORIENTATION: case SDL_EVENT_DISPLAY_ADDED: case SDL_EVENT_DISPLAY_REMOVED: