diff --git a/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.cpp b/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.cpp index ddaea9f..e4f56dc 100644 --- a/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.cpp +++ b/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.cpp @@ -87,6 +87,12 @@ constexpr studio::Selection fbPtToTileAddr( return sel; } +[[nodiscard]] +constexpr bool inside(auto const val, int const min, int const max) noexcept { + auto const v = static_cast(val); + return v < max && v > min; +}; + WorldEditorImGui::WorldEditorImGui(studio::StudioContext &sctx, ox::StringView path): Editor(path), m_sctx(sctx), @@ -245,17 +251,13 @@ void WorldEditorImGui::handleSelection(ox::Size const&paneSz, float fbPaneScale) auto const&io = ImGui::GetIO(); if (io.MouseDown[0]) { auto const fbPos = world::fbPos(ox::Vec2{io.MousePos}); - auto constexpr inside = [](auto val, int min, int max) { - auto const v = static_cast(val); - return v < max && v > min; - }; auto const startSel = io.MouseClicked[0] && inside(fbPos.x, 0, paneSz.width) && inside(fbPos.y, 0, paneSz.height); - m_selection.updateCursorPoint(fbPos, startSel); auto const scaledViewSz = static_cast(m_view.drawSize()) * fbPaneScale; + m_selection.updateCursorPoint(fbPtToTileAddr(fbPos, scaledViewSz), startSel); if (m_selection.selectionOngoing()) { - m_view.setSelection(fbPtToTileAddr(m_selection.selection(), scaledViewSz)); + m_view.setSelection(m_selection.selection()); } } else if (io.MouseReleased[0]) { m_selection.finishSelection(); @@ -273,18 +275,31 @@ ox::Error WorldEditorImGui::handleDrop(float fbPaneScale) noexcept { static_cast(viewSz.width) * fbPaneScale, static_cast(viewSz.height) * fbPaneScale}); if (tileAddr.x < m_doc.columns && tileAddr.y < m_doc.rows) { + ox::Vector mods; + if (tileSelected(tileAddr)) { + studio::iterateSelection(m_selection.selection(), [&](int32_t x, int32_t y) { + mods.emplace_back(ModifyTilesCommand::Mod{ + .layer = m_activeLayer, + .tileAddr = {x, y}, + .objId = objId.objId, + .setId = objId.setId, + }); + }); + } else { + mods = { + { + .layer = m_activeLayer, + .tileAddr = tileAddr, + .objId = objId.objId, + .setId = objId.setId, + }, + }; + } std::ignore = pushCommand( m_doc, m_worldStatic, m_objCache, - ox::Vector{ - { - .layer = m_activeLayer, - .tileAddr = tileAddr, - .objId = objId.objId, - .setId = objId.setId, - }, - }); + std::move(mods)); } oxReturnError(loadWorldStatic(m_objCache, m_doc).moveTo(m_worldStatic)); return ox::Error{}; @@ -322,9 +337,13 @@ ox::Error WorldEditorImGui::loadObjectSets() noexcept { } ox::Error WorldEditorImGui::undoStackChanged(studio::UndoCommand const*cmd) { - auto const clearSelection = dynamic_cast(cmd) != nullptr; oxReturnError(m_view.setupWorld()); return {}; } +bool WorldEditorImGui::tileSelected(ox::Point const&pt) const noexcept { + auto const sel = m_selection.selection(); + return inside(pt.x, sel.a.x, sel.b.x) && inside(pt.y, sel.a.y, sel.b.y); +} + } diff --git a/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.hpp b/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.hpp index 8ddd931..b1dabbb 100644 --- a/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.hpp +++ b/src/jasper/modules/world/src/studio/worldeditor/worldeditor-imgui.hpp @@ -85,6 +85,9 @@ class WorldEditorImGui: public studio::Editor { ox::Error loadObjectSets() noexcept; ox::Error undoStackChanged(studio::UndoCommand const*); + + [[nodiscard]] + bool tileSelected(ox::Point const&pt) const noexcept; }; }