Added back infinite zoom scale up code

This commit is contained in:
Yousef Khadadeh 2025-12-31 16:30:56 +03:00
parent 108da82fd4
commit 85cc0c2457
26 changed files with 191 additions and 62 deletions

View file

@ -49,6 +49,7 @@ set(sources "src/main.cpp"
"src/World.cpp"
"src/FileHelpers.cpp"
"src/VersionConstants.cpp"
"src/ScaleUpCanvas.cpp"
"src/Bookmarks/BookmarkListItem.cpp"
"src/Bookmarks/BookmarkManager.cpp"
"src/ResourceDisplay/ResourceDisplay.cpp"

View file

@ -11,13 +11,13 @@ namespace NetworkingObjects {
std::function<void(const T& o, cereal::PortableBinaryOutputArchive& a)> writeConstructor = [](const T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<void(T& o, cereal::PortableBinaryInputArchive& a)> readConstructor = [](T& o, cereal::PortableBinaryInputArchive& a) {
std::function<void(T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c)> readConstructor = [](T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o);
};
std::function<void(const T& o, cereal::PortableBinaryOutputArchive& a)> writeUpdate = [](const T& o, cereal::PortableBinaryOutputArchive& a) {
a(o);
};
std::function<void(T& o, cereal::PortableBinaryInputArchive& a)> readUpdate = [](T& o, cereal::PortableBinaryInputArchive& a) {
std::function<void(T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c)> readUpdate = [](T& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o);
};
std::function<std::shared_ptr<T>(const T& o)> allocateCopy = [](const T& o) {
@ -35,11 +35,11 @@ namespace NetworkingObjects {
template <typename T> void register_class(NetObjManager& objMan, const CustomConstructors<T>& t = CustomConstructors<T>()) {
objMan.register_class<T, T, T, T>({
.writeConstructorFuncClient = [writeConstructor = t.writeConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {writeConstructor(*o, a);},
.readConstructorFuncClient = [readConstructor = t.readConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {readConstructor(*o, a);},
.readUpdateFuncClient = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){client_read_update_func<T>(o, a, readUpdate);},
.readConstructorFuncClient = [readConstructor = t.readConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {readConstructor(*o, a, nullptr);},
.readUpdateFuncClient = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c){client_read_update_func<T>(o, a, readUpdate);},
.writeConstructorFuncServer = [writeConstructor = t.writeConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {writeConstructor(*o, a);},
.readConstructorFuncServer = [readConstructor = t.readConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {readConstructor(*o, a);},
.readUpdateFuncServer = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&){server_read_update_func<T>(o, a, readUpdate);}
.readConstructorFuncServer = [readConstructor = t.readConstructor](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {readConstructor(*o, a, c);},
.readUpdateFuncServer = [&, readUpdate = t.readUpdate](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c){server_read_update_func<T>(o, a, readUpdate, c);}
});
typeIndexFuncs[std::type_index(typeid(T))] = {
.writeUpdateFunc = [writeFunc = t.writeUpdate](const void* o, cereal::PortableBinaryOutputArchive& a) {
@ -103,15 +103,15 @@ namespace NetworkingObjects {
}
}
template <typename T> void client_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryInputArchive&)>& readUpdate) {
template <typename T> void client_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)>& readUpdate) {
auto it = updatingObjs.find(o.get_net_id());
if(it == updatingObjs.end()) {
readUpdate(*o, a);
readUpdate(*o, a, nullptr);
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(o.get()));
}
else {
auto& [netID, updatingObjData] = *it;
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a);
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a, nullptr);
*updatingObjData.doLastAssignment = true;
}
}
@ -155,12 +155,12 @@ namespace NetworkingObjects {
}
}
template <typename T> void server_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryInputArchive&)>& readUpdate) {
template <typename T> void server_read_update_func(const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryInputArchive& a, const std::function<void(T&, cereal::PortableBinaryInputArchive&, const std::shared_ptr<NetServer::ClientData>&)>& readUpdate, const std::shared_ptr<NetServer::ClientData>& c) {
auto it = updatingObjs.find(o.get_net_id());
bool finalUpdate;
if(it == updatingObjs.end()) {
a(finalUpdate);
readUpdate(*o, a);
readUpdate(*o, a, c);
typeIndexFuncs[std::type_index(typeid(T))].postUpdateFunc(static_cast<void*>(o.get()));
o.send_server_update_to_all_clients(finalUpdate ? RELIABLE_COMMAND_CHANNEL : UNRELIABLE_COMMAND_CHANNEL, [&typeIndexFuncs = typeIndexFuncs](const NetObjTemporaryPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
typeIndexFuncs[std::type_index(typeid(T))].writeUpdateFunc(static_cast<const void*>(o.get()), a);
@ -169,7 +169,7 @@ namespace NetworkingObjects {
else {
auto& [netID, updatingObjData] = *it;
a(finalUpdate);
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a);
readUpdate(*std::static_pointer_cast<T>(updatingObjData.objToUpdateCurrentData), a, c);
*updatingObjData.doLastAssignment = true;
}
}

View file

@ -181,6 +181,8 @@ namespace NetworkingObjects {
return data.end();
}
virtual NetObjOrderedListIterator<T> at(uint32_t index) override {
if(index >= data.size())
return data.end();
return std::next(data.begin(), index);
}
virtual NetObjOrderedListIterator<T> get(const NetObjID& id) override {
@ -196,6 +198,8 @@ namespace NetworkingObjects {
return data.end();
}
virtual NetObjOrderedListConstIterator<T> at(uint32_t index) const override {
if(index >= data.size())
return data.end();
return std::next(data.begin(), index);
}
virtual NetObjOrderedListConstIterator<T> get(const NetObjID& id) const override {
@ -366,6 +370,8 @@ namespace NetworkingObjects {
return clientData.end();
}
virtual NetObjOrderedListIterator<T> at(uint32_t index) override {
if(index >= clientData.size())
return clientData.end();
return std::next(clientData.begin(), index);
}
virtual NetObjOrderedListIterator<T> get(const NetObjID& id) override {
@ -381,6 +387,8 @@ namespace NetworkingObjects {
return clientData.end();
}
virtual NetObjOrderedListConstIterator<T> at(uint32_t index) const override {
if(index >= clientData.size())
return clientData.end();
return std::next(clientData.begin(), index);
}
virtual NetObjOrderedListConstIterator<T> get(const NetObjID& id) const override {

View file

@ -1,6 +1,7 @@
#include "BookmarkListItem.hpp"
#include <cereal/types/string.hpp>
#include "../World.hpp"
#include "../ScaleUpCanvas.hpp"
using namespace NetworkingObjects;
@ -27,6 +28,15 @@ void BookmarkListItem::reassign_netobj_ids_call() {
nameData.reassign_ids();
}
void BookmarkListItem::scale_up(const WorldScalar& scaleUpAmount) {
if(folderData) {
for(auto& i : *folderData->folderList)
i.obj->scale_up(scaleUpAmount);
}
else
bookmarkData->coords.inverseScale *= scaleUpAmount;
}
bool BookmarkListItem::is_folder() const {
return folderData != nullptr;
}
@ -59,12 +69,27 @@ void BookmarkListItem::set_folder_open(bool newIsFolderOpen) {
}
void BookmarkListItem::register_class(World& w) {
auto readConstructorData = [&w](const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
bool isFolder;
a(isFolder);
if(isFolder) {
o->folderData = std::make_unique<BookmarkFolderData>();
o->folderData->folderList = o.get_obj_man()->read_create_message<NetworkingObjects::NetObjOrderedList<BookmarkListItem>>(a, c);
}
else {
o->bookmarkData = std::make_unique<BookmarkData>();
a(*o->bookmarkData);
}
o->nameData = o.get_obj_man()->read_create_message<NameData>(a, c);
canvas_scale_up_check(*o, w, c);
};
w.netObjMan.register_class<BookmarkListItem, BookmarkListItem, BookmarkListItem, BookmarkListItem>({
.writeConstructorFuncClient = write_constructor_data,
.readConstructorFuncClient = read_constructor_data,
.readConstructorFuncClient = readConstructorData,
.readUpdateFuncClient = nullptr,
.writeConstructorFuncServer = write_constructor_data,
.readConstructorFuncServer = read_constructor_data,
.readConstructorFuncServer = readConstructorData,
.readUpdateFuncServer = nullptr
});
NetworkingObjects::register_ordered_list_class<BookmarkListItem>(w.netObjMan);
@ -79,17 +104,3 @@ void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtr<BookmarkL
a(*o->bookmarkData);
o->nameData.write_create_message(a);
}
void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
bool isFolder;
a(isFolder);
if(isFolder) {
o->folderData = std::make_unique<BookmarkFolderData>();
o->folderData->folderList = o.get_obj_man()->read_create_message<NetworkingObjects::NetObjOrderedList<BookmarkListItem>>(a, c);
}
else {
o->bookmarkData = std::make_unique<BookmarkData>();
a(*o->bookmarkData);
}
o->nameData = o.get_obj_man()->read_create_message<NameData>(a, c);
}

View file

@ -26,6 +26,7 @@ class BookmarkListItem {
const std::string& get_name() const;
static void register_class(World& w);
void reassign_netobj_ids_call();
void scale_up(const WorldScalar& scaleUpAmount);
void set_name(NetworkingObjects::DelayUpdateSerializedClassManager& delayedNetObjMan, const std::string& newName);
private:
@ -40,7 +41,6 @@ class BookmarkListItem {
}
};
static void write_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryOutputArchive& a);
static void read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr<BookmarkListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c);
std::unique_ptr<BookmarkFolderData> folderData;
std::unique_ptr<BookmarkData> bookmarkData;
NetworkingObjects::NetObjOwnerPtr<NameData> nameData;

View file

@ -198,4 +198,5 @@ NetworkingObjects::NetObjOrderedListIterator<BookmarkListItem> BookmarkManager::
}
void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) {
bookmarkListRoot->scale_up(scaleUpAmount);
}

View file

@ -17,7 +17,7 @@ void CanvasComponentAllocator::register_class(World& world) {
a(o.comp->get_type());
a(*o.comp);
},
.readConstructor = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a) {
.readConstructor = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
CanvasComponentType typeToAllocate;
a(typeToAllocate);
o.comp = std::unique_ptr<CanvasComponent>(CanvasComponent::allocate_comp(typeToAllocate));
@ -26,7 +26,7 @@ void CanvasComponentAllocator::register_class(World& world) {
.writeUpdate = [](const CanvasComponentAllocator& o, cereal::PortableBinaryOutputArchive& a) {
a(*o.comp);
},
.readUpdate = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a) {
.readUpdate = [](CanvasComponentAllocator& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(*o.comp);
},
.allocateCopy = [](const CanvasComponentAllocator& o) {

View file

@ -5,6 +5,7 @@
#include "../World.hpp"
#include "CanvasComponent.hpp"
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
#include "../ScaleUpCanvas.hpp"
using namespace NetworkingObjects;
@ -22,13 +23,19 @@ CanvasComponentContainer::CanvasComponentContainer(NetworkingObjects::NetObjMana
coords = copyData.coords;
}
void CanvasComponentContainer::register_class(NetObjManager& objMan) {
objMan.register_class<CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer>({
void CanvasComponentContainer::register_class(World& w) {
auto readConstructorFunc = [&w](const NetworkingObjects::NetObjTemporaryPtr<CanvasComponentContainer>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o->coords);
o->compAllocator = o.get_obj_man()->read_create_message<CanvasComponentAllocator>(a, c);
o->compAllocator->comp->compContainer = o.get();
canvas_scale_up_check(*o, w, c);
};
w.netObjMan.register_class<CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer, CanvasComponentContainer>({
.writeConstructorFuncClient = write_constructor_func,
.readConstructorFuncClient = read_constructor_func,
.readConstructorFuncClient = readConstructorFunc,
.readUpdateFuncClient = nullptr,
.writeConstructorFuncServer = write_constructor_func,
.readConstructorFuncServer = read_constructor_func,
.readConstructorFuncServer = readConstructorFunc,
.readUpdateFuncServer = nullptr,
});
}
@ -49,12 +56,6 @@ void CanvasComponentContainer::write_constructor_func(const NetworkingObjects::N
o->compAllocator.write_create_message(a);
}
void CanvasComponentContainer::read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<CanvasComponentContainer>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o->coords);
o->compAllocator = o.get_obj_man()->read_create_message<CanvasComponentAllocator>(a, c);
o->compAllocator->comp->compContainer = o.get();
}
void CanvasComponentContainer::save_file(cereal::PortableBinaryOutputArchive& a) const {
a(coords);
get_comp().save_file(a);
@ -94,7 +95,7 @@ void CanvasComponentContainer::commit_update_dont_invalidate_cache(DrawingProgra
calculate_world_bounds();
}
void CanvasComponentContainer::commit_transform_dont_invalidate_cache(DrawingProgram& drawP) {
void CanvasComponentContainer::commit_transform_dont_invalidate_cache() {
calculate_world_bounds();
}
@ -142,6 +143,11 @@ CanvasComponentContainer::TransformDrawData CanvasComponentContainer::calculate_
return toRet;
}
void CanvasComponentContainer::scale_up(const WorldScalar& scaleUpAmount) {
coords.inverseScale *= scaleUpAmount;
calculate_world_bounds();
}
unsigned CanvasComponentContainer::get_mipmap_level(const DrawData& drawData) const {
if(drawData.mipMapLevelTwo > coords.inverseScale)
return 2;

View file

@ -34,7 +34,7 @@ class CanvasComponentContainer {
CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, CanvasComponentType type);
CanvasComponentContainer(NetworkingObjects::NetObjManager& objMan, const CopyData& copyData);
static void register_class(NetworkingObjects::NetObjManager& t);
static void register_class(World& w);
std::shared_ptr<CopyData> get_data_copy() const;
void save_file(cereal::PortableBinaryOutputArchive& a) const;
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
@ -42,7 +42,7 @@ class CanvasComponentContainer {
SCollision::AABB<WorldScalar> get_world_bounds() const;
void draw(SkCanvas* canvas, const DrawData& drawData) const;
void commit_update(DrawingProgram& drawP);
void commit_transform_dont_invalidate_cache(DrawingProgram& drawP); // Must be thread safe
void commit_transform_dont_invalidate_cache(); // Must be thread safe
void commit_transform(DrawingProgram& drawP);
void commit_update_dont_invalidate_cache(DrawingProgram& drawP); // Must be thread safe
bool should_draw(const DrawData& drawData) const;
@ -50,6 +50,7 @@ class CanvasComponentContainer {
bool collides_with_cam_coords(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection<float>& checkAgainstCam) const;
bool collides_with(const CoordSpaceHelper& camCoords, const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam) const;
void send_comp_update(DrawingProgram& drawP, bool finalUpdate);
void scale_up(const WorldScalar& scaleUpAmount);
std::weak_ptr<DrawingProgramCacheBVHNode> cacheParentBvhNode;
DrawingProgramLayerListItem* parentLayer = nullptr;
@ -60,7 +61,6 @@ class CanvasComponentContainer {
friend class ImageCanvasComponent;
static void write_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<CanvasComponentContainer>& o, cereal::PortableBinaryOutputArchive& a);
static void read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<CanvasComponentContainer>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c);
struct TransformDrawData {
Vector2f translation;

View file

@ -1,7 +1,9 @@
#include "ClientData.hpp"
#include "CommandList.hpp"
#include "World.hpp"
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
#include "MainProgram.hpp"
#include "ScaleUpCanvas.hpp"
using namespace NetworkingObjects;
@ -9,7 +11,8 @@ enum class ClientDataCommand : uint8_t {
SET_CURSOR_POS = 0,
SET_WINDOW_SIZE,
SET_CAM_COORDS,
SEND_CHAT_MESSAGE
SEND_CHAT_MESSAGE,
SET_GRID_SIZE
};
ClientData::ClientData() {
@ -26,6 +29,7 @@ void ClientData::set_from_init_struct(const InitStruct& initStruct) {
cursorPos = initStruct.cursorPos;
cursorColor = initStruct.cursorColor;
displayName = initStruct.displayName;
gridSize = initStruct.gridSize;
}
void ClientData::register_class(World& world) {
@ -49,6 +53,14 @@ void ClientData::register_class(World& world) {
std::string chatMessage;
a(chatMessage);
world.add_chat_message(o->displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
break;
}
case ClientDataCommand::SET_GRID_SIZE: {
uint32_t oldGridSize = o->gridSize;
a(o->gridSize);
if(oldGridSize < o->gridSize)
world.scale_up(WorldScalar(o->gridSize - oldGridSize) * CANVAS_SCALE_UP_STEP);
break;
}
}
},
@ -85,6 +97,16 @@ void ClientData::register_class(World& world) {
});
break;
}
case ClientDataCommand::SET_GRID_SIZE: {
uint32_t oldGridSize = o->gridSize;
a(o->gridSize);
if(oldGridSize < o->gridSize)
world.scale_up(WorldScalar(o->gridSize - oldGridSize) * CANVAS_SCALE_UP_STEP);
o.send_server_update_to_all_clients(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
a(ClientDataCommand::SET_GRID_SIZE, o->gridSize);
});
break;
}
}
},
});
@ -123,6 +145,14 @@ void ClientData::send_chat_message(const NetworkingObjects::NetObjTemporaryPtr<C
});
}
void ClientData::scale_up_step(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, World& world) {
o->gridSize++;
world.scale_up(CANVAS_SCALE_UP_STEP);
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
a(ClientDataCommand::SET_GRID_SIZE, o->gridSize);
});
}
void ClientData::set_display_name(const std::string& newDisplayName) {
displayName = newDisplayName;
}
@ -143,6 +173,10 @@ const Vector2f& ClientData::get_cursor_pos() const {
return cursorPos;
}
uint32_t ClientData::get_grid_size() const {
return gridSize;
}
const std::string& ClientData::get_display_name() const {
return displayName;
}

View file

@ -13,6 +13,7 @@ class ClientData {
Vector3f cursorColor = {1.0f, 1.0f, 1.0f};
std::string displayName;
uint32_t gridSize = 0;
};
ClientData();
@ -22,19 +23,21 @@ class ClientData {
static void set_window_size(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, Vector2f newWindowSize);
static void set_camera_coords(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, const CoordSpaceHelper& newCoords);
static void send_chat_message(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, World& world, const std::string& chatMessage);
static void scale_up_step(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, World& world);
void set_display_name(const std::string& newDisplayName);
void set_cursor_color(const Vector3f& newCursorColor);
const CoordSpaceHelper& get_cam_coords() const;
const Vector2f& get_window_size() const;
const Vector2f& get_cursor_pos() const;
uint32_t get_grid_size() const;
const std::string& get_display_name() const;
const Vector3f& get_cursor_color() const;
void draw_cursor(SkCanvas* canvas, const DrawData& drawData) const;
template <typename Archive> void serialize(Archive& a) {
a(camCoords, windowSize, cursorPos, cursorColor, displayName);
a(camCoords, windowSize, cursorPos, cursorColor, displayName, gridSize);
}
private:
void set_from_init_struct(const InitStruct& initStruct);
@ -44,5 +47,6 @@ class ClientData {
Vector3f cursorColor;
std::string displayName;
uint32_t gridSize;
};

View file

@ -23,6 +23,3 @@ enum ClientCommands : MessageCommandType {
CLIENT_NEW_RESOURCE_DATA,
CLIENT_TRANSFORM_MANY_COMPONENTS
};
// Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage
#define CANVAS_SCALE_UP_STEP WorldScalar("100000000000000000000000000000000000000000000000000")

View file

@ -32,6 +32,7 @@
#include "Layers/DrawingProgramLayer.hpp"
#include "Layers/DrawingProgramLayerListItem.hpp"
#include <Helpers/Parallel.hpp>
#include "../ScaleUpCanvas.hpp"
#include "Tools/EraserTool.hpp"
@ -49,11 +50,10 @@ void DrawingProgram::init() {
}
void DrawingProgram::scale_up(const WorldScalar& scaleUpAmount) {
//for(auto& c : components->get_data())
// c->obj->scale_up(scaleUpAmount);
//selection.deselect_all();
//force_rebuild_cache();
//switch_to_tool(drawTool->get_type() == DrawingProgramToolType::GRIDMODIFY ? DrawingProgramToolType::EDIT : drawTool->get_type(), true);
selection.deselect_all();
layerMan.scale_up(scaleUpAmount);
rebuild_cache();
switch_to_tool(drawTool->get_type() == DrawingProgramToolType::GRIDMODIFY ? DrawingProgramToolType::EDIT : drawTool->get_type(), true);
}
void DrawingProgram::write_components_server(cereal::PortableBinaryOutputArchive& a) {
@ -69,6 +69,14 @@ void DrawingProgram::init_server_callbacks() {
world.netServer->add_recv_callback(SERVER_TRANSFORM_MANY_COMPONENTS, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
std::vector<std::pair<NetworkingObjects::NetObjID, CoordSpaceHelper>> transforms;
message(transforms);
auto clientData = world.netObjMan.get_obj_temporary_ref_from_id<ClientData>(NetworkingObjects::NetObjID(client->customID));
if(clientData->get_grid_size() < world.ownClientData->get_grid_size()) {
WorldScalar scaleUpAmount = get_canvas_scale_up_amount(world.ownClientData->get_grid_size(), clientData->get_grid_size());
for(auto& [netID, coord] : transforms)
coord.inverseScale *= scaleUpAmount;
}
process_transform_message(transforms);
world.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_TRANSFORM_MANY_COMPONENTS, transforms);
});

View file

@ -51,3 +51,8 @@ void DrawingProgramLayer::get_flattened_component_list(std::vector<CanvasCompone
for(auto& p : *components)
objList.emplace_back(&p);
}
void DrawingProgramLayer::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& p : *components)
p.obj->scale_up(scaleUpAmount);
}

View file

@ -13,6 +13,7 @@ class DrawingProgramLayer {
void commit_update_dont_invalidate_cache(DrawingProgramLayerManager& layerMan) const;
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const;
void set_to_erase();
void scale_up(const WorldScalar& scaleUpAmount);
CanvasComponentContainer::NetListOwnerPtr components;
private:

View file

@ -49,3 +49,8 @@ NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> DrawingProgramLaye
}
return {};
}
void DrawingProgramLayerFolder::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& p : *folderList)
p.obj->scale_up(scaleUpAmount);
}

View file

@ -15,6 +15,7 @@ class DrawingProgramLayerFolder {
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const;
void set_to_erase();
NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> get_initial_editing_layer() const;
void scale_up(const WorldScalar& scaleUpAmount);
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjOrderedList<DrawingProgramLayerListItem>> folderList;
bool isFolderOpen = false;

View file

@ -80,6 +80,13 @@ uint32_t DrawingProgramLayerListItem::get_component_count() const {
return layerData->components->size();
}
void DrawingProgramLayerListItem::scale_up(const WorldScalar& scaleUpAmount) {
if(folderData)
folderData->scale_up(scaleUpAmount);
else
layerData->scale_up(scaleUpAmount);
}
bool DrawingProgramLayerListItem::is_folder() const {
return folderData != nullptr;
}

View file

@ -29,6 +29,7 @@ class DrawingProgramLayerListItem {
const std::string& get_name() const;
void get_flattened_component_list(std::vector<CanvasComponentContainer::ObjInfo*>& objList) const;
void get_flattened_layer_list(std::vector<DrawingProgramLayerListItem*>& objList);
void scale_up(const WorldScalar& scaleUpAmount);
void set_alpha(DrawingProgramLayerManager& layerMan, float newAlpha) const;
float get_alpha() const;

View file

@ -15,6 +15,10 @@ void DrawingProgramLayerManager::init() {
}
}
void DrawingProgramLayerManager::scale_up(const WorldScalar& scaleUpAmount) {
layerTreeRoot->scale_up(scaleUpAmount);
}
void DrawingProgramLayerManager::write_components_server(cereal::PortableBinaryOutputArchive& a) {
layerTreeRoot.write_create_message(a);
}
@ -92,3 +96,4 @@ CanvasComponentContainer::ObjInfo* DrawingProgramLayerManager::add_component_to_
return nullptr;
return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj));
}

View file

@ -25,6 +25,7 @@ class DrawingProgramLayerManager {
void write_components_server(cereal::PortableBinaryOutputArchive& a);
void read_components_client(cereal::PortableBinaryInputArchive& a);
bool is_a_layer_being_edited();
void scale_up(const WorldScalar& scaleUpAmount);
template <typename List> void erase_component_container(const List& compsToErase) {
std::unordered_map<DrawingProgramLayerListItem*, std::vector<CanvasComponentContainer::ObjInfoIterator>> idsToEraseInSpecificLayers;
for(auto& c : compsToErase)

5
src/ScaleUpCanvas.cpp Normal file
View file

@ -0,0 +1,5 @@
#include "ScaleUpCanvas.hpp"
WorldScalar get_canvas_scale_up_amount(uint32_t newGridSize, uint32_t oldGridSize) {
return WorldScalar(newGridSize - oldGridSize) * CANVAS_SCALE_UP_STEP;
}

16
src/ScaleUpCanvas.hpp Normal file
View file

@ -0,0 +1,16 @@
#pragma once
#include <Helpers/NetworkingObjects/NetObjManager.hpp>
#include "World.hpp"
// Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage
#define CANVAS_SCALE_UP_STEP WorldScalar("100000000000000000000000000000000000000000000000000")
WorldScalar get_canvas_scale_up_amount(uint32_t newGridSize, uint32_t oldGridSize);
template <typename T> void canvas_scale_up_check(T& obj, World& world, const std::shared_ptr<NetServer::ClientData>& c) {
if(c) {
auto clientData = world.netObjMan.get_obj_temporary_ref_from_id<ClientData>(NetworkingObjects::NetObjID(c->customID));
if(clientData->get_grid_size() < world.ownClientData->get_grid_size())
obj.scale_up(get_canvas_scale_up_amount(world.ownClientData->get_grid_size(), clientData->get_grid_size()));
}
}

View file

@ -112,10 +112,10 @@ void World::init_client_data_list_callbacks() {
void World::init_net_obj_type_list() {
BookmarkListItem::register_class(*this);
delayedUpdateObjectManager.register_class<WorldGrid>(netObjMan);
WorldGrid::register_class(*this);
NetworkingObjects::register_ordered_list_class<WorldGrid>(netObjMan);
CanvasComponentAllocator::register_class(*this);
CanvasComponentContainer::register_class(netObjMan);
CanvasComponentContainer::register_class(*this);
NetworkingObjects::register_ordered_list_class<CanvasComponentContainer>(netObjMan);
DrawingProgramLayerListItem::register_class(*this);
NetworkingObjects::register_ordered_list_class<DrawingProgramLayerListItem>(netObjMan);
@ -135,6 +135,7 @@ void World::init_server_callbacks() {
newClientData.camCoords = ownClientData->get_cam_coords();
newClientData.windowSize = ownClientData->get_window_size();
newClientData.gridSize = ownClientData->get_grid_size();
NetworkingObjects::NetObjTemporaryPtr<ClientData> clientDataObjPtr = clients->emplace_direct(clients, newClientData);
client->customID = clientDataObjPtr.get_net_id().data;
@ -488,9 +489,8 @@ void World::draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData
}
void World::scale_up_step() {
//canvasScale++;
//con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_CANVAS_SCALE, canvasScale);
//scale_up(WorldScalar(CANVAS_SCALE_UP_STEP));
if(ownClientData)
ownClientData->scale_up_step(ownClientData, *this);
}
void World::scale_up(const WorldScalar& scaleUpAmount) {

View file

@ -2,6 +2,7 @@
#include "GridManager.hpp"
#include "Helpers/MathExtras.hpp"
#include "MainProgram.hpp"
#include "ScaleUpCanvas.hpp"
#include <include/core/SkFontMetrics.h>
#include <include/core/SkPathBuilder.h>
@ -10,7 +11,6 @@ sk_sp<SkRuntimeEffect> WorldGrid::squarePointEffect;
sk_sp<SkRuntimeEffect> WorldGrid::squareLinesEffect;
sk_sp<SkRuntimeEffect> WorldGrid::horizontalLinesEffect;
Vector2f WorldGrid::oldWindowSize = Vector2f{0.0f, 0.0f};
unsigned WorldGrid::GRID_UNIT_PIXEL_SIZE = 25;
// NOTE: Skia shaders return premultiplied alpha colors
@ -175,6 +175,17 @@ sk_sp<SkShader> WorldGrid::get_shader(GridType gType, const ShaderData& shaderDa
return s;
}
void WorldGrid::register_class(World& w) {
auto readWorldGrid = [&](WorldGrid& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
a(o);
canvas_scale_up_check(o, w, c);
};
w.delayedUpdateObjectManager.register_class<WorldGrid>(w.netObjMan, NetworkingObjects::DelayUpdateSerializedClassManager::CustomConstructors<WorldGrid>{
.readConstructor = readWorldGrid,
.readUpdate = readWorldGrid
});
}
Vector2f WorldGrid::get_closest_grid_point(const WorldVec& gridOffset, const WorldScalar& gridSize, const DrawData& drawData) {
WorldVec fracCamPosOnGrid;
fracCamPosOnGrid.x() = (drawData.cam.c.pos.x() - gridOffset.x()) % gridSize;

View file

@ -12,6 +12,7 @@ class WorldGrid {
a(name, gridType, size, visible, offset, bounds, color, removeDivisionsOutwards, subdivisions, showCoordinates, displayInFront);
}
static void register_class(World& w);
void draw(GridManager& gMan, SkCanvas* canvas, const DrawData& drawData);
void draw_coordinates(SkCanvas* canvas, const DrawData& drawData, Vector2f& axisOffset);
@ -37,7 +38,7 @@ class WorldGrid {
void set_subdivisions(uint32_t v);
void scale_up(const WorldScalar& scaleUpAmount);
static unsigned GRID_UNIT_PIXEL_SIZE;
static constexpr unsigned GRID_UNIT_PIXEL_SIZE = 25;
WorldScalar coordinatesDivWorldSize;
WorldScalar coordinatesGridCoordDivSize;