Transformations over network work again, with undo and redo
This commit is contained in:
parent
b6a25280e6
commit
7e69688ca6
11 changed files with 128 additions and 33 deletions
|
|
@ -5,7 +5,7 @@
|
|||
#include <poolstl.hpp>
|
||||
#endif
|
||||
|
||||
template <typename ContainerType> void parallel_loop_container(ContainerType& c, std::function<void(typename ContainerType::value_type&)> func) {
|
||||
template <typename ContainerType> void parallel_loop_container(const ContainerType& c, std::function<void(const typename ContainerType::value_type&)> func) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
std::for_each(c.begin(), c.end(), func);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -153,6 +153,14 @@ CoordSpaceHelper CoordSpaceHelper::other_coord_space_to_this_space(const CoordSp
|
|||
return toRet;
|
||||
}
|
||||
|
||||
bool CoordSpaceHelper::operator==(const CoordSpaceHelper& otherCoords) const {
|
||||
return rotation == otherCoords.rotation && pos == otherCoords.pos && inverseScale == otherCoords.inverseScale;
|
||||
}
|
||||
|
||||
bool CoordSpaceHelper::operator!=(const CoordSpaceHelper& otherCoords) const {
|
||||
return rotation != otherCoords.rotation || pos != otherCoords.pos || inverseScale != otherCoords.inverseScale;
|
||||
}
|
||||
|
||||
CoordSpaceHelper CoordSpaceHelper::other_coord_space_from_this_space(const CoordSpaceHelper& other) const {
|
||||
CoordSpaceHelper toRet;
|
||||
toRet.pos = from_space_world(other.pos);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ class CoordSpaceHelper {
|
|||
CoordSpaceHelper();
|
||||
CoordSpaceHelper(const WorldVec& initPos, const WorldScalar& initInverseScale, double initRotation);
|
||||
|
||||
Vector2f to_space(const WorldVec& coord) const;
|
||||
bool operator==(const CoordSpaceHelper& otherCoords) const;
|
||||
bool operator!=(const CoordSpaceHelper& otherCoords) const;
|
||||
|
||||
Vector2f to_space(const WorldVec& coord) const;
|
||||
|
||||
WorldVec from_space(Vector2f coord) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ void DrawComponent::server_send_update_final(MainServer& server, ServerClientID
|
|||
serverIsTempUpdate = false;
|
||||
}
|
||||
|
||||
void DrawComponent::server_send_transform(MainServer& server, ServerClientID id) {
|
||||
server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_COMPONENT, id, this->coords);
|
||||
void DrawComponent::server_send_transform_many(MainServer& server, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms) {
|
||||
server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms);
|
||||
}
|
||||
|
||||
void DrawComponent::server_update(MainServer& server, ServerClientID id) {
|
||||
|
|
@ -156,9 +156,8 @@ void DrawComponent::client_send_update_final(DrawingProgram& drawP) {
|
|||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_UPDATE_COMPONENT, false, collabListInfo.lock()->id, *this);
|
||||
}
|
||||
|
||||
void DrawComponent::client_send_transform(DrawingProgram& drawP) {
|
||||
if(collabListInfo.lock())
|
||||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_COMPONENT, collabListInfo.lock()->id, this->coords);
|
||||
void DrawComponent::client_send_transform_many(DrawingProgram& drawP, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms) {
|
||||
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_TRANSFORM_MANY_COMPONENTS, transforms);
|
||||
}
|
||||
|
||||
void DrawComponent::client_send_erase(DrawingProgram& drawP) {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class DrawComponent {
|
|||
static void server_send_erase_set(MainServer& server, const std::unordered_set<ServerClientID>& ids);
|
||||
void server_send_update_temp(MainServer& server, ServerClientID id);
|
||||
void server_send_update_final(MainServer& server, ServerClientID id);
|
||||
void server_send_transform(MainServer& server, ServerClientID id);
|
||||
static void server_send_transform_many(MainServer& server, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms);
|
||||
|
||||
std::chrono::time_point<std::chrono::steady_clock> tempServerUpdateTimer;
|
||||
bool serverIsTempUpdate = false;
|
||||
|
|
@ -94,7 +94,7 @@ class DrawComponent {
|
|||
static void client_send_erase_set(DrawingProgram& drawP, const std::unordered_set<ServerClientID>& ids);
|
||||
void client_send_update_temp(DrawingProgram& drawP);
|
||||
void client_send_update_final(DrawingProgram& drawP);
|
||||
void client_send_transform(DrawingProgram& drawP);
|
||||
static void client_send_transform_many(DrawingProgram& drawP, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms);
|
||||
|
||||
std::optional<SCollision::AABB<WorldScalar>> worldAABB;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,17 +89,38 @@ void DrawingProgram::init_client_callbacks() {
|
|||
delayedUpdateComponents.emplace(comp);
|
||||
}
|
||||
});
|
||||
world.con.client_add_recv_callback(CLIENT_TRANSFORM_COMPONENT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
ServerClientID id;
|
||||
message(id);
|
||||
auto objPtr = components.get_item_by_id(id);
|
||||
if(!objPtr)
|
||||
return;
|
||||
if(selection.is_selected(objPtr)) // Whatever transformation we're doing right now will overwrite this transformation, so we can ignore this message
|
||||
return;
|
||||
std::shared_ptr<DrawComponent>& comp = objPtr->obj;
|
||||
message(comp->coords);
|
||||
comp->finalize_update(*this); // No need to update draw data during transformation
|
||||
world.con.client_add_recv_callback(CLIENT_TRANSFORM_MANY_COMPONENTS, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transforms;
|
||||
message(transforms);
|
||||
if(transforms.size() >= DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD) {
|
||||
std::atomic<size_t> objsActuallyTransformed = 0;
|
||||
parallel_loop_container(transforms, [&](auto& p) {
|
||||
auto& [id, coords] = p;
|
||||
auto objPtr = components.get_item_by_id(id);
|
||||
if(!objPtr || selection.is_selected(objPtr)) // Whatever transformation we're doing right now will overwrite this transformation, so we can ignore this message
|
||||
return;
|
||||
std::shared_ptr<DrawComponent>& comp = objPtr->obj;
|
||||
if(comp->coords == coords)
|
||||
return;
|
||||
comp->coords = coords;
|
||||
objsActuallyTransformed++;
|
||||
comp->finalize_update(*this, false);
|
||||
});
|
||||
if(objsActuallyTransformed != 0)
|
||||
force_rebuild_cache();
|
||||
}
|
||||
else {
|
||||
for(auto& [id, coords] : transforms) {
|
||||
auto objPtr = components.get_item_by_id(id);
|
||||
if(!objPtr || selection.is_selected(objPtr)) // Whatever transformation we're doing right now will overwrite this transformation, so we can ignore this message
|
||||
continue;
|
||||
std::shared_ptr<DrawComponent>& comp = objPtr->obj;
|
||||
if(comp->coords == coords)
|
||||
return;
|
||||
comp->coords = coords;
|
||||
comp->finalize_update(*this); // No need to update draw data during transformation
|
||||
}
|
||||
}
|
||||
});
|
||||
world.con.client_add_recv_callback(CLIENT_PLACE_SINGLE_COMPONENT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
uint64_t insertPosition;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "DrawingProgram.hpp"
|
||||
#include "../World.hpp"
|
||||
#include "../MainProgram.hpp"
|
||||
#include "Helpers/Parallel.hpp"
|
||||
#include <chrono>
|
||||
|
||||
#ifdef USE_SKIA_BACKEND_GRAPHITE
|
||||
|
|
@ -177,7 +178,7 @@ void DrawingProgramCache::preupdate_component(const CollabListType::ObjectInfoPt
|
|||
invalidate_cache_before_pos(c->pos);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::build_bvh_node(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, std::vector<CollabListType::ObjectInfoPtr> components) {
|
||||
void DrawingProgramCache::build_bvh_node(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, const std::vector<CollabListType::ObjectInfoPtr>& components) {
|
||||
if(components.empty())
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ class DrawingProgramCache {
|
|||
void build(std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
void traverse_bvh_run_function_recursive(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<DrawingProgramCacheBVHNode>& node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
std::pair<std::shared_ptr<DrawingProgramCacheBVHNode>, std::vector<CollabListType::ObjectInfoPtr>::iterator> get_bvh_node_fully_containing_recursive(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, DrawComponent* c);
|
||||
void build_bvh_node(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
|
||||
void build_bvh_node(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, const std::vector<CollabListType::ObjectInfoPtr>& components);
|
||||
|
||||
std::chrono::steady_clock::time_point lastBvhBuildTime;
|
||||
std::shared_ptr<DrawingProgramCacheBVHNode> bvhRoot;
|
||||
|
|
|
|||
|
|
@ -74,11 +74,74 @@ void DrawingProgramSelection::calculate_aabb() {
|
|||
void DrawingProgramSelection::deselect_all() {
|
||||
if(is_something_selected()) {
|
||||
std::vector<CollabListType::ObjectInfoPtr> a(selectedSet.begin(), selectedSet.end());
|
||||
std::vector<std::pair<CollabListType::ObjectInfoPtr, CoordSpaceHelper>> transformsFrom;
|
||||
for(auto& transformedObj : a)
|
||||
transformsFrom.emplace_back(transformedObj, transformedObj->obj->coords);
|
||||
|
||||
parallel_loop_container(a, [&](auto& obj) {
|
||||
obj->obj->coords = selectionTransformCoords.other_coord_space_from_this_space(obj->obj->coords);
|
||||
obj->obj->final_update(drawP, false);
|
||||
obj->obj->client_send_transform(drawP);
|
||||
});
|
||||
std::vector<std::pair<CollabListType::ObjectInfoPtr, CoordSpaceHelper>> transformsTo;
|
||||
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transformsToSend;
|
||||
for(auto& transformedObj : a) {
|
||||
transformsToSend.emplace_back(transformedObj->id, transformedObj->obj->coords);
|
||||
transformsTo.emplace_back(transformedObj, transformedObj->obj->coords);
|
||||
}
|
||||
DrawComponent::client_send_transform_many(drawP, transformsToSend);
|
||||
|
||||
drawP.world.undo.push(UndoManager::UndoRedoPair{
|
||||
[&, transformsFrom = transformsFrom]() {
|
||||
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transformsToSend;
|
||||
for(auto& [comp, coords] : transformsFrom) {
|
||||
auto lockObjInfo = comp->obj->collabListInfo.lock();
|
||||
if(lockObjInfo)
|
||||
transformsToSend.emplace_back(lockObjInfo->id, coords);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
parallel_loop_container(transformsFrom, [&](auto& p) {
|
||||
auto& [comp, coords] = p;
|
||||
comp->obj->coords = coords;
|
||||
comp->obj->finalize_update(drawP, false);
|
||||
});
|
||||
|
||||
DrawComponent::client_send_transform_many(drawP, transformsToSend);
|
||||
|
||||
drawP.reset_tools();
|
||||
|
||||
drawP.force_rebuild_cache();
|
||||
|
||||
return true;
|
||||
},
|
||||
[&, transformsTo = transformsTo]() {
|
||||
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transformsToSend;
|
||||
for(auto& [comp, coords] : transformsTo) {
|
||||
auto lockObjInfo = comp->obj->collabListInfo.lock();
|
||||
if(lockObjInfo)
|
||||
transformsToSend.emplace_back(lockObjInfo->id, coords);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
parallel_loop_container(transformsTo, [&](auto& p) {
|
||||
auto& [comp, coords] = p;
|
||||
comp->obj->coords = coords;
|
||||
comp->obj->finalize_update(drawP, false);
|
||||
});
|
||||
|
||||
DrawComponent::client_send_transform_many(drawP, transformsToSend);
|
||||
|
||||
drawP.reset_tools();
|
||||
|
||||
drawP.force_rebuild_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
selectedSet.clear();
|
||||
cache.clear();
|
||||
selectionTransformCoords = CoordSpaceHelper();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ enum ServerCommands : MessageCommandType {
|
|||
SERVER_MOVE_MOUSE,
|
||||
SERVER_PLACE_SINGLE_COMPONENT,
|
||||
SERVER_PLACE_MANY_COMPONENTS,
|
||||
SERVER_TRANSFORM_COMPONENT,
|
||||
SERVER_TRANSFORM_MANY_COMPONENTS,
|
||||
SERVER_ERASE_SINGLE_COMPONENT,
|
||||
SERVER_ERASE_MANY_COMPONENTS,
|
||||
SERVER_UPDATE_COMPONENT,
|
||||
|
|
@ -28,7 +28,7 @@ enum ClientCommands : MessageCommandType {
|
|||
CLIENT_USER_DISCONNECT,
|
||||
CLIENT_PLACE_SINGLE_COMPONENT,
|
||||
CLIENT_PLACE_MANY_COMPONENTS,
|
||||
CLIENT_TRANSFORM_COMPONENT,
|
||||
CLIENT_TRANSFORM_MANY_COMPONENTS,
|
||||
CLIENT_ERASE_SINGLE_COMPONENT,
|
||||
CLIENT_ERASE_MANY_COMPONENTS,
|
||||
CLIENT_UPDATE_COMPONENT,
|
||||
|
|
|
|||
|
|
@ -185,15 +185,15 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
|
|||
return idsToRemove.contains(p.first);
|
||||
});
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_TRANSFORM_COMPONENT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
ServerClientID idToTransform;
|
||||
message(idToTransform);
|
||||
auto it = data.idToComponentMap.find(idToTransform);
|
||||
if(it != data.idToComponentMap.end()) {
|
||||
std::shared_ptr<DrawComponent>& comp = it->second;
|
||||
message(comp->coords);
|
||||
comp->server_send_transform(*this, idToTransform);
|
||||
netServer->add_recv_callback(SERVER_TRANSFORM_MANY_COMPONENTS, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transformsToSend;
|
||||
message(transformsToSend);
|
||||
for(auto& t : transformsToSend) {
|
||||
auto it = data.idToComponentMap.find(t.first);
|
||||
if(it != data.idToComponentMap.end())
|
||||
it->second->coords = t.second;
|
||||
}
|
||||
DrawComponent::server_send_transform_many(*this, transformsToSend);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_UPDATE_COMPONENT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
bool isTemp;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue