Added clipboard code back (has issues)

This commit is contained in:
Yousef Khadadeh 2025-12-29 19:57:36 +03:00
parent 3df74095a3
commit fb3b13d303
22 changed files with 181 additions and 53 deletions

View file

@ -29,6 +29,12 @@ void BrushStrokeCanvasComponent::load_file(cereal::PortableBinaryInputArchive& a
a(d->points, d->color, d->hasRoundCaps);
}
std::unique_ptr<CanvasComponent> BrushStrokeCanvasComponent::get_data_copy() const {
auto toRet = std::make_unique<BrushStrokeCanvasComponent>();
toRet->d = d;
return toRet;
}
CanvasComponentType BrushStrokeCanvasComponent::get_type() const {
return CanvasComponentType::BRUSHSTROKE;
}

View file

@ -22,6 +22,7 @@ class BrushStrokeCanvasComponent : public CanvasComponent {
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override;
virtual std::unique_ptr<CanvasComponent> get_data_copy() const override;
struct Data {
std::vector<BrushStrokeCanvasComponentPoint> points;

View file

@ -8,6 +8,12 @@
void CanvasComponent::update(DrawingProgram& drawP) {
}
void CanvasComponent::remap_resource_ids(const std::unordered_map<NetworkingObjects::NetObjID, NetworkingObjects::NetObjID>& resourceOldToNewMap) {
}
void CanvasComponent::get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const {
}
CanvasComponent* CanvasComponent::allocate_comp(CanvasComponentType type) {
switch(type) {
case CanvasComponentType::BRUSHSTROKE:

View file

@ -19,8 +19,11 @@ class CanvasComponent {
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const = 0;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) = 0;
virtual void update(DrawingProgram& drawP);
virtual void get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const;
virtual void remap_resource_ids(const std::unordered_map<NetworkingObjects::NetObjID, NetworkingObjects::NetObjID>& resourceOldToNewMap);
virtual void set_data_from(const CanvasComponent& other) = 0;
virtual std::unique_ptr<CanvasComponent> get_data_copy() const = 0;
protected:
friend class CanvasComponentContainer;
friend class CanvasComponentAllocator;

View file

@ -15,6 +15,13 @@ CanvasComponentContainer::CanvasComponentContainer(NetworkingObjects::NetObjMana
compAllocator->comp->compContainer = this;
}
CanvasComponentContainer::CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, const CopyData& copyData) {
compAllocator = objMan.make_obj_direct<CanvasComponentAllocator>(copyData.obj->get_type());
compAllocator->comp->compContainer = this;
compAllocator->comp->set_data_from(*copyData.obj);
coords = copyData.coords;
}
void CanvasComponentContainer::register_class(NetObjManager& objMan) {
objMan.register_class<CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer>({
.writeConstructorFuncClient = write_constructor_func,
@ -26,6 +33,13 @@ void CanvasComponentContainer::register_class(NetObjManager& objMan) {
});
}
std::shared_ptr<CanvasComponentContainer::CopyData> CanvasComponentContainer::get_data_copy() const {
auto toRet = std::make_shared<CopyData>();
toRet->coords = coords;
toRet->obj = compAllocator->comp->get_data_copy();
return toRet;
}
void CanvasComponentContainer::send_comp_update(DrawingProgram& drawP, bool finalUpdate) {
drawP.world.delayedUpdateObjectManager.send_update_to_all<CanvasComponentAllocator>(compAllocator, finalUpdate);
}

View file

@ -25,10 +25,18 @@ class CanvasComponentContainer {
constexpr static int COMP_COLLIDE_MIN_SHIFT_TINY = 9;
constexpr static int COMP_MIPMAP_LEVEL_ONE = 2;
constexpr static int COMP_MIPMAP_LEVEL_TWO = 5;
struct CopyData {
CoordSpaceHelper coords;
std::unique_ptr<CanvasComponent> obj;
};
CanvasComponentContainer();
CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, CanvasComponentType type);
CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, const CopyData& copyData);
static void register_class(NetworkingObjects::NetObjManager& t);
std::shared_ptr<CopyData> get_data_copy() const;
void save_file(cereal::PortableBinaryOutputArchive& a) const;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
CanvasComponent& get_comp() const;

View file

@ -52,6 +52,12 @@ void EllipseCanvasComponent::initialize_draw_data(DrawingProgram& drawP) {
create_collider();
}
std::unique_ptr<CanvasComponent> EllipseCanvasComponent::get_data_copy() const {
auto toRet = std::make_unique<EllipseCanvasComponent>();
toRet->d = d;
return toRet;
}
void EllipseCanvasComponent::set_data_from(const CanvasComponent& other) {
auto& otherEllipse = static_cast<const EllipseCanvasComponent&>(other);
d = otherEllipse.d;

View file

@ -10,6 +10,7 @@ class EllipseCanvasComponent : public CanvasComponent {
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override;
virtual std::unique_ptr<CanvasComponent> get_data_copy() const override;
virtual void set_data_from(const CanvasComponent& other) override;
// User input data

View file

@ -29,6 +29,12 @@ void ImageCanvasComponent::load_file(cereal::PortableBinaryInputArchive& a, Vers
a(d.p1, d.p2, d.imageID);
}
std::unique_ptr<CanvasComponent> ImageCanvasComponent::get_data_copy() const {
auto toRet = std::make_unique<ImageCanvasComponent>();
toRet->d = d;
return toRet;
}
void ImageCanvasComponent::draw_download_progress_bar(SkCanvas* canvas, const DrawData& drawData, float progress) const {
if(progress == 0.0f)
return;
@ -53,6 +59,14 @@ void ImageCanvasComponent::set_data_from(const CanvasComponent& other) {
d = otherImage.d;
}
void ImageCanvasComponent::remap_resource_ids(const std::unordered_map<NetworkingObjects::NetObjID, NetworkingObjects::NetObjID>& resourceOldToNewMap) {
d.imageID = resourceOldToNewMap.at(d.imageID);
}
void ImageCanvasComponent::get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const {
resourceSet.emplace(d.imageID);
}
void ImageCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData) const {
ResourceDisplay* display = drawData.rMan->get_display_data(d.imageID);
if(display)

View file

@ -11,7 +11,10 @@ class ImageCanvasComponent : public CanvasComponent {
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override;
virtual CanvasComponentType get_type() const override;
std::unique_ptr<CanvasComponent> get_data_copy() const override;
virtual void set_data_from(const CanvasComponent& other) override;
virtual void remap_resource_ids(const std::unordered_map<NetworkingObjects::NetObjID, NetworkingObjects::NetObjID>& resourceOldToNewMap) override;
virtual void get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const override;
void draw_download_progress_bar(SkCanvas* canvas, const DrawData& drawData, float progress) const;

View file

@ -27,6 +27,12 @@ void RectangleCanvasComponent::load_file(cereal::PortableBinaryInputArchive& a,
a(d.strokeColor, d.fillColor, d.cornerRadius, d.strokeWidth, d.p1, d.p2, d.fillStrokeMode);
}
std::unique_ptr<CanvasComponent> RectangleCanvasComponent::get_data_copy() const {
auto toRet = std::make_unique<RectangleCanvasComponent>();
toRet->d = d;
return toRet;
}
void RectangleCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData) const {
if(d.fillStrokeMode == 0 || d.fillStrokeMode == 2) {
SkPaint p;

View file

@ -11,6 +11,7 @@ class RectangleCanvasComponent : public CanvasComponent {
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override;
virtual CanvasComponentType get_type() const override;
std::unique_ptr<CanvasComponent> get_data_copy() const override;
virtual void set_data_from(const CanvasComponent& other) override;
// User input data

View file

@ -58,6 +58,12 @@ void TextBoxCanvasComponent::load_file(cereal::PortableBinaryInputArchive& a, Ve
}
}
std::unique_ptr<CanvasComponent> TextBoxCanvasComponent::get_data_copy() const {
auto toRet = std::make_unique<TextBoxCanvasComponent>();
toRet->d = d;
return toRet;
}
void TextBoxCanvasComponent::set_data_from(const CanvasComponent& other) {
auto& otherTextBox = static_cast<const TextBoxCanvasComponent&>(other);
d = otherTextBox.d;

View file

@ -15,6 +15,7 @@ class TextBoxCanvasComponent : public CanvasComponent {
virtual void load(cereal::PortableBinaryInputArchive& a) override;
virtual void save_file(cereal::PortableBinaryOutputArchive& a) const override;
virtual void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version) override;
std::unique_ptr<CanvasComponent> get_data_copy() const override;
virtual void set_data_from(const CanvasComponent& other) override;
// User input data

View file

@ -4,6 +4,7 @@
#include "../MainProgram.hpp"
#include "../InputManager.hpp"
#include <Helpers/Parallel.hpp>
#include <Helpers/Logger.hpp>
#ifdef USE_SKIA_BACKEND_GRAPHITE
#include <include/gpu/graphite/Surface.h>
@ -314,59 +315,60 @@ CanvasComponentContainer::ObjInfoSharedPtr DrawingProgramSelection::get_front_ob
}
void DrawingProgramSelection::selection_to_clipboard() {
//auto& clipboard = drawP.world.main.clipboard;
//std::unordered_set<ServerClientID> resourceSet;
//for(auto& c : selectedSet)
// c->obj->get_used_resources(resourceSet);
//std::vector<CanvasComponentContainer::ObjInfoSharedPtr> compVecSort(selectedSet.begin(), selectedSet.end());
//std::sort(compVecSort.begin(), compVecSort.end(), [&](auto& a, auto& b) {
// return a->pos < b->pos;
//});
//clipboard.components.clear();
//for(auto& c : compVecSort)
// clipboard.components.emplace_back(c->obj->deep_copy(drawP));
//clipboard.pos = initialSelectionAABB.center();
//clipboard.inverseScale = drawP.world.drawData.cam.c.inverseScale;
//drawP.world.rMan.copy_resource_set_to_map(resourceSet, clipboard.resources);
auto& clipboard = drawP.world.main.clipboard;
std::unordered_set<NetworkingObjects::NetObjID> resourceSet;
for(auto& c : selectedSet)
c->obj->get_comp().get_used_resources(resourceSet);
std::vector<CanvasComponentContainer::ObjInfoSharedPtr> compVecSort(selectedSet.begin(), selectedSet.end());
std::vector<DrawingProgramLayerListItem*> flattenedLayerList = drawP.layerMan.get_flattened_layer_list();
std::unordered_map<DrawingProgramLayerListItem*, size_t> flattenedLayerListOrder;
for(size_t i = 0; i < flattenedLayerList.size(); i++)
flattenedLayerListOrder[flattenedLayerList[i]] = i;
std::sort(compVecSort.begin(), compVecSort.end(), [&](auto& a, auto& b) {
return (flattenedLayerListOrder[a->obj->parentLayer] < flattenedLayerListOrder[b->obj->parentLayer]) || (a->obj->parentLayer == b->obj->parentLayer && a->pos < b->pos);
});
clipboard.components.clear();
for(auto& c : compVecSort)
clipboard.components.emplace_back(c->obj->get_data_copy());
clipboard.pos = initialSelectionAABB.center();
clipboard.inverseScale = drawP.world.drawData.cam.c.inverseScale;
clipboard.resources = drawP.world.rMan.copy_resource_set_to_map(resourceSet);
}
void DrawingProgramSelection::paste_clipboard(Vector2f pasteScreenPos) {
//auto& clipboard = drawP.world.main.clipboard;
if(drawP.layerMan.is_a_layer_being_edited()) {
auto& clipboard = drawP.world.main.clipboard;
//if(!drawP.is_selection_allowing_tool(drawP.drawTool->get_type()))
// drawP.switch_to_tool(DrawingProgramToolType::EDIT);
if(!drawP.is_selection_allowing_tool(drawP.drawTool->get_type()))
drawP.switch_to_tool(DrawingProgramToolType::EDIT);
//uint32_t allPlacement = drawP.components->size();
//std::vector<std::shared_ptr<DrawComponent>> placedComponents;
//WorldVec mousePos = drawP.world.drawData.cam.c.from_space(pasteScreenPos);
//WorldVec moveVec = drawP.world.main.clipboard.pos - mousePos;
//WorldMultiplier scaleMultiplier = WorldMultiplier(drawP.world.main.clipboard.inverseScale) / WorldMultiplier(drawP.world.drawData.cam.c.inverseScale);
//WorldScalar scaleLimit(0.001);
//for(auto& c : drawP.world.main.clipboard.components) {
// if((c->coords.inverseScale / scaleMultiplier) < scaleLimit) {
// Logger::get().log("WORLDFATAL", "Some pasted objects will be too small! Scale up the canvas first (zoom in alot)");
// return;
// }
//}
std::vector<std::pair<uint32_t, CanvasComponentContainer*>> placedComponents;
WorldVec mousePos = drawP.world.drawData.cam.c.from_space(pasteScreenPos);
WorldVec moveVec = drawP.world.main.clipboard.pos - mousePos;
WorldMultiplier scaleMultiplier = WorldMultiplier(drawP.world.main.clipboard.inverseScale) / WorldMultiplier(drawP.world.drawData.cam.c.inverseScale);
WorldScalar scaleLimit(0.001);
for(auto& c : drawP.world.main.clipboard.components) {
if((c->coords.inverseScale / scaleMultiplier) < scaleLimit) {
Logger::get().log("WORLDFATAL", "Some pasted objects will be too small! Scale up the canvas first (zoom in alot)");
return;
}
}
//std::unordered_map<ServerClientID, ServerClientID> resourceRemapIDs;
//for(auto& r : clipboard.resources)
// resourceRemapIDs[r.first] = drawP.world.rMan.add_resource(r.second);
//for(auto& c : clipboard.components)
// placedComponents.emplace_back(c->deep_copy(drawP));
//drawP.addToCompCacheOnInsert = false;
//auto compListInserted = drawP.components.client_insert_ordered_vector_items(allPlacement, placedComponents);
//parallel_loop_container(compListInserted, [&](auto& c) {
// c->obj->remap_resource_ids(resourceRemapIDs);
// c->obj->get_coords().translate(-moveVec);
// c->obj->get_coords().scale_about(mousePos, scaleMultiplier);
// c->obj->commit_transform(drawP, false);
//});
//DrawComponent::client_send_place_many(drawP, compListInserted);
//drawP.addToCompCacheOnInsert = true;
//std::unordered_set<CanvasComponentContainer::ObjInfoSharedPtr> compSetInserted(compListInserted.begin(), compListInserted.end());
//set_to_selection(compSetInserted);
//drawP.add_undo_place_components(compSetInserted);
std::unordered_map<NetworkingObjects::NetObjID, NetworkingObjects::NetObjID> resourceRemapIDs;
for(auto& r : clipboard.resources)
resourceRemapIDs[r.first] = drawP.world.rMan.add_resource(r.second).get_net_id();
for(auto& c : clipboard.components) {
CanvasComponentContainer* newComponentContainer = new CanvasComponentContainer(drawP.world.netObjMan, *c);
newComponentContainer->get_comp().remap_resource_ids(resourceRemapIDs);
c->coords.translate(-moveVec);
c->coords.scale_about(mousePos, scaleMultiplier);
placedComponents.emplace_back(drawP.layerMan.edited_layer_component_count() + placedComponents.size(), newComponentContainer);
}
auto newlyInsertedObjects = drawP.layerMan.add_many_components_to_layer_being_edited(placedComponents);
std::unordered_set<CanvasComponentContainer::ObjInfoSharedPtr> compSetInserted(newlyInsertedObjects.begin(), newlyInsertedObjects.end());
set_to_selection(compSetInserted);
//drawP.add_undo_place_components(compSetInserted);
}
}
bool DrawingProgramSelection::is_being_transformed() {

View file

@ -53,6 +53,15 @@ void DrawingProgramLayerListItem::get_flattened_component_list(std::vector<Canva
layerData->get_flattened_component_list(objList);
}
void DrawingProgramLayerListItem::get_flattened_layer_list(std::vector<DrawingProgramLayerListItem*>& objList) {
if(folderData) {
for(auto& c : folderData->folderList->get_data())
c->obj->get_flattened_layer_list(objList);
}
else
objList.emplace_back(this);
}
bool DrawingProgramLayerListItem::is_folder() const {
return folderData != nullptr;
}

View file

@ -27,6 +27,7 @@ class DrawingProgramLayerListItem {
void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName) const;
const std::string& get_name() const;
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfoSharedPtr>& objList) const;
void get_flattened_layer_list(std::vector<DrawingProgramLayerListItem*>& objList);
void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const;
float get_alpha() const;

View file

@ -28,6 +28,10 @@ bool DrawingProgramLayerManager::is_a_layer_being_edited() {
return !editingLayer.expired();
}
uint32_t DrawingProgramLayerManager::edited_layer_component_count() {
return editingLayer.lock()->get_layer().components->size();
}
void DrawingProgramLayerManager::draw(SkCanvas* canvas, const DrawData& drawData) {
if(layerTreeRoot)
layerTreeRoot->draw(canvas, drawData);
@ -39,6 +43,12 @@ std::vector<CanvasComponentContainer::ObjInfoSharedPtr> DrawingProgramLayerManag
return toRet;
}
std::vector<DrawingProgramLayerListItem*> DrawingProgramLayerManager::get_flattened_layer_list() {
std::vector<DrawingProgramLayerListItem*> toRet;
layerTreeRoot->get_flattened_layer_list(toRet);
return toRet;
}
bool DrawingProgramLayerManager::layer_tree_root_exists() {
return layerTreeRoot;
}
@ -66,3 +76,17 @@ bool DrawingProgramLayerManager::component_passes_layer_selector(const CanvasCom
}
return false;
}
std::vector<CanvasComponentContainer::ObjInfoSharedPtr> DrawingProgramLayerManager::add_many_components_to_layer_being_edited(const std::vector<std::pair<uint32_t, CanvasComponentContainer*>>& newObjs) {
auto editLayerPtr = editingLayer.lock();
if(!editLayerPtr)
return {};
return editLayerPtr->get_layer().components->insert_ordered_list_and_send_create(editLayerPtr->get_layer().components, newObjs);
}
CanvasComponentContainer::ObjInfoSharedPtr DrawingProgramLayerManager::add_component_to_layer_being_edited(CanvasComponentContainer* newObj) {
auto editLayerPtr = editingLayer.lock();
if(!editLayerPtr)
return nullptr;
return editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj);
}

View file

@ -24,17 +24,15 @@ class DrawingProgramLayerManager {
void read_components_client(cereal::PortableBinaryInputArchive& a);
bool is_a_layer_being_edited();
void erase_component_set(const std::unordered_set<CanvasComponentContainer::ObjInfoSharedPtr>& compsToErase);
uint32_t edited_layer_component_count();
bool component_passes_layer_selector(const CanvasComponentContainer::ObjInfoSharedPtr& c, LayerSelector layerSelector);
bool layer_tree_root_exists();
const DrawingProgramLayerListItem& get_layer_root();
template <typename T> CanvasComponentContainer::ObjInfoSharedPtr add_component_to_layer_being_edited(T* newObj) {
auto editLayerPtr = editingLayer.lock();
if(!editLayerPtr)
return nullptr;
return editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj);
}
CanvasComponentContainer::ObjInfoSharedPtr add_component_to_layer_being_edited(CanvasComponentContainer* newObj);
std::vector<CanvasComponentContainer::ObjInfoSharedPtr> add_many_components_to_layer_being_edited(const std::vector<std::pair<uint32_t, CanvasComponentContainer*>>& newObjs);
std::vector<CanvasComponentContainer::ObjInfoSharedPtr> get_flattened_component_list() const;
std::vector<DrawingProgramLayerListItem*> get_flattened_layer_list();
DrawingProgramLayerManagerGUI listGUI;
};

View file

@ -62,6 +62,13 @@ class MainProgram {
SDL_Window* sdlWindow;
} window;
struct Clipboard {
std::vector<std::shared_ptr<CanvasComponentContainer::CopyData>> components;
std::unordered_map<NetworkingObjects::NetObjID, ResourceData> resources;
WorldVec pos;
WorldScalar inverseScale;
} clipboard;
std::shared_ptr<FontData> fonts;
TimePoint deltaTime;
Toolbar toolbar;

View file

@ -167,6 +167,16 @@ ResourceDisplay* ResourceManager::get_display_data(const NetworkingObjects::NetO
return displays[fileID].get();
}
std::unordered_map<NetworkingObjects::NetObjID, ResourceData> ResourceManager::copy_resource_set_to_map(const std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const {
std::unordered_map<NetworkingObjects::NetObjID, ResourceData> toRet;
for(auto& netID : resourceSet) {
auto tempPtr = world.netObjMan.get_obj_temporary_ref_from_id<ResourceData>(netID);
if(tempPtr)
toRet.emplace(netID, *tempPtr);
}
return toRet;
}
const std::vector<NetworkingObjects::NetObjOwnerPtr<ResourceData>>& ResourceManager::resource_list() {
return resourceList;
}

View file

@ -31,6 +31,7 @@ class ResourceManager {
ResourceDisplay* get_display_data(const NetworkingObjects::NetObjID& fileID);
const std::vector<NetworkingObjects::NetObjOwnerPtr<ResourceData>>& resource_list();
float get_resource_retrieval_progress(const NetworkingObjects::NetObjID& id);
std::unordered_map<NetworkingObjects::NetObjID, ResourceData> copy_resource_set_to_map(const std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const;
World& world;
private: