Screenshot tool works with events

This commit is contained in:
Yousef Khadadeh 2026-03-03 13:10:27 +03:00
parent 017102a2b1
commit 451bf9b6b2
2 changed files with 179 additions and 143 deletions

View file

@ -53,11 +53,11 @@ void ScreenshotTool::gui_toolbox() {
t.gui.push_id("screenshot tool");
t.gui.text_label_centered("Screenshot");
auto oldImgSize = controls.imageSize;
if(controls.selectionMode == 0)
if(controls.selectionMode == ScreenshotControls::SelectionMode::NO_SELECTION)
t.gui.text_label("Select an area on the canvas...");
if(controls.selectionMode != 0 && screenshotConfig.selectedType != SCREENSHOT_SVG)
if(controls.selectionMode != ScreenshotControls::SelectionMode::NO_SELECTION && screenshotConfig.selectedType != SCREENSHOT_SVG)
t.gui.input_scalar_fields("Image Size", "Image Size", &controls.imageSize, 2, 0, 999999999);
if(controls.selectionMode == 2) {
if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS) {
t.gui.left_to_right_line_layout([&]() {
t.gui.text_label("Image Type");
t.gui.dropdown_select("image type select", (size_t*)(&screenshotConfig.selectedType), controls.typeSelections);
@ -79,7 +79,7 @@ void ScreenshotTool::gui_toolbox() {
controls.imageSize.x() = controls.imageSize.y() * (controls.rectX2 - controls.rectX1) / (controls.rectY2 - controls.rectY1);
}
if(t.gui.text_button_wide("Take Screenshot", "Take Screenshot")) {
controls.selectionMode = 0;
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
#ifdef __EMSCRIPTEN__
take_screenshot("a" + controls.typeSelections[screenshotConfig.selectedType]);
#else
@ -119,6 +119,165 @@ bool ScreenshotTool::right_click_popup_gui(Vector2f popupPos) {
return true;
}
void ScreenshotTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) {
if(button.button == InputManager::MouseButton::LEFT) {
switch(controls.selectionMode) {
case ScreenshotControls::SelectionMode::NO_SELECTION: {
if(button.down) {
controls.rectX1 = controls.rectX2 = button.pos.x();
controls.rectY1 = controls.rectY2 = button.pos.y();
controls.coords = drawP.world.drawData.cam.c;
controls.dragType = 0;
controls.selectionMode = ScreenshotControls::SelectionMode::DRAGGING_BORDER;
}
break;
}
case ScreenshotControls::SelectionMode::DRAGGING_BORDER: {
if(!button.down && dragging_border_update(button.pos)) {
controls.selectionMode = ScreenshotControls::SelectionMode::SELECTION_EXISTS;
commit_rect();
}
break;
}
case ScreenshotControls::SelectionMode::SELECTION_EXISTS: {
if(button.down && selection_exists_update()) {
for(int i = 0; i < 8; i++)
if(SCollision::collide(controls.circles[i], drawP.world.main.input.mouse.pos))
controls.dragType = i;
if(controls.dragType == -1) {
Vector2f mousePosScreenshotCoords = controls.coords.from_cam_space_to_this(drawP.world, button.pos);
if(SCollision::collide(mousePosScreenshotCoords, SCollision::AABB<float>({controls.rectX1, controls.rectY1}, {controls.rectX2, controls.rectY2})))
controls.dragType = -2;
}
if(controls.dragType == -1)
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
else if(controls.dragType == -2) {
controls.translateBeginPos = drawP.world.drawData.cam.c.from_space(button.pos);
controls.translateBeginCoords = controls.coords;
controls.selectionMode = ScreenshotControls::SelectionMode::DRAGGING_AREA;
}
else
controls.selectionMode = ScreenshotControls::SelectionMode::DRAGGING_BORDER;
}
break;
}
case ScreenshotControls::SelectionMode::DRAGGING_AREA: {
if(!button.down && dragging_border_update(button.pos)) {
controls.selectionMode = ScreenshotControls::SelectionMode::SELECTION_EXISTS;
commit_rect();
}
break;
}
}
}
}
void ScreenshotTool::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {
switch(controls.selectionMode) {
case ScreenshotControls::SelectionMode::NO_SELECTION: {
break;
}
case ScreenshotControls::SelectionMode::DRAGGING_BORDER: {
dragging_border_update(motion.pos);
break;
}
case ScreenshotControls::SelectionMode::SELECTION_EXISTS: {
break;
}
case ScreenshotControls::SelectionMode::DRAGGING_AREA: {
dragging_area_update(motion.pos);
break;
}
}
}
bool ScreenshotTool::dragging_border_update(const Vector2f& camCursorPos) {
auto& screenshotConfig = drawP.world.main.toolConfig.screenshot;
Vector2f curPos = controls.coords.from_cam_space_to_this(drawP.world, camCursorPos);
float oldX1 = controls.rectX1;
float oldX2 = controls.rectX2;
float oldY1 = controls.rectY1;
float oldY2 = controls.rectY2;
switch(controls.dragType) {
case 0:
controls.rectX2 = curPos.x();
controls.rectY2 = curPos.y();
break;
case 1:
controls.rectY2 = curPos.y();
break;
case 2:
controls.rectX1 = curPos.x();
controls.rectY2 = curPos.y();
break;
case 3:
controls.rectX1 = curPos.x();
break;
case 4:
controls.rectX1 = curPos.x();
controls.rectY1 = curPos.y();
break;
case 5:
controls.rectY1 = curPos.y();
break;
case 6:
controls.rectX2 = curPos.x();
controls.rectY1 = curPos.y();
break;
case 7:
controls.rectX2 = curPos.x();
break;
}
if(std::fabs(controls.rectX1 - controls.rectX2) > 1e10 || std::fabs(controls.rectY1 - controls.rectY2) > 1e10) { // Limit before screenshot tool starts breaking
controls.rectX1 = oldX1;
controls.rectX2 = oldX2;
controls.rectY1 = oldY1;
controls.rectY2 = oldY2;
}
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
return false;
}
float tempX1 = std::min(controls.rectX1, controls.rectX2);
float tempX2 = std::max(controls.rectX1, controls.rectX2);
float tempY1 = std::min(controls.rectY1, controls.rectY2);
float tempY2 = std::max(controls.rectY1, controls.rectY2);
if(screenshotConfig.setDimensionIsX) {
controls.imageSize.x() = screenshotConfig.setDimensionSize;
controls.imageSize.y() = controls.imageSize.x() * (tempY2 - tempY1) / (tempX2 - tempX1);
}
else {
controls.imageSize.y() = screenshotConfig.setDimensionSize;
controls.imageSize.x() = controls.imageSize.y() * (tempX2 - tempX1) / (tempY2 - tempY1);
}
return true;
}
bool ScreenshotTool::selection_exists_update() {
commit_rect();
controls.dragType = -1;
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
return false;
}
return true;
}
bool ScreenshotTool::dragging_area_update(const Vector2f& camCursorPos) {
controls.coords = controls.translateBeginCoords;
controls.coords.translate(drawP.world.drawData.cam.c.from_space(camCursorPos) - controls.translateBeginPos);
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
return false;
}
return true;
}
void ScreenshotTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) {
}
@ -302,138 +461,16 @@ void ScreenshotTool::take_screenshot_area_hw(const sk_sp<SkSurface>& surface, Sk
}
void ScreenshotTool::switch_tool(DrawingProgramToolType newTool) {
controls.selectionMode = 0;
controls.selectionMode = ScreenshotControls::SelectionMode::NO_SELECTION;
}
void ScreenshotTool::tool_update() {
auto& screenshotConfig = drawP.world.main.toolConfig.screenshot;
if(controls.setToTakeScreenshot) {
controls.setToTakeScreenshot = false;
take_screenshot(controls.screenshotSavePath);
}
switch(controls.selectionMode) {
case 0: {
if(drawP.controls.leftClick) {
controls.rectX1 = controls.rectX2 = drawP.world.main.input.mouse.pos.x();
controls.rectY1 = controls.rectY2 = drawP.world.main.input.mouse.pos.y();
controls.coords = drawP.world.drawData.cam.c;
controls.dragType = 0;
controls.selectionMode = 1;
}
break;
}
case 1: {
Vector2f curPos = controls.coords.get_mouse_pos(drawP.world);
float oldX1 = controls.rectX1;
float oldX2 = controls.rectX2;
float oldY1 = controls.rectY1;
float oldY2 = controls.rectY2;
switch(controls.dragType) {
case 0:
controls.rectX2 = curPos.x();
controls.rectY2 = curPos.y();
break;
case 1:
controls.rectY2 = curPos.y();
break;
case 2:
controls.rectX1 = curPos.x();
controls.rectY2 = curPos.y();
break;
case 3:
controls.rectX1 = curPos.x();
break;
case 4:
controls.rectX1 = curPos.x();
controls.rectY1 = curPos.y();
break;
case 5:
controls.rectY1 = curPos.y();
break;
case 6:
controls.rectX2 = curPos.x();
controls.rectY1 = curPos.y();
break;
case 7:
controls.rectX2 = curPos.x();
break;
}
if(std::fabs(controls.rectX1 - controls.rectX2) > 1e10 || std::fabs(controls.rectY1 - controls.rectY2) > 1e10) { // Limit before screenshot tool starts breaking
controls.rectX1 = oldX1;
controls.rectX2 = oldX2;
controls.rectY1 = oldY1;
controls.rectY2 = oldY2;
}
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = 0;
break;
}
float tempX1 = std::min(controls.rectX1, controls.rectX2);
float tempX2 = std::max(controls.rectX1, controls.rectX2);
float tempY1 = std::min(controls.rectY1, controls.rectY2);
float tempY2 = std::max(controls.rectY1, controls.rectY2);
if(screenshotConfig.setDimensionIsX) {
controls.imageSize.x() = screenshotConfig.setDimensionSize;
controls.imageSize.y() = controls.imageSize.x() * (tempY2 - tempY1) / (tempX2 - tempX1);
}
else {
controls.imageSize.y() = screenshotConfig.setDimensionSize;
controls.imageSize.x() = controls.imageSize.y() * (tempX2 - tempX1) / (tempY2 - tempY1);
}
if(!drawP.controls.leftClickHeld) {
controls.selectionMode = 2;
commit_rect();
}
break;
}
case 2: {
commit_rect();
controls.dragType = -1;
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = 0;
break;
}
if(drawP.controls.cursorHoveringOverCanvas && drawP.controls.leftClick) {
for(int i = 0; i < 8; i++)
if(SCollision::collide(controls.circles[i], drawP.world.main.input.mouse.pos))
controls.dragType = i;
if(controls.dragType == -1) {
Vector2f mousePosScreenshotCoords = controls.coords.get_mouse_pos(drawP.world);
if(SCollision::collide(mousePosScreenshotCoords, SCollision::AABB<float>({controls.rectX1, controls.rectY1}, {controls.rectX2, controls.rectY2})))
controls.dragType = -2;
}
if(controls.dragType == -1)
controls.selectionMode = 0;
else if(controls.dragType == -2) {
controls.translateBeginPos = drawP.world.get_mouse_world_pos();
controls.translateBeginCoords = controls.coords;
controls.selectionMode = 3;
}
else
controls.selectionMode = 1;
}
break;
}
case 3: {
controls.coords = controls.translateBeginCoords;
controls.coords.translate(drawP.world.get_mouse_world_pos() - controls.translateBeginPos);
if((drawP.world.drawData.cam.c.inverseScale << 8) < controls.coords.inverseScale || (drawP.world.drawData.cam.c.inverseScale >> 15) > controls.coords.inverseScale) {
controls.selectionMode = 0;
break;
}
if(!drawP.controls.leftClickHeld) {
controls.selectionMode = 2;
commit_rect();
}
break;
}
}
if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS)
selection_exists_update();
}
void ScreenshotTool::commit_rect() {
@ -461,7 +498,7 @@ bool ScreenshotTool::prevent_undo_or_redo() {
}
void ScreenshotTool::draw(SkCanvas* canvas, const DrawData& drawData) {
if(controls.selectionMode == 0) {
if(controls.selectionMode == ScreenshotControls::SelectionMode::NO_SELECTION) {
SkPaint paint1;
paint1.setColor4f({0.0f, 0.0f, 0.0f, 0.3f});
canvas->drawPaint(paint1);
@ -491,7 +528,7 @@ void ScreenshotTool::draw(SkCanvas* canvas, const DrawData& drawData) {
canvas->restore();
if(controls.selectionMode == 2) {
if(controls.selectionMode == ScreenshotControls::SelectionMode::SELECTION_EXISTS) {
paint2.setStyle(SkPaint::kFill_Style);
for(auto& circ : controls.circles)
drawP.draw_drag_circle(canvas, circ.pos, {0.1f, 0.9f, 0.9f, 1.0f}, drawData, 1.0f);

View file

@ -18,6 +18,8 @@ class ScreenshotTool : public DrawingProgramToolBase {
virtual void draw(SkCanvas* canvas, const DrawData& drawData) override;
virtual void switch_tool(DrawingProgramToolType newTool) override;
virtual bool prevent_undo_or_redo() 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;
enum ScreenshotType : size_t {
SCREENSHOT_JPG,
@ -31,17 +33,6 @@ class ScreenshotTool : public DrawingProgramToolBase {
void take_screenshot_area_hw(const sk_sp<SkSurface>& surface, SkCanvas* canvas, void* fullImgRawData, const Vector2i& fullImageSize, const Vector2i& sectionImagePos, const Vector2i& sectionImageSize, const Vector2i& canvasSize, bool transparentBackground);
void take_screenshot_svg(SkCanvas* canvas, bool transparentBackground);
//static constexpr std::array<InputManager::SystemCursorType, 8> cursors{
// InputManager::SystemCursorType::SE_RESIZE,
// InputManager::SystemCursorType::S_RESIZE,
// InputManager::SystemCursorType::SW_RESIZE,
// InputManager::SystemCursorType::W_RESIZE,
// InputManager::SystemCursorType::NW_RESIZE,
// InputManager::SystemCursorType::N_RESIZE,
// InputManager::SystemCursorType::NE_RESIZE,
// InputManager::SystemCursorType::E_RESIZE
//};
struct ScreenshotControls {
CoordSpaceHelper translateBeginCoords;
WorldVec translateBeginPos;
@ -51,7 +42,12 @@ class ScreenshotTool : public DrawingProgramToolBase {
float rectX2;
float rectY1;
float rectY2;
int selectionMode = 0;
enum class SelectionMode {
NO_SELECTION,
DRAGGING_BORDER,
SELECTION_EXISTS,
DRAGGING_AREA
} selectionMode;
int dragType = 0;
Vector2i imageSize = {0, 0};
std::array<SCollision::Circle<float>, 8> circles;
@ -64,6 +60,9 @@ class ScreenshotTool : public DrawingProgramToolBase {
std::atomic<bool> setToTakeScreenshot = false;
std::filesystem::path screenshotSavePath;
} controls;
bool dragging_border_update(const Vector2f& camCursorPos);
bool selection_exists_update();
bool dragging_area_update(const Vector2f& camCursorPos);
};
NLOHMANN_JSON_SERIALIZE_ENUM(ScreenshotTool::ScreenshotType, {