infinipaint/src/GridManager.cpp

227 lines
9.6 KiB
C++
Raw Normal View History

2025-07-06 20:43:53 +03:00
#include "GridManager.hpp"
#include "World.hpp"
2025-09-17 17:17:43 +03:00
#include "MainProgram.hpp"
2026-01-02 19:24:12 +03:00
#include "WorldUndoManager.hpp"
2026-01-02 09:22:52 +03:00
#include <cereal/types/unordered_map.hpp>
2025-07-06 20:43:53 +03:00
2025-09-06 19:06:30 +03:00
GridManager::GridManager(World& w):
2025-12-10 17:23:05 +03:00
world(w) {}
2026-01-01 22:46:02 +03:00
void GridManager::server_init_no_file() {
grids = world.netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<WorldGrid>>();
2025-08-01 10:58:45 +03:00
}
2025-12-10 13:06:45 +03:00
void GridManager::add_default_grid(const std::string& newName) {
if(grids) {
WorldGrid g;
g.name = newName;
2025-12-16 23:06:46 +03:00
g.color = color_mul_alpha(convert_vec4<Vector4f>(world.canvasTheme.get_tool_front_color()), 0.4f);
2025-12-10 13:06:45 +03:00
g.size = world.drawData.cam.c.inverseScale * WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
g.offset = world.drawData.cam.c.pos + world.drawData.cam.c.dir_from_space(world.main.window.size.cast<float>() * 0.5f);
2026-01-02 19:24:12 +03:00
auto it = grids->emplace_back_direct(grids, g);
class AddGridWorldUndoAction : public WorldUndoAction {
public:
AddGridWorldUndoAction(std::unique_ptr<WorldGrid> initGridData, uint32_t newPos, WorldUndoManager::UndoObjectID initUndoID):
gridData(std::move(initGridData)),
pos(newPos),
2026-01-02 19:24:12 +03:00
undoID(initUndoID)
{}
std::string get_name() const override {
return "Add Grid";
}
2026-01-02 19:24:12 +03:00
bool undo(WorldUndoManager& undoMan) override {
std::optional<NetworkingObjects::NetObjID> toEraseID = undoMan.get_netid_from_undoid(undoID);
if(!toEraseID.has_value())
return false;
auto& gridList = undoMan.world.gridMan.grids;
auto it = gridList->get(toEraseID.value());
gridData = std::make_unique<WorldGrid>(*it->obj);
gridList->erase(gridList, it);
2026-01-02 19:24:12 +03:00
return true;
}
bool redo(WorldUndoManager& undoMan) override {
std::optional<NetworkingObjects::NetObjID> toInsertID = undoMan.get_netid_from_undoid(undoID);
if(toInsertID.has_value())
return false;
auto& gridList = undoMan.world.gridMan.grids;
auto insertedIt = gridList->emplace_direct(gridList, gridList->at(pos), *gridData);
2026-01-02 19:24:12 +03:00
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
gridData = nullptr;
2026-01-02 19:24:12 +03:00
return true;
}
void scale_up(const WorldScalar& scaleAmount) override {
if(gridData)
gridData->scale_up(scaleAmount);
2026-01-02 19:24:12 +03:00
}
~AddGridWorldUndoAction() {}
std::unique_ptr<WorldGrid> gridData;
uint32_t pos;
2026-01-02 19:24:12 +03:00
WorldUndoManager::UndoObjectID undoID;
};
world.undo.push(std::make_unique<AddGridWorldUndoAction>(std::make_unique<WorldGrid>(*it->obj), it->pos, world.undo.get_undoid_from_netid(it->obj.get_net_id())));
2025-07-06 20:43:53 +03:00
}
2025-09-06 19:06:30 +03:00
}
2025-07-06 20:43:53 +03:00
2025-12-10 13:06:45 +03:00
void GridManager::remove_grid(uint32_t indexToRemove) {
2026-01-02 19:24:12 +03:00
if(grids) {
2026-01-03 13:35:24 +03:00
class DeleteGridWorldUndoAction : public WorldUndoAction {
2026-01-02 19:24:12 +03:00
public:
DeleteGridWorldUndoAction(std::unique_ptr<WorldGrid> initGridData, uint32_t newPos, WorldUndoManager::UndoObjectID initUndoID):
gridData(std::move(initGridData)),
pos(newPos),
2026-01-02 19:24:12 +03:00
undoID(initUndoID)
{}
std::string get_name() const override {
2026-01-03 13:35:24 +03:00
return "Delete Grid";
}
2026-01-02 19:24:12 +03:00
bool undo(WorldUndoManager& undoMan) override {
std::optional<NetworkingObjects::NetObjID> toInsertID = undoMan.get_netid_from_undoid(undoID);
if(toInsertID.has_value())
return false;
auto& gridList = undoMan.world.gridMan.grids;
auto insertedIt = gridList->emplace_direct(gridList, gridList->at(pos), *gridData);
2026-01-02 19:24:12 +03:00
undoMan.register_new_netid_to_existing_undoid(undoID, insertedIt->obj.get_net_id());
gridData = nullptr;
2026-01-02 19:24:12 +03:00
return true;
}
bool redo(WorldUndoManager& undoMan) override {
std::optional<NetworkingObjects::NetObjID> toEraseID = undoMan.get_netid_from_undoid(undoID);
if(!toEraseID.has_value())
return false;
auto& gridList = undoMan.world.gridMan.grids;
auto it = gridList->get(toEraseID.value());
gridData = std::make_unique<WorldGrid>(*it->obj);
gridList->erase(gridList, it);
2026-01-02 19:24:12 +03:00
return true;
}
void scale_up(const WorldScalar& scaleAmount) override {
if(gridData)
gridData->scale_up(scaleAmount);
2026-01-02 19:24:12 +03:00
}
2026-01-03 13:35:24 +03:00
~DeleteGridWorldUndoAction() {}
2026-01-02 19:24:12 +03:00
std::unique_ptr<WorldGrid> gridData;
uint32_t pos;
2026-01-02 19:24:12 +03:00
WorldUndoManager::UndoObjectID undoID;
};
auto it = grids->at(indexToRemove);
world.undo.push(std::make_unique<DeleteGridWorldUndoAction>(std::make_unique<WorldGrid>(*it->obj), it->pos, world.undo.get_undoid_from_netid(it->obj.get_net_id())));
2026-01-02 19:24:12 +03:00
grids->erase(grids, it);
}
}
void GridManager::finalize_grid_modify(const NetworkingObjects::NetObjTemporaryPtr<WorldGrid>& wGrid, const WorldGrid& oldGridData) {
2026-01-03 13:35:24 +03:00
class EditGridWorldUndoAction : public WorldUndoAction {
2026-01-02 19:24:12 +03:00
public:
EditGridWorldUndoAction(std::unique_ptr<WorldGrid> initGridData, WorldUndoManager::UndoObjectID initUndoID):
gridData(std::move(initGridData)),
2026-01-02 19:24:12 +03:00
undoID(initUndoID)
{}
std::string get_name() const override {
2026-01-03 13:35:24 +03:00
return "Edit Grid";
}
2026-01-02 19:24:12 +03:00
bool undo(WorldUndoManager& undoMan) override {
return undo_redo(undoMan);
2026-01-02 19:24:12 +03:00
}
bool redo(WorldUndoManager& undoMan) override {
return undo_redo(undoMan);
}
bool undo_redo(WorldUndoManager& undoMan) {
2026-01-03 13:35:24 +03:00
std::optional<NetworkingObjects::NetObjID> toEditID = undoMan.get_netid_from_undoid(undoID);
if(!toEditID.has_value())
2026-01-02 19:24:12 +03:00
return false;
2026-01-03 13:35:24 +03:00
auto gridPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<WorldGrid>(toEditID.value());
auto newGrid = std::make_unique<WorldGrid>(*gridPtr);
*gridPtr = *gridData;
gridData = std::move(newGrid);
2026-01-02 19:24:12 +03:00
undoMan.world.delayedUpdateObjectManager.send_update_to_all<WorldGrid>(gridPtr, true);
return true;
}
void scale_up(const WorldScalar& scaleAmount) override {
gridData->scale_up(scaleAmount);
2026-01-02 19:24:12 +03:00
}
2026-01-03 13:35:24 +03:00
~EditGridWorldUndoAction() {}
2026-01-02 19:24:12 +03:00
std::unique_ptr<WorldGrid> gridData;
2026-01-02 19:24:12 +03:00
WorldUndoManager::UndoObjectID undoID;
};
world.undo.push(std::make_unique<EditGridWorldUndoAction>(std::make_unique<WorldGrid>(oldGridData), world.undo.get_undoid_from_netid(wGrid.get_net_id())));
2026-01-02 19:24:12 +03:00
world.delayedUpdateObjectManager.send_update_to_all<WorldGrid>(wGrid, true);
}
void GridManager::draw_back(SkCanvas* canvas, const DrawData& drawData) {
2025-12-10 13:06:45 +03:00
if(grids) {
for(uint32_t i = 0; i < grids->size(); i++) {
2025-12-13 13:03:27 +03:00
auto& g = grids->at(i)->obj;
if(!g->displayInFront)
g->draw(*this, canvas, drawData);
2025-12-10 13:06:45 +03:00
}
}
}
void GridManager::draw_front(SkCanvas* canvas, const DrawData& drawData) {
2025-12-10 13:06:45 +03:00
if(grids) {
for(uint32_t i = 0; i < grids->size(); i++) {
2025-12-13 13:03:27 +03:00
auto& g = grids->at(i)->obj;
if(g->displayInFront)
g->draw(*this, canvas, drawData);
2025-12-10 13:06:45 +03:00
}
}
}
void GridManager::draw_coordinates(SkCanvas* canvas, const DrawData& drawData) {
2025-12-10 13:06:45 +03:00
if(grids) {
Vector2f axisOffset{0.0f, 0.0f};
for(uint32_t i = 0; i < grids->size(); i++) {
2025-12-13 13:03:27 +03:00
auto& g = grids->at(i)->obj;
2025-12-10 13:06:45 +03:00
if(g->coordinatesWillBeDrawn && g->coordinatesAxisOnBounds) {
g->draw_coordinates(canvas, drawData, axisOffset);
g->coordinatesWillBeDrawn = false;
}
}
for(uint32_t i = 0; i < grids->size(); i++) {
2025-12-13 13:03:27 +03:00
auto& g = grids->at(i)->obj;
2025-12-10 13:06:45 +03:00
if(g->coordinatesWillBeDrawn && !g->coordinatesAxisOnBounds)
g->draw_coordinates(canvas, drawData, axisOffset);
g->coordinatesWillBeDrawn = false;
}
}
2025-07-06 20:43:53 +03:00
}
void GridManager::scale_up(const WorldScalar& scaleUpAmount) {
2025-12-10 13:06:45 +03:00
if(grids) {
2025-12-13 13:03:27 +03:00
for(uint32_t i = 0; i < grids->size(); i++)
grids->at(i)->obj->scale_up(scaleUpAmount);
}
}
2026-01-01 22:46:02 +03:00
void GridManager::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(grids->size());
for(auto& item : *grids)
a(*item.obj);
}
void GridManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) {
grids = world.netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<WorldGrid>>();
2026-01-02 09:22:52 +03:00
if(version >= VersionNumber(0, 4, 0)) {
uint32_t gridSize;
a(gridSize);
for(uint32_t i = 0; i < gridSize; i++) {
WorldGrid* g = new WorldGrid;
a(*g);
grids->push_back_and_send_create(grids, g);
}
}
else if(version >= VersionNumber(0, 2, 0)) {
std::unordered_map<NetworkingObjects::NetObjID, WorldGrid> gridMap;
a(gridMap);
for(auto& [netID, wGrid] : gridMap)
grids->emplace_back_direct(grids, wGrid);
2026-01-01 22:46:02 +03:00
}
}