Translation works on selection

This commit is contained in:
Yousef Khadadeh 2025-07-24 19:35:51 +03:00
parent ff1355234f
commit 759f551cd3
9 changed files with 119 additions and 55 deletions

View file

@ -22,19 +22,7 @@
#include "../World.hpp"
#include "../MainProgram.hpp"
#include <Helpers/Logger.hpp>
#include <execution>
#ifdef __APPLE__
#define POOLSTL_STD_SUPPLEMENT
#include <poolstl.hpp>
#endif
template <typename ContainerType> void parallel_loop_container(ContainerType& c, std::function<void(typename ContainerType::value_type&)> func) {
#ifdef __EMSCRIPTEN__
std::for_each(c.begin(), c.end(), func);
#else
std::for_each(std::execution::par_unseq, c.begin(), c.end(), func);
#endif
}
#include <Helpers/Parallel.hpp>
DrawingProgram::DrawingProgram(World& initWorld):
world(initWorld),
@ -444,7 +432,6 @@ void DrawingProgram::reset_tools() {
ellipseDrawTool.reset_tool();
editTool.reset_tool();
eraserTool.reset_tool();
reset_selection();
}
void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a) {
@ -464,11 +451,6 @@ void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a)
compCache.force_rebuild(components.client_list());
}
void DrawingProgram::reset_selection() {
for(auto& c : components.client_list())
c->obj->selected = false;
}
void DrawingProgram::add_undo_place_component(uint64_t placement, const std::shared_ptr<DrawComponent>& comp) {
world.undo.push(UndoManager::UndoRedoPair{
[&, comp]() {
@ -573,8 +555,9 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
drawProgCacheCanvas->clear(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f});
compCache.refresh_all_draw_cache(drawData);
compCache.draw_components_to_canvas(drawProgCacheCanvas, drawData);
selection.draw_components(drawProgCacheCanvas, drawData);
canvas->drawImage(world.main.drawProgCache.surface->makeTemporaryImage(), 0, 0);
selection.draw(canvas, drawData);
selection.draw_gui(canvas, drawData);
}
}

View file

@ -68,7 +68,6 @@ class DrawingProgram {
void add_file_to_canvas_by_path_execute(const std::string& filePath, Vector2f dropPos);
void reset_selection();
void reset_tools();
void drag_drop_update();
@ -135,4 +134,5 @@ class DrawingProgram {
friend class EditTool;
friend class ImageTool;
friend class DrawingProgramCache;
friend class DrawingProgramSelection;
};

View file

@ -2,6 +2,9 @@
#include "DrawingProgram.hpp"
#include "../World.hpp"
#include "../MainProgram.hpp"
#include <Helpers/MathExtras.hpp>
#include <Helpers/SCollision.hpp>
#include <Helpers/Parallel.hpp>
DrawingProgramSelection::DrawingProgramSelection(DrawingProgram& initDrawP):
cache(initDrawP),
@ -56,21 +59,24 @@ bool DrawingProgramSelection::is_something_selected() {
void DrawingProgramSelection::calculate_aabb() {
if(is_something_selected()) {
selectionAABB = (*selectedSet.begin())->obj->worldAABB.value();
initialSelectionAABB = (*selectedSet.begin())->obj->worldAABB.value();
for(auto& c : selectedSet)
selectionAABB.include_aabb_in_bounds(c->obj->worldAABB.value());
initialSelectionAABB.include_aabb_in_bounds(c->obj->worldAABB.value());
}
}
void DrawingProgramSelection::deselect_all() {
for(auto& obj : selectedSet) {
obj->obj->coords = selectionTransformCoords.other_coord_space_from_this_space(obj->obj->coords);
obj->obj->final_update(drawP);
if(is_something_selected()) {
std::vector<CollabListType::ObjectInfoPtr> a(selectedSet.begin(), selectedSet.end());
parallel_loop_container(a, [&](auto& obj) {
obj->obj->coords = selectionTransformCoords.other_coord_space_from_this_space(obj->obj->coords);
obj->obj->final_update(drawP, false);
});
selectedSet.clear();
cache.clear();
selectionTransformCoords = CoordSpaceHelper();
drawP.compCache.force_rebuild(drawP.components.client_list());
}
selectedSet.clear();
cache.clear();
selectionTransformCoords = CoordSpaceHelper();
drawP.compCache.force_rebuild(drawP.components.client_list());
}
void DrawingProgramSelection::update() {
@ -79,26 +85,39 @@ void DrawingProgramSelection::update() {
cache.force_rebuild(std::vector<CollabListType::ObjectInfoPtr>(selectedSet.begin(), selectedSet.end()));
if(drawP.world.main.input.key(InputManager::KEY_DRAW_UNSELECT).pressed)
deselect_all();
if(drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held)
selectionTransformCoords.translate(WorldVec{0, -drawP.world.drawData.cam.c.inverseScale});
if(drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held)
selectionTransformCoords.translate(WorldVec{0, drawP.world.drawData.cam.c.inverseScale});
if(drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held)
selectionTransformCoords.translate(WorldVec{-drawP.world.drawData.cam.c.inverseScale, 0});
if(drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held)
selectionTransformCoords.translate(WorldVec{drawP.world.drawData.cam.c.inverseScale, 0});
if(drawP.world.main.input.key(InputManager::KEY_TEXT_CTRL).held)
selectionTransformCoords.scale_about_double(selectionTransformCoords.pos, 1.01);
if(drawP.world.main.input.key(InputManager::KEY_TEXT_SHIFT).held)
selectionTransformCoords.scale_about_double(selectionTransformCoords.pos, 0.99);
selectionRectMin = selectionTransformCoords.from_space_world(initialSelectionAABB.min);
selectionRectMax = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
rebuild_cam_space();
if(drawP.controls.leftClick && mouse_collided_with_selection_aabb())
translation.happening = true;
else if(drawP.controls.leftClickHeld && translation.happening)
selectionTransformCoords.translate(drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.input.mouse.move));
else
translation.happening = false;
}
}
bool DrawingProgramSelection::mouse_collided_with_selection_aabb() {
return false;
void DrawingProgramSelection::rebuild_cam_space() {
std::array<WorldVec, 4> collideRectTriangleVerticesWorld = triangle_from_rect_points(selectionRectMin, selectionRectMax);
SCollision::ColliderCollection<WorldScalar> collideRectWorld;
collideRectWorld.triangle.emplace_back(collideRectTriangleVerticesWorld[0], collideRectTriangleVerticesWorld[1], collideRectTriangleVerticesWorld[2]);
collideRectWorld.triangle.emplace_back(collideRectTriangleVerticesWorld[0], collideRectTriangleVerticesWorld[2], collideRectTriangleVerticesWorld[3]);
collideRectWorld.recalculate_bounds();
camSpaceSelection = drawP.world.drawData.cam.c.world_collider_to_coords<SCollision::ColliderCollection<float>>(collideRectWorld);
}
void DrawingProgramSelection::draw(SkCanvas* canvas, const DrawData& drawData) {
bool DrawingProgramSelection::mouse_collided_with_selection_aabb() {
return SCollision::collide(camSpaceSelection, drawP.world.main.input.mouse.pos);
}
void DrawingProgramSelection::draw_components(SkCanvas* canvas, const DrawData& drawData) {
if(is_something_selected()) {
DrawData selectionDrawData = drawData;
selectionDrawData.cam.c = selectionTransformCoords.other_coord_space_to_this_space(selectionDrawData.cam.c);
@ -107,13 +126,20 @@ void DrawingProgramSelection::draw(SkCanvas* canvas, const DrawData& drawData) {
cache.refresh_all_draw_cache(selectionDrawData);
cache.draw_components_to_canvas(canvas, selectionDrawData);
}
}
void DrawingProgramSelection::draw_gui(SkCanvas* canvas, const DrawData& drawData) {
if(is_something_selected() && !camSpaceSelection.triangle.empty()) {
canvas->save();
selectionTransformCoords.transform_sk_canvas(canvas, selectionDrawData);
Vector2f minRectPos = selectionTransformCoords.to_space(selectionAABB.min);
Vector2f maxRectPos = selectionTransformCoords.to_space(selectionAABB.max);
SkPaint p{SkColor4f{0.0f, 0.0f, 1.0f, 0.3f}};
canvas->drawRect(SkRect::MakeLTRB(minRectPos.x(), minRectPos.y(), maxRectPos.x(), maxRectPos.y()), p);
SkPath selectionRectPath;
selectionRectPath.moveTo(convert_vec2<SkPoint>(camSpaceSelection.triangle[0].p[0]));
selectionRectPath.lineTo(convert_vec2<SkPoint>(camSpaceSelection.triangle[0].p[1]));
selectionRectPath.lineTo(convert_vec2<SkPoint>(camSpaceSelection.triangle[0].p[2]));
selectionRectPath.lineTo(convert_vec2<SkPoint>(camSpaceSelection.triangle[1].p[2]));
selectionRectPath.close();
SkPaint p{SkColor4f{0.3f, 0.6f, 0.9f, 0.4f}};
canvas->drawPath(selectionRectPath, p);
canvas->restore();
}
}

View file

@ -9,15 +9,26 @@ class DrawingProgramSelection {
void add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection<float>& cC);
void deselect_all();
void update();
void draw(SkCanvas* canvas, const DrawData& drawData);
void draw_components(SkCanvas* canvas, const DrawData& drawData);
void draw_gui(SkCanvas* canvas, const DrawData& drawData);
bool is_something_selected();
bool mouse_collided_with_selection_aabb();
private:
void calculate_aabb();
bool mouse_collided_with_selection_aabb();
void rebuild_cam_space();
SCollision::AABB<WorldScalar> initialSelectionAABB;
SCollision::ColliderCollection<float> camSpaceSelection;
WorldVec selectionRectMin;
WorldVec selectionRectMax;
SCollision::AABB<WorldScalar> selectionAABB;
CoordSpaceHelper selectionTransformCoords;
std::unordered_set<CollabListType::ObjectInfoPtr> selectedSet;
DrawingProgramCache cache;
DrawingProgram& drawP;
struct TranslationData {
bool happening = false;
} translation;
};

View file

@ -33,7 +33,9 @@ void RectSelectTool::gui_toolbox() {
}
void RectSelectTool::reset_tool() {
drawP.selection.deselect_all();
controls = RectSelectControls();
drawP.compCache.disableRefresh = false;
}
void RectSelectTool::tool_update() {
@ -41,10 +43,16 @@ void RectSelectTool::tool_update() {
case 0: {
drawP.compCache.disableRefresh = false;
if(drawP.controls.leftClick) {
reset_tool();
controls.coords = drawP.world.drawData.cam.c;
controls.selectStartAt = controls.coords.get_mouse_pos(drawP.world);
controls.selectionMode = 1;
if(drawP.selection.is_something_selected()) {
if(!drawP.selection.mouse_collided_with_selection_aabb())
reset_tool();
}
else {
reset_tool();
controls.coords = drawP.world.drawData.cam.c;
controls.selectStartAt = controls.coords.get_mouse_pos(drawP.world);
controls.selectionMode = 1;
}
}
break;
}
@ -62,6 +70,7 @@ void RectSelectTool::tool_update() {
drawP.selection.add_from_cam_coord_collider_to_selection(cC);
controls.selectionMode = 0;
drawP.compCache.disableRefresh = true;
}
break;
}