diff --git a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp index ab3b855..4e61af3 100644 --- a/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp +++ b/include/Helpers/NetworkingObjects/NetObjOrderedList.hpp @@ -9,22 +9,18 @@ #include #include "NetObjManagerTypeList.hpp" #include +#include namespace NetworkingObjects { enum class ObjPtrOrderedListCommand_StoC : uint8_t { - INSERT_SINGLE_CONSTRUCT, - INSERT_SINGLE_REFERENCE, - INSERT_MANY_CONSTRUCT, - INSERT_MANY_REFERENCE, - ERASE_SINGLE, - ERASE_MANY + INSERT_LIST_CONSTRUCT, + INSERT_LIST_REFERENCE, + ERASE_ID_LIST }; enum class ObjPtrOrderedListCommand_CtoS : uint8_t { - INSERT_SINGLE, - INSERT_MANY, - ERASE_SINGLE, - ERASE_MANY + INSERT_LIST, + ERASE_ID_LIST }; template struct NetObjOrderedListObjectInfo { @@ -32,61 +28,74 @@ namespace NetworkingObjects { obj(std::move(iObj)), pos(iPos) {} + bool operator<(NetObjOrderedListObjectInfo& other) const { + return pos < other.pos; + } NetObjOrderedListObjectInfo() = delete; NetObjOwnerPtr obj; uint32_t pos; }; - template using NetObjOrderedListObjectInfoPtr = std::shared_ptr>; + template using NetObjOrderedListIterator = std::list>::iterator; + template using NetObjOrderedListConstIterator = std::list>::const_iterator; - template void set_positions_for_object_info_vector(std::vector>& v, uint32_t i = 0) { - uint32_t vSize = static_cast(v.size()); - for(; i < vSize; i++) - v[i]->pos = i; + template void set_position_obj_info_list(NetObjOrderedListIterator start, NetObjOrderedListIterator end) { + if(start == end) + return; + uint32_t i = start->pos; + for(; start != end; ++start) { + start->pos = i; + ++i; + } } template class NetObjOrderedList { public: // Don't use this function unless you're sure that class T isn't a base class - template NetObjOrderedListObjectInfoPtr emplace_back_direct(const NetObjTemporaryPtr>& l, Args&&... items) { - NetObjOwnerPtr newObj = l.get_obj_man()->template make_obj_direct(items...); - return l->insert(l, nullptr, l->size(), std::move(newObj)); + template NetObjOrderedListIterator emplace_back_direct(const NetObjTemporaryPtr>& l, Args&&... items) { + std::vector, NetObjOwnerPtr>> newObjOwner; + newObjOwner.emplace_back(l->end(), std::move(l.get_obj_man()->template make_obj_direct(items...))); + auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); + return toRet.empty() ? l->end() : toRet.back(); } - static NetObjOrderedListObjectInfoPtr push_back_and_send_create(const NetObjTemporaryPtr>& l, T* newObj) { - NetObjOwnerPtr newObjOwner = l.get_obj_man()->template make_obj_from_ptr(newObj); - return l->insert(l, nullptr, l->size(), std::move(newObjOwner)); + static NetObjOrderedListIterator push_back_and_send_create(const NetObjTemporaryPtr>& l, T* newObj) { + std::vector, NetObjOwnerPtr>> newObjOwner; + newObjOwner.emplace_back(l->end(), std::move(l.get_obj_man()->template make_obj_from_ptr(newObj))); + auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); + return toRet.empty() ? l->end() : toRet.back(); } - static NetObjOrderedListObjectInfoPtr insert_and_send_create(const NetObjTemporaryPtr>& l, uint32_t posToInsertAt, T* newObj) { - NetObjOwnerPtr newObjOwner = l.get_obj_man()->template make_obj_from_ptr(newObj); - return l->insert(l, nullptr, posToInsertAt, std::move(newObjOwner)); + static NetObjOrderedListIterator insert_and_send_create(const NetObjTemporaryPtr>& l, const NetObjOrderedListIterator& it, T* newObj) { + std::vector, NetObjOwnerPtr>> newObjOwner; + newObjOwner.emplace_back(it, std::move(l.get_obj_man()->template make_obj_from_ptr(newObj))); + auto toRet = l->insert_ordered_list(l, nullptr, newObjOwner); + return toRet.empty() ? l->end() : toRet.back(); } - static std::vector> insert_ordered_list_and_send_create(const NetObjTemporaryPtr>& l, const std::vector>& newObjs) { + static std::vector> insert_ordered_list_and_send_create(const NetObjTemporaryPtr>& l, const std::vector, T*>>& newObjs) { if(newObjs.empty()) return {}; - std::vector>> ownerPtrOrderedList; + std::vector, NetObjOwnerPtr>> ownerPtrOrderedList; for(uint32_t i = 0; i < static_cast(newObjs.size()); i++) ownerPtrOrderedList.emplace_back(newObjs[i].first, std::move(l.get_obj_man()->template make_obj_from_ptr(newObjs[i].second))); return l->insert_ordered_list(l, nullptr, ownerPtrOrderedList); } - static std::vector> insert_ordered_list_and_send_create(const NetObjTemporaryPtr>& l, std::vector>>& newObjPtrs) { + static std::vector> insert_ordered_list_and_send_create(const NetObjTemporaryPtr>& l, std::vector, NetObjOwnerPtr>>& newObjPtrs) { if(newObjPtrs.empty()) return {}; return l->insert_ordered_list(l, nullptr, newObjPtrs); } - static void erase_unordered_set(const NetObjTemporaryPtr>& l, const std::unordered_set& ids, std::vector>* erasedObjects = nullptr) { - l->erase_by_unordered_set_ids(l, ids, erasedObjects); + static void erase_list(const NetObjTemporaryPtr>& l, const std::vector>& iterators, std::vector>* erasedObjects = nullptr) { + l->erase_it_list(l, iterators, erasedObjects); } - static void erase(const NetObjTemporaryPtr>& l, uint32_t indexToErase) { - l->erase_by_index(l, indexToErase); - } - static uint32_t erase(const NetObjTemporaryPtr>& l, const NetObjID& id) { - return l->erase_by_id(l, id); + static void erase(const NetObjTemporaryPtr>& l, const NetObjOrderedListIterator& it) { + l->erase_it_list(l, {it}, nullptr); } virtual void reassign_netobj_ids_call() = 0; - typedef std::function& objInfo)> InsertCallback; - typedef std::function& objInfo)> EraseCallback; - typedef std::function& objInfo, uint32_t oldPos)> MoveCallback; + typedef std::function& objInfo)> InsertCallback; + typedef std::function& objInfo)> EraseCallback; + typedef std::function& objInfo, uint32_t oldPos)> MoveCallback; + + typedef NetObjOrderedListObjectInfo value_type; void set_insert_callback(const InsertCallback& func) { insertCallback = func; @@ -99,28 +108,30 @@ namespace NetworkingObjects { } virtual bool contains(const NetObjID& p) const = 0; - virtual const std::vector>& get_data() const = 0; + virtual NetObjOrderedListIterator begin() = 0; + virtual NetObjOrderedListIterator end() = 0; + virtual NetObjOrderedListIterator at(uint32_t index) = 0; + virtual NetObjOrderedListIterator get(const NetObjID& id) = 0; + virtual NetObjOrderedListConstIterator begin() const = 0; + virtual NetObjOrderedListConstIterator end() const = 0; + virtual NetObjOrderedListConstIterator at(uint32_t index) const = 0; + virtual NetObjOrderedListConstIterator get(const NetObjID& id) const = 0; virtual uint32_t size() const = 0; - virtual const NetObjOrderedListObjectInfoPtr& at(uint32_t index) const = 0; - virtual NetObjOrderedListObjectInfoPtr get(const NetObjID& id) const = 0; virtual bool empty() const = 0; virtual ~NetObjOrderedList() {} protected: - virtual NetObjOrderedListObjectInfoPtr insert(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, uint32_t posToInsertAt, NetObjOwnerPtr newObj) = 0; - virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector>>& newObj) = 0; - virtual void erase_by_index(const NetObjTemporaryPtr>& l, uint32_t indexToErase) = 0; - virtual uint32_t erase_by_id(const NetObjTemporaryPtr>& l, const NetObjID& id) = 0; - virtual void erase_by_unordered_set_ids(const NetObjTemporaryPtr>& l, std::unordered_set ids, std::vector>* erasedObjects) = 0; + virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObj) = 0; + virtual void erase_it_list(const NetObjTemporaryPtr>& l, const std::vector>& itList, std::vector>* erasedObjects) = 0; virtual void write_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) = 0; virtual void read_update(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) = 0; virtual void read_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) = 0; // Call after inserting - void call_insert_callback(const NetObjOrderedListObjectInfoPtr& objInfo) { + void call_insert_callback(const NetObjOrderedListIterator& objInfo) { if(insertCallback) insertCallback(objInfo); } - void call_insert_callback_list(const std::vector>& objInfos) { + void call_insert_callback_list(const std::vector>& objInfos) { if(insertCallback) { for(auto objInfo : objInfos) insertCallback(objInfo); @@ -128,12 +139,12 @@ namespace NetworkingObjects { } // Call before erasing - void call_erase_callback(const NetObjOrderedListObjectInfoPtr& objInfo) { + void call_erase_callback(const NetObjOrderedListIterator& objInfo) { if(eraseCallback) eraseCallback(objInfo); } - void call_move_callback(const NetObjOrderedListObjectInfoPtr& objInfo, uint32_t oldPos) { + void call_move_callback(const NetObjOrderedListIterator& objInfo, uint32_t oldPos) { if(moveCallback) moveCallback(objInfo, oldPos); } @@ -160,19 +171,37 @@ namespace NetworkingObjects { virtual bool contains(const NetObjID& id) const override { return idToDataMap.contains(id); } - virtual const std::vector>& get_data() const override { - return data; - } virtual uint32_t size() const override { return data.size(); } - virtual const NetObjOrderedListObjectInfoPtr& at(uint32_t index) const override { - return data[index]; + virtual NetObjOrderedListIterator begin() override { + return data.begin(); } - virtual NetObjOrderedListObjectInfoPtr get(const NetObjID& id) const override { + virtual NetObjOrderedListIterator end() override { + return data.end(); + } + virtual NetObjOrderedListIterator at(uint32_t index) override { + return std::next(data.begin(), index); + } + virtual NetObjOrderedListIterator get(const NetObjID& id) override { auto it = idToDataMap.find(id); if(it == idToDataMap.end()) - return nullptr; + return data.end(); + return it->second; + } + virtual NetObjOrderedListConstIterator begin() const override { + return data.begin(); + } + virtual NetObjOrderedListConstIterator end() const override { + return data.end(); + } + virtual NetObjOrderedListConstIterator at(uint32_t index) const override { + return std::next(data.begin(), index); + } + virtual NetObjOrderedListConstIterator get(const NetObjID& id) const override { + auto it = idToDataMap.find(id); + if(it == idToDataMap.end()) + return data.end(); return it->second; } virtual bool empty() const override { @@ -180,110 +209,87 @@ namespace NetworkingObjects { } virtual void reassign_netobj_ids_call() override { idToDataMap.clear(); - for(auto& d : data) { - d->obj.reassign_ids(); - idToDataMap[d->obj.get_net_id()] = d; + for(auto it = data.begin(); it != data.end(); ++it) { + it->obj.reassign_ids(); + idToDataMap[it->obj.get_net_id()] = it; } } protected: - virtual NetObjOrderedListObjectInfoPtr insert(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, uint32_t posToInsertAt, NetObjOwnerPtr newObj) override { - posToInsertAt = std::min(posToInsertAt, data.size()); - auto newObjInfoPtr = std::make_shared>(std::move(newObj), 0); - data.insert(data.begin() + posToInsertAt, newObjInfoPtr); - idToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr, posToInsertAt](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE_CONSTRUCT, posToInsertAt); - newObjInfoPtr->obj.write_create_message(a); - }); - l.send_server_update_to_client(clientInserting, RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr, posToInsertAt](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::INSERT_SINGLE_REFERENCE, posToInsertAt, newObjInfoPtr->obj.get_net_id()); - }); - set_positions_for_object_info_vector(data, posToInsertAt); - this->call_insert_callback(data[posToInsertAt]); - return data[posToInsertAt]; - } - virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector>>& newObjs) override { - std::vector> toRet; - for(auto& [pos, newObj] : newObjs) { - uint32_t posToInsertAt = std::min(pos, data.size()); - auto newObjInfoPtr = std::make_shared>(std::move(newObj), 0); - data.insert(data.begin() + posToInsertAt, newObjInfoPtr); - idToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - toRet.emplace_back(data[posToInsertAt]); + virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObjs) override { + if(newObjs.empty()) + return {}; + + std::vector idPositionList; + for(auto& [itToInsertAt, newObj] : newObjs) { + if(itToInsertAt == data.begin()) + idPositionList.emplace_back(NetworkingObjects::NetObjID{0, 0}); + else + idPositionList.emplace_back(std::prev(itToInsertAt)->obj.get_net_id()); } - set_positions_for_object_info_vector(data, newObjs[0].first); - l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::INSERT_MANY_CONSTRUCT, static_cast(toRet.size())); - for(const NetObjOrderedListObjectInfoPtr& objInfo : toRet) { - a(objInfo->pos); - objInfo->obj.write_create_message(a); + + std::vector> toRet; + for(auto& [itToInsertAt, newObj] : newObjs) { + auto newObjIt = data.emplace(itToInsertAt, std::move(newObj), itToInsertAt == data.end() ? data.size() : itToInsertAt->pos); // All position values will be wrong except the first one, which is all that matters + idToDataMap.emplace(newObjIt->obj.get_net_id(), newObjIt); + toRet.emplace_back(newObjIt); + } + + set_position_obj_info_list(toRet[0], data.end()); + l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet, &idPositionList](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_LIST_CONSTRUCT, static_cast(toRet.size())); + for(auto [newObjIt, idPosition] : std::views::zip(toRet, idPositionList)) { + a(idPosition); + newObjIt->obj.write_create_message(a); } }); - l.send_server_update_to_client(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::INSERT_MANY_REFERENCE, static_cast(toRet.size())); - for(const NetObjOrderedListObjectInfoPtr& objInfo : toRet) - a(objInfo->pos, objInfo->obj.get_net_id()); + l.send_server_update_to_client(clientInserting, RELIABLE_COMMAND_CHANNEL, [&toRet, &idPositionList](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::INSERT_LIST_REFERENCE, static_cast(toRet.size())); + for(auto [newObjIt, idPosition] : std::views::zip(toRet, idPositionList)) + a(idPosition, newObjIt->obj.get_net_id()); }); this->call_insert_callback_list(toRet); return toRet; } - virtual void erase_by_index(const NetObjTemporaryPtr>& l, uint32_t indexToErase) override { - if(data.empty()) + virtual void erase_it_list(const NetObjTemporaryPtr>& l, const std::vector>& itList, std::vector>* erasedObjects) { + if(itList.empty()) return; - indexToErase = std::min(indexToErase, data.size() - 1); - l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase); - }); - NetObjID idToErase = data[indexToErase]->obj.get_net_id(); - this->call_erase_callback(data[indexToErase]); - data.erase(data.begin() + indexToErase); - idToDataMap.erase(idToErase); - set_positions_for_object_info_vector(data, indexToErase); - } - virtual uint32_t erase_by_id(const NetObjTemporaryPtr>& l, const NetObjID& id) override { - if(data.empty()) - return std::numeric_limits::max(); - auto it = idToDataMap.find(id); - if(it == idToDataMap.end()) - return std::numeric_limits::max(); - uint32_t indexToErase = it->second->pos; - this->call_erase_callback(data[indexToErase]); - data.erase(data.begin() + indexToErase); - idToDataMap.erase(it); - l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [indexToErase](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::ERASE_SINGLE, indexToErase); - }); - set_positions_for_object_info_vector(data, indexToErase); - return indexToErase; - } - virtual void erase_by_unordered_set_ids(const NetObjTemporaryPtr>& l, std::unordered_set ids, std::vector>* erasedObjects) { - std::vector indicesToErase; - std::erase_if(ids, [&](const NetObjID& id) { - auto it = idToDataMap.find(id); - if(it == idToDataMap.end()) - return true; - indicesToErase.emplace_back(it->second->pos); - idToDataMap.erase(it); // Erase here since we already have the iterator - return false; - }); - if(ids.empty()) - return; - std::sort(indicesToErase.begin(), indicesToErase.end()); - for(uint32_t indexToErase : indicesToErase | std::views::reverse) { - this->call_erase_callback(data[indexToErase]); + + std::vector>> erasedObjectsWithPos; + + NetObjOrderedListIterator smallestPosIt = data.end(); + std::vector idListToSend; + for(auto& it : itList) { + if(smallestPosIt == data.end() || smallestPosIt->pos >= it->pos) { + smallestPosIt = std::next(it); + if(smallestPosIt != data.end()) + smallestPosIt->pos = it->pos; + } + idListToSend.emplace_back(it->obj.get_net_id()); + this->call_erase_callback(it); + idToDataMap.erase(it->obj.get_net_id()); if(erasedObjects) - erasedObjects->emplace_back(std::move(data[indexToErase]->obj)); - data.erase(data.begin() + indexToErase); + erasedObjectsWithPos.emplace_back(it->pos, std::move(it->obj)); + data.erase(it); } - l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&indicesToErase](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_StoC::ERASE_MANY, indicesToErase); + + if(erasedObjects) { + std::sort(erasedObjectsWithPos.begin(), erasedObjectsWithPos.end(), [](auto& a, auto& b) { + return a.first < b.first; + }); + for(auto& e : erasedObjectsWithPos) + erasedObjects->emplace_back(std::move(e.second)); + } + + l.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [&idListToSend](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_StoC::ERASE_ID_LIST, idListToSend); }); - set_positions_for_object_info_vector(data, indicesToErase.front()); + + set_position_obj_info_list(smallestPosIt, data.end()); } virtual void write_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) override { a(static_cast(data.size())); - for(size_t i = 0; i < data.size(); i++) - data[i]->obj.write_create_message(a); + for(auto& c : data) + c.obj.write_create_message(a); } virtual void read_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c) override { uint32_t constructedSize; @@ -291,8 +297,8 @@ namespace NetworkingObjects { data.clear(); idToDataMap.clear(); for(uint32_t i = 0; i < constructedSize; i++) { - data.emplace_back(std::make_shared>(l.get_obj_man()->template read_create_message(a, c), i)); - idToDataMap.emplace(data.back()->obj.get_net_id(), data.back()); + auto it = data.emplace(data.end(), l.get_obj_man()->template read_create_message(a, c), i); + idToDataMap.emplace(data.back().obj.get_net_id(), it); } // Dont send the object data to all clients in the constructor, as the function that called read_create_message is also the one that will decide where to send the data of the constructed object // Example: the INSERT_SINGLE command in read_update, if it was inserting another NetObjOrderedList, would first construct the list using read_create_message, then it will call insert() to send it to clients @@ -301,43 +307,47 @@ namespace NetworkingObjects { ObjPtrOrderedListCommand_CtoS command; a(command); switch(command) { - case ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE: { - uint32_t newPos; - a(newPos); - insert(l, c, newPos, l.get_obj_man()->template read_create_message(a, c)); - break; - } - case ObjPtrOrderedListCommand_CtoS::INSERT_MANY: { - std::vector>> newObjs; + case ObjPtrOrderedListCommand_CtoS::INSERT_LIST: { + std::vector, NetObjOwnerPtr>> newObjs; + uint32_t newObjsSize; a(newObjsSize); for(uint32_t i = 0; i < newObjsSize; i++) { - uint32_t pos; - a(pos); - newObjs.emplace_back(pos, l.get_obj_man()->template read_create_message(a, c)); + NetworkingObjects::NetObjID idBeforeElement; + a(idBeforeElement); + NetObjOrderedListIterator itToInsertAt; + if(idBeforeElement == NetworkingObjects::NetObjID{0, 0}) + itToInsertAt = data.begin(); + else { + auto idToDataMapIt = idToDataMap.find(idBeforeElement); + if(idToDataMapIt == idToDataMap.end()) + itToInsertAt = data.end(); + else + itToInsertAt = std::next(idToDataMapIt->second); + } + + newObjs.emplace_back(itToInsertAt, l.get_obj_man()->template read_create_message(a, c)); } insert_ordered_list(l, c, newObjs); break; } - case ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE: { - NetObjID idToErase; - a(idToErase); - auto it = idToDataMap.find(idToErase); - if(it != idToDataMap.end()) - erase_by_index(l, it->second->pos); - break; - } - case ObjPtrOrderedListCommand_CtoS::ERASE_MANY: { - std::unordered_set idsToErase; + case ObjPtrOrderedListCommand_CtoS::ERASE_ID_LIST: { + std::vector idsToErase; a(idsToErase); - erase_by_unordered_set_ids(l, idsToErase, nullptr); + std::vector> iteratorsToErase; + for(auto& id : idsToErase) { + auto it = idToDataMap.find(id); + if(it != idToDataMap.end()) + iteratorsToErase.emplace_back(it->second); + } + erase_it_list(l, iteratorsToErase, nullptr); break; } } } private: - std::vector> data; - std::unordered_map> idToDataMap; + std::list> data; + std::unordered_map> idToDataMap; }; template class NetObjOrderedListClient : public NetObjOrderedList { @@ -346,135 +356,126 @@ namespace NetworkingObjects { virtual bool contains(const NetObjID& id) const override { return clientIdToDataMap.contains(id); } - virtual const std::vector>& get_data() const override { - return clientData; - } virtual uint32_t size() const override { return clientData.size(); } - virtual const NetObjOrderedListObjectInfoPtr& at(uint32_t index) const override { - return clientData[index]; + virtual NetObjOrderedListIterator begin() override { + return clientData.begin(); } - virtual NetObjOrderedListObjectInfoPtr get(const NetObjID& id) const override { + virtual NetObjOrderedListIterator end() override { + return clientData.end(); + } + virtual NetObjOrderedListIterator at(uint32_t index) override { + return std::next(clientData.begin(), index); + } + virtual NetObjOrderedListIterator get(const NetObjID& id) override { auto it = clientIdToDataMap.find(id); if(it == clientIdToDataMap.end()) - return nullptr; + return clientData.end(); + return it->second; + } + virtual NetObjOrderedListConstIterator begin() const override { + return clientData.begin(); + } + virtual NetObjOrderedListConstIterator end() const override { + return clientData.end(); + } + virtual NetObjOrderedListConstIterator at(uint32_t index) const override { + return std::next(clientData.begin(), index); + } + virtual NetObjOrderedListConstIterator get(const NetObjID& id) const override { + auto it = clientIdToDataMap.find(id); + if(it == clientIdToDataMap.end()) + return clientData.end(); return it->second; } virtual bool empty() const override { return clientData.empty(); } virtual void reassign_netobj_ids_call() override { - clientIdToDataMap.clear(); - clientJustInsertedSyncIgnore.clear(); serverData.clear(); - for(auto& d : clientData) { - d->obj.reassign_ids(); - clientIdToDataMap[d->obj.get_net_id()] = d; - serverData.emplace_back(d->obj.get_net_id()); + serverIdToDataMap.clear(); + clientIdToDataMap.clear(); + for(auto it = clientData.begin(); it != clientData.end(); ++it) { + it->obj.reassign_ids(); + clientIdToDataMap[it->obj.get_net_id()] = it; + auto serverIt = serverData.emplace(serverData.end(), it->obj.get_net_id()); + serverIdToDataMap[it->obj.get_net_id()] = serverIt; } } protected: - virtual NetObjOrderedListObjectInfoPtr insert(const NetObjTemporaryPtr>& l, const std::shared_ptr&, uint32_t posToInsertAt, NetObjOwnerPtr newObj) { - posToInsertAt = std::min(posToInsertAt, clientData.size()); - auto newObjInfoPtr = std::make_shared>(std::move(newObj), 0); - clientData.insert(clientData.begin() + posToInsertAt, newObjInfoPtr); - clientIdToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - clientJustInsertedSyncIgnore.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObjInfoPtr, posToInsertAt](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_CtoS::INSERT_SINGLE, posToInsertAt); // Don't put actual pos to insert at, since the server will check for duplicates and might shift the index on its own - newObjInfoPtr->obj.write_create_message(a); - }); - set_positions_for_object_info_vector(clientData, posToInsertAt); - this->call_insert_callback(clientData[posToInsertAt]); - return clientData[posToInsertAt]; - } - virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector>>& newObjs) override { - std::vector> toRet; - for(auto& [pos, newObj] : newObjs) { - uint32_t posToInsertAt = std::min(pos, clientData.size()); - auto newObjInfoPtr = std::make_shared>(std::move(newObj), 0); - clientData.insert(clientData.begin() + posToInsertAt, newObjInfoPtr); - clientIdToDataMap.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - clientJustInsertedSyncIgnore.emplace(newObjInfoPtr->obj.get_net_id(), newObjInfoPtr); - toRet.emplace_back(clientData[posToInsertAt]); + virtual std::vector> insert_ordered_list(const NetObjTemporaryPtr>& l, const std::shared_ptr& clientInserting, std::vector, NetObjOwnerPtr>>& newObjs) override { + if(newObjs.empty()) + return {}; + + std::vector idPositionList; + for(auto& [itToInsertAt, newObj] : newObjs) { + if(itToInsertAt == clientData.begin()) + idPositionList.emplace_back(NetworkingObjects::NetObjID{0, 0}); + else + idPositionList.emplace_back(std::prev(itToInsertAt)->obj.get_net_id()); } - set_positions_for_object_info_vector(clientData, newObjs[0].first); - l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&toRet](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_CtoS::INSERT_MANY, static_cast(toRet.size())); - for(const NetObjOrderedListObjectInfoPtr& objInfo : toRet) { - a(objInfo->pos); - objInfo->obj.write_create_message(a); + + std::vector> toRet; + for(auto& [itToInsertAt, newObj] : newObjs) { + auto newObjIt = clientData.emplace(itToInsertAt, std::move(newObj), itToInsertAt == clientData.end() ? clientData.size() : itToInsertAt->pos); // All position values will be wrong except the first one, which is all that matters + clientIdToDataMap.emplace(newObjIt->obj.get_net_id(), newObjIt); + toRet.emplace_back(newObjIt); + } + set_position_obj_info_list(toRet[0], clientData.end()); + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&toRet, &idPositionList](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_CtoS::INSERT_LIST, static_cast(toRet.size())); + for(auto [newObjIt, idPosition] : std::views::zip(toRet, idPositionList)) { + a(idPosition); + newObjIt->obj.write_create_message(a); } }); this->call_insert_callback_list(toRet); return toRet; } - virtual void erase_by_index(const NetObjTemporaryPtr>& l, uint32_t indexToErase) override { - if(clientData.empty()) + virtual void erase_it_list(const NetObjTemporaryPtr>& l, const std::vector>& itList, std::vector>* erasedObjects) { + if(itList.empty()) return; - indexToErase = std::min(indexToErase, clientData.size() - 1); - auto p = clientData[indexToErase]; - l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&p](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, p->obj.get_net_id()); - }); - uint32_t iToErase = p->pos; - this->call_erase_callback(clientData[indexToErase]); - clientIdToDataMap.erase(p->obj.get_net_id()); - clientJustInsertedSyncIgnore.erase(p->obj.get_net_id()); - clientData.erase(clientData.begin() + iToErase); - set_positions_for_object_info_vector(clientData, iToErase); - } - virtual uint32_t erase_by_id(const NetObjTemporaryPtr>& l, const NetObjID& id) override { - if(clientData.empty()) - return std::numeric_limits::max(); - auto it = clientIdToDataMap.find(id); - if(it == clientIdToDataMap.end()) - return std::numeric_limits::max(); - l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&id](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_CtoS::ERASE_SINGLE, id); - }); - uint32_t iToErase = it->second->pos; - auto toRet = clientData[iToErase]; - this->call_erase_callback(clientData[iToErase]); - clientIdToDataMap.erase(it); - clientJustInsertedSyncIgnore.erase(id); - clientData.erase(clientData.begin() + iToErase); - set_positions_for_object_info_vector(clientData, iToErase); - return iToErase; - } - virtual void erase_by_unordered_set_ids(const NetObjTemporaryPtr>& l, std::unordered_set ids, std::vector>* erasedObjects) { - std::vector indicesToErase; - std::erase_if(ids, [&](const NetObjID& id) { - auto it = clientIdToDataMap.find(id); - if(it == clientIdToDataMap.end()) - return true; - indicesToErase.emplace_back(it->second->pos); - clientIdToDataMap.erase(it); // Erase here since we already have the iterator - clientJustInsertedSyncIgnore.erase(id); - return false; - }); - if(ids.empty()) - return; - std::sort(indicesToErase.begin(), indicesToErase.end()); - for(uint32_t indexToErase : indicesToErase | std::views::reverse) { - this->call_erase_callback(clientData[indexToErase]); + + std::vector>> erasedObjectsWithPos; + NetObjOrderedListIterator smallestPosIt = clientData.end(); + std::vector idListToSend; + for(auto& it : itList) { + if(smallestPosIt == clientData.end() || smallestPosIt->pos >= it->pos) { + smallestPosIt = std::next(it); + if(smallestPosIt != clientData.end()) + smallestPosIt->pos = it->pos; + } + idListToSend.emplace_back(it->obj.get_net_id()); + this->call_erase_callback(it); + clientIdToDataMap.erase(it->obj.get_net_id()); if(erasedObjects) - erasedObjects->emplace_back(std::move(clientData[indexToErase]->obj)); - clientData.erase(clientData.begin() + indexToErase); + erasedObjectsWithPos.emplace_back(it->pos, std::move(it->obj)); + clientData.erase(it); } - l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&ids](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { - a(ObjPtrOrderedListCommand_CtoS::ERASE_MANY, ids); + + if(erasedObjects) { + std::sort(erasedObjectsWithPos.begin(), erasedObjectsWithPos.end(), [](auto& a, auto& b) { + return a.first < b.first; + }); + for(auto& e : erasedObjectsWithPos) + erasedObjects->emplace_back(std::move(e.second)); + } + + l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&idListToSend](const NetObjTemporaryPtr>&, cereal::PortableBinaryOutputArchive& a) { + a(ObjPtrOrderedListCommand_CtoS::ERASE_ID_LIST, idListToSend); }); - set_positions_for_object_info_vector(clientData, indicesToErase.front()); + + set_position_obj_info_list(smallestPosIt, clientData.end()); } virtual void write_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryOutputArchive& a) override { a(static_cast(clientData.size())); serverData.clear(); - clientJustInsertedSyncIgnore.clear(); // Server will get the data and won't send back references to these objects, so dont ignore sync for these objects - for(size_t i = 0; i < clientData.size(); i++) { - clientData[i]->obj.write_create_message(a); - serverData.emplace_back(clientData[i]->obj.get_net_id()); // We are the ones who made this list, so fill up + serverIdToDataMap.clear(); + for(auto& c : clientData) { + c.obj.write_create_message(a); + auto serverIt = serverData.emplace(serverData.end(), c.obj.get_net_id()); // We are the ones who made this list, so fill up + serverIdToDataMap.emplace(c.obj.get_net_id(), serverIt); } } virtual void read_constructor(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { @@ -483,152 +484,214 @@ namespace NetworkingObjects { clientData.clear(); serverData.clear(); clientIdToDataMap.clear(); - clientJustInsertedSyncIgnore.clear(); + serverIdToDataMap.clear(); for(uint32_t i = 0; i < constructedSize; i++) { - clientData.emplace_back(std::make_shared>(l.get_obj_man()->template read_create_message(a, nullptr), i)); - clientIdToDataMap.emplace(clientData.back()->obj.get_net_id(), clientData.back()); - serverData.emplace_back(clientData.back()->obj.get_net_id()); + auto clientIt = clientData.emplace(clientData.end(), l.get_obj_man()->template read_create_message(a, nullptr), i); + clientIdToDataMap.emplace(clientIt->obj.get_net_id(), clientIt); + auto serverIt = serverData.emplace(serverData.end(), clientIt->obj.get_net_id()); + serverIdToDataMap.emplace(clientIt->obj.get_net_id(), serverIt); } } virtual void read_update(const NetObjTemporaryPtr>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr&) override { ObjPtrOrderedListCommand_StoC c; a(c); switch(c) { - case ObjPtrOrderedListCommand_StoC::INSERT_SINGLE_CONSTRUCT: { - uint32_t newServerPos; - a(newServerPos); - auto objInfoToInsert = std::make_shared>(l.get_obj_man()->template read_create_message(a, nullptr), std::numeric_limits::max()); - serverData.insert(serverData.begin() + newServerPos, objInfoToInsert->obj.get_net_id()); - clientJustInsertedSyncIgnore.erase(objInfoToInsert->obj.get_net_id()); + case ObjPtrOrderedListCommand_StoC::INSERT_LIST_CONSTRUCT: { + uint32_t newObjsSize; + a(newObjsSize); + + std::vector idsBeforeElements; + std::vector, NetObjOwnerPtr>> newObjs; + + for(uint32_t i = 0; i < newObjsSize; i++) { + auto& idBeforeElement = idsBeforeElements.emplace_back(); + a(idBeforeElement); + newObjs.emplace_back(get_client_iterator_from_server_previous_net_obj_id(idBeforeElement), l.get_obj_man()->template read_create_message(a, nullptr)); + } + + for(uint32_t i = 0; i < newObjsSize; i++) { + auto serverInsertAtIt = get_server_iterator_from_server_previous_net_obj_id(idsBeforeElements[i]); + auto serverIt = serverData.emplace(serverInsertAtIt, newObjs[i].second.get_net_id()); + serverIdToDataMap.emplace(newObjs[i].second.get_net_id(), serverIt); + } + + auto firstInsertedIt = clientData.end(); + for(uint32_t i = 0; i < newObjs.size(); i++) { + auto& [itToInsertAt, newObj] = newObjs[i]; + auto newObjIt = clientData.emplace(itToInsertAt, std::move(newObj), itToInsertAt == clientData.end() ? clientData.size() : itToInsertAt->pos); // All position values will be wrong except the first one, which is all that matters + clientIdToDataMap.emplace(newObjIt->obj.get_net_id(), newObjIt); + if(i == 0) + firstInsertedIt = newObjIt; + } + set_position_obj_info_list(firstInsertedIt, clientData.end()); + + for(auto& newObj : newObjs) + this->call_insert_callback(newObj.first); - std::unordered_map> serverNewObjects; - serverNewObjects.emplace(objInfoToInsert->obj.get_net_id(), objInfoToInsert); - sync(serverNewObjects); break; } - case ObjPtrOrderedListCommand_StoC::INSERT_SINGLE_REFERENCE: { - NetObjID newObjID; - uint32_t newServerPos; - a(newServerPos, newObjID); - serverData.insert(serverData.begin() + newServerPos, newObjID); - clientJustInsertedSyncIgnore.erase(newObjID); - sync(std::unordered_map>()); - break; - } - case ObjPtrOrderedListCommand_StoC::INSERT_MANY_CONSTRUCT: { - std::unordered_map> serverNewObjects; + case ObjPtrOrderedListCommand_StoC::INSERT_LIST_REFERENCE: { uint32_t newObjsSize; a(newObjsSize); + + struct PerElementData { + NetworkingObjects::NetObjID idBeforeElement; + NetworkingObjects::NetObjID refID; + bool foundInClient; + NetObjOrderedListIterator clientObjectIt; + NetObjOrderedListIterator clientInsertPosIt; + }; + std::vector receivedElements; + for(uint32_t i = 0; i < newObjsSize; i++) { - uint32_t newServerPos; - a(newServerPos); - auto objInfoToInsert = std::make_shared>(l.get_obj_man()->template read_create_message(a, nullptr), std::numeric_limits::max()); - serverData.insert(serverData.begin() + newServerPos, objInfoToInsert->obj.get_net_id()); - clientJustInsertedSyncIgnore.erase(objInfoToInsert->obj.get_net_id()); - serverNewObjects.emplace(objInfoToInsert->obj.get_net_id(), objInfoToInsert); + auto& elemData = receivedElements.emplace_back(); + a(elemData.idBeforeElement, elemData.refID); } - sync(serverNewObjects); - break; - } - case ObjPtrOrderedListCommand_StoC::INSERT_MANY_REFERENCE: { - uint32_t newObjsSize; - a(newObjsSize); - for(uint32_t i = 0; i < newObjsSize; i++) { - NetObjID newObjID; - uint32_t newServerPos; - a(newServerPos, newObjID); - serverData.insert(serverData.begin() + newServerPos, newObjID); - clientJustInsertedSyncIgnore.erase(newObjID); + + std::list> referredToObjectData; + std::unordered_map referredToObjectOldPos; + + auto startRefreshFrom = clientData.end(); + + for(auto& elemData : receivedElements) { + auto clientIdToDataMapIt = clientIdToDataMap.find(elemData.refID); + if(clientIdToDataMapIt != clientIdToDataMap.end()) { + elemData.clientObjectIt = clientIdToDataMapIt->second; + referredToObjectOldPos.emplace(elemData.clientObjectIt->obj.get_net_id(), elemData.clientObjectIt->pos); + if(startRefreshFrom == clientData.end() || startRefreshFrom == elemData.clientObjectIt) { + startRefreshFrom = std::next(elemData.clientObjectIt); + if(startRefreshFrom != clientData.end()) + startRefreshFrom->pos = elemData.clientObjectIt->pos; + } + referredToObjectData.splice(referredToObjectData.end(), clientData, elemData.clientObjectIt, std::next(elemData.clientObjectIt)); + clientIdToDataMap.erase(clientIdToDataMapIt); + elemData.foundInClient = true; + } + else + elemData.foundInClient = false; } - sync(std::unordered_map>()); - break; - } - case ObjPtrOrderedListCommand_StoC::ERASE_SINGLE: { - uint32_t serverPosToErase; - a(serverPosToErase); - NetObjID objID = serverData[serverPosToErase]; - serverData.erase(serverData.begin() + serverPosToErase); - auto it = clientIdToDataMap.find(objID); - if(it != clientIdToDataMap.end()) { - uint32_t clientPosToErase = it->second->pos; - this->call_erase_callback(clientData[clientPosToErase]); - clientIdToDataMap.erase(it); - clientJustInsertedSyncIgnore.erase(objID); - clientData.erase(clientData.begin() + clientPosToErase); - set_positions_for_object_info_vector(clientData, clientPosToErase); + + set_position_obj_info_list(startRefreshFrom, clientData.end()); + + for(auto& elemData : receivedElements) { + if(elemData.foundInClient) + elemData.clientInsertPosIt = get_client_iterator_from_server_previous_net_obj_id(elemData.idBeforeElement); } - break; - } - case ObjPtrOrderedListCommand_StoC::ERASE_MANY: { - std::vector serverPositionsToErase; - a(serverPositionsToErase); - std::vector clientIndicesToErase; - for(uint32_t serverPosToErase : serverPositionsToErase | std::views::reverse) { - NetObjID objID = serverData[serverPosToErase]; - serverData.erase(serverData.begin() + serverPosToErase); - auto it = clientIdToDataMap.find(objID); - if(it != clientIdToDataMap.end()) { - clientIdToDataMap.erase(it); - clientJustInsertedSyncIgnore.erase(objID); - clientIndicesToErase.emplace_back(it->second->pos); + + for(auto& elemData : receivedElements) { + auto serverInsertAtIt = get_server_iterator_from_server_previous_net_obj_id(elemData.idBeforeElement); + auto serverIt = serverData.emplace(serverInsertAtIt, elemData.refID); + serverIdToDataMap.emplace(elemData.refID, serverIt); + } + + auto firstInsertedIt = clientData.end(); + uint32_t firstInsertedActualPos = 0; + for(auto& elemData : receivedElements) { + if(!elemData.foundInClient) + continue; + if(firstInsertedIt == clientData.end()) { + firstInsertedActualPos = elemData.clientInsertPosIt->pos; + firstInsertedIt = elemData.clientObjectIt; + } + clientData.splice(elemData.clientInsertPosIt, referredToObjectData, elemData.clientObjectIt, std::next(elemData.clientObjectIt)); + clientIdToDataMap.emplace(elemData.clientObjectIt->obj.get_net_id(), elemData.clientObjectIt); + } + + // Instead of set_position_obj_info_list + if(firstInsertedIt != clientData.end()) { + auto& it = firstInsertedIt; + auto& actualPos = firstInsertedActualPos; + for(; it != clientData.end(); ++it) { + it->pos = actualPos; + auto referredToObjectOldPosIt = referredToObjectOldPos.find(it->obj.get_net_id()); + if(referredToObjectOldPosIt != referredToObjectOldPos.end()) { + uint32_t oldPos = referredToObjectOldPosIt->second; + if(oldPos != it->pos) + this->call_move_callback(it, oldPos); + } + actualPos++; } } - std::sort(clientIndicesToErase.begin(), clientIndicesToErase.end()); - if(clientIndicesToErase.empty()) - break; - for(uint32_t indexToErase : clientIndicesToErase | std::views::reverse) { - this->call_erase_callback(clientData[indexToErase]); - clientData.erase(clientData.begin() + indexToErase); + break; + } + case ObjPtrOrderedListCommand_StoC::ERASE_ID_LIST: { + std::vector idsToErase; + a(idsToErase); + + for(auto& id : idsToErase) { + auto serverIDToDataMapIt = serverIdToDataMap.find(id); + serverData.erase(serverIDToDataMapIt->second); + serverIdToDataMap.erase(serverIDToDataMapIt); } - set_positions_for_object_info_vector(clientData, clientIndicesToErase.front()); + + NetObjOrderedListIterator smallestPosIt = clientData.end(); + for(auto& id : idsToErase) { + auto clientIt = clientIdToDataMap.find(id); + if(clientIt == clientIdToDataMap.end()) + continue; + auto it = clientIt->second; + if(smallestPosIt == clientData.end() || smallestPosIt->pos >= it->pos) { + smallestPosIt = std::next(it); + if(smallestPosIt != clientData.end()) + smallestPosIt->pos = it->pos; + } + this->call_erase_callback(it); + clientIdToDataMap.erase(clientIt); + clientData.erase(it); + } + + set_position_obj_info_list(smallestPosIt, clientData.end()); break; } } } private: - void sync(const std::unordered_map>& newServerObjects) { - std::map> ignoredToReinsert; - for(auto& [netID, objInfoPtr] : clientJustInsertedSyncIgnore) - ignoredToReinsert.emplace(objInfoPtr->pos, objInfoPtr); - - clientData.clear(); - for(const NetObjID& id : serverData) { - auto itFoundInClient = clientIdToDataMap.find(id); - if(itFoundInClient != clientIdToDataMap.end()) - clientData.emplace_back(itFoundInClient->second); - else { - auto itFoundInServer = newServerObjects.find(id); - if(itFoundInServer != newServerObjects.end()) { - clientData.emplace_back(itFoundInServer->second); - clientIdToDataMap.emplace(itFoundInServer->first, itFoundInServer->second); - } + NetworkingObjects::NetObjOrderedListIterator get_client_iterator_from_server_previous_net_obj_id(NetworkingObjects::NetObjID previousObjId) { + if(previousObjId == NetworkingObjects::NetObjID{0, 0}) + return clientData.begin(); + else { + auto serverIt = serverIdToDataMap[previousObjId]; + for(;;) { + NetworkingObjects::NetObjID netObjID = *serverIt; + auto clientIt = clientIdToDataMap.find(netObjID); + if(clientIt != clientIdToDataMap.end()) + return std::next(clientIt->second); + if(serverIt == serverData.begin()) + return clientData.begin(); + --serverIt; } } - - for(auto& [pos, objInfoPtr] : ignoredToReinsert) { - if(pos > clientData.size()) - clientData.emplace_back(objInfoPtr); - else - clientData.insert(clientData.begin() + pos, objInfoPtr); - } - - uint32_t bumpFromServerInsert = 0; - for(uint32_t i = 0; i < clientData.size(); i++) { - uint32_t oldPos = clientData[i]->pos; - clientData[i]->pos = i; - if(oldPos == std::numeric_limits::max()) { - this->call_insert_callback(clientData[i]); - bumpFromServerInsert++; - } - else if(oldPos != (i + bumpFromServerInsert)) - this->call_move_callback(clientData[i], oldPos); - } + return clientData.begin(); } - std::vector serverData; - std::vector> clientData; - std::unordered_map> clientIdToDataMap; - std::unordered_map> clientJustInsertedSyncIgnore; + NetworkingObjects::NetObjOrderedListIterator get_prev_client_iterator_from_server_previous_net_obj_id(NetworkingObjects::NetObjID previousObjId) { + if(previousObjId == NetworkingObjects::NetObjID{0, 0}) + return clientData.begin(); + else { + auto serverIt = serverIdToDataMap[previousObjId]; + for(;;) { + NetworkingObjects::NetObjID netObjID = *serverIt; + auto clientIt = clientIdToDataMap.find(netObjID); + if(clientIt != clientIdToDataMap.end()) + return clientIt->second; + if(serverIt == serverData.begin()) + return clientData.begin(); + --serverIt; + } + } + return clientData.begin(); + } + + std::list::iterator get_server_iterator_from_server_previous_net_obj_id(NetworkingObjects::NetObjID previousObjId) { + if(previousObjId == NetworkingObjects::NetObjID{0, 0}) + return serverData.begin(); + return std::next(serverIdToDataMap[previousObjId]); + } + + std::list serverData; + std::unordered_map::iterator> serverIdToDataMap; + std::list> clientData; + std::unordered_map> clientIdToDataMap; }; template void register_ordered_list_class(NetObjManager& objMan) { diff --git a/src/Bookmarks/BookmarkManager.cpp b/src/Bookmarks/BookmarkManager.cpp index 33dd3a1..c90cb7e 100644 --- a/src/Bookmarks/BookmarkManager.cpp +++ b/src/Bookmarks/BookmarkManager.cpp @@ -43,10 +43,11 @@ void BookmarkManager::setup_list_gui(const std::string& id) { NetObjOrderedList& bookmarkParentFolder = *world.netObjMan.get_obj_temporary_ref_from_id(parentId)->get_folder_list(); if(bookmarkParentFolder.size() <= index) return std::nullopt; + auto itemAtIndex = bookmarkParentFolder.at(index); return GUIStuff::TreeListing::DisplayData::ObjInList{ - .id = bookmarkParentFolder.at(index)->obj.get_net_id(), - .isDirectory = bookmarkParentFolder.at(index)->obj->is_folder(), - .isDirectoryOpen = bookmarkParentFolder.at(index)->obj->is_folder() ? bookmarkParentFolder.at(index)->obj->is_folder_open() : false + .id = itemAtIndex->obj.get_net_id(), + .isDirectory = itemAtIndex->obj->is_folder(), + .isDirectoryOpen = itemAtIndex->obj->is_folder() ? itemAtIndex->obj->is_folder_open() : false }; }, .getIndexOfObjInList = [&](const GUIStuff::TreeListing::ParentObjectIDPair& idPair) { @@ -92,28 +93,30 @@ void BookmarkManager::setup_list_gui(const std::string& id) { }, .moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector& objsToInsert) { world.netObjMan.send_multi_update_messsage([&]() { - std::unordered_map> toEraseMap; + std::unordered_map>> toEraseMap; uint32_t newIndex = index; std::vector> toInsertObjPtrs; auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id(listObj)->get_folder_list(); for(size_t i = 0; i < objsToInsert.size(); i++) { - toEraseMap[objsToInsert[i].parent].emplace(objsToInsert[i].object); + auto& parentListPtr = world.netObjMan.get_obj_temporary_ref_from_id(objsToInsert[i].parent)->get_folder_list(); + toEraseMap[objsToInsert[i].parent].emplace_back(parentListPtr->get(objsToInsert[i].object)); if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index) newIndex--; } for(auto& [listToEraseFrom, setToErase] : toEraseMap) { auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id(listToEraseFrom)->get_folder_list(); - listToEraseFromPtr->erase_unordered_set(listToEraseFromPtr, setToErase, &toInsertObjPtrs); + listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs); } - std::vector>> toInsert; + std::vector, NetObjOwnerPtr>> toInsert; + auto insertIt = listPtr->at(newIndex); for(uint32_t i = 0; i < objsToInsert.size(); i++) { auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [id = objsToInsert[i].object](NetObjOwnerPtr& objPtr) { return objPtr.get_net_id() == id; }); - toInsert.emplace_back(newIndex + i, std::move(*it)); + toInsert.emplace_back(insertIt, std::move(*it)); toInsert.back().second.reassign_ids(); } listPtr->insert_ordered_list_and_send_create(listPtr, toInsert); @@ -138,7 +141,7 @@ void BookmarkManager::setup_list_gui(const std::string& id) { if(toDeleteObject.has_value()) { auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id(toDeleteParent.value())->get_folder_list(); - folderList->erase(folderList, toDeleteObject.value()); + folderList->erase(folderList, folderList->get(toDeleteObject.value())); } } @@ -169,30 +172,29 @@ void BookmarkManager::setup_list_gui(const std::string& id) { } } -NetworkingObjects::NetObjOrderedListObjectInfoPtr BookmarkManager::try_to_create_in_proper_position(BookmarkListItem* newItem) { +std::optional> BookmarkManager::try_to_create_in_proper_position(BookmarkListItem* newItem) { using namespace NetworkingObjects; if(selectionData.orderedObjsSelected.empty()) - return nullptr; + return std::nullopt; auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back(); NetObjTemporaryPtr parentPtr = world.netObjMan.get_obj_temporary_ref_from_id(backObjParentObjectPair.parent); if(!parentPtr) - return nullptr; + return std::nullopt; NetObjTemporaryPtr objectPtr = world.netObjMan.get_obj_temporary_ref_from_id(backObjParentObjectPair.object); if(!objectPtr) - return nullptr; + return std::nullopt; if(objectPtr->is_folder()) { objectPtr->set_folder_open(true); return objectPtr->get_folder_list()->push_back_and_send_create(objectPtr->get_folder_list(), newItem); } - uint32_t insertPos = parentPtr->get_folder_list()->get(objectPtr.get_net_id())->pos; - return parentPtr->get_folder_list()->insert_and_send_create(parentPtr->get_folder_list(), insertPos + 1, newItem); + return parentPtr->get_folder_list()->insert_and_send_create(parentPtr->get_folder_list(), std::next(parentPtr->get_folder_list()->get(objectPtr.get_net_id())), newItem); } -NetworkingObjects::NetObjOrderedListObjectInfoPtr BookmarkManager::create_in_proper_position(BookmarkListItem* newItem) { +NetworkingObjects::NetObjOrderedListIterator BookmarkManager::create_in_proper_position(BookmarkListItem* newItem) { auto toRet = try_to_create_in_proper_position(newItem); if(!toRet) return bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), newItem); - return toRet; + return toRet.value(); } void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) { diff --git a/src/Bookmarks/BookmarkManager.hpp b/src/Bookmarks/BookmarkManager.hpp index 5c6b920..9b9991b 100644 --- a/src/Bookmarks/BookmarkManager.hpp +++ b/src/Bookmarks/BookmarkManager.hpp @@ -23,8 +23,8 @@ class BookmarkManager { NetworkingObjects::NetObjOwnerPtr bookmarkListRoot; private: - NetworkingObjects::NetObjOrderedListObjectInfoPtr create_in_proper_position(BookmarkListItem* newItem); - NetworkingObjects::NetObjOrderedListObjectInfoPtr try_to_create_in_proper_position(BookmarkListItem* newItem); + NetworkingObjects::NetObjOrderedListIterator create_in_proper_position(BookmarkListItem* newItem); + std::optional> try_to_create_in_proper_position(BookmarkListItem* newItem); GUIStuff::TreeListing::SelectionData selectionData; std::unordered_set oldSelection; std::string nameToEdit; diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index 6b0ef68..d1c9385 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -74,25 +74,19 @@ void CanvasComponentContainer::draw(SkCanvas* canvas, const DrawData& drawData) } } -void CanvasComponentContainer::set_owner_obj_info(const ObjInfoSharedPtr& ownerObjInfo) { - objInfo = ownerObjInfo; -} - void CanvasComponentContainer::commit_update(DrawingProgram& drawP) { - auto lockedObjInfo = objInfo.lock(); if(worldAABB.has_value()) // This is the only point where worldAABB could be nullopt - drawP.preupdate_component(lockedObjInfo); + drawP.preupdate_component(&(*objInfo)); get_comp().initialize_draw_data(drawP); calculate_world_bounds(); - drawP.preupdate_component(lockedObjInfo); + drawP.preupdate_component(&(*objInfo)); } void CanvasComponentContainer::commit_transform(DrawingProgram& drawP) { - auto lockedObjInfo = objInfo.lock(); if(worldAABB.has_value()) // This is the only point where worldAABB could be nullopt - drawP.preupdate_component(lockedObjInfo); + drawP.preupdate_component(&(*objInfo)); calculate_world_bounds(); - drawP.preupdate_component(lockedObjInfo); + drawP.preupdate_component(&(*objInfo)); } void CanvasComponentContainer::commit_update_dont_invalidate_cache(DrawingProgram& drawP) { diff --git a/src/CanvasComponents/CanvasComponentContainer.hpp b/src/CanvasComponents/CanvasComponentContainer.hpp index f5cbc8a..0590d27 100644 --- a/src/CanvasComponents/CanvasComponentContainer.hpp +++ b/src/CanvasComponents/CanvasComponentContainer.hpp @@ -16,8 +16,7 @@ class CanvasComponentContainer { typedef NetworkingObjects::NetObjOrderedList NetList; typedef NetworkingObjects::NetObjOwnerPtr NetListOwnerPtr; typedef NetworkingObjects::NetObjOrderedListObjectInfo ObjInfo; - typedef std::shared_ptr ObjInfoSharedPtr; - typedef std::weak_ptr ObjInfoWeakPtr; + typedef NetworkingObjects::NetObjOrderedListIterator ObjInfoIterator; constexpr static int COMP_MAX_SHIFT_BEFORE_STOP_COLLISIONS = 14; constexpr static int COMP_MAX_SHIFT_BEFORE_STOP_SCALING = 14; @@ -50,12 +49,12 @@ class CanvasComponentContainer { bool collides_with_world_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection& checkAgainstWorld) const; bool collides_with_cam_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection& checkAgainstCam) const; bool collides_with(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection& checkAgainstWorld, const SCollision::ColliderCollection& checkAgainstCam) const; - void set_owner_obj_info(const ObjInfoSharedPtr& ownerObjInfo); void send_comp_update(DrawingProgram& drawP, bool finalUpdate); std::weak_ptr cacheParentBvhNode; DrawingProgramLayerListItem* parentLayer = nullptr; CoordSpaceHelper coords; + ObjInfoIterator objInfo; private: friend class BrushStrokeCanvasComponent; friend class ImageCanvasComponent; @@ -75,7 +74,6 @@ class CanvasComponentContainer { TransformDrawData calculate_draw_transform(const DrawData& drawData) const; void calculate_world_bounds(); - ObjInfoWeakPtr objInfo; std::optional> worldAABB; NetworkingObjects::NetObjOwnerPtr compAllocator; }; diff --git a/src/CanvasComponents/ImageCanvasComponent.cpp b/src/CanvasComponents/ImageCanvasComponent.cpp index 125f1cb..e8e4b32 100644 --- a/src/CanvasComponents/ImageCanvasComponent.cpp +++ b/src/CanvasComponents/ImageCanvasComponent.cpp @@ -79,7 +79,7 @@ void ImageCanvasComponent::update(DrawingProgram& drawP) { ResourceDisplay* display = drawP.world.drawData.rMan->get_display_data(d.imageID); if(display) { if(display->update_draw()) - drawP.invalidate_cache_at_component(compContainer->objInfo.lock()); + drawP.invalidate_cache_at_component(&(*compContainer->objInfo)); } } diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 80a4d51..5ad1a10 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -288,12 +288,12 @@ void DrawingProgram::update() { rebuild_cache(); } -void DrawingProgram::invalidate_cache_at_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck) { +void DrawingProgram::invalidate_cache_at_component(CanvasComponentContainer::ObjInfo* objToCheck) { if(!selection.is_selected(objToCheck)) drawCache.invalidate_cache_at_aabb(objToCheck->obj->get_world_bounds()); } -void DrawingProgram::preupdate_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck) { +void DrawingProgram::preupdate_component(CanvasComponentContainer::ObjInfo* objToCheck) { if(!selection.is_selected(objToCheck)) drawCache.preupdate_component(objToCheck); } @@ -395,7 +395,7 @@ void DrawingProgram::update_downloading_dropped_files() { if(display->get_type() == ResourceDisplay::Type::FILE) { Logger::get().log("WORLDFATAL", "Failed to parse image from URL"); auto& parentLayerComponents = downFile.comp->obj->parentLayer->get_layer().components; - parentLayerComponents->erase(parentLayerComponents, downFile.comp->obj.get_net_id()); + parentLayerComponents->erase(parentLayerComponents, downFile.comp->obj->objInfo); } else { Vector2f imTrueDim = display->get_dimensions(); @@ -414,7 +414,7 @@ void DrawingProgram::update_downloading_dropped_files() { case FileDownloader::DownloadData::Status::FAILURE: { Logger::get().log("WORLDFATAL", "Failed to download data from URL"); auto& parentLayerComponents = downFile.comp->obj->parentLayer->get_layer().components; - parentLayerComponents->erase(parentLayerComponents, downFile.comp->obj.get_net_id()); + parentLayerComponents->erase(parentLayerComponents, downFile.comp->obj->objInfo); return true; } case FileDownloader::DownloadData::Status::IN_PROGRESS: diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 1e9020d..4bfc618 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -50,8 +50,8 @@ class DrawingProgram { void switch_to_tool_ptr(std::unique_ptr newTool); void modify_grid(const NetworkingObjects::NetObjWeakPtr& gridToModify); - void invalidate_cache_at_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck); - void preupdate_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck); + void invalidate_cache_at_component(CanvasComponentContainer::ObjInfo* objToCheck); + void preupdate_component(CanvasComponentContainer::ObjInfo* objToCheck); private: void drag_drop_update(); void add_file_to_canvas_by_path_execute(const std::filesystem::path& filePath, Vector2f dropPos); @@ -76,7 +76,7 @@ class DrawingProgram { DrawingProgramSelection selection; std::unique_ptr toolToSwitchToAfterUpdate; - std::unordered_set updateableComponents; + std::unordered_set updateableComponents; bool temporaryEraser = false; bool temporaryPan = false; @@ -103,7 +103,7 @@ class DrawingProgram { } controls; struct DroppedDownloadingFile { - CanvasComponentContainer::ObjInfoSharedPtr comp; + CanvasComponentContainer::ObjInfo* comp; Vector2f windowSizeWhenDropped; std::shared_ptr downData; }; diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 120c871..8f48b00 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -17,12 +17,12 @@ DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP): drawP(initDrawP) {} -void DrawingProgramCache::add_component(const CanvasComponentContainer::ObjInfoSharedPtr& c) { +void DrawingProgramCache::add_component(CanvasComponentContainer::ObjInfo* c) { unsortedComponents.emplace_back(c); invalidate_cache_at_aabb(c->obj->get_world_bounds()); } -void DrawingProgramCache::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& c) { +void DrawingProgramCache::erase_component(CanvasComponentContainer::ObjInfo* c) { auto cacheParentBvhNodeLock = c->obj->cacheParentBvhNode.lock(); if(cacheParentBvhNodeLock) { std::erase(cacheParentBvhNodeLock->components, c); @@ -54,11 +54,11 @@ bool DrawingProgramCache::unsorted_components_exist() const { return !unsortedComponents.empty(); } -void DrawingProgramCache::build(const std::unordered_set& objsToExclude) { +void DrawingProgramCache::build(const std::unordered_set& objsToExclude) { internal_build(drawP.layerMan.get_flattened_component_list(), objsToExclude); } -void DrawingProgramCache::internal_build(std::vector componentsToBuild, const std::unordered_set& objsToNotInclude) { +void DrawingProgramCache::internal_build(std::vector componentsToBuild, const std::unordered_set& objsToNotInclude) { std::erase_if(componentsToBuild, [&objsToNotInclude](auto& c) { return objsToNotInclude.contains(c); }); @@ -74,9 +74,9 @@ void DrawingProgramCache::clear_own_cached_surfaces() { }); } -CanvasComponentContainer::ObjInfoSharedPtr DrawingProgramCache::get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC) { +CanvasComponentContainer::ObjInfo* DrawingProgramCache::get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC) { auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); - CanvasComponentContainer::ObjInfoSharedPtr p; + CanvasComponentContainer::ObjInfo* p = nullptr; traverse_bvh_run_function(cCWorld.bounds, [&](const std::shared_ptr& bvhNode) { node_loop_components(bvhNode, [&](const auto& c) { if(drawP.layerMan.component_passes_layer_selector(c, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED) && (!p || c->pos >= p->pos) && c->obj->collides_with_world_coords(drawP.world.drawData.cam.c, cCWorld)) @@ -87,7 +87,7 @@ CanvasComponentContainer::ObjInfoSharedPtr DrawingProgramCache::get_front_object return p; } -void DrawingProgramCache::node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f) { +void DrawingProgramCache::node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f) { if(bvhNode) { std::erase_if(bvhNode->components, [&f](const auto& comp) { if(f(comp)) { @@ -101,14 +101,14 @@ void DrawingProgramCache::node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f) { +void DrawingProgramCache::node_loop_components(const std::shared_ptr& bvhNode, std::function f) { if(bvhNode) std::for_each(bvhNode->components.begin(), bvhNode->components.end(), f); else std::for_each(unsortedComponents.begin(), unsortedComponents.end(), f); } -void DrawingProgramCache::preupdate_component(const CanvasComponentContainer::ObjInfoSharedPtr& c) { +void DrawingProgramCache::preupdate_component(CanvasComponentContainer::ObjInfo* c) { // Can be called even if object isn't in cache yet. In that case, it'll just invalidate the cache at the object's AABB auto cacheParentBvhNodeLock = c->obj->cacheParentBvhNode.lock(); if(cacheParentBvhNodeLock) { @@ -119,7 +119,7 @@ void DrawingProgramCache::preupdate_component(const CanvasComponentContainer::Ob invalidate_cache_at_aabb(c->obj->get_world_bounds()); } -void DrawingProgramCache::build_bvh_node(const std::shared_ptr& bvhNode, const std::vector& components) { +void DrawingProgramCache::build_bvh_node(const std::shared_ptr& bvhNode, const std::vector& components) { if(components.empty()) return; @@ -138,7 +138,7 @@ void DrawingProgramCache::build_bvh_node(const std::shared_ptrbounds.center(); - std::array, 4> parts; + std::array, 4> parts; for(auto& c : components) { const auto& cAABB = c->obj->get_world_bounds(); @@ -338,11 +338,11 @@ void DrawingProgramCache::recursive_draw_layer_item_to_canvas(const DrawingProgr layerPaint.setBlendMode(serialized_blend_mode_to_sk_blend_mode(layerListItem.get_blend_mode())); canvas->saveLayer(nullptr, &layerPaint); if(layerListItem.is_folder()) { - for(auto& p : layerListItem.get_folder().folderList->get_data() | std::views::reverse) - recursive_draw_layer_item_to_canvas(*p->obj, canvas, drawData, drawBounds, nodesToDraw); + for(auto& p : *layerListItem.get_folder().folderList | std::views::reverse) + recursive_draw_layer_item_to_canvas(*p.obj, canvas, drawData, drawBounds, nodesToDraw); } else { - std::vector compsToDraw; + std::vector compsToDraw; for(auto& c : unsortedComponents) { if(c->obj->parentLayer == &layerListItem && (!drawBounds.has_value() || SCollision::collide(drawBounds.value(), c->obj->get_world_bounds()))) compsToDraw.emplace_back(c); diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index ddf9949..4bcf05c 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -8,7 +8,7 @@ struct DrawingProgramCacheBVHNode { CoordSpaceHelper coords; Vector2i resolution; private: - std::vector components; + std::vector components; std::vector> children; friend class DrawingProgramCache; }; @@ -20,22 +20,22 @@ class DrawingProgramCache { static constexpr size_t MAXIMUM_DRAW_CACHE_SURFACES = 40; DrawingProgramCache(DrawingProgram& initDrawP); - void add_component(const CanvasComponentContainer::ObjInfoSharedPtr& c); - void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& c); + void add_component(CanvasComponentContainer::ObjInfo* c); + void erase_component(CanvasComponentContainer::ObjInfo* c); void clear_own_cached_surfaces(); - void preupdate_component(const CanvasComponentContainer::ObjInfoSharedPtr& c); - void build(const std::unordered_set& objsToExclude); + void preupdate_component(CanvasComponentContainer::ObjInfo* c); + void build(const std::unordered_set& objsToExclude); void traverse_bvh_run_function(const SCollision::AABB& aabb, std::function& node)> f); void traverse_bvh_run_function_starting_at_node(const std::shared_ptr& bvhNode, const SCollision::AABB& aabb, std::function& node)> f); void traverse_bvh_run_function_starting_at_node_no_collision_check(const std::shared_ptr& bvhNode, std::function& node)> f); - void node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f); - void node_loop_components(const std::shared_ptr& bvhNode, std::function f); + void node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f); + void node_loop_components(const std::shared_ptr& bvhNode, std::function f); bool should_rebuild() const; void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::optional>& drawBounds); bool unsorted_components_exist() const; void invalidate_cache_at_aabb(const SCollision::AABB& aabb); void refresh_all_draw_cache(const DrawData& drawData); - CanvasComponentContainer::ObjInfoSharedPtr get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); + CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); ~DrawingProgramCache(); private: struct NodeCache { @@ -46,14 +46,14 @@ class DrawingProgramCache { }; static std::unordered_map, NodeCache> nodeCacheMap; - void internal_build(std::vector componentsToBuild, const std::unordered_set& objsToNotInclude); - void build_bvh_node(const std::shared_ptr& bvhNode, const std::vector& components); + void internal_build(std::vector componentsToBuild, const std::unordered_set& objsToNotInclude); + void build_bvh_node(const std::shared_ptr& bvhNode, const std::vector& components); void build_bvh_node_coords_and_resolution(DrawingProgramCacheBVHNode& node); void refresh_draw_cache(const std::shared_ptr& bvhNode, const DrawData& drawData); void draw_cache_image_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr& bvhNode); void recursive_draw_layer_item_to_canvas(const DrawingProgramLayerListItem& layerListItem, SkCanvas* canvas, const DrawData& drawData, const std::optional>& drawBounds, const std::vector>& nodesToDraw); std::shared_ptr bvhRoot; - std::vector unsortedComponents; + std::vector unsortedComponents; DrawingProgram& drawP; }; diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index 7ee94c8..85c3920 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -23,9 +23,9 @@ DrawingProgramSelection::DrawingProgramSelection(DrawingProgram& initDrawP): {} void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC, DrawingProgramLayerManager::LayerSelector layerSelector, bool frontObjectOnly) { - std::unordered_set selectedComponents; + std::unordered_set selectedComponents; if(frontObjectOnly) { - CanvasComponentContainer::ObjInfoSharedPtr a = drawP.drawCache.get_front_object_colliding_with_in_editing_layer(cC); + CanvasComponentContainer::ObjInfo* a = drawP.drawCache.get_front_object_colliding_with_in_editing_layer(cC); if(a) { selectedComponents.emplace(a); drawP.drawCache.erase_component(a); @@ -40,7 +40,7 @@ void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCo void DrawingProgramSelection::remove_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC, DrawingProgramLayerManager::LayerSelector layerSelector, bool frontObjectOnly) { if(frontObjectOnly) { - CanvasComponentContainer::ObjInfoSharedPtr p = get_front_object_colliding_with_in_editing_layer(cC); + CanvasComponentContainer::ObjInfo* p = get_front_object_colliding_with_in_editing_layer(cC); if(p) { drawP.drawCache.add_component(p); selectedSet.erase(p); @@ -60,7 +60,7 @@ void DrawingProgramSelection::remove_from_cam_coord_collider_to_selection(const calculate_aabb(); } -std::function&)> DrawingProgramSelection::erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld, DrawingProgramLayerManager::LayerSelector layerSelector) { +std::function&)> DrawingProgramSelection::erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld, DrawingProgramLayerManager::LayerSelector layerSelector) { auto toRet = [&](const auto& bvhNode) { if(bvhNode && (bvhNode->coords.inverseScale << 9) < drawP.world.drawData.cam.c.inverseScale && SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.min)) && @@ -69,7 +69,7 @@ std::function&)> DrawingP SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.bottom_left()))) { drawP.drawCache.invalidate_cache_at_aabb(bvhNode->bounds); drawP.drawCache.traverse_bvh_run_function_starting_at_node_no_collision_check(bvhNode, [&](const auto& bvhNodeChild) { - drawP.drawCache.node_loop_erase_if_components(bvhNodeChild, [&](auto& c) { + drawP.drawCache.node_loop_erase_if_components(bvhNodeChild, [&](auto c) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) { selectedComponents.emplace(c); return true; @@ -80,7 +80,7 @@ std::function&)> DrawingP }); return false; } - drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto& c) { + drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto c) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC)) { selectedComponents.emplace(c); drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds()); @@ -94,12 +94,12 @@ std::function&)> DrawingP return toRet; } -void DrawingProgramSelection::add_to_selection(const std::unordered_set& newSelection) { +void DrawingProgramSelection::add_to_selection(const std::unordered_set& newSelection) { selectedSet.insert(newSelection.begin(), newSelection.end()); calculate_aabb(); } -void DrawingProgramSelection::set_to_selection(const std::unordered_set& newSelection) { +void DrawingProgramSelection::set_to_selection(const std::unordered_set& newSelection) { selectedSet = newSelection; calculate_aabb(); } @@ -117,7 +117,7 @@ bool DrawingProgramSelection::is_something_selected() { return !selectedSet.empty(); } -bool DrawingProgramSelection::is_selected(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck) { +bool DrawingProgramSelection::is_selected(CanvasComponentContainer::ObjInfo* objToCheck) { return selectedSet.contains(objToCheck); } @@ -149,15 +149,15 @@ bool DrawingProgramSelection::mouse_collided_with_rotate_handle_point() { void DrawingProgramSelection::commit_transform_selection() { auto selectedSetTemp = selectedSet; - std::vector a(selectedSet.begin(), selectedSet.end()); - std::vector> transformsFrom; + std::vector a(selectedSet.begin(), selectedSet.end()); + std::vector> transformsFrom; for(auto& transformedObj : a) transformsFrom.emplace_back(transformedObj, transformedObj->obj->coords); for(auto& comp : a) { comp->obj->coords = selectionTransformCoords.other_coord_space_from_this_space(comp->obj->coords); comp->obj->commit_transform(drawP); } - std::vector> transformsTo; + std::vector> transformsTo; std::vector> transformsToSend; for(auto& transformedObj : a) { transformsToSend.emplace_back(transformedObj->obj.get_net_id(), transformedObj->obj->coords); @@ -296,7 +296,7 @@ void DrawingProgramSelection::delete_all() { } } -void DrawingProgramSelection::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck) { +void DrawingProgramSelection::erase_component(CanvasComponentContainer::ObjInfo* objToCheck) { if(is_selected(objToCheck)) { selectedSet.erase(objToCheck); if(selectedSet.empty()) @@ -304,9 +304,9 @@ void DrawingProgramSelection::erase_component(const CanvasComponentContainer::Ob } } -CanvasComponentContainer::ObjInfoSharedPtr DrawingProgramSelection::get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC) { +CanvasComponentContainer::ObjInfo* DrawingProgramSelection::get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC) { auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); - CanvasComponentContainer::ObjInfoSharedPtr p; + CanvasComponentContainer::ObjInfo* p = nullptr; for(auto& c : selectedSet) { if(drawP.layerMan.component_passes_layer_selector(c, DrawingProgramLayerManager::LayerSelector::LAYER_BEING_EDITED) && (!p || c->pos >= p->pos) && c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC)) p = c; @@ -319,7 +319,7 @@ void DrawingProgramSelection::selection_to_clipboard() { std::unordered_set resourceSet; for(auto& c : selectedSet) c->obj->get_comp().get_used_resources(resourceSet); - std::vector compVecSort(selectedSet.begin(), selectedSet.end()); + std::vector compVecSort(selectedSet.begin(), selectedSet.end()); std::vector flattenedLayerList = drawP.layerMan.get_flattened_layer_list(); std::unordered_map flattenedLayerListOrder; for(size_t i = 0; i < flattenedLayerList.size(); i++) @@ -342,7 +342,7 @@ void DrawingProgramSelection::paste_clipboard(Vector2f pasteScreenPos) { if(!drawP.is_selection_allowing_tool(drawP.drawTool->get_type())) drawP.switch_to_tool(DrawingProgramToolType::EDIT); - std::vector> placedComponents; + std::vector> 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); @@ -362,10 +362,12 @@ void DrawingProgramSelection::paste_clipboard(Vector2f pasteScreenPos) { newComponentContainer->get_comp().remap_resource_ids(resourceRemapIDs); newComponentContainer->coords.translate(-moveVec); newComponentContainer->coords.scale_about(mousePos, scaleMultiplier); - placedComponents.emplace_back(drawP.layerMan.edited_layer_component_count() + placedComponents.size(), newComponentContainer); + placedComponents.emplace_back(drawP.layerMan.get_edited_layer_end_iterator(), newComponentContainer); } - auto newlyInsertedObjects = drawP.layerMan.add_many_components_to_layer_being_edited(placedComponents); - std::unordered_set compSetInserted(newlyInsertedObjects.begin(), newlyInsertedObjects.end()); + auto newlyInsertedObjectIts = drawP.layerMan.add_many_components_to_layer_being_edited(placedComponents); + std::unordered_set compSetInserted; + for(auto& it : newlyInsertedObjectIts) + compSetInserted.emplace(&(*it)); set_to_selection(compSetInserted); //drawP.add_undo_place_components(compSetInserted); } @@ -375,7 +377,7 @@ bool DrawingProgramSelection::is_being_transformed() { return transformOpHappening != TransformOperation::NONE; } -const std::unordered_set& DrawingProgramSelection::get_selected_set() { +const std::unordered_set& DrawingProgramSelection::get_selected_set() { return selectedSet; } @@ -459,8 +461,8 @@ void DrawingProgramSelection::draw_components_recursive(const DrawingProgramLaye //layerPaint.setBlendMode(serialized_blend_mode_to_sk_blend_mode(displayData->blendMode)); // For selection, everything should just be in default blend mode (SrcOver) canvas->saveLayer(nullptr, &layerPaint); if(layerItem.is_folder()) { - for(auto& p : layerItem.get_folder().folderList->get_data() | std::views::reverse) - draw_components_recursive(*p->obj, canvas, drawData); + for(auto& p : *layerItem.get_folder().folderList | std::views::reverse) + draw_components_recursive(*p.obj, canvas, drawData); } else { for(auto& c : selectedSet) { // Loop on selected set and not layer component list, since i'm assuming selected set will be small diff --git a/src/DrawingProgram/DrawingProgramSelection.hpp b/src/DrawingProgram/DrawingProgramSelection.hpp index c62f11e..75bf1fa 100644 --- a/src/DrawingProgram/DrawingProgramSelection.hpp +++ b/src/DrawingProgram/DrawingProgramSelection.hpp @@ -10,19 +10,19 @@ class DrawingProgramSelection { DrawingProgramSelection(DrawingProgram& initDrawP); void add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC, DrawingProgramLayerManager::LayerSelector layerSelector, bool frontObjectOnly); void remove_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC, DrawingProgramLayerManager::LayerSelector layerSelector, bool frontObjectOnly); - void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck); + void erase_component(CanvasComponentContainer::ObjInfo* objToCheck); bool is_something_selected(); - bool is_selected(const CanvasComponentContainer::ObjInfoSharedPtr& objToCheck); + bool is_selected(CanvasComponentContainer::ObjInfo* objToCheck); void draw_components(SkCanvas* canvas, const DrawData& drawData); void draw_gui(SkCanvas* canvas, const DrawData& drawData); bool is_being_transformed(); void update(); void deselect_all(); void paste_clipboard(Vector2f pasteScreenPos); - const std::unordered_set& get_selected_set(); + const std::unordered_set& get_selected_set(); void delete_all(); void selection_to_clipboard(); - CanvasComponentContainer::ObjInfoSharedPtr get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); + CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); private: void draw_components_recursive(const DrawingProgramLayerListItem& layerItem, SkCanvas* canvas, const DrawData& drawData); bool mouse_collided_with_selection_aabb(); @@ -34,16 +34,16 @@ class DrawingProgramSelection { void rebuild_cam_space(); Vector2f get_rotation_point_pos_from_angle(double angle); - void set_to_selection(const std::unordered_set& newSelection); - void add_to_selection(const std::unordered_set& newSelection); + void set_to_selection(const std::unordered_set& newSelection); + void add_to_selection(const std::unordered_set& newSelection); void calculate_aabb(); void reset_all(); - std::function&)> erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld, DrawingProgramLayerManager::LayerSelector layerSelector); + std::function&)> erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld, DrawingProgramLayerManager::LayerSelector layerSelector); SCollision::ColliderCollection camSpaceSelection; std::array selectionRectPoints; CoordSpaceHelperTransform selectionTransformCoords; - std::unordered_set selectedSet; + std::unordered_set selectedSet; SCollision::AABB initialSelectionAABB; DrawingProgram& drawP; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp index 661242b..7632cea 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.cpp @@ -4,39 +4,40 @@ #include void DrawingProgramLayer::draw(SkCanvas* canvas, const DrawData& drawData) const { - for(auto& p : components->get_data()) - p->obj->draw(canvas, drawData); + for(auto& p : *components) + p.obj->draw(canvas, drawData); } void DrawingProgramLayer::set_component_list_callbacks(DrawingProgramLayerListItem& layerListItem, DrawingProgramLayerManager& layerMan) const { - components->set_insert_callback([&](const CanvasComponentContainer::ObjInfoSharedPtr& c) { - c->obj->set_owner_obj_info(c); + components->set_insert_callback([&](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); + layerMan.drawP.drawCache.add_component(&(*c)); if(c->obj->get_comp().get_type() == CanvasComponentType::IMAGE) - layerMan.drawP.updateableComponents.emplace(c); + layerMan.drawP.updateableComponents.emplace(&(*c)); }); - components->set_erase_callback([&](const CanvasComponentContainer::ObjInfoSharedPtr& c) { - layerMan.drawP.selection.erase_component(c); - layerMan.drawP.drawCache.erase_component(c); - layerMan.drawP.drawTool->erase_component(c); + components->set_erase_callback([&](const CanvasComponentContainer::ObjInfoIterator& c) { + layerMan.drawP.selection.erase_component(&(*c)); + layerMan.drawP.drawCache.erase_component(&(*c)); + layerMan.drawP.drawTool->erase_component(&(*c)); std::erase_if(layerMan.drawP.droppedDownloadingFiles, [&c](auto& downloadingFile) { - return downloadingFile.comp == c; + return downloadingFile.comp == &(*c); }); - layerMan.drawP.updateableComponents.erase(c); + layerMan.drawP.updateableComponents.erase(&(*c)); }); - components->set_move_callback([&](const CanvasComponentContainer::ObjInfoSharedPtr& c, uint32_t oldPos) { + components->set_move_callback([&](const CanvasComponentContainer::ObjInfoIterator& c, uint32_t oldPos) { layerMan.drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds()); }); } void DrawingProgramLayer::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const { - parallel_loop_container(components->get_data(), [&layerMan](auto& comp) { - comp->obj->commit_update_dont_invalidate_cache(layerMan.drawP); + parallel_loop_container(*components, [&layerMan](auto& comp) { + comp.obj->commit_update_dont_invalidate_cache(layerMan.drawP); }); } -void DrawingProgramLayer::get_flattened_component_list(std::vector& objList) const { - objList.insert(objList.begin(), components->get_data().begin(), components->get_data().end()); +void DrawingProgramLayer::get_flattened_component_list(std::vector& objList) const { + for(auto& p : *components) + objList.emplace_back(&p); } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp index 59f6f4e..d73d186 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayer.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayer.hpp @@ -1,6 +1,7 @@ #pragma once #include #include "../../CanvasComponents/CanvasComponent.hpp" +#include class DrawingProgramLayerListItem; class DrawingProgramLayerManager; @@ -10,7 +11,7 @@ class DrawingProgramLayer { void draw(SkCanvas* canvas, const DrawData& drawData) const; void set_component_list_callbacks(DrawingProgramLayerListItem& layerListItem, DrawingProgramLayerManager& layerMan) const; void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const; - void get_flattened_component_list(std::vector& objList) const; + void get_flattened_component_list(std::vector& objList) const; CanvasComponentContainer::NetListOwnerPtr components; }; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp index 82c8b04..dbbdae6 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.cpp @@ -4,24 +4,24 @@ #include void DrawingProgramLayerFolder::draw(SkCanvas* canvas, const DrawData& drawData) const { - for(auto& p : folderList->get_data() | std::views::reverse) - p->obj->draw(canvas, drawData); + for(auto& p : (*folderList) | std::views::reverse) + p.obj->draw(canvas, drawData); } void DrawingProgramLayerFolder::set_component_list_callbacks(DrawingProgramLayerManager& layerMan) const { folderList->set_insert_callback([&](auto& c) { c->obj->set_component_list_callbacks(layerMan); }); - for(auto& listItem : folderList->get_data()) - listItem->obj->set_component_list_callbacks(layerMan); + for(auto& listItem : *folderList) + listItem.obj->set_component_list_callbacks(layerMan); } void DrawingProgramLayerFolder::commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const { - for(auto& listItem : folderList->get_data()) - listItem->obj->commit_update_dont_invalidate_cache(layerMan); + for(auto& listItem : *folderList) + listItem.obj->commit_update_dont_invalidate_cache(layerMan); } -void DrawingProgramLayerFolder::get_flattened_component_list(std::vector& objList) const { - for(auto& listItem : folderList->get_data()) - listItem->obj->get_flattened_component_list(objList); +void DrawingProgramLayerFolder::get_flattened_component_list(std::vector& objList) const { + for(auto& listItem : (*folderList) | std::views::reverse) + listItem.obj->get_flattened_component_list(objList); } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp index 5ed7907..21497cc 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerFolder.hpp @@ -12,7 +12,7 @@ class DrawingProgramLayerFolder { void draw(SkCanvas* canvas, const DrawData& drawData) const; void set_component_list_callbacks(DrawingProgramLayerManager& layerMan) const; void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const; - void get_flattened_component_list(std::vector& objList) const; + void get_flattened_component_list(std::vector& objList) const; NetworkingObjects::NetObjOwnerPtr> folderList; bool isFolderOpen = false; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp index 9c82b7f..0de1a62 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.cpp @@ -46,7 +46,7 @@ void DrawingProgramLayerListItem::commit_update_dont_invalidate_cache(DrawingPro layerData->commit_update_dont_invalidate_cache(layerMan); } -void DrawingProgramLayerListItem::get_flattened_component_list(std::vector& objList) const { +void DrawingProgramLayerListItem::get_flattened_component_list(std::vector& objList) const { if(folderData) folderData->get_flattened_component_list(objList); else @@ -55,8 +55,8 @@ void DrawingProgramLayerListItem::get_flattened_component_list(std::vector& objList) { if(folderData) { - for(auto& c : folderData->folderList->get_data()) - c->obj->get_flattened_layer_list(objList); + for(auto& c : *folderData->folderList) + c.obj->get_flattened_layer_list(objList); } else objList.emplace_back(this); @@ -65,8 +65,8 @@ void DrawingProgramLayerListItem::get_flattened_layer_list(std::vectorfolderList->get_data()) - toRet += c->obj->get_component_count(); + for(auto& c : *folderData->folderList) + toRet += c.obj->get_component_count(); return toRet; } else diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp index e2e6044..2dfe8ff 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerListItem.hpp @@ -26,7 +26,7 @@ class DrawingProgramLayerListItem { 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; - void get_flattened_component_list(std::vector& objList) const; + void get_flattened_component_list(std::vector& objList) const; void get_flattened_layer_list(std::vector& objList); void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index 2b178ff..0b1012f 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -1,5 +1,6 @@ #include "DrawingProgramLayerManager.hpp" #include "../../World.hpp" +#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" DrawingProgramLayerManager::DrawingProgramLayerManager(DrawingProgram& drawProg): drawP(drawProg), // initialize drawP first for next objects to be initialized properly @@ -32,13 +33,17 @@ uint32_t DrawingProgramLayerManager::edited_layer_component_count() { return editingLayer.lock()->get_layer().components->size(); } +CanvasComponentContainer::ObjInfoIterator DrawingProgramLayerManager::get_edited_layer_end_iterator() { + return editingLayer.lock()->get_layer().components->end(); +} + void DrawingProgramLayerManager::draw(SkCanvas* canvas, const DrawData& drawData) { if(layerTreeRoot) layerTreeRoot->draw(canvas, drawData); } -std::vector DrawingProgramLayerManager::get_flattened_component_list() const { - std::vector toRet; +std::vector DrawingProgramLayerManager::get_flattened_component_list() const { + std::vector toRet; layerTreeRoot->get_flattened_component_list(toRet); return toRet; } @@ -57,17 +62,17 @@ const DrawingProgramLayerListItem& DrawingProgramLayerManager::get_layer_root() return *layerTreeRoot; } -void DrawingProgramLayerManager::erase_component_set(const std::unordered_set& compsToErase) { - std::unordered_map> idsToEraseInSpecificLayers; +void DrawingProgramLayerManager::erase_component_set(const std::unordered_set& compsToErase) { + std::unordered_map> idsToEraseInSpecificLayers; for(auto& c : compsToErase) - idsToEraseInSpecificLayers[c->obj->parentLayer].emplace(c->obj.get_net_id()); + idsToEraseInSpecificLayers[c->obj->parentLayer].emplace_back(c->obj->objInfo); for(auto& [layerListItem, netObjSetToErase] : idsToEraseInSpecificLayers) { auto& layerComponentList = layerListItem->get_layer().components; - layerComponentList->erase_unordered_set(layerComponentList, netObjSetToErase); + layerComponentList->erase_list(layerComponentList, netObjSetToErase); } } -bool DrawingProgramLayerManager::component_passes_layer_selector(const CanvasComponentContainer::ObjInfoSharedPtr& c, LayerSelector layerSelector) { +bool DrawingProgramLayerManager::component_passes_layer_selector(CanvasComponentContainer::ObjInfo* c, LayerSelector layerSelector) { switch(layerSelector) { case LayerSelector::ALL_VISIBLE_LAYERS: return c->obj->parentLayer->get_visible(); @@ -77,16 +82,16 @@ bool DrawingProgramLayerManager::component_passes_layer_selector(const CanvasCom return false; } -std::vector DrawingProgramLayerManager::add_many_components_to_layer_being_edited(const std::vector>& newObjs) { +std::vector DrawingProgramLayerManager::add_many_components_to_layer_being_edited(const std::vector>& 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) { +CanvasComponentContainer::ObjInfo* 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); + return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj)); } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp index 754bdf3..104ad4a 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.hpp @@ -1,6 +1,7 @@ #pragma once #include "DrawingProgramLayerListItem.hpp" #include "DrawingProgramLayerManagerGUI.hpp" +#include class DrawingProgramLayerManager { private: @@ -23,16 +24,17 @@ class DrawingProgramLayerManager { void write_components_server(cereal::PortableBinaryOutputArchive& a); void read_components_client(cereal::PortableBinaryInputArchive& a); bool is_a_layer_being_edited(); - void erase_component_set(const std::unordered_set& compsToErase); + void erase_component_set(const std::unordered_set& compsToErase); uint32_t edited_layer_component_count(); - bool component_passes_layer_selector(const CanvasComponentContainer::ObjInfoSharedPtr& c, LayerSelector layerSelector); + CanvasComponentContainer::ObjInfoIterator get_edited_layer_end_iterator(); + bool component_passes_layer_selector(CanvasComponentContainer::ObjInfo* c, LayerSelector layerSelector); bool layer_tree_root_exists(); const DrawingProgramLayerListItem& get_layer_root(); - CanvasComponentContainer::ObjInfoSharedPtr add_component_to_layer_being_edited(CanvasComponentContainer* newObj); - std::vector add_many_components_to_layer_being_edited(const std::vector>& newObjs); - std::vector get_flattened_component_list() const; + CanvasComponentContainer::ObjInfo* add_component_to_layer_being_edited(CanvasComponentContainer* newObj); + std::vector add_many_components_to_layer_being_edited(const std::vector>& newObjs); + std::vector get_flattened_component_list() const; std::vector get_flattened_layer_list(); DrawingProgramLayerManagerGUI listGUI; }; diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.cpp index 473445f..46ba980 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.cpp @@ -1,9 +1,11 @@ #include "DrawingProgramLayerManagerGUI.hpp" +#include "DrawingProgramLayerListItem.hpp" #include "DrawingProgramLayerManager.hpp" #include "../DrawingProgram.hpp" #include "../../World.hpp" #include "../../MainProgram.hpp" #include "Helpers/ConvertVec.hpp" +#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" #include "SerializedBlendMode.hpp" DrawingProgramLayerManagerGUI::DrawingProgramLayerManagerGUI(DrawingProgramLayerManager& drawLayerMan): @@ -97,28 +99,29 @@ void DrawingProgramLayerManagerGUI::setup_list_gui(const std::string& id, bool& }, .moveObjectsToListAtIndex = [&](NetObjID listObj, size_t index, const std::vector& objsToInsert) { world.netObjMan.send_multi_update_messsage([&]() { - std::unordered_map> toEraseMap; + std::unordered_map>> toEraseMap; uint32_t newIndex = index; std::vector> toInsertObjPtrs; auto& listPtr = world.netObjMan.get_obj_temporary_ref_from_id(listObj)->get_folder().folderList; for(size_t i = 0; i < objsToInsert.size(); i++) { - toEraseMap[objsToInsert[i].parent].emplace(objsToInsert[i].object); + toEraseMap[objsToInsert[i].parent].emplace_back(listPtr->get(objsToInsert[i].object)); if(newIndex != 0 && objsToInsert[i].parent == listObj && listPtr->get(objsToInsert[i].object)->pos <= index) newIndex--; } for(auto& [listToEraseFrom, setToErase] : toEraseMap) { auto& listToEraseFromPtr = world.netObjMan.get_obj_temporary_ref_from_id(listToEraseFrom)->get_folder().folderList; - listToEraseFromPtr->erase_unordered_set(listToEraseFromPtr, setToErase, &toInsertObjPtrs); + listToEraseFromPtr->erase_list(listToEraseFromPtr, setToErase, &toInsertObjPtrs); } - std::vector>> toInsert; + std::vector, NetObjOwnerPtr>> toInsert; + auto insertIt = listPtr->at(newIndex); for(uint32_t i = 0; i < objsToInsert.size(); i++) { auto it = std::find_if(toInsertObjPtrs.begin(), toInsertObjPtrs.end(), [id = objsToInsert[i].object](NetObjOwnerPtr& objPtr) { return objPtr.get_net_id() == id; }); - toInsert.emplace_back(newIndex + i, std::move(*it)); + toInsert.emplace_back(insertIt, std::move(*it)); toInsert.back().second.reassign_ids(); } listPtr->insert_ordered_list_and_send_create(listPtr, toInsert); @@ -151,7 +154,7 @@ void DrawingProgramLayerManagerGUI::setup_list_gui(const std::string& id, bool& if(toDeleteObject.has_value()) { auto& folderList = world.netObjMan.get_obj_temporary_ref_from_id(toDeleteParent.value())->get_folder().folderList; - folderList->erase(folderList, toDeleteObject.value()); + folderList->erase(folderList, folderList->get(toDeleteObject.value())); } } @@ -194,29 +197,28 @@ void DrawingProgramLayerManagerGUI::setup_list_gui(const std::string& id, bool& } } -NetworkingObjects::NetObjOrderedListObjectInfoPtr DrawingProgramLayerManagerGUI::try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem) { +std::optional> DrawingProgramLayerManagerGUI::try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem) { using namespace NetworkingObjects; auto& world = layerMan.drawP.world; if(selectionData.orderedObjsSelected.empty()) - return nullptr; + return std::nullopt; auto& backObjParentObjectPair = selectionData.orderedObjsSelected.back(); NetObjTemporaryPtr parentPtr = world.netObjMan.get_obj_temporary_ref_from_id(backObjParentObjectPair.parent); if(!parentPtr) - return nullptr; + return std::nullopt; NetObjTemporaryPtr objectPtr = world.netObjMan.get_obj_temporary_ref_from_id(backObjParentObjectPair.object); if(!objectPtr) - return nullptr; + return std::nullopt; if(objectPtr->is_folder()) { objectPtr->get_folder().isFolderOpen = true; - return objectPtr->get_folder().folderList->insert_and_send_create(objectPtr->get_folder().folderList, 0, newItem); + return objectPtr->get_folder().folderList->insert_and_send_create(objectPtr->get_folder().folderList, objectPtr->get_folder().folderList->begin(), newItem); } - uint32_t insertPos = parentPtr->get_folder().folderList->get(objectPtr.get_net_id())->pos; - return parentPtr->get_folder().folderList->insert_and_send_create(parentPtr->get_folder().folderList, insertPos, newItem); + return parentPtr->get_folder().folderList->insert_and_send_create(parentPtr->get_folder().folderList, parentPtr->get_folder().folderList->get(objectPtr.get_net_id()), newItem); } -NetworkingObjects::NetObjOrderedListObjectInfoPtr DrawingProgramLayerManagerGUI::create_in_proper_position(DrawingProgramLayerListItem* newItem) { +NetworkingObjects::NetObjOrderedListIterator DrawingProgramLayerManagerGUI::create_in_proper_position(DrawingProgramLayerListItem* newItem) { auto toRet = try_to_create_in_proper_position(newItem); if(!toRet) - return layerMan.layerTreeRoot->get_folder().folderList->insert_and_send_create(layerMan.layerTreeRoot->get_folder().folderList, 0, newItem); - return toRet; + return layerMan.layerTreeRoot->get_folder().folderList->insert_and_send_create(layerMan.layerTreeRoot->get_folder().folderList, layerMan.layerTreeRoot->get_folder().folderList->begin(), newItem); + return toRet.value(); } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.hpp b/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.hpp index 5c8f5b8..ccbd55a 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.hpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManagerGUI.hpp @@ -13,8 +13,8 @@ class DrawingProgramLayerManagerGUI { void refresh_gui_data(); void setup_list_gui(const std::string& id, bool& hoveringOverDropdown); private: - NetworkingObjects::NetObjOrderedListObjectInfoPtr try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem); - NetworkingObjects::NetObjOrderedListObjectInfoPtr create_in_proper_position(DrawingProgramLayerListItem* newItem); + std::optional> try_to_create_in_proper_position(DrawingProgramLayerListItem* newItem); + NetworkingObjects::NetObjOrderedListIterator create_in_proper_position(DrawingProgramLayerListItem* newItem); GUIStuff::TreeListing::SelectionData selectionData; std::unordered_set oldSelection; diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index 4ed4247..d546601 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -26,11 +26,9 @@ void BrushTool::switch_tool(DrawingProgramToolType newTool) { commit_stroke(); } -void BrushTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { - if(objInfoBeingEdited == erasedComp) { - isDrawing = false; +void BrushTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { + if(objInfoBeingEdited == erasedComp) objInfoBeingEdited = nullptr; - } } bool BrushTool::extensive_point_checking(const BrushStrokeCanvasComponent& brushStroke, const Vector2f& newPoint) { @@ -59,7 +57,7 @@ void BrushTool::tool_update() { if(drawP.controls.cursorHoveringOverCanvas) drawP.world.main.input.hideCursor = true; - if(!isDrawing) + if(!objInfoBeingEdited) penSmoothingData.clear(); if(drawP.world.main.input.pen.isDown && drawP.controls.leftClickHeld && drawP.world.main.toolbar.tabletOptions.pressureAffectsBrushWidth) { @@ -89,9 +87,8 @@ void BrushTool::tool_update() { isPenDown = true; if(isPenDown) { - if(!isDrawing) { + if(!objInfoBeingEdited) { if(drawP.layerMan.is_a_layer_being_edited()) { - isDrawing = true; CanvasComponentContainer* newBrushStrokeContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::BRUSHSTROKE); BrushStrokeCanvasComponent& newBrushStroke = static_cast(newBrushStrokeContainer->get_comp()); @@ -148,10 +145,8 @@ void BrushTool::tool_update() { containerPtr->commit_update(drawP); } } - else if(isDrawing) { - isDrawing = false; + else if(objInfoBeingEdited) commit_stroke(); - } } void BrushTool::commit_stroke() { @@ -179,7 +174,7 @@ bool BrushTool::right_click_popup_gui(Vector2f popupPos) { } bool BrushTool::prevent_undo_or_redo() { - return isDrawing; + return objInfoBeingEdited; } void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) { @@ -189,7 +184,7 @@ void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) { linePaint.setStroke(true); linePaint.setStrokeWidth(0.0f); float width; - if(isDrawing) + if(objInfoBeingEdited) width = drawP.controls.relativeWidth * penWidth * 0.5f; else width = drawP.controls.relativeWidth * 0.5f; diff --git a/src/DrawingProgram/Tools/BrushTool.hpp b/src/DrawingProgram/Tools/BrushTool.hpp index 7d449ff..1d182c7 100644 --- a/src/DrawingProgram/Tools/BrushTool.hpp +++ b/src/DrawingProgram/Tools/BrushTool.hpp @@ -20,7 +20,7 @@ class BrushTool : public DrawingProgramToolBase { virtual void gui_toolbox() override; virtual void tool_update() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; @@ -37,8 +37,7 @@ class BrushTool : public DrawingProgramToolBase { }; std::deque penSmoothingData; - CanvasComponentContainer::ObjInfoSharedPtr objInfoBeingEdited; - bool isDrawing = false; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr; bool hasRoundCaps = true; bool drawingMinimumRelativeToSize = true; bool midwayInterpolation = true; diff --git a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp index 3a27d05..ba834ed 100644 --- a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp +++ b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp @@ -28,7 +28,7 @@ class DrawingProgramToolBase { DrawingProgramToolBase(DrawingProgram& initDrawP); virtual DrawingProgramToolType get_type() = 0; virtual void gui_toolbox() = 0; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) = 0; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) = 0; virtual bool right_click_popup_gui(Vector2f popupPos) = 0; virtual void tool_update() = 0; virtual void draw(SkCanvas* canvas, const DrawData& drawData) = 0; diff --git a/src/DrawingProgram/Tools/EditTool.cpp b/src/DrawingProgram/Tools/EditTool.cpp index b9f4cdb..7c34387 100644 --- a/src/DrawingProgram/Tools/EditTool.cpp +++ b/src/DrawingProgram/Tools/EditTool.cpp @@ -24,7 +24,7 @@ DrawingProgramToolType EditTool::get_type() { void EditTool::gui_toolbox() { Toolbar& t = drawP.world.main.toolbar; - if(isEditing) { + if(objInfoBeingEdited) { bool editHappened = compEditTool->edit_gui(objInfoBeingEdited); if(editHappened) objInfoBeingEdited->obj->commit_update(drawP); @@ -36,13 +36,13 @@ void EditTool::gui_toolbox() { } } -void EditTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void EditTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { if(erasedComp == objInfoBeingEdited) switch_tool(get_type()); } bool EditTool::right_click_popup_gui(Vector2f popupPos) { - if(isEditing) + if(objInfoBeingEdited) return compEditTool->right_click_popup_gui(objInfoBeingEdited, popupPos); else return drawP.selection_action_menu(popupPos); @@ -61,14 +61,13 @@ void EditTool::switch_tool(DrawingProgramToolType newTool) { } pointHandles.clear(); pointDragging = nullptr; - isEditing = false; if(!drawP.is_selection_allowing_tool(newTool)) drawP.selection.deselect_all(); } -void EditTool::edit_start(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { - isEditing = true; +void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp) { + bool isEditing = true; switch(comp->obj->get_comp().get_type()) { case CanvasComponentType::TEXTBOX: { compEditTool = std::make_unique(drawP); @@ -97,12 +96,12 @@ void EditTool::edit_start(const CanvasComponentContainer::ObjInfoSharedPtr& comp } } -bool EditTool::is_editable(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool EditTool::is_editable(CanvasComponentContainer::ObjInfo* comp) { return comp->obj->get_comp().get_type() != CanvasComponentType::BRUSHSTROKE; } void EditTool::tool_update() { - if(!isEditing) { + if(!objInfoBeingEdited) { SCollision::AABB mouseAABB{drawP.world.get_mouse_world_pos() - WorldVec{0.5f, 0.5f}, drawP.world.get_mouse_world_pos() + WorldVec{0.5f, 0.5f}}; SCollision::ColliderCollection cMouseAABB; cMouseAABB.aabb.emplace_back(mouseAABB); @@ -116,7 +115,7 @@ void EditTool::tool_update() { if(drawP.controls.leftClick) { bool modifySelection = !drawP.selection.is_being_transformed(); if(drawP.world.main.input.mouse.leftClicks >= 2 && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) { - CanvasComponentContainer::ObjInfoSharedPtr selectedObjectToEdit = drawP.selection.get_front_object_colliding_with_in_editing_layer(camCMouseAABB); + CanvasComponentContainer::ObjInfo* selectedObjectToEdit = drawP.selection.get_front_object_colliding_with_in_editing_layer(camCMouseAABB); if(selectedObjectToEdit && is_editable(selectedObjectToEdit)) { drawP.selection.deselect_all(); @@ -181,14 +180,12 @@ void EditTool::tool_update() { } bool EditTool::prevent_undo_or_redo() { - return isEditing; + return objInfoBeingEdited; } void EditTool::draw(SkCanvas* canvas, const DrawData& drawData) { - if(isEditing) { - if(objInfoBeingEdited) { - for(HandleData& h : pointHandles) - drawP.draw_drag_circle(canvas, drawData.cam.c.to_space((objInfoBeingEdited->obj->coords.from_space(*h.p))), {0.1f, 0.9f, 0.9f, 1.0f}, drawData); - } + if(objInfoBeingEdited) { + for(HandleData& h : pointHandles) + drawP.draw_drag_circle(canvas, drawData.cam.c.to_space((objInfoBeingEdited->obj->coords.from_space(*h.p))), {0.1f, 0.9f, 0.9f, 1.0f}, drawData); } } diff --git a/src/DrawingProgram/Tools/EditTool.hpp b/src/DrawingProgram/Tools/EditTool.hpp index 30fd221..6437dc4 100644 --- a/src/DrawingProgram/Tools/EditTool.hpp +++ b/src/DrawingProgram/Tools/EditTool.hpp @@ -20,19 +20,18 @@ class EditTool : public DrawingProgramToolBase { virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; virtual void tool_update() override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; void add_point_handle(const HandleData& handle); - void edit_start(const CanvasComponentContainer::ObjInfoSharedPtr& comp); - bool is_editable(const CanvasComponentContainer::ObjInfoSharedPtr& comp); + void edit_start(CanvasComponentContainer::ObjInfo* comp); + bool is_editable(CanvasComponentContainer::ObjInfo* comp); std::unique_ptr compEditTool; std::vector pointHandles; - CanvasComponentContainer::ObjInfoSharedPtr objInfoBeingEdited; - bool isEditing = false; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited; HandleData* pointDragging = nullptr; std::any prevData; }; diff --git a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp index 2987f01..32c43f6 100644 --- a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp +++ b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp @@ -5,7 +5,7 @@ DrawingProgramEditToolBase::DrawingProgramEditToolBase(DrawingProgram& initDrawP drawP(initDrawP) {} -bool DrawingProgramEditToolBase::right_click_popup_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp, Vector2f popupPos) { +bool DrawingProgramEditToolBase::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) { Toolbar& t = drawP.world.main.toolbar; t.paint_popup(popupPos); return true; diff --git a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp index 283a784..2391d27 100644 --- a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp +++ b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp @@ -9,11 +9,11 @@ class EditTool; class DrawingProgramEditToolBase { public: DrawingProgramEditToolBase(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& compContainer, std::any& prevData) = 0; - virtual void commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& compContainer, std::any& prevData) = 0; - virtual bool edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& compContainer) = 0; - virtual bool edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& compContainer) = 0; - virtual bool right_click_popup_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp, Vector2f popupPos); + virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0; + virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0; + virtual bool edit_update(CanvasComponentContainer::ObjInfo* compContainer) = 0; + virtual bool edit_gui(CanvasComponentContainer::ObjInfo* compContainer) = 0; + virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos); virtual ~DrawingProgramEditToolBase(); protected: DrawingProgram& drawP; diff --git a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp index 32131e9..24de66f 100644 --- a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp @@ -11,7 +11,7 @@ EllipseDrawEditTool::EllipseDrawEditTool(DrawingProgram& initDrawP): DrawingProgramEditToolBase(initDrawP) {} -bool EllipseDrawEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; @@ -42,7 +42,7 @@ bool EllipseDrawEditTool::edit_gui(const CanvasComponentContainer::ObjInfoShared return editHappened; } -void EllipseDrawEditTool::edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void EllipseDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); prevData = a.d; @@ -50,9 +50,9 @@ void EllipseDrawEditTool::edit_start(EditTool& editTool, const CanvasComponentCo editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr}); } -void EllipseDrawEditTool::commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void EllipseDrawEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { } -bool EllipseDrawEditTool::edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool EllipseDrawEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp index a8721da..9b0bff3 100644 --- a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp @@ -10,10 +10,10 @@ class DrawingProgram; class EllipseDrawEditTool : public DrawingProgramEditToolBase { public: EllipseDrawEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual void commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual bool edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; - virtual bool edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; + virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; + virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override; private: void commit(); diff --git a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp index 6d6fcfe..0cd7cac 100644 --- a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp @@ -16,17 +16,17 @@ ImageEditTool::ImageEditTool(DrawingProgram& initDrawP): DrawingProgramEditToolBase(initDrawP) {} -void ImageEditTool::edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void ImageEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { } -void ImageEditTool::commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void ImageEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { } -bool ImageEditTool::edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool ImageEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { return true; } -bool ImageEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { ImageCanvasComponent& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; t.gui.push_id("edit tool image"); diff --git a/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp b/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp index fce2ae5..0f7985f 100644 --- a/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp @@ -7,8 +7,8 @@ class DrawingProgram; class ImageEditTool : public DrawingProgramEditToolBase { public: ImageEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual void commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual bool edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; - virtual bool edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; + virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; + virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override; }; diff --git a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp index 0c001b3..af180de 100644 --- a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp @@ -9,7 +9,7 @@ RectDrawEditTool::RectDrawEditTool(DrawingProgram& initDrawP): DrawingProgramEditToolBase(initDrawP) {} -bool RectDrawEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; t.gui.push_id("edit tool rectangle"); @@ -40,16 +40,16 @@ bool RectDrawEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr return editHappened; } -void RectDrawEditTool::edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void RectDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); prevData = a.d; editTool.add_point_handle({&a.d.p1, nullptr, &a.d.p2}); editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr}); } -void RectDrawEditTool::commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void RectDrawEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { } -bool RectDrawEditTool::edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool RectDrawEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp index ca27183..6e81f8f 100644 --- a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp @@ -9,10 +9,10 @@ class DrawingProgram; class RectDrawEditTool : public DrawingProgramEditToolBase { public: RectDrawEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual void commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual bool edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; - virtual bool edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; + virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; + virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override; private: std::optional oldData; }; diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp index c10ecfd..0b8bbc1 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp @@ -20,7 +20,7 @@ TextBoxEditTool::TextBoxEditTool(DrawingProgram& initDrawP): DrawingProgramEditToolBase(initDrawP) {} -bool TextBoxEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; @@ -152,7 +152,7 @@ bool TextBoxEditTool::edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& return oldInputChangedTextBox; } -bool TextBoxEditTool::right_click_popup_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp, Vector2f popupPos) { +bool TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) { Toolbar& t = drawP.world.main.toolbar; bool shouldClose = false; auto& a = static_cast(comp->obj->get_comp()); @@ -250,7 +250,7 @@ void TextBoxEditTool::set_styles_at_selection(TextBoxCanvasComponent& a) { currentPStyle = a.textBox->get_paragraph_style_data_at(start.fParagraphIndex); } -void TextBoxEditTool::commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void TextBoxEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); a.d.editing = false; comp->obj->commit_update(drawP); @@ -263,7 +263,7 @@ TextBoxEditTool::TextBoxEditToolAllData TextBoxEditTool::get_all_data(const Text }; } -void TextBoxEditTool::edit_start(EditTool& editTool, const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) { +void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); auto& cur = a.cursor; auto& textbox = a.textBox; @@ -280,7 +280,7 @@ void TextBoxEditTool::edit_start(EditTool& editTool, const CanvasComponentContai editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr}); } -bool TextBoxEditTool::edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) { +bool TextBoxEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { auto& a = static_cast(comp->obj->get_comp()); SCollision::ColliderCollection mousePointCollection; diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp index 19cd152..d30efe6 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp @@ -10,11 +10,11 @@ class TextBoxEditTool : public DrawingProgramEditToolBase { public: TextBoxEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool,const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual void commit_edit_updates(const CanvasComponentContainer::ObjInfoSharedPtr& comp, std::any& prevData) override; - virtual bool edit_update(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; - virtual bool edit_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp) override; - virtual bool right_click_popup_gui(const CanvasComponentContainer::ObjInfoSharedPtr& comp, Vector2f popupPos) override; + virtual void edit_start(EditTool& editTool,CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; + virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; + virtual bool edit_gui(CanvasComponentContainer::ObjInfo* comp) override; + virtual bool right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) override; private: struct TextBoxEditToolAllData { TextBoxCanvasComponent::Data textboxData; diff --git a/src/DrawingProgram/Tools/EllipseDrawTool.cpp b/src/DrawingProgram/Tools/EllipseDrawTool.cpp index 73bf4b9..3b22b34 100644 --- a/src/DrawingProgram/Tools/EllipseDrawTool.cpp +++ b/src/DrawingProgram/Tools/EllipseDrawTool.cpp @@ -29,11 +29,9 @@ void EllipseDrawTool::gui_toolbox() { t.gui.pop_id(); } -void EllipseDrawTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { - if(objInfoBeingEdited == erasedComp) { +void EllipseDrawTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { + if(objInfoBeingEdited == erasedComp) objInfoBeingEdited = nullptr; - drawStage = 0; - } } bool EllipseDrawTool::right_click_popup_gui(Vector2f popupPos) { @@ -47,53 +45,46 @@ void EllipseDrawTool::switch_tool(DrawingProgramToolType newTool) { } void EllipseDrawTool::tool_update() { - switch(drawStage) { - case 0: { - if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { - CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::ELLIPSE); - EllipseCanvasComponent& newEllipse = static_cast(newContainer->get_comp()); + if(objInfoBeingEdited) { + if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { + CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::ELLIPSE); + EllipseCanvasComponent& newEllipse = static_cast(newContainer->get_comp()); - startAt = drawP.world.main.input.mouse.pos; - newEllipse.d.strokeColor = drawP.controls.foregroundColor; - newEllipse.d.fillColor = drawP.controls.backgroundColor; - newEllipse.d.strokeWidth = drawP.controls.relativeWidth; - newEllipse.d.p1 = startAt; - newEllipse.d.p2 = startAt; - newEllipse.d.p2 = ensure_points_have_distance(newEllipse.d.p1, newEllipse.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - newEllipse.d.fillStrokeMode = static_cast(fillStrokeMode); - newContainer->coords = drawP.world.drawData.cam.c; + startAt = drawP.world.main.input.mouse.pos; + newEllipse.d.strokeColor = drawP.controls.foregroundColor; + newEllipse.d.fillColor = drawP.controls.backgroundColor; + newEllipse.d.strokeWidth = drawP.controls.relativeWidth; + newEllipse.d.p1 = startAt; + newEllipse.d.p2 = startAt; + newEllipse.d.p2 = ensure_points_have_distance(newEllipse.d.p1, newEllipse.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + newEllipse.d.fillStrokeMode = static_cast(fillStrokeMode); + newContainer->coords = drawP.world.drawData.cam.c; - objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); - drawStage = 1; - } - break; + objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); } - case 1: { - if(drawP.controls.leftClickHeld) { - NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; - Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { - float height = std::fabs(startAt.y() - newPos.y()); - newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); - } - EllipseCanvasComponent& ellipse = static_cast(containerPtr->get_comp()); - ellipse.d.p1 = cwise_vec_min(startAt, newPos); - ellipse.d.p2 = cwise_vec_max(startAt, newPos); - ellipse.d.p2 = ensure_points_have_distance(ellipse.d.p1, ellipse.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - containerPtr->send_comp_update(drawP, false); - containerPtr->commit_update(drawP); + } + else { + if(drawP.controls.leftClickHeld) { + NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; + Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { + float height = std::fabs(startAt.y() - newPos.y()); + newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); } - else { - commit(); - drawStage = 0; - } - break; + EllipseCanvasComponent& ellipse = static_cast(containerPtr->get_comp()); + ellipse.d.p1 = cwise_vec_min(startAt, newPos); + ellipse.d.p2 = cwise_vec_max(startAt, newPos); + ellipse.d.p2 = ensure_points_have_distance(ellipse.d.p1, ellipse.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + containerPtr->send_comp_update(drawP, false); + containerPtr->commit_update(drawP); } + else + commit(); } } bool EllipseDrawTool::prevent_undo_or_redo() { - return (drawStage == 1); + return objInfoBeingEdited; } void EllipseDrawTool::commit() { diff --git a/src/DrawingProgram/Tools/EllipseDrawTool.hpp b/src/DrawingProgram/Tools/EllipseDrawTool.hpp index 56a0eea..4ff76c6 100644 --- a/src/DrawingProgram/Tools/EllipseDrawTool.hpp +++ b/src/DrawingProgram/Tools/EllipseDrawTool.hpp @@ -12,7 +12,7 @@ class EllipseDrawTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; @@ -22,6 +22,5 @@ class EllipseDrawTool : public DrawingProgramToolBase { Vector2f startAt; int fillStrokeMode = 1; - int drawStage = 0; - CanvasComponentContainer::ObjInfoSharedPtr objInfoBeingEdited; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited; }; diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 25f52b0..bbe4077 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -31,7 +31,7 @@ bool EraserTool::right_click_popup_gui(Vector2f popupPos) { return true; } -void EraserTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void EraserTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { erasedComponents.erase(erasedComp); } @@ -57,7 +57,7 @@ void EraserTool::tool_update() { SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.bottom_left()))) { drawP.drawCache.invalidate_cache_at_aabb(bvhNode->bounds); drawP.drawCache.traverse_bvh_run_function_starting_at_node_no_collision_check(bvhNode, [&](const auto& bvhNodeChild) { - drawP.drawCache.node_loop_erase_if_components(bvhNodeChild, [&](auto& c) { + drawP.drawCache.node_loop_erase_if_components(bvhNodeChild, [&](auto c) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) { erasedComponents.emplace(c); return true; @@ -68,7 +68,7 @@ void EraserTool::tool_update() { }); return false; } - drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto& c) { + drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto c) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC)) { erasedComponents.emplace(c); drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds()); diff --git a/src/DrawingProgram/Tools/EraserTool.hpp b/src/DrawingProgram/Tools/EraserTool.hpp index a81edf8..54995ec 100644 --- a/src/DrawingProgram/Tools/EraserTool.hpp +++ b/src/DrawingProgram/Tools/EraserTool.hpp @@ -12,11 +12,11 @@ class EraserTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; - std::unordered_set erasedComponents; // Pointers will be erased from this set if theyre erased in the main list (done by callback) + std::unordered_set erasedComponents; // Pointers will be erased from this set if theyre erased in the main list (done by callback) }; diff --git a/src/DrawingProgram/Tools/EyeDropperTool.cpp b/src/DrawingProgram/Tools/EyeDropperTool.cpp index cfb458b..186b7fd 100644 --- a/src/DrawingProgram/Tools/EyeDropperTool.cpp +++ b/src/DrawingProgram/Tools/EyeDropperTool.cpp @@ -44,7 +44,7 @@ bool EyeDropperTool::right_click_popup_gui(Vector2f popupPos) { return true; } -void EyeDropperTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void EyeDropperTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void EyeDropperTool::tool_update() { diff --git a/src/DrawingProgram/Tools/EyeDropperTool.hpp b/src/DrawingProgram/Tools/EyeDropperTool.hpp index 8c672f8..10c5b4b 100644 --- a/src/DrawingProgram/Tools/EyeDropperTool.hpp +++ b/src/DrawingProgram/Tools/EyeDropperTool.hpp @@ -10,7 +10,7 @@ class EyeDropperTool : public DrawingProgramToolBase { virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; virtual void tool_update() override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; virtual void switch_tool(DrawingProgramToolType newTool) override; diff --git a/src/DrawingProgram/Tools/GridModifyTool.cpp b/src/DrawingProgram/Tools/GridModifyTool.cpp index 1806ddb..9dfef71 100644 --- a/src/DrawingProgram/Tools/GridModifyTool.cpp +++ b/src/DrawingProgram/Tools/GridModifyTool.cpp @@ -33,7 +33,7 @@ DrawingProgramToolType GridModifyTool::get_type() { return DrawingProgramToolType::GRIDMODIFY; } -void GridModifyTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void GridModifyTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void GridModifyTool::gui_toolbox() { diff --git a/src/DrawingProgram/Tools/GridModifyTool.hpp b/src/DrawingProgram/Tools/GridModifyTool.hpp index fc392e2..e6364e9 100644 --- a/src/DrawingProgram/Tools/GridModifyTool.hpp +++ b/src/DrawingProgram/Tools/GridModifyTool.hpp @@ -13,7 +13,7 @@ class GridModifyTool : public DrawingProgramToolBase { virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; virtual void tool_update() override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; virtual void switch_tool(DrawingProgramToolType newTool) override; diff --git a/src/DrawingProgram/Tools/LassoSelectTool.cpp b/src/DrawingProgram/Tools/LassoSelectTool.cpp index 9f9fb9d..0158237 100644 --- a/src/DrawingProgram/Tools/LassoSelectTool.cpp +++ b/src/DrawingProgram/Tools/LassoSelectTool.cpp @@ -54,7 +54,7 @@ bool LassoSelectTool::right_click_popup_gui(Vector2f popupPos) { return drawP.selection_action_menu(popupPos); } -void LassoSelectTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void LassoSelectTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void LassoSelectTool::switch_tool(DrawingProgramToolType newTool) { diff --git a/src/DrawingProgram/Tools/LassoSelectTool.hpp b/src/DrawingProgram/Tools/LassoSelectTool.hpp index 2980259..a981514 100644 --- a/src/DrawingProgram/Tools/LassoSelectTool.hpp +++ b/src/DrawingProgram/Tools/LassoSelectTool.hpp @@ -13,7 +13,7 @@ class LassoSelectTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual void switch_tool(DrawingProgramToolType newTool) override; diff --git a/src/DrawingProgram/Tools/PanCanvasTool.cpp b/src/DrawingProgram/Tools/PanCanvasTool.cpp index a795a26..053812a 100644 --- a/src/DrawingProgram/Tools/PanCanvasTool.cpp +++ b/src/DrawingProgram/Tools/PanCanvasTool.cpp @@ -25,7 +25,7 @@ bool PanCanvasTool::right_click_popup_gui(Vector2f popupPos) { return drawP.selection_action_menu(popupPos); } -void PanCanvasTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void PanCanvasTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void PanCanvasTool::tool_update() { diff --git a/src/DrawingProgram/Tools/PanCanvasTool.hpp b/src/DrawingProgram/Tools/PanCanvasTool.hpp index f03e87b..8a3af6e 100644 --- a/src/DrawingProgram/Tools/PanCanvasTool.hpp +++ b/src/DrawingProgram/Tools/PanCanvasTool.hpp @@ -9,7 +9,7 @@ class PanCanvasTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; diff --git a/src/DrawingProgram/Tools/RectDrawTool.cpp b/src/DrawingProgram/Tools/RectDrawTool.cpp index ecac899..11a4f41 100644 --- a/src/DrawingProgram/Tools/RectDrawTool.cpp +++ b/src/DrawingProgram/Tools/RectDrawTool.cpp @@ -27,11 +27,9 @@ void RectDrawTool::gui_toolbox() { t.gui.pop_id(); } -void RectDrawTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { - if(objInfoBeingEdited == erasedComp) { +void RectDrawTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { + if(objInfoBeingEdited == erasedComp) objInfoBeingEdited = nullptr; - drawStage = 0; - } } bool RectDrawTool::right_click_popup_gui(Vector2f popupPos) { @@ -42,57 +40,49 @@ bool RectDrawTool::right_click_popup_gui(Vector2f popupPos) { void RectDrawTool::switch_tool(DrawingProgramToolType newTool) { commit(); - drawStage = 0; } void RectDrawTool::tool_update() { - switch(drawStage) { - case 0: { - if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { - CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::RECTANGLE); - RectangleCanvasComponent& newRectangle = static_cast(newContainer->get_comp()); + if(objInfoBeingEdited) { + if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { + CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::RECTANGLE); + RectangleCanvasComponent& newRectangle = static_cast(newContainer->get_comp()); - startAt = drawP.world.main.input.mouse.pos; - newRectangle.d.strokeColor = drawP.controls.foregroundColor; - newRectangle.d.fillColor = drawP.controls.backgroundColor; - newRectangle.d.cornerRadius = relativeRadiusWidth; - newRectangle.d.strokeWidth = drawP.controls.relativeWidth; - newRectangle.d.p1 = startAt; - newRectangle.d.p2 = startAt; - newRectangle.d.p2 = ensure_points_have_distance(newRectangle.d.p1, newRectangle.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - newRectangle.d.fillStrokeMode = static_cast(fillStrokeMode); - newContainer->coords = drawP.world.drawData.cam.c; - objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); - drawStage = 1; - } - break; + startAt = drawP.world.main.input.mouse.pos; + newRectangle.d.strokeColor = drawP.controls.foregroundColor; + newRectangle.d.fillColor = drawP.controls.backgroundColor; + newRectangle.d.cornerRadius = relativeRadiusWidth; + newRectangle.d.strokeWidth = drawP.controls.relativeWidth; + newRectangle.d.p1 = startAt; + newRectangle.d.p2 = startAt; + newRectangle.d.p2 = ensure_points_have_distance(newRectangle.d.p1, newRectangle.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + newRectangle.d.fillStrokeMode = static_cast(fillStrokeMode); + newContainer->coords = drawP.world.drawData.cam.c; + objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); } - case 1: { - NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; - if(drawP.controls.leftClickHeld) { - Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { - float height = std::fabs(startAt.y() - newPos.y()); - newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); - } - RectangleCanvasComponent& rectangle = static_cast(containerPtr->get_comp()); - rectangle.d.p1 = cwise_vec_min(startAt, newPos); - rectangle.d.p2 = cwise_vec_max(startAt, newPos); - rectangle.d.p2 = ensure_points_have_distance(rectangle.d.p1, rectangle.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - containerPtr->send_comp_update(drawP, false); - containerPtr->commit_update(drawP); + } + else { + NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; + if(drawP.controls.leftClickHeld) { + Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { + float height = std::fabs(startAt.y() - newPos.y()); + newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); } - else { - commit(); - drawStage = 0; - } - break; + RectangleCanvasComponent& rectangle = static_cast(containerPtr->get_comp()); + rectangle.d.p1 = cwise_vec_min(startAt, newPos); + rectangle.d.p2 = cwise_vec_max(startAt, newPos); + rectangle.d.p2 = ensure_points_have_distance(rectangle.d.p1, rectangle.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + containerPtr->send_comp_update(drawP, false); + containerPtr->commit_update(drawP); } + else + commit(); } } bool RectDrawTool::prevent_undo_or_redo() { - return (drawStage == 1); + return objInfoBeingEdited; } void RectDrawTool::commit() { diff --git a/src/DrawingProgram/Tools/RectDrawTool.hpp b/src/DrawingProgram/Tools/RectDrawTool.hpp index 41f262c..976e3d0 100644 --- a/src/DrawingProgram/Tools/RectDrawTool.hpp +++ b/src/DrawingProgram/Tools/RectDrawTool.hpp @@ -11,7 +11,7 @@ class RectDrawTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; @@ -22,6 +22,5 @@ class RectDrawTool : public DrawingProgramToolBase { Vector2f startAt; float relativeRadiusWidth = 10.0f; int fillStrokeMode = 1; - int drawStage = 0; - CanvasComponentContainer::ObjInfoSharedPtr objInfoBeingEdited; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited; }; diff --git a/src/DrawingProgram/Tools/RectSelectTool.cpp b/src/DrawingProgram/Tools/RectSelectTool.cpp index ae7fa73..6c6fa2a 100644 --- a/src/DrawingProgram/Tools/RectSelectTool.cpp +++ b/src/DrawingProgram/Tools/RectSelectTool.cpp @@ -28,7 +28,7 @@ void RectSelectTool::gui_toolbox() { t.gui.pop_id(); } -void RectSelectTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void RectSelectTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } bool RectSelectTool::right_click_popup_gui(Vector2f popupPos) { diff --git a/src/DrawingProgram/Tools/RectSelectTool.hpp b/src/DrawingProgram/Tools/RectSelectTool.hpp index 4d0aa71..09fa1ff 100644 --- a/src/DrawingProgram/Tools/RectSelectTool.hpp +++ b/src/DrawingProgram/Tools/RectSelectTool.hpp @@ -10,7 +10,7 @@ class RectSelectTool : public DrawingProgramToolBase { RectSelectTool(DrawingProgram& initDrawP); virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual bool right_click_popup_gui(Vector2f popupPos) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; diff --git a/src/DrawingProgram/Tools/ScreenshotTool.cpp b/src/DrawingProgram/Tools/ScreenshotTool.cpp index 0f06597..ddac6c5 100644 --- a/src/DrawingProgram/Tools/ScreenshotTool.cpp +++ b/src/DrawingProgram/Tools/ScreenshotTool.cpp @@ -116,7 +116,7 @@ bool ScreenshotTool::right_click_popup_gui(Vector2f popupPos) { return true; } -void ScreenshotTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void ScreenshotTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void ScreenshotTool::take_screenshot(const std::filesystem::path& filePath) { diff --git a/src/DrawingProgram/Tools/ScreenshotTool.hpp b/src/DrawingProgram/Tools/ScreenshotTool.hpp index 0e5ef1a..283a3e2 100644 --- a/src/DrawingProgram/Tools/ScreenshotTool.hpp +++ b/src/DrawingProgram/Tools/ScreenshotTool.hpp @@ -13,7 +13,7 @@ class ScreenshotTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual void switch_tool(DrawingProgramToolType newTool) override; diff --git a/src/DrawingProgram/Tools/TextBoxTool.cpp b/src/DrawingProgram/Tools/TextBoxTool.cpp index ef2f807..945ab4c 100644 --- a/src/DrawingProgram/Tools/TextBoxTool.cpp +++ b/src/DrawingProgram/Tools/TextBoxTool.cpp @@ -26,11 +26,9 @@ void TextBoxTool::gui_toolbox() { t.gui.pop_id(); } -void TextBoxTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { - if(objInfoBeingEdited == erasedComp) { +void TextBoxTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { + if(objInfoBeingEdited == erasedComp) objInfoBeingEdited = nullptr; - drawStage = 0; - } } bool TextBoxTool::right_click_popup_gui(Vector2f popupPos) { @@ -41,58 +39,52 @@ bool TextBoxTool::right_click_popup_gui(Vector2f popupPos) { void TextBoxTool::switch_tool(DrawingProgramToolType newTool) { commit(); - drawStage = 0; } void TextBoxTool::tool_update() { - switch(drawStage) { - case 0: { - if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { - startAt = drawP.world.main.input.mouse.pos; - endAt = startAt; + if(objInfoBeingEdited) { + if(drawP.controls.leftClick && drawP.layerMan.is_a_layer_being_edited()) { + startAt = drawP.world.main.input.mouse.pos; + endAt = startAt; - CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::TEXTBOX); - TextBoxCanvasComponent& newTextBox = static_cast(newContainer->get_comp()); + CanvasComponentContainer* newContainer = new CanvasComponentContainer(drawP.world.netObjMan, CanvasComponentType::TEXTBOX); + TextBoxCanvasComponent& newTextBox = static_cast(newContainer->get_comp()); - newTextBox.d.p1 = newTextBox.d.p2 = startAt; - newTextBox.d.p2 = ensure_points_have_distance(newTextBox.d.p1, newTextBox.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - newTextBox.d.editing = true; - newContainer->coords = drawP.world.drawData.cam.c; - objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); - drawStage = 1; - } - break; + newTextBox.d.p1 = newTextBox.d.p2 = startAt; + newTextBox.d.p2 = ensure_points_have_distance(newTextBox.d.p1, newTextBox.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + newTextBox.d.editing = true; + newContainer->coords = drawP.world.drawData.cam.c; + objInfoBeingEdited = drawP.layerMan.add_component_to_layer_being_edited(newContainer); } - case 1: { - NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; - TextBoxCanvasComponent& textBox = static_cast(containerPtr->get_comp()); + } + else { + NetworkingObjects::NetObjOwnerPtr& containerPtr = objInfoBeingEdited->obj; + TextBoxCanvasComponent& textBox = static_cast(containerPtr->get_comp()); - Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { - float height = std::fabs(startAt.y() - newPos.y()); - newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); - } - endAt = newPos; - textBox.d.p1 = cwise_vec_min(endAt, startAt); - textBox.d.p2 = cwise_vec_max(endAt, startAt); - textBox.d.p2 = ensure_points_have_distance(textBox.d.p1, textBox.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); - if(!drawP.controls.leftClickHeld) { - auto editTool = std::make_unique(drawP); - editTool->edit_start(objInfoBeingEdited); - drawP.toolToSwitchToAfterUpdate = std::move(editTool); - return; - } - else { - containerPtr->send_comp_update(drawP, false); - containerPtr->commit_update(drawP); - } - break; + Vector2f newPos = containerPtr->coords.get_mouse_pos(drawP.world); + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { + float height = std::fabs(startAt.y() - newPos.y()); + newPos.x() = startAt.x() + (((newPos.x() - startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); + } + endAt = newPos; + textBox.d.p1 = cwise_vec_min(endAt, startAt); + textBox.d.p2 = cwise_vec_max(endAt, startAt); + textBox.d.p2 = ensure_points_have_distance(textBox.d.p1, textBox.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); + if(!drawP.controls.leftClickHeld) { + auto editTool = std::make_unique(drawP); + editTool->edit_start(objInfoBeingEdited); + drawP.toolToSwitchToAfterUpdate = std::move(editTool); + return; + } + else { + containerPtr->send_comp_update(drawP, false); + containerPtr->commit_update(drawP); } } } bool TextBoxTool::prevent_undo_or_redo() { - return (drawStage == 1); + return objInfoBeingEdited; } void TextBoxTool::commit() { diff --git a/src/DrawingProgram/Tools/TextBoxTool.hpp b/src/DrawingProgram/Tools/TextBoxTool.hpp index 178735d..3d0c705 100644 --- a/src/DrawingProgram/Tools/TextBoxTool.hpp +++ b/src/DrawingProgram/Tools/TextBoxTool.hpp @@ -11,7 +11,7 @@ class TextBoxTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual void switch_tool(DrawingProgramToolType newTool) override; @@ -22,5 +22,5 @@ class TextBoxTool : public DrawingProgramToolBase { Vector2f startAt; Vector2f endAt; int drawStage = 0; - CanvasComponentContainer::ObjInfoSharedPtr objInfoBeingEdited; + CanvasComponentContainer::ObjInfo* objInfoBeingEdited; }; diff --git a/src/DrawingProgram/Tools/ZoomCanvasTool.cpp b/src/DrawingProgram/Tools/ZoomCanvasTool.cpp index bc073f9..a0fbec6 100644 --- a/src/DrawingProgram/Tools/ZoomCanvasTool.cpp +++ b/src/DrawingProgram/Tools/ZoomCanvasTool.cpp @@ -25,7 +25,7 @@ bool ZoomCanvasTool::right_click_popup_gui(Vector2f popupPos) { return drawP.selection_action_menu(popupPos); } -void ZoomCanvasTool::erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) { +void ZoomCanvasTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { } void ZoomCanvasTool::tool_update() { diff --git a/src/DrawingProgram/Tools/ZoomCanvasTool.hpp b/src/DrawingProgram/Tools/ZoomCanvasTool.hpp index ed8520d..4f75284 100644 --- a/src/DrawingProgram/Tools/ZoomCanvasTool.hpp +++ b/src/DrawingProgram/Tools/ZoomCanvasTool.hpp @@ -9,7 +9,7 @@ class ZoomCanvasTool : public DrawingProgramToolBase { virtual DrawingProgramToolType get_type() override; virtual void gui_toolbox() override; virtual bool right_click_popup_gui(Vector2f popupPos) override; - virtual void erase_component(const CanvasComponentContainer::ObjInfoSharedPtr& erasedComp) override; + virtual void erase_component(CanvasComponentContainer::ObjInfo* erasedComp) override; virtual void tool_update() override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; diff --git a/src/GridManager.cpp b/src/GridManager.cpp index 2332604..882cc51 100644 --- a/src/GridManager.cpp +++ b/src/GridManager.cpp @@ -23,7 +23,7 @@ void GridManager::add_default_grid(const std::string& newName) { void GridManager::remove_grid(uint32_t indexToRemove) { if(grids) - grids->erase(grids, indexToRemove); + grids->erase(grids, grids->at(indexToRemove)); } void GridManager::draw_back(SkCanvas* canvas, const DrawData& drawData) {