2025-09-10 15:03:06 +03:00
|
|
|
#include "GridModifyTool.hpp"
|
|
|
|
|
#include "DrawingProgram.hpp"
|
|
|
|
|
#include "../MainProgram.hpp"
|
|
|
|
|
#include "../DrawData.hpp"
|
2025-12-10 17:23:05 +03:00
|
|
|
#include "Helpers/Networking/NetLibrary.hpp"
|
2025-12-11 16:05:41 +03:00
|
|
|
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
|
2025-12-10 13:06:45 +03:00
|
|
|
#include <Helpers/NetworkingObjects/NetObjWeakPtr.hpp>
|
|
|
|
|
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
|
2025-09-20 13:28:28 +03:00
|
|
|
#include <cstddef>
|
2025-09-10 15:03:06 +03:00
|
|
|
|
2025-12-10 13:06:45 +03:00
|
|
|
using namespace NetworkingObjects;
|
|
|
|
|
|
2025-09-10 15:03:06 +03:00
|
|
|
GridModifyTool::GridModifyTool(DrawingProgram& initDrawP):
|
|
|
|
|
DrawingProgramToolBase(initDrawP)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-11 16:05:41 +03:00
|
|
|
void GridModifyTool::set_grid(const NetObjWeakPtr<WorldGrid>& newGrid) {
|
2025-12-10 13:06:45 +03:00
|
|
|
grid = newGrid;
|
2025-12-11 16:05:41 +03:00
|
|
|
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
|
|
|
|
|
if(gLock) {
|
|
|
|
|
WorldGrid& g = *gLock;
|
2025-11-16 12:40:56 +03:00
|
|
|
oldGrid = g;
|
2025-09-17 17:17:43 +03:00
|
|
|
CoordSpaceHelper newCam;
|
|
|
|
|
newCam.inverseScale = g.size / WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
|
|
|
|
|
newCam.pos = g.offset - drawP.world.main.window.size.cast<WorldScalar>() * newCam.inverseScale * WorldScalar(0.5);
|
|
|
|
|
newCam.rotation = 0.0;
|
|
|
|
|
drawP.world.drawData.cam.smooth_move_to(drawP.world, newCam, drawP.world.main.window.size.cast<float>());
|
|
|
|
|
}
|
2025-09-10 15:03:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DrawingProgramToolType GridModifyTool::get_type() {
|
|
|
|
|
return DrawingProgramToolType::GRIDMODIFY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridModifyTool::gui_toolbox() {
|
|
|
|
|
Toolbar& t = drawP.world.main.toolbar;
|
|
|
|
|
t.gui.push_id("Grid modify tool");
|
|
|
|
|
t.gui.text_label_centered("Edit Grid");
|
2025-12-11 16:05:41 +03:00
|
|
|
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
|
|
|
|
|
if(gLock) {
|
|
|
|
|
WorldGrid& g = *gLock;
|
2025-09-24 13:32:50 +03:00
|
|
|
t.gui.input_text_field("grid name", "Name", &g.name);
|
2025-09-17 17:17:43 +03:00
|
|
|
t.gui.checkbox_field("Visible", "Visible", &g.visible);
|
2025-10-01 21:31:16 +03:00
|
|
|
t.gui.checkbox_field("Display in Front", "Display in front of canvas", &g.displayInFront);
|
2025-09-16 16:44:33 +03:00
|
|
|
size_t typeSelected = static_cast<size_t>(g.gridType);
|
|
|
|
|
std::vector<std::string> listOfGridTypes = {
|
|
|
|
|
"Circle Points",
|
|
|
|
|
"Square Points",
|
|
|
|
|
"Square Lines",
|
2025-10-04 15:31:05 +03:00
|
|
|
"Horizontal Lines"
|
2025-09-16 16:44:33 +03:00
|
|
|
};
|
|
|
|
|
t.gui.left_to_right_line_layout([&]() {
|
|
|
|
|
t.gui.text_label("Type");
|
|
|
|
|
t.gui.dropdown_select("filepicker select type", &typeSelected, listOfGridTypes, 200.0f);
|
|
|
|
|
});
|
|
|
|
|
g.gridType = static_cast<WorldGrid::GridType>(typeSelected);
|
2025-09-24 13:32:50 +03:00
|
|
|
uint32_t sDiv = g.subdivisions;
|
2025-09-23 19:53:45 +03:00
|
|
|
t.gui.input_scalar_field<uint32_t>("Subdivisions", "Subdivisions", &sDiv, 1, 10);
|
2025-09-16 16:44:33 +03:00
|
|
|
g.set_subdivisions(sDiv);
|
2025-09-24 13:32:50 +03:00
|
|
|
bool divOut = g.removeDivisionsOutwards;
|
2025-09-25 16:28:28 +03:00
|
|
|
t.gui.checkbox_field("Subdivide outwards", "Subdivide when zooming out", &divOut);
|
2025-09-16 16:44:33 +03:00
|
|
|
g.set_remove_divisions_outwards(divOut);
|
|
|
|
|
t.gui.left_to_right_line_layout([&]() {
|
2025-11-24 18:23:53 +03:00
|
|
|
if(t.gui.color_button_big("Grid Color", &g.color, &g.color == t.colorRight))
|
|
|
|
|
t.color_selector_right(&g.color == t.colorRight ? nullptr : &g.color);
|
2025-09-16 16:44:33 +03:00
|
|
|
t.gui.text_label("Grid Color");
|
|
|
|
|
});
|
2025-09-20 13:28:28 +03:00
|
|
|
bool bounded = g.bounds.has_value();
|
|
|
|
|
bool prevBoundedValue = bounded;
|
|
|
|
|
t.gui.checkbox_field("Bounded", "Bounded", &bounded);
|
|
|
|
|
if(bounded && !prevBoundedValue) {
|
|
|
|
|
SCollision::AABB<WorldScalar> newBounds;
|
|
|
|
|
newBounds.min = g.offset - drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast<float>() * 0.3f);
|
|
|
|
|
newBounds.max = g.offset + drawP.world.drawData.cam.c.dir_from_space(drawP.world.main.window.size.cast<float>() * 0.3f);
|
|
|
|
|
g.bounds = newBounds;
|
|
|
|
|
}
|
|
|
|
|
else if(!bounded && prevBoundedValue)
|
|
|
|
|
g.bounds = std::nullopt;
|
2025-09-25 16:28:28 +03:00
|
|
|
t.gui.checkbox_field("Show Coordinates", "Show Coordinates (visible\nwhen canvas isn't rotated)", &g.showCoordinates);
|
2025-09-16 16:44:33 +03:00
|
|
|
}
|
2025-09-10 15:03:06 +03:00
|
|
|
t.gui.pop_id();
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-01 17:33:14 +03:00
|
|
|
bool GridModifyTool::right_click_popup_gui(Vector2f popupPos) {
|
|
|
|
|
Toolbar& t = drawP.world.main.toolbar;
|
|
|
|
|
t.paint_popup(popupPos);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-10 15:03:06 +03:00
|
|
|
void GridModifyTool::tool_update() {
|
2025-12-11 16:05:41 +03:00
|
|
|
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
|
|
|
|
|
if(gLock) {
|
|
|
|
|
WorldGrid& g = *gLock;
|
2025-09-18 18:02:11 +03:00
|
|
|
switch(selectionMode) {
|
2025-09-20 13:28:28 +03:00
|
|
|
case 0:
|
2025-09-18 18:02:11 +03:00
|
|
|
if(drawP.controls.leftClick) {
|
|
|
|
|
Vector2f gOffsetScreenPos = drawP.world.drawData.cam.c.to_space(g.offset);
|
|
|
|
|
Vector2f gSizeScreenPos = drawP.world.drawData.cam.c.to_space(g.offset + WorldVec{g.size, 0});
|
2025-11-23 15:02:02 +03:00
|
|
|
if(SCollision::collide(SCollision::Circle(gOffsetScreenPos, drawP.drag_point_radius()), drawP.world.main.input.mouse.pos))
|
2025-09-18 18:02:11 +03:00
|
|
|
selectionMode = 1;
|
2025-11-23 15:02:02 +03:00
|
|
|
else if(SCollision::collide(SCollision::Circle(gSizeScreenPos, drawP.drag_point_radius()), drawP.world.main.input.mouse.pos))
|
2025-09-18 18:02:11 +03:00
|
|
|
selectionMode = 2;
|
2025-09-20 13:28:28 +03:00
|
|
|
else if(g.bounds.has_value()) {
|
|
|
|
|
const auto& b = g.bounds.value();
|
|
|
|
|
Vector2f bMin = drawP.world.drawData.cam.c.to_space(b.min);
|
|
|
|
|
Vector2f bMax = drawP.world.drawData.cam.c.to_space(b.max);
|
2025-11-23 15:02:02 +03:00
|
|
|
if(SCollision::collide(SCollision::Circle(bMin, drawP.drag_point_radius()), drawP.world.main.input.mouse.pos))
|
2025-09-20 13:28:28 +03:00
|
|
|
selectionMode = 3;
|
2025-11-23 15:02:02 +03:00
|
|
|
else if(SCollision::collide(SCollision::Circle(bMax, drawP.drag_point_radius()), drawP.world.main.input.mouse.pos))
|
2025-09-20 13:28:28 +03:00
|
|
|
selectionMode = 4;
|
|
|
|
|
}
|
2025-09-18 18:02:11 +03:00
|
|
|
}
|
|
|
|
|
break;
|
2025-09-20 13:28:28 +03:00
|
|
|
case 1:
|
|
|
|
|
if(drawP.controls.leftClickHeld)
|
|
|
|
|
g.offset = drawP.world.get_mouse_world_pos();
|
|
|
|
|
else
|
2025-09-18 18:02:11 +03:00
|
|
|
selectionMode = 0;
|
|
|
|
|
break;
|
2025-09-20 13:28:28 +03:00
|
|
|
case 2:
|
|
|
|
|
if(drawP.controls.leftClickHeld)
|
|
|
|
|
g.size = std::max(FixedPoint::abs(drawP.world.get_mouse_world_pos().x() - g.offset.x()), WorldScalar(1));
|
|
|
|
|
else
|
|
|
|
|
selectionMode = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
if(drawP.controls.leftClickHeld && g.bounds.has_value()) {
|
|
|
|
|
auto& b = g.bounds.value();
|
|
|
|
|
b.min = cwise_vec_min(drawP.world.get_mouse_world_pos(), b.max);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
selectionMode = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
if(drawP.controls.leftClickHeld && g.bounds.has_value()) {
|
|
|
|
|
auto& b = g.bounds.value();
|
|
|
|
|
b.max = cwise_vec_max(drawP.world.get_mouse_world_pos(), b.min);
|
|
|
|
|
}
|
|
|
|
|
else
|
2025-09-18 18:02:11 +03:00
|
|
|
selectionMode = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-12-13 13:03:27 +03:00
|
|
|
drawP.world.delayedUpdateObjectManager.send_update_to_all<WorldGrid>(gLock, nullptr, false);
|
2025-09-18 18:02:11 +03:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
selectionMode = 0;
|
2025-09-10 15:03:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GridModifyTool::prevent_undo_or_redo() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) {
|
2025-12-11 16:05:41 +03:00
|
|
|
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
|
|
|
|
|
if(gLock) {
|
|
|
|
|
WorldGrid& g = *gLock;
|
2025-09-20 13:28:28 +03:00
|
|
|
if(g.bounds.has_value()) {
|
|
|
|
|
const auto& b = g.bounds.value();
|
|
|
|
|
Vector2f bMin = drawP.world.drawData.cam.c.to_space(b.min);
|
|
|
|
|
Vector2f bMax = drawP.world.drawData.cam.c.to_space(b.max);
|
|
|
|
|
SkPaint rectBoundsPaint;
|
|
|
|
|
rectBoundsPaint.setColor4f(drawP.world.canvasTheme.toolFrontColor);
|
|
|
|
|
rectBoundsPaint.setStroke(true);
|
|
|
|
|
rectBoundsPaint.setStrokeWidth(0.0f);
|
|
|
|
|
canvas->drawRect(SkRect::MakeLTRB(bMin.x(), bMin.y(), bMax.x(), bMax.y()), rectBoundsPaint);
|
|
|
|
|
if(selectionMode == 0 || selectionMode == 4)
|
|
|
|
|
drawP.draw_drag_circle(canvas, bMax, {0.9f, 0.5f, 0.1f, 1.0f}, drawData);
|
|
|
|
|
if(selectionMode == 0 || selectionMode == 3)
|
|
|
|
|
drawP.draw_drag_circle(canvas, bMin, {0.9f, 0.5f, 0.1f, 1.0f}, drawData);
|
|
|
|
|
}
|
2025-09-18 18:02:11 +03:00
|
|
|
if(selectionMode == 0 || selectionMode == 2) {
|
2025-09-20 13:28:28 +03:00
|
|
|
Vector2f gSizeScreenPos;
|
|
|
|
|
if(drawP.world.get_mouse_world_pos().x() < g.offset.x() && selectionMode == 2)
|
|
|
|
|
gSizeScreenPos = drawData.cam.c.to_space(g.offset - WorldVec{g.size, 0});
|
|
|
|
|
else
|
|
|
|
|
gSizeScreenPos = drawData.cam.c.to_space(g.offset + WorldVec{g.size, 0});
|
2025-09-18 18:02:11 +03:00
|
|
|
drawP.draw_drag_circle(canvas, gSizeScreenPos, {0.1f, 0.9f, 0.9f, 1.0f}, drawData);
|
|
|
|
|
}
|
2025-09-20 13:28:28 +03:00
|
|
|
if(selectionMode == 0 || selectionMode == 1 || selectionMode == 3 || selectionMode == 4) {
|
2025-09-18 18:02:11 +03:00
|
|
|
Vector2f gOffset = drawData.cam.c.to_space(g.offset);
|
|
|
|
|
drawP.draw_drag_circle(canvas, gOffset, {1.0f, 0.27f, 0.27f, 1.0f}, drawData);
|
|
|
|
|
}
|
2025-09-17 17:17:43 +03:00
|
|
|
}
|
2025-09-10 15:03:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridModifyTool::switch_tool(DrawingProgramToolType newTool) {
|
2025-12-11 16:05:41 +03:00
|
|
|
NetworkingObjects::NetObjTemporaryPtr<WorldGrid> gLock = grid.lock();
|
|
|
|
|
if(gLock)
|
2025-12-13 13:03:27 +03:00
|
|
|
drawP.world.delayedUpdateObjectManager.send_update_to_all<WorldGrid>(gLock, nullptr, true);
|
2025-09-10 15:03:06 +03:00
|
|
|
}
|