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;

View file

@ -160,8 +160,6 @@ bool InputManager::Text::is_accepting_input() {
return !textBoxes.empty();
}
SDL_Rect r;
void InputManager::Text::update_accepting_input(SDL_Window* window) {
if(!textBoxes.empty()) {
auto& textbox = textBoxes.front();
@ -174,8 +172,12 @@ void InputManager::Text::update_accepting_input(SDL_Window* window) {
SDL_SetNumberProperty(propIDVal, SDL_PROP_TEXTINPUT_AUTOCORRECT_BOOLEAN, textbox.textInputProperties.autocorrect);
SDL_SetNumberProperty(propIDVal, SDL_PROP_TEXTINPUT_MULTILINE_BOOLEAN, textbox.textInputProperties.multiline);
SDL_SetNumberProperty(propIDVal, SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER, (textbox.textInputProperties.androidInputType & ANDROIDTEXT_TYPE_CLASS_NUMBER) ? ANDROIDTEXT_TYPE_CLASS_TEXT : textbox.textInputProperties.androidInputType);
r = textBoxes.front().rect->get_sdl_rect();
SDL_SetTextInputArea(window, &r, 0);
if(!textBoxes.front().rect)
SDL_SetTextInputArea(window, nullptr, 0);
else {
SDL_Rect r = textBoxes.front().rect->get_sdl_rect();
SDL_SetTextInputArea(window, &r, 0);
}
SDL_StartTextInputWithProperties(window, propIDVal);
}
else {

View file

@ -144,6 +144,7 @@ class TextBox {
void process_mouse_left_button(Cursor& cur, const Vector2f& pos, int clickCount, bool held, bool shift);
void process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, const std::optional<TextStyleModifier::ModifierMap>& inputModMap = std::nullopt);
std::pair<std::string, TextData> process_copy(Cursor& cur);
std::pair<std::string, TextData> process_cut(Cursor& cur);
std::string get_text_between(TextPosition p1, TextPosition p2);

View file

@ -834,6 +834,14 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
get_refresh_rate(mS);
break;
}
case SDL_EVENT_SCREEN_KEYBOARD_SHOWN: {
Logger::get().log("INFO", "YAYYYYYYYYYYYYYYYYYYYYY! " + std::to_string(event->type));
break;
}
case SDL_EVENT_SCREEN_KEYBOARD_HIDDEN: {
Logger::get().log("INFO", "NOOOOOOOOOOOOOOOOOOOOOOO! " + std::to_string(event->type));
break;
}
default:
break;
}