Setting text box input no longer involves repeatedly setting it each frame
This commit is contained in:
parent
8c11141ac5
commit
e1e93b8a31
14 changed files with 271 additions and 212 deletions
|
|
@ -158,10 +158,10 @@ void DrawCamera::update_main(World& w) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_COUNTERCLOCKWISE).held && !w.main.input.text.get_accepting_input()) {
|
||||
if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_COUNTERCLOCKWISE).held && !w.main.input.text.is_accepting_input()) {
|
||||
c.rotate_about(c.from_space(w.main.window.size.cast<float>() * 0.5f), -w.main.deltaTime);
|
||||
}
|
||||
if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_CLOCKWISE).held && !w.main.input.text.get_accepting_input()) {
|
||||
if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_CLOCKWISE).held && !w.main.input.text.is_accepting_input()) {
|
||||
c.rotate_about(c.from_space(w.main.window.size.cast<float>() * 0.5f), w.main.deltaTime);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,55 +46,55 @@ DrawingProgram::DrawingProgram(World& initWorld):
|
|||
}
|
||||
|
||||
void DrawingProgram::register_callbacks() {
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::BRUSH);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::ERASER);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::RECTSELECT);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::RECTANGLE);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::ELLIPSE);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::TEXTBOX);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::EYEDROPPER);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::SCREENSHOT);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::ZOOM);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::LASSOSELECT);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::PAN);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
switch_to_tool(DrawingProgramToolType::LINE);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_HOLD_TO_PAN] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_PAN].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_HOLD_TO_PAN] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_PAN].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat && tempMoveToolSwitch == TemporaryMoveToolSwitch::NONE) {
|
||||
toolTypeAfterTempMove = drawTool->get_type();
|
||||
switch_to_tool(DrawingProgramToolType::PAN);
|
||||
|
|
@ -105,7 +105,7 @@ void DrawingProgram::register_callbacks() {
|
|||
tempMoveToolSwitch = TemporaryMoveToolSwitch::NONE;
|
||||
}
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM].register_callback([&](auto& key) {
|
||||
world.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat && tempMoveToolSwitch == TemporaryMoveToolSwitch::NONE) {
|
||||
toolTypeAfterTempMove = drawTool->get_type();
|
||||
switch_to_tool(DrawingProgramToolType::ZOOM);
|
||||
|
|
@ -120,10 +120,8 @@ void DrawingProgram::register_callbacks() {
|
|||
}
|
||||
|
||||
void DrawingProgram::deregister_callbacks() {
|
||||
for(auto& [key, callback] : keyCallbacks)
|
||||
world.main.input.keyCallbacks[key].deregister_callback(callback);
|
||||
keyCallbacks.clear();
|
||||
tempMoveToolSwitch = TemporaryMoveToolSwitch::NONE;
|
||||
selection.deselect_all();
|
||||
}
|
||||
|
||||
void DrawingProgram::server_init_no_file() {
|
||||
|
|
|
|||
|
|
@ -125,8 +125,6 @@ class DrawingProgram {
|
|||
|
||||
uint32_t nextID = 0;
|
||||
|
||||
std::unordered_map<unsigned, InputManager::KeyCallbackManager::Callback*> keyCallbacks;
|
||||
|
||||
friend class EyeDropperTool;
|
||||
friend class RectDrawTool;
|
||||
friend class EllipseDrawTool;
|
||||
|
|
|
|||
|
|
@ -353,19 +353,8 @@ void DrawingProgramSelection::commit_transform_selection() {
|
|||
|
||||
void DrawingProgramSelection::update() {
|
||||
if(is_something_selected()) {
|
||||
selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min);
|
||||
selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left());
|
||||
selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
|
||||
selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right());
|
||||
|
||||
scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(initialSelectionAABB.max);
|
||||
rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(rotateData.centerPos);
|
||||
rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle);
|
||||
|
||||
rebuild_cam_space();
|
||||
|
||||
constexpr float KEY_TRANSLATE_MAGNITUDE = 5.0f;
|
||||
|
||||
if(drawP.is_actual_selection_tool(drawP.drawTool->get_type())) {
|
||||
switch(transformOpHappening) {
|
||||
case TransformOperation::NONE:
|
||||
|
|
@ -392,53 +381,9 @@ void DrawingProgramSelection::update() {
|
|||
check_add_stroke_color_change_undo();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Vector2f moveVec = {0, 0};
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_UP).pressed)
|
||||
moveVec.y() -= 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).pressed)
|
||||
moveVec.y() += 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).pressed)
|
||||
moveVec.x() += 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).pressed)
|
||||
moveVec.x() -= 1.0f;
|
||||
if(moveVec != Vector2f{0.0f, 0.0f}) {
|
||||
moveVec *= KEY_TRANSLATE_MAGNITUDE;
|
||||
translateData.startPos = drawP.world.drawData.cam.c.dir_from_space(moveVec);
|
||||
translateData.translateWithKeys = true;
|
||||
selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos);
|
||||
transformOpHappening = TransformOperation::TRANSLATE;
|
||||
translateData.keyTranslateLastMoveTime = std::chrono::steady_clock::now();
|
||||
check_add_stroke_color_change_undo();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TransformOperation::TRANSLATE:
|
||||
if(translateData.translateWithKeys) {
|
||||
Vector2f moveVec = {0, 0};
|
||||
constexpr auto TIME_TO_NEXT_MOVE = std::chrono::milliseconds(700);
|
||||
constexpr auto TIME_TO_SUBTRACT_BETWEEN_REPEATS = std::chrono::milliseconds(650);
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held)
|
||||
moveVec.y() -= 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held)
|
||||
moveVec.y() += 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held)
|
||||
moveVec.x() += 1.0f;
|
||||
if(drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held)
|
||||
moveVec.x() -= 1.0f;
|
||||
if(moveVec != Vector2f{0.0f, 0.0f} && (std::chrono::steady_clock::now() - translateData.keyTranslateLastMoveTime) >= TIME_TO_NEXT_MOVE) {
|
||||
moveVec *= KEY_TRANSLATE_MAGNITUDE;
|
||||
translateData.startPos += drawP.world.drawData.cam.c.dir_from_space(moveVec);
|
||||
selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos);
|
||||
translateData.keyTranslateLastMoveTime = std::chrono::steady_clock::now() - TIME_TO_SUBTRACT_BETWEEN_REPEATS; // Time between repeat moves is shorter than time between first press and first repeat
|
||||
}
|
||||
bool anyKeyHeld = drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held || drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held;
|
||||
if(!anyKeyHeld) {
|
||||
commit_transform_selection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!translateData.translateWithKeys) {
|
||||
if(drawP.controls.leftClickHeld)
|
||||
selectionTransformCoords = CoordSpaceHelperTransform(drawP.world.get_mouse_world_pos() - translateData.startPos);
|
||||
else {
|
||||
|
|
@ -498,33 +443,34 @@ void DrawingProgramSelection::update() {
|
|||
}
|
||||
|
||||
void DrawingProgramSelection::register_key_callbacks() {
|
||||
drawP.keyCallbacks[InputManager::KEY_DRAW_DELETE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DRAW_DELETE].register_callback([&](auto& key) {
|
||||
auto& keyCallbacks = drawP.world.keyCallbacks;
|
||||
keyCallbacks[InputManager::KEY_DRAW_DELETE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DRAW_DELETE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
delete_all();
|
||||
});
|
||||
drawP.keyCallbacks[InputManager::KEY_COPY] = drawP.world.main.input.keyCallbacks[InputManager::KEY_COPY].register_callback([&](auto& key) {
|
||||
keyCallbacks[InputManager::KEY_COPY] = drawP.world.main.input.keyCallbacks[InputManager::KEY_COPY].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
selection_to_clipboard();
|
||||
});
|
||||
drawP.keyCallbacks[InputManager::KEY_CUT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_CUT].register_callback([&](auto& key) {
|
||||
keyCallbacks[InputManager::KEY_CUT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_CUT].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat) {
|
||||
selection_to_clipboard();
|
||||
delete_all();
|
||||
}
|
||||
});
|
||||
drawP.keyCallbacks[InputManager::KEY_PASTE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE].register_callback([&](auto& key) {
|
||||
keyCallbacks[InputManager::KEY_PASTE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat) {
|
||||
deselect_all();
|
||||
paste_clipboard(drawP.world.main.input.mouse.pos);
|
||||
}
|
||||
});
|
||||
drawP.keyCallbacks[InputManager::KEY_PASTE_IMAGE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE_IMAGE].register_callback([&](auto& key) {
|
||||
keyCallbacks[InputManager::KEY_PASTE_IMAGE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE_IMAGE].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat) {
|
||||
deselect_all();
|
||||
paste_image(drawP.world.main.input.mouse.pos);
|
||||
}
|
||||
});
|
||||
drawP.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL].register_callback([&](auto& key) {
|
||||
keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat) {
|
||||
if(is_something_selected())
|
||||
deselect_all();
|
||||
|
|
@ -532,6 +478,58 @@ void DrawingProgramSelection::register_key_callbacks() {
|
|||
drawP.switch_to_tool(DrawingProgramToolType::EDIT, true);
|
||||
}
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_TEXT_UP] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_UP].register_callback([&](auto& key) {
|
||||
translate_key(InputManager::KEY_TEXT_UP, key.down);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_TEXT_DOWN] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_DOWN].register_callback([&](auto& key) {
|
||||
translate_key(InputManager::KEY_TEXT_DOWN, key.down);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_TEXT_LEFT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_LEFT].register_callback([&](auto& key) {
|
||||
translate_key(InputManager::KEY_TEXT_LEFT, key.down);
|
||||
});
|
||||
keyCallbacks[InputManager::KEY_TEXT_RIGHT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_RIGHT].register_callback([&](auto& key) {
|
||||
translate_key(InputManager::KEY_TEXT_RIGHT, key.down);
|
||||
});
|
||||
}
|
||||
|
||||
void DrawingProgramSelection::translate_key(unsigned keyPressed, bool pressed) {
|
||||
if(pressed) {
|
||||
constexpr float KEY_TRANSLATE_MAGNITUDE = 5.0f;
|
||||
Vector2f moveVec;
|
||||
switch(keyPressed) {
|
||||
case InputManager::KEY_TEXT_UP:
|
||||
moveVec = {0.0f, -1.0f};
|
||||
break;
|
||||
case InputManager::KEY_TEXT_DOWN:
|
||||
moveVec = {0.0f, 1.0f};
|
||||
break;
|
||||
case InputManager::KEY_TEXT_RIGHT:
|
||||
moveVec = {1.0f, 0.0f};
|
||||
break;
|
||||
case InputManager::KEY_TEXT_LEFT:
|
||||
moveVec = {-1.0f, 0.0f};
|
||||
break;
|
||||
}
|
||||
moveVec *= KEY_TRANSLATE_MAGNITUDE;
|
||||
if(transformOpHappening == TransformOperation::NONE) {
|
||||
translateData.startPos = drawP.world.drawData.cam.c.dir_from_space(moveVec);
|
||||
translateData.translateWithKeys = true;
|
||||
transformOpHappening = TransformOperation::TRANSLATE;
|
||||
check_add_stroke_color_change_undo();
|
||||
}
|
||||
else if(transformOpHappening == TransformOperation::TRANSLATE && translateData.translateWithKeys) {
|
||||
moveVec *= KEY_TRANSLATE_MAGNITUDE;
|
||||
translateData.startPos += drawP.world.drawData.cam.c.dir_from_space(moveVec);
|
||||
}
|
||||
selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos);
|
||||
}
|
||||
else if(transformOpHappening == TransformOperation::TRANSLATE && translateData.translateWithKeys) {
|
||||
bool anyKeyHeld = drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held || drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held;
|
||||
if(!anyKeyHeld) {
|
||||
commit_transform_selection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingProgramSelection::deselect_all() {
|
||||
|
|
@ -700,6 +698,15 @@ std::unordered_set<CanvasComponentContainer::ObjInfo*> DrawingProgramSelection::
|
|||
}
|
||||
|
||||
void DrawingProgramSelection::rebuild_cam_space() {
|
||||
selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min);
|
||||
selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left());
|
||||
selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
|
||||
selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right());
|
||||
|
||||
scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(initialSelectionAABB.max);
|
||||
rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(rotateData.centerPos);
|
||||
rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle);
|
||||
|
||||
SCollision::ColliderCollection<WorldScalar> collideRectWorld;
|
||||
collideRectWorld.triangle.emplace_back(selectionRectPoints[0], selectionRectPoints[1], selectionRectPoints[2]);
|
||||
collideRectWorld.triangle.emplace_back(selectionRectPoints[0], selectionRectPoints[2], selectionRectPoints[3]);
|
||||
|
|
@ -714,15 +721,6 @@ Vector2f DrawingProgramSelection::get_rotation_point_pos_from_angle(double angle
|
|||
|
||||
void DrawingProgramSelection::draw_components(SkCanvas* canvas, const DrawData& drawData) {
|
||||
if(is_something_selected()) {
|
||||
selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min);
|
||||
selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left());
|
||||
selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max);
|
||||
selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right());
|
||||
|
||||
scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(initialSelectionAABB.max));
|
||||
rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(rotateData.centerPos));
|
||||
rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle);
|
||||
|
||||
rebuild_cam_space();
|
||||
|
||||
DrawData selectionDrawData = drawData;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class DrawingProgramSelection {
|
|||
CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection<float>& cC);
|
||||
void register_key_callbacks();
|
||||
private:
|
||||
void translate_key(unsigned keyPressed, bool pressed);
|
||||
bool mouse_collided_with_selection_aabb();
|
||||
bool mouse_collided_with_scale_point();
|
||||
bool mouse_collided_with_rotate_center_handle_point();
|
||||
|
|
@ -75,7 +76,6 @@ class DrawingProgramSelection {
|
|||
struct TranslationData {
|
||||
WorldVec startPos;
|
||||
bool translateWithKeys;
|
||||
std::chrono::steady_clock::time_point keyTranslateLastMoveTime;
|
||||
} translateData;
|
||||
|
||||
struct ScaleData {
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ bool TextBoxEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) {
|
|||
|
||||
bool collidesWithBox = comp->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection);
|
||||
|
||||
input.text.set_rich_text_box_input(a.textBox, a.cursor, true, currentMods);
|
||||
//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;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,9 @@ struct UpdateInputData {
|
|||
std::optional<std::string> textOut;
|
||||
} clipboard;
|
||||
|
||||
std::function<void(std::shared_ptr<RichText::TextBox>, std::shared_ptr<RichText::TextBox::Cursor>)> richTextBoxEdit;
|
||||
std::shared_ptr<RichText::TextBox> previousRichTextBoxToEdit;
|
||||
std::shared_ptr<RichText::TextBox> richTextBoxToEdit;
|
||||
std::shared_ptr<RichText::TextBox::Cursor> richTextBoxToEditCursor;
|
||||
|
||||
SkFont get_font(float fSize) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ template <typename T> class TextBox : public Element {
|
|||
}) {
|
||||
selection.update(Clay_Hovered(), io.mouse.leftClick, io.mouse.leftHeld);
|
||||
if(data && selection.selected) {
|
||||
io.richTextBoxEdit(textbox, cur);
|
||||
io.richTextBoxToEdit = textbox;
|
||||
io.richTextBoxToEditCursor = cur;
|
||||
textbox->process_mouse_left_button(*cur, io.mouse.pos - bb.min, io.mouse.leftClick, io.mouse.leftHeld, io.key.leftShift);
|
||||
if((updateEveryEdit && textbox->inputChangedTextBox) || io.key.enter) {
|
||||
update_on_edit();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "InputManager.hpp"
|
||||
|
||||
#include <SDL3/SDL_clipboard.h>
|
||||
#include <SDL3/SDL_keyboard.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
|
||||
#include <optional>
|
||||
|
|
@ -83,47 +84,60 @@ InputManager::InputManager() {
|
|||
}
|
||||
|
||||
void InputManager::text_input_silence_everything() {
|
||||
text.set_accepting_input();
|
||||
for(auto& p : keys) {
|
||||
p.pressed = false;
|
||||
p.repeat = false;
|
||||
// Not silencing p.held, as that causes double presses on some keyboards
|
||||
}
|
||||
text.newInput.clear();
|
||||
}
|
||||
|
||||
void InputManager::Text::set_rich_text_box_input(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap) {
|
||||
set_accepting_input();
|
||||
newTextBox = nTextBox;
|
||||
newCursor = nCursor;
|
||||
newModMap = nModMap;
|
||||
newIsRichTextBox = isRichTextBox;
|
||||
void InputManager::set_rich_text_box_input_front(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap) {
|
||||
text.set_accepting_input(sdlWindow, true);
|
||||
Text::TextBoxInfo textBoxInfo;
|
||||
textBoxInfo.textBox = nTextBox;
|
||||
textBoxInfo.cursor = nCursor;
|
||||
textBoxInfo.modMap = nModMap;
|
||||
textBoxInfo.isRichTextBox = isRichTextBox;
|
||||
text.textBoxes.emplace_front(textBoxInfo);
|
||||
}
|
||||
|
||||
void InputManager::set_rich_text_box_input_back(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap) {
|
||||
text.set_accepting_input(sdlWindow, true);
|
||||
Text::TextBoxInfo textBoxInfo;
|
||||
textBoxInfo.textBox = nTextBox;
|
||||
textBoxInfo.cursor = nCursor;
|
||||
textBoxInfo.modMap = nModMap;
|
||||
textBoxInfo.isRichTextBox = isRichTextBox;
|
||||
text.textBoxes.emplace_back(textBoxInfo);
|
||||
}
|
||||
|
||||
void InputManager::remove_rich_text_box_input(const std::shared_ptr<RichText::TextBox>& nTextBox) {
|
||||
std::erase_if(text.textBoxes, [&nTextBox](Text::TextBoxInfo& info) {
|
||||
return (info.textBox == nTextBox);
|
||||
});
|
||||
if(text.textBoxes.empty())
|
||||
text.set_accepting_input(sdlWindow, false);
|
||||
}
|
||||
|
||||
void InputManager::Text::add_text_to_textbox(const std::string& inputText) {
|
||||
if(textBox && !inputText.empty())
|
||||
if(!textBoxes.empty() && !inputText.empty()) {
|
||||
auto& frontTextBox = textBoxes.front();
|
||||
do_textbox_operation_with_undo([&]() {
|
||||
textBox->process_text_input(*cursor, inputText, modMap);
|
||||
frontTextBox.textBox->process_text_input(*frontTextBox.cursor, inputText, frontTextBox.modMap);
|
||||
});
|
||||
}
|
||||
|
||||
void InputManager::Text::set_accepting_input() {
|
||||
acceptingInputNew = true;
|
||||
}
|
||||
|
||||
bool InputManager::Text::get_accepting_input() {
|
||||
return acceptingInput;
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::Text::add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText) {
|
||||
if(textBox) {
|
||||
textboxUndo.push({[textBox = textBox, cursor = cursor, prevCursor = prevCursor, prevRichText = prevRichText]() {
|
||||
if(!textBoxes.empty()) {
|
||||
auto& frontTextBox = textBoxes.front();
|
||||
frontTextBox.textboxUndo.push({[textBox = frontTextBox.textBox, cursor = frontTextBox.cursor, prevCursor = prevCursor, prevRichText = prevRichText]() {
|
||||
textBox->set_rich_text_data(prevRichText);
|
||||
cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(prevCursor.selectionEndPos, prevCursor.selectionBeginPos);
|
||||
cursor->previousX = std::nullopt;
|
||||
return true;
|
||||
},
|
||||
[textBox = textBox, cursor = cursor, currentCursor = *cursor, currentRichText = textBox->get_rich_text_data()]() {
|
||||
[textBox = frontTextBox.textBox, cursor = frontTextBox.cursor, currentCursor = *frontTextBox.cursor, currentRichText = frontTextBox.textBox->get_rich_text_data()]() {
|
||||
textBox->set_rich_text_data(currentRichText);
|
||||
cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(currentCursor.selectionEndPos, currentCursor.selectionBeginPos);
|
||||
cursor->previousX = std::nullopt;
|
||||
|
|
@ -133,14 +147,30 @@ void InputManager::Text::add_textbox_undo(const RichText::TextBox::Cursor& prevC
|
|||
}
|
||||
|
||||
void InputManager::Text::do_textbox_operation_with_undo(const std::function<void()>& func) {
|
||||
if(textBox) {
|
||||
auto prevRichText = textBox->get_rich_text_data();
|
||||
auto prevCursor = *cursor;
|
||||
if(!textBoxes.empty()) {
|
||||
auto& frontTextBox = textBoxes.front();
|
||||
auto prevRichText = frontTextBox.textBox->get_rich_text_data();
|
||||
auto prevCursor = *frontTextBox.cursor;
|
||||
func();
|
||||
add_textbox_undo(prevCursor, prevRichText);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputManager::Text::is_accepting_input() {
|
||||
return acceptingInput;
|
||||
}
|
||||
|
||||
void InputManager::Text::set_accepting_input(SDL_Window* window, bool newAcceptingInputVal) {
|
||||
if(!acceptingInput && newAcceptingInputVal) {
|
||||
SDL_StartTextInput(window);
|
||||
acceptingInput = true;
|
||||
}
|
||||
else if(acceptingInput && !newAcceptingInputVal) {
|
||||
SDL_StopTextInput(window);
|
||||
acceptingInput = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string InputManager::get_clipboard_str_SDL() {
|
||||
char* data = SDL_GetClipboardText();
|
||||
std::string toRet(data);
|
||||
|
|
@ -356,55 +386,59 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
|
||||
// e.key != SDLK_LMETA && e.key != SDLK_RMETA &&
|
||||
|
||||
if(stopKeyInput && !e.down)
|
||||
if(stopKeyInput)
|
||||
return;
|
||||
|
||||
sdlKeyCallbacks.run_callbacks(e);
|
||||
|
||||
std::shared_ptr<RichText::TextBox> textBox = text.textBoxes.empty() ? nullptr : text.textBoxes.front().textBox;
|
||||
std::shared_ptr<RichText::TextBox::Cursor> cursor = text.textBoxes.empty() ? nullptr : text.textBoxes.front().cursor;
|
||||
std::optional<RichText::TextStyleModifier::ModifierMap> modMap = text.textBoxes.empty() ? std::nullopt : text.textBoxes.front().modMap;
|
||||
|
||||
switch(kPress) {
|
||||
case SDLK_UP:
|
||||
set_key_down(e, KEY_TEXT_UP);
|
||||
if(text.textBox && key(KEY_TEXT_UP).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_UP).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
set_key_down(e, KEY_TEXT_DOWN);
|
||||
if(text.textBox && key(KEY_TEXT_DOWN).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_DOWN).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
set_key_down(e, KEY_TEXT_LEFT);
|
||||
if(text.textBox && key(KEY_TEXT_LEFT).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_LEFT).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
set_key_down(e, KEY_TEXT_RIGHT);
|
||||
if(text.textBox && key(KEY_TEXT_RIGHT).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_RIGHT).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
set_key_down(e, KEY_TEXT_BACKSPACE);
|
||||
if(text.textBox && key(KEY_TEXT_BACKSPACE).repeat)
|
||||
if(textBox && key(KEY_TEXT_BACKSPACE).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
});
|
||||
break;
|
||||
case SDLK_DELETE:
|
||||
set_key_down(e, KEY_TEXT_DELETE);
|
||||
if(text.textBox && key(KEY_TEXT_DELETE).repeat)
|
||||
if(textBox && key(KEY_TEXT_DELETE).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DEL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::DEL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
});
|
||||
break;
|
||||
case SDLK_HOME:
|
||||
set_key_down(e, KEY_TEXT_HOME);
|
||||
if(text.textBox && key(KEY_TEXT_HOME).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_HOME).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_END:
|
||||
set_key_down(e, KEY_TEXT_END);
|
||||
if(text.textBox && key(KEY_TEXT_END).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_END).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
set_key_down(e, KEY_TEXT_SHIFT);
|
||||
|
|
@ -425,21 +459,21 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
// Use either Ctrl or Meta (command for Mac) keys. We do either instead of checking, since checking can get complicated on Emscripten
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_COPY);
|
||||
if(text.textBox && key(KEY_TEXT_COPY).repeat)
|
||||
set_clipboard_plain_and_richtext_pair(text.textBox->process_copy(*text.cursor));
|
||||
if(textBox && key(KEY_TEXT_COPY).repeat)
|
||||
set_clipboard_plain_and_richtext_pair(textBox->process_copy(*cursor));
|
||||
break;
|
||||
case SDLK_X:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_CUT);
|
||||
if(text.textBox && key(KEY_TEXT_CUT).repeat)
|
||||
if(textBox && key(KEY_TEXT_CUT).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
set_clipboard_plain_and_richtext_pair(text.textBox->process_cut(*text.cursor));
|
||||
set_clipboard_plain_and_richtext_pair(textBox->process_cut(*cursor));
|
||||
});
|
||||
break;
|
||||
case SDLK_V:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_PASTE);
|
||||
if(text.textBox && key(KEY_TEXT_PASTE).repeat)
|
||||
if(textBox && key(KEY_TEXT_PASTE).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
call_text_paste(true);
|
||||
});
|
||||
|
|
@ -447,34 +481,34 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
case SDLK_A:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_SELECTALL);
|
||||
if(text.textBox && key(KEY_TEXT_SELECTALL).repeat)
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
if(textBox && key(KEY_TEXT_SELECTALL).repeat)
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
break;
|
||||
case SDLK_Z:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_UNDO);
|
||||
if(text.textBox && key(KEY_TEXT_UNDO).repeat)
|
||||
text.textboxUndo.undo();
|
||||
if(textBox && key(KEY_TEXT_UNDO).repeat)
|
||||
text.textBoxes.front().textboxUndo.undo();
|
||||
break;
|
||||
case SDLK_R:
|
||||
if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL))
|
||||
set_key_down(e, KEY_TEXT_REDO);
|
||||
if(text.textBox && key(KEY_TEXT_REDO).repeat)
|
||||
text.textboxUndo.redo();
|
||||
if(textBox && key(KEY_TEXT_REDO).repeat)
|
||||
text.textBoxes.front().textboxUndo.redo();
|
||||
break;
|
||||
case SDLK_RETURN: {
|
||||
set_key_down(e, KEY_TEXT_ENTER);
|
||||
if(text.textBox && key(KEY_TEXT_ENTER).repeat)
|
||||
if(textBox && key(KEY_TEXT_ENTER).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SDLK_TAB: {
|
||||
set_key_down(e, KEY_TEXT_TAB);
|
||||
if(text.textBox && key(KEY_TEXT_TAB).repeat)
|
||||
if(textBox && key(KEY_TEXT_TAB).repeat)
|
||||
text.do_textbox_operation_with_undo([&]() {
|
||||
text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap);
|
||||
textBox->process_key_input(*cursor, RichText::TextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -485,13 +519,28 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(text.get_accepting_input() && e.down)
|
||||
if(text.acceptingInput)
|
||||
return;
|
||||
|
||||
auto f = keyAssignments.find({make_generic_key_mod(kMod), kPress});
|
||||
KeyCallbackArgs keyArgs{.down = e.down, .repeat = e.repeat};
|
||||
if(f != keyAssignments.end()) {
|
||||
set_key_down(e, f->second);
|
||||
keyCallbacks[f->second].run_callbacks(KeyCallbackArgs{.down = e.down, .repeat = e.repeat});
|
||||
keyCallbacks[f->second].run_callbacks(keyArgs);
|
||||
}
|
||||
switch(kPress) {
|
||||
case SDLK_UP:
|
||||
keyCallbacks[KEY_TEXT_UP].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
keyCallbacks[KEY_TEXT_DOWN].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
keyCallbacks[KEY_TEXT_LEFT].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
keyCallbacks[KEY_TEXT_RIGHT].run_callbacks(keyArgs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -509,16 +558,16 @@ void InputManager::call_text_paste(bool isRichTextPaste) {
|
|||
}
|
||||
|
||||
void InputManager::process_text_paste(const std::string& plainClipboardStr) {
|
||||
if(text.textBox) {
|
||||
if(!text.textBoxes.empty()) {
|
||||
// Workaround for not being able to copy richtext to system clipboard, this should at least work within the application itself
|
||||
if(text.isRichTextBox && text.isNextPasteRich && lastCopiedRichText.has_value()) {
|
||||
if(text.textBoxes.front().isRichTextBox && text.isNextPasteRich && lastCopiedRichText.has_value()) {
|
||||
if(lastCopiedRichText.value().get_plain_text() == remove_carriage_returns_from_str(plainClipboardStr))
|
||||
text.textBox->process_rich_text_input(*text.cursor, lastCopiedRichText.value());
|
||||
text.textBoxes.front().textBox->process_rich_text_input(*text.textBoxes.front().cursor, lastCopiedRichText.value());
|
||||
else
|
||||
text.textBox->process_text_input(*text.cursor, plainClipboardStr, text.modMap);
|
||||
text.textBoxes.front().textBox->process_text_input(*text.textBoxes.front().cursor, plainClipboardStr, text.textBoxes.front().modMap);
|
||||
}
|
||||
else
|
||||
text.textBox->process_text_input(*text.cursor, plainClipboardStr, text.modMap);
|
||||
text.textBoxes.front().textBox->process_text_input(*text.textBoxes.front().cursor, plainClipboardStr, text.textBoxes.front().modMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -597,9 +646,27 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) {
|
|||
break;
|
||||
}
|
||||
|
||||
KeyCallbackArgs keyArgs{.down = e.down, .repeat = e.repeat};
|
||||
for(auto& p : keyAssignments) {
|
||||
if(p.first.y() == kPress) // Dont try matching modifiers when setting key to go up
|
||||
if(p.first.y() == kPress) { // Dont try matching modifiers when setting key to go up
|
||||
set_key_up(e, p.second);
|
||||
keyCallbacks[p.second].run_callbacks(keyArgs);
|
||||
}
|
||||
}
|
||||
|
||||
switch(kPress) {
|
||||
case SDLK_UP:
|
||||
keyCallbacks[KEY_TEXT_UP].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
keyCallbacks[KEY_TEXT_DOWN].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
keyCallbacks[KEY_TEXT_LEFT].run_callbacks(keyArgs);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
keyCallbacks[KEY_TEXT_RIGHT].run_callbacks(keyArgs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -619,21 +686,7 @@ void InputManager::frame_reset(const Vector2i& windowSize) {
|
|||
mouse.leftClicks = 0;
|
||||
mouse.rightClicks = 0;
|
||||
mouse.middleClicks = 0;
|
||||
text.acceptingInput = text.acceptingInputNew;
|
||||
text.acceptingInputNew = false;
|
||||
if(text.cursor != text.newCursor || text.textBox != text.newTextBox)
|
||||
text.textboxUndo.clear();
|
||||
text.cursor = text.newCursor;
|
||||
text.textBox = text.newTextBox;
|
||||
text.modMap = text.newModMap;
|
||||
text.isRichTextBox = text.newIsRichTextBox;
|
||||
|
||||
text.newCursor = nullptr;
|
||||
text.newTextBox = nullptr;
|
||||
text.newModMap = std::nullopt;
|
||||
text.newIsRichTextBox = false;
|
||||
|
||||
text.newInput.clear();
|
||||
droppedItems.clear();
|
||||
|
||||
cursorIcon = SystemCursorType::DEFAULT;
|
||||
|
|
|
|||
|
|
@ -89,36 +89,33 @@ struct InputManager {
|
|||
std::array<KeyData, 256> buttons;
|
||||
} pen;
|
||||
|
||||
void set_rich_text_box_input_front(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
|
||||
void set_rich_text_box_input_back(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
|
||||
void remove_rich_text_box_input(const std::shared_ptr<RichText::TextBox>& nTextBox);
|
||||
|
||||
struct Text {
|
||||
std::string newInput;
|
||||
bool lastAcceptingTextInputVal = false;
|
||||
bool is_accepting_input();
|
||||
|
||||
void set_accepting_input();
|
||||
bool get_accepting_input();
|
||||
|
||||
void set_rich_text_box_input(const std::shared_ptr<RichText::TextBox>& nTextBox, const std::shared_ptr<RichText::TextBox::Cursor>& nCursor, bool isRichTextBox, const std::optional<RichText::TextStyleModifier::ModifierMap>& nModMap = std::nullopt);
|
||||
void add_text_to_textbox(const std::string& inputText);
|
||||
|
||||
void add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText);
|
||||
void do_textbox_operation_with_undo(const std::function<void()>& func);
|
||||
|
||||
private:
|
||||
struct TextBoxInfo {
|
||||
bool isRichTextBox;
|
||||
std::shared_ptr<RichText::TextBox> textBox;
|
||||
std::shared_ptr<RichText::TextBox::Cursor> cursor;
|
||||
std::optional<RichText::TextStyleModifier::ModifierMap> modMap;
|
||||
UndoManager textboxUndo;
|
||||
};
|
||||
|
||||
void set_accepting_input(SDL_Window* window, bool newAcceptingInputVal);
|
||||
|
||||
bool isNextPasteRich = false;
|
||||
|
||||
bool isRichTextBox;
|
||||
std::shared_ptr<RichText::TextBox> textBox;
|
||||
std::shared_ptr<RichText::TextBox::Cursor> cursor;
|
||||
std::optional<RichText::TextStyleModifier::ModifierMap> modMap;
|
||||
|
||||
bool newIsRichTextBox;
|
||||
std::shared_ptr<RichText::TextBox> newTextBox;
|
||||
std::shared_ptr<RichText::TextBox::Cursor> newCursor;
|
||||
std::optional<RichText::TextStyleModifier::ModifierMap> newModMap;
|
||||
|
||||
UndoManager textboxUndo;
|
||||
|
||||
bool acceptingInput = false;
|
||||
bool acceptingInputNew = false;
|
||||
|
||||
std::deque<TextBoxInfo> textBoxes;
|
||||
|
||||
friend struct InputManager;
|
||||
} text;
|
||||
|
|
@ -245,6 +242,8 @@ struct InputManager {
|
|||
std::unordered_map<Vector2ui32, KeyCode> keyAssignments;
|
||||
std::unordered_map<Vector2ui32, KeyCode> defaultKeyAssignments;
|
||||
std::array<KeyData, KEY_COUNT> keys;
|
||||
|
||||
SDL_Window* sdlWindow;
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(InputManager::KeyCodeEnum, {
|
||||
|
|
|
|||
|
|
@ -2275,9 +2275,9 @@ void Toolbar::initialize_io_before_update() {
|
|||
io->key.leftCtrl = main.input.key(InputManager::KEY_TEXT_CTRL).held;
|
||||
io->key.enter = main.input.key(InputManager::KEY_TEXT_ENTER).repeat;
|
||||
io->key.escape = main.input.key(InputManager::KEY_GENERIC_ESCAPE).repeat;
|
||||
io->richTextBoxEdit = [&](std::shared_ptr<RichText::TextBox> t, std::shared_ptr<RichText::TextBox::Cursor> c) {
|
||||
main.input.text.set_rich_text_box_input(t, c, false);
|
||||
};
|
||||
io->previousRichTextBoxToEdit = io->richTextBoxToEdit;
|
||||
io->richTextBoxToEditCursor = nullptr;
|
||||
io->richTextBoxToEdit = nullptr;
|
||||
|
||||
if(io->acceptingTextInput)
|
||||
main.input.text_input_silence_everything();
|
||||
|
|
@ -2319,6 +2319,12 @@ void Toolbar::end_gui() {
|
|||
gui.end();
|
||||
if(io->clipboard.textOut)
|
||||
main.input.set_clipboard_str(*io->clipboard.textOut);
|
||||
if(io->richTextBoxToEdit != io->previousRichTextBoxToEdit) {
|
||||
if(io->richTextBoxToEdit)
|
||||
main.input.set_rich_text_box_input_front(io->richTextBoxToEdit, io->richTextBoxToEditCursor, false);
|
||||
if(io->previousRichTextBoxToEdit)
|
||||
main.input.remove_rich_text_box_input(io->previousRichTextBoxToEdit);
|
||||
}
|
||||
}
|
||||
|
||||
void Toolbar::draw(SkCanvas* canvas) {
|
||||
|
|
|
|||
|
|
@ -259,20 +259,21 @@ void World::on_tab_in() {
|
|||
|
||||
void World::register_callbacks() {
|
||||
drawProg.register_callbacks();
|
||||
redoKeyCallback = main.input.keyCallbacks[InputManager::KEY_REDO].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
keyCallbacks[InputManager::KEY_REDO] = main.input.keyCallbacks[InputManager::KEY_REDO].register_callback([&](auto& key) {
|
||||
if(key.down)
|
||||
redo_with_checks();
|
||||
});
|
||||
undoKeyCallback = main.input.keyCallbacks[InputManager::KEY_UNDO].register_callback([&](auto& key) {
|
||||
if(key.down && !key.repeat)
|
||||
keyCallbacks[InputManager::KEY_UNDO] = main.input.keyCallbacks[InputManager::KEY_UNDO].register_callback([&](auto& key) {
|
||||
if(key.down)
|
||||
undo_with_checks();
|
||||
});
|
||||
}
|
||||
|
||||
void World::deregister_callbacks() {
|
||||
drawProg.deregister_callbacks();
|
||||
main.input.keyCallbacks[InputManager::KEY_REDO].deregister_callback(redoKeyCallback);
|
||||
main.input.keyCallbacks[InputManager::KEY_UNDO].deregister_callback(undoKeyCallback);
|
||||
for(auto& [key, callback] : keyCallbacks)
|
||||
main.input.keyCallbacks[key].deregister_callback(callback);
|
||||
keyCallbacks.clear();
|
||||
}
|
||||
|
||||
void World::send_chat_message(const std::string& message) {
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ class World {
|
|||
|
||||
std::shared_ptr<NetServer> netServer;
|
||||
std::shared_ptr<NetClient> netClient;
|
||||
|
||||
std::unordered_map<unsigned, InputManager::KeyCallbackManager::Callback*> keyCallbacks;
|
||||
private:
|
||||
InputManager::KeyCallbackManager::Callback* undoKeyCallback;
|
||||
InputManager::KeyCallbackManager::Callback* redoKeyCallback;
|
||||
void register_callbacks();
|
||||
void deregister_callbacks();
|
||||
|
||||
|
|
|
|||
17
src/main.cpp
17
src/main.cpp
|
|
@ -1,6 +1,7 @@
|
|||
#include "Helpers/SCollision.hpp"
|
||||
#include "Helpers/StringHelpers.hpp"
|
||||
#include "Helpers/FileDownloader.hpp"
|
||||
#include "VersionConstants.hpp"
|
||||
#include "include/gpu/GpuTypes.h"
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <SDL3/SDL_hints.h>
|
||||
|
|
@ -195,6 +196,14 @@ void get_refresh_rate(MainStruct& mS) {
|
|||
}
|
||||
|
||||
void initialize_sdl(MainStruct& mS, int wWidth, int wHeight) {
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, "InfiniPaint");
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, VersionConstants::CURRENT_VERSION_STRING.c_str());
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, "com.infinipaint.infinipaint");
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_CREATOR_STRING, "Yousef Khadadeh (ErrorAtLine0)");
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Copyright (c) 2026 Yousef Khadadeh");
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_URL_STRING, "https://infinipaint.com/");
|
||||
SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, "application");
|
||||
|
||||
SDL_SetHint(SDL_HINT_APP_NAME, "InfiniPaint");
|
||||
SDL_SetHint(SDL_HINT_PEN_MOUSE_EVENTS, "0");
|
||||
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
||||
|
|
@ -455,6 +464,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
|
|||
mS.m->documentsPath = std::filesystem::path(documentsPathSDL);
|
||||
#endif
|
||||
mS.m->window.sdlWindow = mS.window;
|
||||
mS.m->input.sdlWindow = mS.window;
|
||||
mS.m->update_scale_and_density();
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_beforeunload_callback((void*)mSPtr, emscripten_before_unload);
|
||||
|
|
@ -659,12 +669,6 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
|
|||
SDL_SetCursor(mS.systemCursors[static_cast<unsigned>(mS.m->input.cursorIcon)]);
|
||||
}
|
||||
|
||||
if(mS.m->input.text.get_accepting_input() && !mS.m->input.text.lastAcceptingTextInputVal)
|
||||
SDL_StartTextInput(mS.window);
|
||||
else if(!mS.m->input.text.get_accepting_input() && mS.m->input.text.lastAcceptingTextInputVal)
|
||||
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);
|
||||
regular_draw(mS);
|
||||
|
|
@ -769,7 +773,6 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
|||
mS.m->input.backend_key_up_update(event->key);
|
||||
break;
|
||||
case SDL_EVENT_TEXT_INPUT:
|
||||
mS.m->input.text.newInput += event->text.text;
|
||||
mS.m->input.text.add_text_to_textbox(event->text.text);
|
||||
break;
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue