2025-12-25 17:18:28 +03:00
# include "DrawingProgramLayerManager.hpp"
# include "../../World.hpp"
2026-01-04 16:50:47 +03:00
# include "Helpers/NetworkingObjects/NetObjID.hpp"
2025-12-30 19:46:08 +03:00
# include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
2026-01-02 10:29:50 +03:00
# include "Helpers/NetworkingObjects/NetObjOwnerPtr.decl.hpp"
2026-01-04 16:50:47 +03:00
# include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
2026-01-01 22:46:02 +03:00
# include "Helpers/Parallel.hpp"
2026-01-02 09:22:52 +03:00
# include "../../CanvasComponents/CanvasComponentContainer.hpp"
# include "../../CanvasComponents/CanvasComponentAllocator.hpp"
# include "../../CanvasComponents/CanvasComponent.hpp"
2026-01-02 10:29:50 +03:00
# include <chrono>
2025-12-25 17:18:28 +03:00
DrawingProgramLayerManager : : DrawingProgramLayerManager ( DrawingProgram & drawProg ) :
drawP ( drawProg ) , // initialize drawP first for next objects to be initialized properly
listGUI ( * this )
{ }
2026-01-01 22:46:02 +03:00
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 ;
2025-12-25 17:18:28 +03:00
}
2025-12-31 16:30:56 +03:00
void DrawingProgramLayerManager : : scale_up ( const WorldScalar & scaleUpAmount ) {
layerTreeRoot - > scale_up ( scaleUpAmount ) ;
}
2025-12-25 17:18:28 +03:00
void DrawingProgramLayerManager : : write_components_server ( cereal : : PortableBinaryOutputArchive & a ) {
layerTreeRoot . write_create_message ( a ) ;
}
void DrawingProgramLayerManager : : read_components_client ( cereal : : PortableBinaryInputArchive & a ) {
layerTreeRoot = drawP . world . netObjMan . read_create_message < DrawingProgramLayerListItem > ( a , nullptr ) ;
2026-01-01 22:46:02 +03:00
commitUpdateOnComponentInsert = false ;
2025-12-26 10:10:19 +03:00
layerTreeRoot - > set_component_list_callbacks ( * this ) ;
2026-01-01 22:46:02 +03:00
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 ( ) ;
2025-12-31 11:59:53 +03:00
editingLayer = layerTreeRoot - > get_folder ( ) . get_initial_editing_layer ( ) ;
2025-12-26 10:10:19 +03:00
}
bool DrawingProgramLayerManager : : is_a_layer_being_edited ( ) {
return ! editingLayer . expired ( ) ;
}
2025-12-29 19:57:36 +03:00
uint32_t DrawingProgramLayerManager : : edited_layer_component_count ( ) {
return editingLayer . lock ( ) - > get_layer ( ) . components - > size ( ) ;
}
2025-12-31 11:42:16 +03:00
uint32_t DrawingProgramLayerManager : : total_component_count ( ) {
if ( layerTreeRoot )
return layerTreeRoot - > get_component_count ( ) ;
return 0 ;
}
2025-12-30 19:46:08 +03:00
CanvasComponentContainer : : ObjInfoIterator DrawingProgramLayerManager : : get_edited_layer_end_iterator ( ) {
return editingLayer . lock ( ) - > get_layer ( ) . components - > end ( ) ;
}
2025-12-26 10:10:19 +03:00
void DrawingProgramLayerManager : : draw ( SkCanvas * canvas , const DrawData & drawData ) {
if ( layerTreeRoot )
layerTreeRoot - > draw ( canvas , drawData ) ;
2025-12-25 17:18:28 +03:00
}
2025-12-26 19:52:36 +03:00
2025-12-30 19:46:08 +03:00
std : : vector < CanvasComponentContainer : : ObjInfo * > DrawingProgramLayerManager : : get_flattened_component_list ( ) const {
std : : vector < CanvasComponentContainer : : ObjInfo * > toRet ;
2025-12-26 19:52:36 +03:00
layerTreeRoot - > get_flattened_component_list ( toRet ) ;
return toRet ;
}
2025-12-28 17:34:33 +03:00
2025-12-29 19:57:36 +03:00
std : : vector < DrawingProgramLayerListItem * > DrawingProgramLayerManager : : get_flattened_layer_list ( ) {
std : : vector < DrawingProgramLayerListItem * > toRet ;
layerTreeRoot - > get_flattened_layer_list ( toRet ) ;
return toRet ;
}
2025-12-28 17:34:33 +03:00
bool DrawingProgramLayerManager : : layer_tree_root_exists ( ) {
return layerTreeRoot ;
}
const DrawingProgramLayerListItem & DrawingProgramLayerManager : : get_layer_root ( ) {
return * layerTreeRoot ;
}
2025-12-30 19:46:08 +03:00
bool DrawingProgramLayerManager : : component_passes_layer_selector ( CanvasComponentContainer : : ObjInfo * c , LayerSelector layerSelector ) {
2025-12-28 17:34:33 +03:00
switch ( layerSelector ) {
case LayerSelector : : ALL_VISIBLE_LAYERS :
return c - > obj - > parentLayer - > get_visible ( ) ;
case LayerSelector : : LAYER_BEING_EDITED :
return is_a_layer_being_edited ( ) & & c - > obj - > parentLayer = = editingLayer . lock ( ) . get ( ) ;
}
return false ;
}
2025-12-29 19:57:36 +03:00
2025-12-30 19:46:08 +03:00
std : : vector < CanvasComponentContainer : : ObjInfoIterator > DrawingProgramLayerManager : : add_many_components_to_layer_being_edited ( const std : : vector < std : : pair < CanvasComponentContainer : : ObjInfoIterator , CanvasComponentContainer * > > & newObjs ) {
2026-01-04 16:50:47 +03:00
if ( ! newObjs . empty ( ) ) {
auto editLayerPtr = editingLayer . lock ( ) ;
if ( ! editLayerPtr )
2026-01-05 19:15:42 +03:00
throw std : : runtime_error ( " [DrawingProgramLayerManager::add_many_components_to_layer_being_edited] No layer selected! " ) ;
2026-01-04 16:50:47 +03:00
auto toRet = editLayerPtr - > get_layer ( ) . components - > insert_ordered_list_and_send_create ( editLayerPtr - > get_layer ( ) . components , newObjs ) ;
add_undo_place_components ( editingLayer . lock ( ) . get ( ) , toRet ) ;
}
return { } ;
2025-12-29 19:57:36 +03:00
}
2025-12-30 19:46:08 +03:00
CanvasComponentContainer : : ObjInfo * DrawingProgramLayerManager : : add_component_to_layer_being_edited ( CanvasComponentContainer * newObj ) {
2025-12-29 19:57:36 +03:00
auto editLayerPtr = editingLayer . lock ( ) ;
if ( ! editLayerPtr )
2026-01-05 19:15:42 +03:00
throw std : : runtime_error ( " [DrawingProgramLayerManager::add_component_to_layer_being_edited] No layer selected! " ) ;
2025-12-30 19:46:08 +03:00
return & ( * editLayerPtr - > get_layer ( ) . components - > push_back_and_send_create ( editLayerPtr - > get_layer ( ) . components , newObj ) ) ;
2025-12-29 19:57:36 +03:00
}
2025-12-31 16:30:56 +03:00
2026-01-01 22:46:02 +03:00
void DrawingProgramLayerManager : : load_file ( cereal : : PortableBinaryInputArchive & a , VersionNumber version ) {
2026-01-02 09:22:52 +03:00
if ( version > = VersionNumber ( 0 , 4 , 0 ) ) {
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 ;
}
else {
server_init_no_file ( ) ;
2026-01-02 10:29:50 +03:00
commitUpdateOnComponentInsert = false ;
CanvasComponentContainer : : NetListTemporaryPtr editingLayerTmpPtrComponents = editingLayer . lock ( ) - > get_layer ( ) . components ;
2026-01-02 09:22:52 +03:00
uint64_t compCount ;
a ( compCount ) ;
for ( uint64_t i = 0 ; i < compCount ; i + + ) {
CanvasComponentContainer * newContainer = new CanvasComponentContainer ( ) ;
newContainer - > load_file ( a , version , drawP . world . netObjMan ) ;
2026-01-02 10:29:50 +03:00
editingLayerTmpPtrComponents - > push_back_and_send_create ( editingLayerTmpPtrComponents , newContainer ) ;
2026-01-02 09:22:52 +03:00
}
2026-01-02 10:29:50 +03:00
commitUpdateOnComponentInsert = true ;
2026-01-02 09:22:52 +03:00
}
2026-01-01 22:46:02 +03:00
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 ) ;
}
2026-01-01 23:28:26 +03:00
void DrawingProgramLayerManager : : get_used_resources ( std : : unordered_set < NetworkingObjects : : NetObjID > & resourceSet ) {
layerTreeRoot - > get_used_resources ( resourceSet ) ;
}
2026-01-04 16:50:47 +03:00
void DrawingProgramLayerManager : : add_undo_place_component ( CanvasComponentContainer : : ObjInfo * objInfo ) {
using namespace NetworkingObjects ;
class AddCanvasComponentWorldUndoAction : public WorldUndoAction {
public :
2026-01-06 12:55:44 +03:00
AddCanvasComponentWorldUndoAction ( uint32_t newPos , WorldUndoManager : : UndoObjectID initUndoID , WorldUndoManager : : UndoObjectID initComponentListUndoID ) :
2026-01-04 16:50:47 +03:00
pos ( newPos ) ,
undoID ( initUndoID ) ,
componentListUndoID ( initComponentListUndoID )
{ }
std : : string get_name ( ) const override {
return " Add Canvas Object " ;
}
bool undo ( WorldUndoManager & undoMan ) override {
std : : optional < NetObjID > toEraseID = undoMan . get_netid_from_undoid ( undoID ) ;
if ( ! toEraseID . has_value ( ) )
return false ;
std : : optional < NetObjID > toEraseCompListID = undoMan . get_netid_from_undoid ( componentListUndoID ) ;
if ( ! toEraseCompListID . has_value ( ) )
return false ;
auto compList = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( toEraseCompListID . value ( ) ) ;
2026-01-06 12:55:44 +03:00
auto toEraseIt = compList - > get ( toEraseID . value ( ) ) ;
copyData = toEraseIt - > obj - > get_data_copy ( ) ;
compList - > erase ( compList , toEraseIt ) ;
2026-01-04 16:50:47 +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 ;
std : : optional < NetObjID > toEraseCompListID = undoMan . get_netid_from_undoid ( componentListUndoID ) ;
if ( ! toEraseCompListID . has_value ( ) )
return false ;
auto compList = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( toEraseCompListID . value ( ) ) ;
auto insertedIt = compList - > emplace_direct ( compList , compList - > at ( pos ) , undoMan . world . netObjMan , * copyData ) ;
undoMan . register_new_netid_to_existing_undoid ( undoID , insertedIt - > obj . get_net_id ( ) ) ;
2026-01-06 15:15:36 +03:00
copyData = nullptr ;
2026-01-04 16:50:47 +03:00
return true ;
}
void scale_up ( const WorldScalar & scaleAmount ) override {
2026-01-06 15:15:36 +03:00
if ( copyData )
copyData - > scale_up ( scaleAmount ) ;
2026-01-04 16:50:47 +03:00
}
~ AddCanvasComponentWorldUndoAction ( ) { }
std : : unique_ptr < CanvasComponentContainer : : CopyData > copyData ;
uint32_t pos ;
WorldUndoManager : : UndoObjectID undoID ;
WorldUndoManager : : UndoObjectID componentListUndoID ;
} ;
2026-01-06 12:55:44 +03:00
drawP . world . undo . push ( std : : make_unique < AddCanvasComponentWorldUndoAction > ( objInfo - > pos , drawP . world . undo . get_undoid_from_netid ( objInfo - > obj . get_net_id ( ) ) , drawP . world . undo . get_undoid_from_netid ( objInfo - > obj - > parentLayer - > get_layer ( ) . components . get_net_id ( ) ) ) ) ;
2026-01-04 16:50:47 +03:00
}
void DrawingProgramLayerManager : : erase_component_map ( const std : : unordered_map < DrawingProgramLayerListItem * , std : : vector < CanvasComponentContainer : : ObjInfoIterator > > & eraseMap ) {
add_undo_erase_components ( eraseMap ) ;
drawP . world . netObjMan . send_multi_update_messsage ( [ & ] ( ) {
for ( auto & [ layerListItem , netObjSetToErase ] : eraseMap ) {
auto & layerComponentList = layerListItem - > get_layer ( ) . components ;
layerComponentList - > erase_list ( layerComponentList , netObjSetToErase ) ;
}
} , NetworkingObjects : : NetObjManager : : SendUpdateType : : SEND_TO_ALL , nullptr ) ;
}
void DrawingProgramLayerManager : : add_undo_erase_components ( const std : : unordered_map < DrawingProgramLayerListItem * , std : : vector < CanvasComponentContainer : : ObjInfoIterator > > & eraseMap ) {
using namespace NetworkingObjects ;
struct EraseListData {
std : : vector < WorldUndoManager : : UndoObjectID > undoID ;
std : : vector < uint32_t > pos ;
std : : vector < std : : unique_ptr < CanvasComponentContainer : : CopyData > > copyData ;
} ;
class EraseCanvasComponentsWorldUndoAction : public WorldUndoAction {
public :
EraseCanvasComponentsWorldUndoAction ( std : : unordered_map < WorldUndoManager : : UndoObjectID , EraseListData > initEraseMap ) :
undoEraseMap ( std : : move ( initEraseMap ) )
{ }
std : : string get_name ( ) const override {
return " Erase Canvas Objects " ;
}
bool undo ( WorldUndoManager & undoMan ) override {
struct InsertData {
std : : vector < NetObjOrderedListIterator < CanvasComponentContainer > > it ;
std : : vector < std : : unique_ptr < CanvasComponentContainer : : CopyData > > * copyData ;
std : : vector < WorldUndoManager : : UndoObjectID > * undoID ;
} ;
std : : unordered_map < NetObjID , InsertData > insertMap ;
{
for ( auto & [ parentUndoID , eData ] : undoEraseMap ) {
std : : optional < NetObjID > parentNetID = undoMan . get_netid_from_undoid ( parentUndoID ) ;
if ( ! parentNetID )
return false ;
auto & insertData = insertMap [ parentNetID . value ( ) ] ;
auto parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID . value ( ) ) ;
insertData . it = parentListPtr - > at_ordered_indices ( eData . pos ) ;
insertData . copyData = & eData . copyData ;
insertData . undoID = & eData . undoID ;
}
}
undoMan . world . netObjMan . send_multi_update_messsage ( [ & ] ( ) {
for ( auto & [ parentNetID , insertData ] : insertMap ) {
auto parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID ) ;
std : : vector < std : : pair < NetObjOrderedListIterator < CanvasComponentContainer > , NetObjOwnerPtr < CanvasComponentContainer > > > toInsert ( insertData . it . size ( ) ) ;
for ( size_t i = 0 ; i < insertData . it . size ( ) ; i + + ) {
toInsert [ i ] . first = insertData . it [ i ] ;
toInsert [ i ] . second = undoMan . world . netObjMan . make_obj_direct < CanvasComponentContainer > ( undoMan . world . netObjMan , * insertData . copyData - > at ( i ) ) ;
undoMan . register_new_netid_to_existing_undoid ( insertData . undoID - > at ( i ) , toInsert [ i ] . second . get_net_id ( ) ) ;
}
parentListPtr - > insert_ordered_list_and_send_create ( parentListPtr , toInsert ) ;
2026-01-06 15:15:36 +03:00
insertData . copyData - > clear ( ) ;
2026-01-04 16:50:47 +03:00
}
} , NetworkingObjects : : NetObjManager : : SendUpdateType : : SEND_TO_ALL , nullptr ) ;
return true ;
}
bool redo ( WorldUndoManager & undoMan ) override {
std : : unordered_map < NetObjID , std : : vector < NetObjOrderedListIterator < CanvasComponentContainer > > > eraseMap ;
{
for ( auto & [ parentUndoID , eData ] : undoEraseMap ) {
std : : optional < NetObjID > parentNetID = undoMan . get_netid_from_undoid ( parentUndoID ) ;
if ( ! parentNetID )
return false ;
auto & eraseData = eraseMap [ parentNetID . value ( ) ] ;
auto parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID . value ( ) ) ;
std : : vector < NetObjID > netIDList ;
if ( ! undoMan . fill_netid_list_from_undoid_list ( netIDList , eData . undoID ) )
return false ;
eraseData = parentListPtr - > get_list ( netIDList ) ;
2026-01-06 15:15:36 +03:00
for ( auto & it : eraseData )
eData . copyData . emplace_back ( it - > obj - > get_data_copy ( ) ) ;
2026-01-04 16:50:47 +03:00
}
}
undoMan . world . netObjMan . send_multi_update_messsage ( [ & ] ( ) {
for ( auto & [ parentNetID , eData ] : eraseMap ) {
auto parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID ) ;
parentListPtr - > erase_list ( parentListPtr , eData ) ;
}
} , NetworkingObjects : : NetObjManager : : SendUpdateType : : SEND_TO_ALL , nullptr ) ;
return true ;
}
void scale_up ( const WorldScalar & scaleAmount ) override {
for ( auto & [ undoID , eData ] : undoEraseMap ) {
for ( auto & c : eData . copyData )
c - > scale_up ( scaleAmount ) ;
}
}
~ EraseCanvasComponentsWorldUndoAction ( ) { }
std : : unordered_map < WorldUndoManager : : UndoObjectID , EraseListData > undoEraseMap ;
} ;
auto & undoMan = drawP . world . undo ;
std : : unordered_map < WorldUndoManager : : UndoObjectID , EraseListData > undoMap ;
for ( auto & [ item , compContainer ] : eraseMap ) {
auto & undoData = undoMap [ undoMan . get_undoid_from_netid ( item - > get_layer ( ) . components . get_net_id ( ) ) ] ;
// Vectors must be sorted
uint32_t i = 0 ;
for ( auto & comp : compContainer ) {
undoData . undoID . emplace_back ( undoMan . get_undoid_from_netid ( comp - > obj . get_net_id ( ) ) ) ;
undoData . copyData . emplace_back ( comp - > obj - > get_data_copy ( ) ) ;
undoData . pos . emplace_back ( comp - > pos - i ) ;
+ + i ;
}
}
undoMan . push ( std : : make_unique < EraseCanvasComponentsWorldUndoAction > ( std : : move ( undoMap ) ) ) ;
}
void DrawingProgramLayerManager : : add_undo_place_components ( DrawingProgramLayerListItem * parent , const std : : vector < CanvasComponentContainer : : ObjInfoIterator > & placeList ) {
using namespace NetworkingObjects ;
struct PlaceListData {
std : : vector < WorldUndoManager : : UndoObjectID > undoID ;
std : : vector < uint32_t > pos ;
std : : vector < std : : unique_ptr < CanvasComponentContainer : : CopyData > > copyData ;
} ;
class PlaceCanvasComponentsWorldUndoAction : public WorldUndoAction {
public :
PlaceCanvasComponentsWorldUndoAction ( WorldUndoManager : : UndoObjectID parentList , PlaceListData initPlaceData ) :
parentUndoID ( parentList ) ,
undoPlaceData ( std : : move ( initPlaceData ) )
{ }
std : : string get_name ( ) const override {
return " Place Canvas Objects " ;
}
bool undo ( WorldUndoManager & undoMan ) override {
NetObjTemporaryPtr < NetObjOrderedList < CanvasComponentContainer > > parentListPtr ;
std : : vector < NetObjOrderedListIterator < CanvasComponentContainer > > eraseData ;
{
std : : optional < NetObjID > parentNetID = undoMan . get_netid_from_undoid ( parentUndoID ) ;
if ( ! parentNetID )
return false ;
parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID . value ( ) ) ;
}
{
std : : vector < NetObjID > netIDList ;
if ( ! undoMan . fill_netid_list_from_undoid_list ( netIDList , undoPlaceData . undoID ) )
return false ;
eraseData = parentListPtr - > get_list ( netIDList ) ;
2026-01-06 15:15:36 +03:00
for ( auto & it : eraseData )
undoPlaceData . copyData . emplace_back ( it - > obj - > get_data_copy ( ) ) ;
2026-01-04 16:50:47 +03:00
}
parentListPtr - > erase_list ( parentListPtr , eraseData ) ;
return true ;
}
bool redo ( WorldUndoManager & undoMan ) override {
std : : vector < NetObjOrderedListIterator < CanvasComponentContainer > > it ;
NetObjTemporaryPtr < NetObjOrderedList < CanvasComponentContainer > > parentListPtr ;
{
std : : optional < NetObjID > parentNetID = undoMan . get_netid_from_undoid ( parentUndoID ) ;
if ( ! parentNetID )
return false ;
parentListPtr = undoMan . world . netObjMan . get_obj_temporary_ref_from_id < NetObjOrderedList < CanvasComponentContainer > > ( parentNetID . value ( ) ) ;
}
{
it = parentListPtr - > at_ordered_indices ( undoPlaceData . pos ) ;
}
std : : vector < std : : pair < NetObjOrderedListIterator < CanvasComponentContainer > , NetObjOwnerPtr < CanvasComponentContainer > > > toInsert ( it . size ( ) ) ;
for ( size_t i = 0 ; i < it . size ( ) ; i + + ) {
toInsert [ i ] . first = it [ i ] ;
toInsert [ i ] . second = undoMan . world . netObjMan . make_obj_direct < CanvasComponentContainer > ( undoMan . world . netObjMan , * undoPlaceData . copyData . at ( i ) ) ;
undoMan . register_new_netid_to_existing_undoid ( undoPlaceData . undoID . at ( i ) , toInsert [ i ] . second . get_net_id ( ) ) ;
}
parentListPtr - > insert_ordered_list_and_send_create ( parentListPtr , toInsert ) ;
2026-01-06 15:15:36 +03:00
undoPlaceData . copyData . clear ( ) ;
2026-01-04 16:50:47 +03:00
return true ;
}
void scale_up ( const WorldScalar & scaleAmount ) override {
for ( auto & c : undoPlaceData . copyData )
c - > scale_up ( scaleAmount ) ;
}
~ PlaceCanvasComponentsWorldUndoAction ( ) { }
WorldUndoManager : : UndoObjectID parentUndoID ;
PlaceListData undoPlaceData ;
} ;
auto & undoMan = drawP . world . undo ;
PlaceListData undoData ;
// Vectors must be sorted
uint32_t i = 0 ;
for ( auto & comp : placeList ) {
undoData . undoID . emplace_back ( undoMan . get_undoid_from_netid ( comp - > obj . get_net_id ( ) ) ) ;
undoData . pos . emplace_back ( comp - > pos - i ) ;
+ + i ;
}
undoMan . push ( std : : make_unique < PlaceCanvasComponentsWorldUndoAction > ( undoMan . get_undoid_from_netid ( parent - > get_layer ( ) . components . get_net_id ( ) ) , std : : move ( undoData ) ) ) ;
}