Edit tool works with events

This commit is contained in:
Yousef Khadadeh 2026-03-07 13:00:10 +03:00
parent 32b84d0813
commit 783f645699
10 changed files with 187 additions and 98 deletions

View file

@ -42,6 +42,113 @@ void EditTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
switch_tool(get_type());
}
void EditTool::input_key_callback(const InputManager::KeyCallbackArgs& key) {
drawP.selection.input_key_callback_modify_selection(key);
}
void EditTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) {
drawP.selection.input_mouse_button_on_canvas_callback_modify_selection(button);
if(button.button == InputManager::MouseButton::LEFT) {
if(button.down) {
if(!objInfoBeingEdited) {
WorldVec mouseWorldPos = drawP.world.drawData.cam.c.from_space(button.pos);
SCollision::AABB<WorldScalar> mouseAABB{mouseWorldPos - WorldVec{0.5f, 0.5f}, mouseWorldPos + WorldVec{0.5f, 0.5f}};
SCollision::ColliderCollection<WorldScalar> cMouseAABB;
cMouseAABB.aabb.emplace_back(mouseAABB);
cMouseAABB.recalculate_bounds();
SCollision::AABB<float> camMouseAABB{drawP.world.main.input.mouse.pos - Vector2f{0.5f, 0.5f}, button.pos + Vector2f{0.5f, 0.5f}};
SCollision::ColliderCollection<float> camCMouseAABB;
camCMouseAABB.aabb.emplace_back(camMouseAABB);
camCMouseAABB.recalculate_bounds();
bool modifySelection = !drawP.selection.is_being_transformed();
if(button.clicks >= 2 && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) {
CanvasComponentContainer::ObjInfo* selectedObjectToEdit = drawP.selection.get_front_object_colliding_with_in_editing_layer(camCMouseAABB);
if(selectedObjectToEdit && is_editable(selectedObjectToEdit)) {
drawP.selection.deselect_all();
edit_start(selectedObjectToEdit);
modifySelection = false;
}
}
if(modifySelection) {
if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held)
drawP.selection.add_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
else if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held)
drawP.selection.remove_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
else {
drawP.selection.deselect_all();
drawP.selection.add_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
}
}
}
else {
SCollision::Circle<float> mouseCircle{button.pos, 1.0f};
SCollision::ColliderCollection<float> cMouseCircle;
cMouseCircle.circle.emplace_back(mouseCircle);
cMouseCircle.recalculate_bounds();
bool isMovingPoint = false;
bool clickedAway = false;
if(!pointDragging) {
for(HandleData& h : pointHandles) {
if(SCollision::collide(mouseCircle, SCollision::Circle<float>(drawP.world.drawData.cam.c.to_space(objInfoBeingEdited->obj->coords.from_space(h.coordMatrix * (*h.p))), drawP.drag_point_radius()))) {
pointDragging = &h;
isMovingPoint = true;
break;
}
}
if(!isMovingPoint && !objInfoBeingEdited->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, cMouseCircle))
clickedAway = true;
}
for(HandleData& h : pointHandles) {
if(SCollision::collide(mouseCircle, SCollision::Circle<float>(drawP.world.drawData.cam.c.to_space(objInfoBeingEdited->obj->coords.from_space(h.coordMatrix * (*h.p))), drawP.drag_point_radius()))) {
pointDragging = &h;
isMovingPoint = true;
break;
}
}
if(!isMovingPoint && !objInfoBeingEdited->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, cMouseCircle))
clickedAway = true;
if(clickedAway)
switch_tool(get_type());
if(objInfoBeingEdited)
compEditTool->input_mouse_button_on_canvas_callback(objInfoBeingEdited, button, pointDragging);
}
}
else {
if(objInfoBeingEdited)
compEditTool->input_mouse_button_on_canvas_callback(objInfoBeingEdited, button, pointDragging);
if(pointDragging)
pointDragging = nullptr;
}
}
}
void EditTool::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
if(objInfoBeingEdited) {
if(drawP.controls.leftClickHeld && pointDragging) {
Vector2f newPos = pointDragging->coordMatrix.inverse() * objInfoBeingEdited->obj->coords.get_mouse_pos(drawP.world);
if(newPos != *pointDragging->p) {
if(pointDragging->min)
newPos = cwise_vec_max((*pointDragging->min + Vector2f{pointDragging->minimumDistanceBetweenBoundsAndPoint, pointDragging->minimumDistanceBetweenBoundsAndPoint}).eval(), newPos);
if(pointDragging->max)
newPos = cwise_vec_min((*pointDragging->max - Vector2f{pointDragging->minimumDistanceBetweenBoundsAndPoint, pointDragging->minimumDistanceBetweenBoundsAndPoint}).eval(), newPos);
*pointDragging->p = newPos;
objInfoBeingEdited->obj->commit_update(drawP);
}
}
compEditTool->input_mouse_motion_callback(objInfoBeingEdited, motion, pointDragging);
}
drawP.selection.input_mouse_motion_callback_modify_selection(motion);
}
bool EditTool::right_click_popup_gui(Vector2f popupPos) {
if(objInfoBeingEdited)
return compEditTool->right_click_popup_gui(objInfoBeingEdited, popupPos);
@ -147,80 +254,10 @@ bool EditTool::is_editable(CanvasComponentContainer::ObjInfo* comp) {
}
void EditTool::tool_update() {
if(!objInfoBeingEdited) {
SCollision::AABB<WorldScalar> mouseAABB{drawP.world.get_mouse_world_pos() - WorldVec{0.5f, 0.5f}, drawP.world.get_mouse_world_pos() + WorldVec{0.5f, 0.5f}};
SCollision::ColliderCollection<WorldScalar> cMouseAABB;
cMouseAABB.aabb.emplace_back(mouseAABB);
cMouseAABB.recalculate_bounds();
SCollision::AABB<float> camMouseAABB{drawP.world.main.input.mouse.pos - Vector2f{0.5f, 0.5f}, drawP.world.main.input.mouse.pos + Vector2f{0.5f, 0.5f}};
SCollision::ColliderCollection<float> camCMouseAABB;
camCMouseAABB.aabb.emplace_back(camMouseAABB);
camCMouseAABB.recalculate_bounds();
if(drawP.controls.leftClick) {
bool modifySelection = !drawP.selection.is_being_transformed();
if(drawP.world.main.input.mouse.leftClicks >= 2 && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) {
CanvasComponentContainer::ObjInfo* selectedObjectToEdit = drawP.selection.get_front_object_colliding_with_in_editing_layer(camCMouseAABB);
if(selectedObjectToEdit && is_editable(selectedObjectToEdit)) {
drawP.selection.deselect_all();
edit_start(selectedObjectToEdit);
modifySelection = false;
}
}
if(modifySelection) {
if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held)
drawP.selection.add_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
else if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held)
drawP.selection.remove_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
else {
drawP.selection.deselect_all();
drawP.selection.add_from_cam_coord_collider_to_selection(camCMouseAABB, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED, true);
}
}
}
}
else {
SCollision::Circle<float> mouseCircle{drawP.world.main.input.mouse.pos, 1.0f};
SCollision::ColliderCollection<float> cMouseCircle;
cMouseCircle.circle.emplace_back(mouseCircle);
cMouseCircle.recalculate_bounds();
bool isMovingPoint = false;
bool clickedAway = false;
if(!pointDragging && drawP.controls.leftClick) {
for(HandleData& h : pointHandles) {
if(SCollision::collide(mouseCircle, SCollision::Circle<float>(drawP.world.drawData.cam.c.to_space(objInfoBeingEdited->obj->coords.from_space(h.coordMatrix * (*h.p))), drawP.drag_point_radius()))) {
pointDragging = &h;
isMovingPoint = true;
break;
}
}
if(!isMovingPoint && !objInfoBeingEdited->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, cMouseCircle))
clickedAway = true;
}
else if(pointDragging) {
if(drawP.controls.leftClickHeld) {
Vector2f newPos = pointDragging->coordMatrix.inverse() * objInfoBeingEdited->obj->coords.get_mouse_pos(drawP.world);
if(newPos != *pointDragging->p) {
if(pointDragging->min)
newPos = cwise_vec_max((*pointDragging->min + Vector2f{pointDragging->minimumDistanceBetweenBoundsAndPoint, pointDragging->minimumDistanceBetweenBoundsAndPoint}).eval(), newPos);
if(pointDragging->max)
newPos = cwise_vec_min((*pointDragging->max - Vector2f{pointDragging->minimumDistanceBetweenBoundsAndPoint, pointDragging->minimumDistanceBetweenBoundsAndPoint}).eval(), newPos);
*pointDragging->p = newPos;
objInfoBeingEdited->obj->commit_update(drawP);
}
isMovingPoint = true;
}
else
pointDragging = nullptr;
}
if(objInfoBeingEdited) {
objInfoBeingEdited->obj->send_comp_update(drawP, false);
bool shouldNotReset = compEditTool->edit_update(objInfoBeingEdited);
if(!shouldNotReset || clickedAway)
if(!shouldNotReset)
switch_tool(get_type());
}
}

View file

@ -25,6 +25,9 @@ class EditTool : public DrawingProgramToolBase {
virtual void switch_tool(DrawingProgramToolType newTool) override;
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
virtual bool prevent_undo_or_redo() override;
virtual void input_key_callback(const InputManager::KeyCallbackArgs& key) override;
virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) override;
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
~EditTool();
void add_point_handle(const HandleData& handle);

View file

@ -11,4 +11,8 @@ bool DrawingProgramEditToolBase::right_click_popup_gui(CanvasComponentContainer:
return true;
}
void DrawingProgramEditToolBase::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) {}
void DrawingProgramEditToolBase::input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) {}
void DrawingProgramEditToolBase::input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) {}
DrawingProgramEditToolBase::~DrawingProgramEditToolBase() {}

View file

@ -14,6 +14,9 @@ class DrawingProgramEditToolBase {
virtual bool edit_update(CanvasComponentContainer::ObjInfo* compContainer) = 0;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* compContainer) = 0;
virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos);
virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key);
virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint);
virtual void input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint);
virtual ~DrawingProgramEditToolBase();
protected:
DrawingProgram& drawP;

View file

@ -60,11 +60,7 @@ bool ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
);
#endif
t.open_file_selector("Download File", {{"Any File", "*"}}, [resourceData](const std::filesystem::path& p, const auto& e) {
std::ofstream f(p, std::ios::binary);
if(f.is_open()) {
f << *resourceData->data;
f.close();
}
SDL_SaveFile(p.c_str(), resourceData->data->c_str(), resourceData->data->size());
}, resourceData->name, true);
}
}

View file

@ -139,8 +139,6 @@ bool TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::HIGHLIGHT_COLOR]);
}
t.gui.pop_id();
if(a.textBox->inputChangedTextBox)
@ -152,6 +150,42 @@ bool TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) {
return oldInputChangedTextBox;
}
void TextBoxEditTool::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) {
}
void TextBoxEditTool::input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) {
if(button.button == InputManager::MouseButton::LEFT && !isDraggingPoint) {
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
SCollision::ColliderCollection<float> mousePointCollection;
mousePointCollection.circle.emplace_back(button.pos, 1.0f);
mousePointCollection.recalculate_bounds();
InputManager& input = drawP.world.main.input;
bool collidesWithBox = comp->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection);
a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), (button.down && button.clicks && collidesWithBox) ? button.clicks : 0, button.down, input.key(InputManager::KEY_GENERIC_LSHIFT).held);
}
}
void TextBoxEditTool::input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) {
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
a.init_text_box(drawP);
if(!isDraggingPoint) {
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
SCollision::ColliderCollection<float> mousePointCollection;
mousePointCollection.circle.emplace_back(motion.pos, 1.0f);
mousePointCollection.recalculate_bounds();
InputManager& input = drawP.world.main.input;
a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), 0, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held);
}
}
bool TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) {
Toolbar& t = drawP.world.main.toolbar;
bool shouldClose = false;
@ -254,6 +288,7 @@ void TextBoxEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* com
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
a.d.editing = false;
comp->obj->commit_update(drawP);
drawP.world.main.input.remove_rich_text_box_input(a.textBox);
}
TextBoxEditTool::TextBoxEditToolAllData TextBoxEditTool::get_all_data(const TextBoxCanvasComponent& a) {
@ -267,6 +302,9 @@ void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::O
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
auto& cur = a.cursor;
auto& textbox = a.textBox;
a.init_text_box(drawP);
cur = std::make_shared<TextBox::Cursor>();
Vector2f textSelectPos = a.get_mouse_pos(drawP);
textbox->process_mouse_left_button(*cur, textSelectPos, 1, false, false);
@ -280,23 +318,16 @@ void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::O
editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr});
comp->obj->commit_update(drawP);
drawP.world.main.input.set_rich_text_box_input_back(a.textBox, a.cursor, true, nullptr, {
.inputType = SDL_TextInputType::SDL_TEXTINPUT_TYPE_TEXT,
.capitalization = SDL_Capitalization::SDL_CAPITALIZE_NONE,
.autocorrect = true,
.multiline = true,
.androidInputType = InputManager::AndroidInputType::ANDROIDTEXT_TYPE_CLASS_TEXT
});
}
bool TextBoxEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) {
auto& a = static_cast<TextBoxCanvasComponent&>(comp->obj->get_comp());
SCollision::ColliderCollection<float> mousePointCollection;
mousePointCollection.circle.emplace_back(drawP.world.main.input.mouse.pos, 1.0f);
mousePointCollection.recalculate_bounds();
a.init_text_box(drawP);
InputManager& input = drawP.world.main.input;
bool collidesWithBox = comp->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection);
//input.text.set_rich_text_box_input_back(a.textBox, a.cursor, true, currentMods);
a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), (drawP.controls.leftClick && collidesWithBox) ? drawP.world.main.input.mouse.leftClicks : 0, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held);
return true;
}

View file

@ -15,6 +15,10 @@ class TextBoxEditTool : public DrawingProgramEditToolBase {
virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override;
virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) override;
virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) override;
virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) override;
virtual void input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) override;
private:
struct TextBoxEditToolAllData {
TextBoxCanvasComponent::Data textboxData;