Ship 0.8 fog/freistellen and fix Windows CI for friends
Some checks are pending
Windows Release / windows-x86_64 (push) Waiting to run

Publish the portable zip to public Forgejo from the private GitHub
builder, and force Ninja so MSVC 195 deps build without CMake 4.2.
This commit is contained in:
copilot 2026-10-25 18:07:47 +01:00
parent 97b136de3b
commit 1c1d63f376
46 changed files with 1748 additions and 156 deletions

View file

@ -17,6 +17,7 @@
*/
#include "DrawingProgramLayerManager.hpp"
#include "FogStripper.hpp"
#include "../../World.hpp"
#include "Helpers/NetworkingObjects/NetObjID.hpp"
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
@ -27,6 +28,7 @@
#include "../../CanvasComponents/CanvasComponentAllocator.hpp"
#include "../../CanvasComponents/CanvasComponent.hpp"
#include <chrono>
#include <functional>
DrawingProgramLayerManager::DrawingProgramLayerManager(DrawingProgram& drawProg):
drawP(drawProg), // initialize drawP first for next objects to be initialized properly
@ -44,7 +46,10 @@ void DrawingProgramLayerManager::scale_up(const WorldScalar& scaleUpAmount) {
}
void DrawingProgramLayerManager::write_components_server(cereal::PortableBinaryOutputArchive& a) {
layerTreeRoot.write_create_message(a);
auto hidden = FogStripper::compute_hidden_component_ids(*this);
clientHiddenComponentIds = hidden;
a(layerTreeRoot.get_net_id());
layerTreeRoot->write_stripped_constructor(a, hidden);
}
void DrawingProgramLayerManager::read_components_client(cereal::PortableBinaryInputArchive& a) {
@ -58,6 +63,7 @@ void DrawingProgramLayerManager::read_components_client(cereal::PortableBinaryIn
});
drawP.rebuild_cache();
editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer();
ensure_editing_layer_is_editable();
}
bool DrawingProgramLayerManager::is_a_layer_being_edited() {
@ -104,6 +110,10 @@ const DrawingProgramLayerListItem& DrawingProgramLayerManager::get_layer_root()
}
bool DrawingProgramLayerManager::component_passes_layer_selector(CanvasComponentContainer::ObjInfo* c, LayerSelector layerSelector) {
if(!c || !c->obj || !c->obj->parentLayer)
return false;
if(!can_current_peer_edit_layer(c->obj->parentLayer))
return false;
switch(layerSelector) {
case LayerSelector::ALL_VISIBLE_LAYERS:
return c->obj->parentLayer->get_visible();
@ -243,6 +253,11 @@ std::vector<CanvasComponentContainer::ObjInfoIterator> DrawingProgramLayerManage
auto editLayerPtr = editingLayer.lock();
if(!editLayerPtr)
throw std::runtime_error("[DrawingProgramLayerManager::add_many_components_to_layer_being_edited] No layer selected!");
if(!can_current_peer_edit_layer(editLayerPtr.get())) {
for(auto& [it, obj] : newObjs)
delete obj;
return {};
}
auto toRet = editLayerPtr->get_layer().components->insert_sorted_list_and_send_create(editLayerPtr->get_layer().components, newObjs);
add_undo_place_components(editingLayer.lock().get(), toRet);
return toRet;
@ -276,10 +291,90 @@ void DrawingProgramLayerManager::disable_add_to_cache_and_commit_update_block(co
addToCacheOnComponentInsert = true;
}
bool DrawingProgramLayerManager::can_current_peer_edit_layer(const DrawingProgramLayerListItem* layer) const {
if(!layer)
return false;
if(FogStripper::world_is_host(drawP.world))
return true;
return !layer->is_player_edit_blocked();
}
bool DrawingProgramLayerManager::client_may_modify_component(const CanvasComponentContainer* comp) const {
// Host-side authority check for CLIENT messages — must NOT use can_current_peer_edit_layer
// (that always returns true on the host).
if(!comp || !comp->parentLayer)
return false;
return !comp->parentLayer->is_player_edit_blocked();
}
void DrawingProgramLayerManager::ensure_editing_layer_is_editable() {
auto cur = editingLayer.lock();
if(cur && can_current_peer_edit_layer(cur.get()))
return;
if(!layerTreeRoot)
return;
std::function<NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem>(const DrawingProgramLayerFolder&)> findEditable;
findEditable = [&](const DrawingProgramLayerFolder& folder) -> NetworkingObjects::NetObjWeakPtr<DrawingProgramLayerListItem> {
for(auto& c : *folder.folderList) {
if(!c.obj->is_folder() && can_current_peer_edit_layer(c.obj.get()))
return c.obj;
}
for(auto& c : *folder.folderList) {
if(c.obj->is_folder()) {
auto found = findEditable(c.obj->get_folder());
if(!found.expired())
return found;
}
}
return {};
};
editingLayer = findEditable(layerTreeRoot->get_folder());
drawP.selection.remove_uneditable_from_selection();
}
void DrawingProgramLayerManager::refresh_fog_client_projection() {
fogClientProjectionDirty = false;
FogStripper::sync_hidden_set_to_clients(drawP.world, *this);
}
void DrawingProgramLayerManager::mark_fog_client_projection_dirty() {
if(drawP.world.netServer)
fogClientProjectionDirty = true;
}
void DrawingProgramLayerManager::flush_fog_client_projection_if_dirty() {
if(!fogClientProjectionDirty)
return;
refresh_fog_client_projection();
}
void DrawingProgramLayerManager::defer_reject_component(DrawingProgramLayerListItem* layer, NetworkingObjects::NetObjID compId) {
deferredRejectInserts.emplace_back(layer, compId);
}
void DrawingProgramLayerManager::flush_deferred_rejects() {
if(deferredRejectInserts.empty())
return;
auto pending = std::move(deferredRejectInserts);
deferredRejectInserts.clear();
for(auto& [layer, compId] : pending) {
if(!layer || layer->is_folder())
continue;
auto& comps = layer->get_layer().components;
if(!comps->contains(compId))
continue;
comps->erase(comps, comps->get(compId));
}
}
CanvasComponentContainer::ObjInfo* DrawingProgramLayerManager::add_component_to_layer_being_edited(CanvasComponentContainer* newObj) {
auto editLayerPtr = editingLayer.lock();
if(!editLayerPtr)
throw std::runtime_error("[DrawingProgramLayerManager::add_component_to_layer_being_edited] No layer selected!");
if(!can_current_peer_edit_layer(editLayerPtr.get())) {
delete newObj;
return nullptr;
}
return &(*editLayerPtr->get_layer().components->push_back_and_send_create(editLayerPtr->get_layer().components, newObj));
}
@ -311,6 +406,7 @@ void DrawingProgramLayerManager::load_file(cereal::PortableBinaryInputArchive& a
layerTreeRoot->erase_invalid_components();
drawP.rebuild_cache();
editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer();
ensure_editing_layer_is_editable();
}
void DrawingProgramLayerManager::save_file(cereal::PortableBinaryOutputArchive& a) const {