Reimplementing save/load file

This commit is contained in:
Yousef Khadadeh 2026-01-01 22:46:02 +03:00
parent 260288a1b0
commit 9913eb6c8e
37 changed files with 437 additions and 350 deletions

View file

@ -45,8 +45,8 @@ DrawingProgram::DrawingProgram(World& initWorld):
drawTool = DrawingProgramToolBase::allocate_tool_type(*this, DrawingProgramToolType::BRUSH);
}
void DrawingProgram::init() {
layerMan.init();
void DrawingProgram::server_init_no_file() {
layerMan.server_init_no_file();
}
void DrawingProgram::scale_up(const WorldScalar& scaleUpAmount) {
@ -83,7 +83,7 @@ void DrawingProgram::init_server_callbacks() {
}
void DrawingProgram::init_client_callbacks() {
world.con.client_add_recv_callback(CLIENT_TRANSFORM_MANY_COMPONENTS, [&](cereal::PortableBinaryInputArchive& message) {
world.netClient->add_recv_callback(CLIENT_TRANSFORM_MANY_COMPONENTS, [&](cereal::PortableBinaryInputArchive& message) {
std::vector<std::pair<NetworkingObjects::NetObjID, CoordSpaceHelper>> transforms;
message(transforms);
process_transform_message(transforms);
@ -111,7 +111,7 @@ void DrawingProgram::send_transforms_for(const std::vector<CanvasComponentContai
if(world.netObjMan.is_server())
world.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms);
else
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_MANY_COMPONENTS, transforms);
world.netClient->send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_MANY_COMPONENTS, transforms);
}
}
@ -538,29 +538,11 @@ void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, co
}
void DrawingProgram::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) {
//uint64_t compCount;
//a(compCount);
//for(uint64_t i = 0; i < compCount; i++) {
// DrawComponentType t;
// a(t);
// auto newComp = DrawComponent::allocate_comp_type(t);
// a(newComp->id, newComp->coords);
// newComp->load_file(a, version);
// components.init_emplace_back(newComp);
//}
//parallel_loop_all_components([&](const auto& c){
// c->obj->commit_update(*this, false);
//});
//compCache.test_rebuild(components.client_list(), true);
layerMan.load_file(a, version);
}
void DrawingProgram::save_file(cereal::PortableBinaryOutputArchive& a) const {
//auto& cList = components->get_data();
//a((uint64_t)cList.size());
//for(size_t i = 0; i < cList.size(); i++) {
// a(cList[i]->obj->get_type(), cList[i]->obj->id, cList[i]->obj->coords);
// cList[i]->obj->save_file(a);
//}
layerMan.save_file(a);
}
void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {

View file

@ -23,7 +23,7 @@ class World;
class DrawingProgram {
public:
DrawingProgram(World& initWorld);
void init();
void server_init_no_file();
void toolbar_gui();
void tool_options_gui();
bool right_click_popup_gui(Vector2f popupPos);

View file

@ -1,6 +1,7 @@
#include "DrawingProgramLayer.hpp"
#include "DrawingProgramLayerManager.hpp"
#include "../DrawingProgram.hpp"
#include "../../World.hpp"
#include <Helpers/Parallel.hpp>
void DrawingProgramLayer::draw(SkCanvas* canvas, const DrawData& drawData) const {
@ -12,8 +13,10 @@ void DrawingProgramLayer::set_component_list_callbacks(DrawingProgramLayerListIt
auto insertCallback = [&](const CanvasComponentContainer::ObjInfoIterator& c) {
c->obj->objInfo = c;
c->obj->parentLayer = &layerListItem;
c->obj->commit_update(layerMan.drawP); // Run commit update on insert so that world bounds are calculated
layerMan.drawP.drawCache.add_component(&(*c));
if(layerMan.commitUpdateOnComponentInsert) {
c->obj->commit_update(layerMan.drawP); // Run commit update on insert so that world bounds are calculated
layerMan.drawP.drawCache.add_component(&(*c));
}
if(c->obj->get_comp().get_type() == CanvasComponentType::IMAGE)
layerMan.drawP.updateableComponents.emplace(&(*c));
};
@ -41,12 +44,6 @@ void DrawingProgramLayer::set_to_erase() {
eraseCallback(it);
}
void DrawingProgramLayer::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const {
parallel_loop_container(*components, [&layerMan](auto& comp) {
comp.obj->commit_update_dont_invalidate_cache(layerMan.drawP);
});
}
void DrawingProgramLayer::get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const {
for(auto& p : *components)
objList.emplace_back(&p);
@ -56,3 +53,20 @@ void DrawingProgramLayer::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& p : *components)
p.obj->scale_up(scaleUpAmount);
}
void DrawingProgramLayer::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) {
components = layerMan.drawP.world.netObjMan.make_obj<CanvasComponentContainer::NetList>();
uint32_t layerListSize;
a(layerListSize);
for(uint32_t i = 0; i < layerListSize; i++) {
CanvasComponentContainer* item = new CanvasComponentContainer();
item->load_file(a, version, layerMan.drawP.world.netObjMan);
components->push_back_and_send_create(components, item);
}
}
void DrawingProgramLayer::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(components->size());
for(auto& comp : *components)
comp.obj->save_file(a);
}

View file

@ -10,12 +10,14 @@ class DrawingProgramLayer {
public:
void draw(SkCanvas* canvas, const DrawData& drawData) const;
void set_component_list_callbacks(DrawingProgramLayerListItem& layerListItem, DrawingProgramLayerManager& layerMan);
void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const;
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const;
void set_to_erase();
void scale_up(const WorldScalar& scaleUpAmount);
CanvasComponentContainer::NetListOwnerPtr components;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan);
void save_file(cereal::PortableBinaryOutputArchive& a) const;
private:
std::function<void(const CanvasComponentContainer::ObjInfoIterator& c)> eraseCallback;
};

View file

@ -2,6 +2,9 @@
#include "DrawingProgramLayerListItem.hpp"
#include "DrawingProgramLayer.hpp"
#include <Helpers/Parallel.hpp>
#include "DrawingProgramLayerManager.hpp"
#include "../DrawingProgram.hpp"
#include "../../World.hpp"
void DrawingProgramLayerFolder::draw(SkCanvas* canvas, const DrawData& drawData) const {
for(auto& p : (*folderList) | std::views::reverse)
@ -24,11 +27,6 @@ void DrawingProgramLayerFolder::set_to_erase() {
listItem.obj->set_to_erase();
}
void DrawingProgramLayerFolder::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const {
for(auto& listItem : *folderList)
listItem.obj->commit_update_dont_invalidate_cache(layerMan);
}
void DrawingProgramLayerFolder::get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const {
for(auto& listItem : (*folderList) | std::views::reverse)
listItem.obj->get_flattened_component_list(objList);
@ -54,3 +52,20 @@ void DrawingProgramLayerFolder::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& p : *folderList)
p.obj->scale_up(scaleUpAmount);
}
void DrawingProgramLayerFolder::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) {
folderList = layerMan.drawP.world.netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>>();
uint32_t folderListSize;
a(folderListSize);
for(uint32_t i = 0; i < folderListSize; i++) {
DrawingProgramLayerListItem* item = new DrawingProgramLayerListItem();
item->load_file(a, version, layerMan);
folderList->push_back_and_send_create(folderList, item);
}
}
void DrawingProgramLayerFolder::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(folderList->size());
for(auto& listItem : *folderList)
listItem.obj->save_file(a);
}

View file

@ -11,7 +11,6 @@ class DrawingProgramLayerFolder {
public:
void draw(SkCanvas* canvas, const DrawData& drawData) const;
void set_component_list_callbacks(DrawingProgramLayerManager& layerMan);
void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const;
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const;
void set_to_erase();
NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> get_initial_editing_layer() const;
@ -19,4 +18,7 @@ class DrawingProgramLayerFolder {
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>> folderList;
bool isFolderOpen = false;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan);
void save_file(cereal::PortableBinaryOutputArchive& a) const;
};

View file

@ -46,13 +46,6 @@ void DrawingProgramLayerListItem::set_component_list_callbacks(DrawingProgramLay
layerData->set_component_list_callbacks(*this, layerMan);
}
void DrawingProgramLayerListItem::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) {
if(folderData)
folderData->commit_update_dont_invalidate_cache(layerMan);
else
layerData->commit_update_dont_invalidate_cache(layerMan);
}
void DrawingProgramLayerListItem::get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const {
if(folderData)
folderData->get_flattened_component_list(objList);
@ -99,6 +92,35 @@ DrawingProgramLayer& DrawingProgramLayerListItem::get_layer() const {
return *layerData;
}
void DrawingProgramLayerListItem::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan) {
nameData = layerMan.drawP.world.netObjMan.make_obj<NameData>();
a(*nameData);
displayData = layerMan.drawP.world.netObjMan.make_obj<DisplayData>();
a(*displayData);
bool isFolder;
a(isFolder);
if(isFolder) {
folderData = std::make_unique<DrawingProgramLayerFolder>();
folderData->load_file(a, version, layerMan);
}
else {
layerData = std::make_unique<DrawingProgramLayer>();
layerData->load_file(a, version, layerMan);
}
}
void DrawingProgramLayerListItem::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(*nameData);
a(*displayData);
a(static_cast<bool>(folderData));
if(folderData)
folderData->save_file(a);
else
layerData->save_file(a);
}
void DrawingProgramLayerListItem::draw(SkCanvas* canvas, const DrawData& drawData) const {
if(displayData->visible) {
SkPaint layerPaint;

View file

@ -23,7 +23,6 @@ class DrawingProgramLayerListItem {
void reassign_netobj_ids_call();
void set_to_erase();
void set_component_list_callbacks(DrawingProgramLayerManager &layerMan);
void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan);
void draw(SkCanvas* canvas, const DrawData& drawData) const;
void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) const;
const std::string& get_name() const;
@ -34,6 +33,9 @@ class DrawingProgramLayerListItem {
void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const;
float get_alpha() const;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version, DrawingProgramLayerManager& layerMan);
void save_file(cereal::PortableBinaryOutputArchive& a) const;
void set_visible(DrawingProgramLayerManager& layerMan, bool newVisible) const;
bool get_visible() const;

View file

@ -1,18 +1,17 @@
#include "DrawingProgramLayerManager.hpp"
#include "../../World.hpp"
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
#include "Helpers/Parallel.hpp"
DrawingProgramLayerManager::DrawingProgramLayerManager(DrawingProgram& drawProg):
drawP(drawProg), // initialize drawP first for next objects to be initialized properly
listGUI(*this)
{}
void DrawingProgramLayerManager::init() {
if(drawP.world.netObjMan.is_server()) {
layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr<DrawingProgramLayerListItem>(new DrawingProgramLayerListItem(drawP.world.netObjMan, "ROOT", true));
layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well
editingLayer = layerTreeRoot->get_folder().folderList->emplace_back_direct(layerTreeRoot->get_folder().folderList, drawP.world.netObjMan, "First Layer", false)->obj;
}
void DrawingProgramLayerManager::server_init_no_file() {
layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr<DrawingProgramLayerListItem>(new DrawingProgramLayerListItem(drawP.world.netObjMan, "ROOT", true));
layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well
editingLayer = layerTreeRoot->get_folder().folderList->emplace_back_direct(layerTreeRoot->get_folder().folderList, drawP.world.netObjMan, "First Layer", false)->obj;
}
void DrawingProgramLayerManager::scale_up(const WorldScalar& scaleUpAmount) {
@ -25,8 +24,14 @@ void DrawingProgramLayerManager::write_components_server(cereal::PortableBinaryO
void DrawingProgramLayerManager::read_components_client(cereal::PortableBinaryInputArchive& a) {
layerTreeRoot = drawP.world.netObjMan.read_create_message<DrawingProgramLayerListItem>(a, nullptr);
layerTreeRoot->commit_update_dont_invalidate_cache(*this);
commitUpdateOnComponentInsert = false;
layerTreeRoot->set_component_list_callbacks(*this);
commitUpdateOnComponentInsert = true;
auto flattenedCompList = get_flattened_component_list();
parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) {
comp->obj->commit_update_dont_invalidate_cache(drawP);
});
drawP.rebuild_cache();
editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer();
}
@ -97,3 +102,21 @@ CanvasComponentContainer::ObjInfo* DrawingProgramLayerManager::add_component_to_
return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj));
}
void DrawingProgramLayerManager::load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) {
layerTreeRoot = drawP.world.netObjMan.make_obj_from_ptr<DrawingProgramLayerListItem>(new DrawingProgramLayerListItem());
layerTreeRoot->load_file(a, version, *this);
commitUpdateOnComponentInsert = false;
layerTreeRoot->get_folder().set_component_list_callbacks(*this); // Only need to call set_component_list_callbacks on root, and the rest will get the callbacks set as well
commitUpdateOnComponentInsert = true;
auto flattenedCompList = get_flattened_component_list();
parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) {
comp->obj->commit_update_dont_invalidate_cache(drawP);
});
drawP.rebuild_cache();
editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer();
}
void DrawingProgramLayerManager::save_file(cereal::PortableBinaryOutputArchive& a) const {
layerTreeRoot->save_file(a);
}

View file

@ -13,6 +13,7 @@ class DrawingProgramLayerManager {
NetworkingObjects::NetObjOwnerPtr<DrawingProgramLayerListItem> layerTreeRoot;
NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> editingLayer;
void set_initial_editing_layer();
bool commitUpdateOnComponentInsert = true;
public:
enum class LayerSelector {
ALL_VISIBLE_LAYERS,
@ -20,7 +21,7 @@ class DrawingProgramLayerManager {
};
DrawingProgramLayerManager(DrawingProgram& drawProg);
void init();
void server_init_no_file();
void draw(SkCanvas* canvas, const DrawData& drawData);
void write_components_server(cereal::PortableBinaryOutputArchive& a);
void read_components_client(cereal::PortableBinaryInputArchive& a);
@ -39,6 +40,9 @@ class DrawingProgramLayerManager {
CanvasComponentContainer::ObjInfoIterator get_edited_layer_end_iterator();
bool component_passes_layer_selector(CanvasComponentContainer::ObjInfo* c, LayerSelector layerSelector);
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
void save_file(cereal::PortableBinaryOutputArchive& a) const;
bool layer_tree_root_exists();
const DrawingProgramLayerListItem& get_layer_root();
uint32_t total_component_count();