diff --git a/include/ilayer.h b/include/ilayer.h index 9de129ae05..929ffe02a2 100644 --- a/include/ilayer.h +++ b/include/ilayer.h @@ -53,8 +53,7 @@ class Layered virtual void assignToLayers(const LayerList& newLayers) = 0; }; -class ILayerManager : - public RegisterableModule +class ILayerManager { public: typedef std::shared_ptr Ptr; @@ -214,20 +213,8 @@ class ILayerModule : } // namespace scene -const char* const MODULE_LAYERSYSTEM("LayerSystem"); const char* const MODULE_LAYERS("LayerModule"); -inline scene::ILayerManager& GlobalLayerSystem() -{ - // Cache the reference locally - static scene::ILayerManager& _layerManager( - *std::static_pointer_cast( - module::GlobalModuleRegistry().getModule(MODULE_LAYERSYSTEM) - ) - ); - return _layerManager; -} - inline scene::ILayerModule& GlobalLayerModule() { // Cache the reference locally diff --git a/libs/scenelib.h b/libs/scenelib.h index 760ad10b4d..25db8f6bc8 100644 --- a/libs/scenelib.h +++ b/libs/scenelib.h @@ -1,6 +1,7 @@ #pragma once #include "inode.h" +#include "ilayer.h" #include "iscenegraph.h" #include "iselectable.h" #include "ipatch.h" @@ -142,10 +143,19 @@ class UpdateNodeVisibilityWalker : public NodeVisitor { std::stack _visibilityStack; + + scene::IMapRootNodePtr _root; public: - bool pre(const INodePtr& node) { + UpdateNodeVisibilityWalker(const scene::IMapRootNodePtr& root) : + _root(root) + { + assert(_root); + } + + bool pre(const INodePtr& node) + { // Update the node visibility and store the result - bool nodeIsVisible = GlobalLayerSystem().updateNodeVisibility(node); + bool nodeIsVisible = _root->getLayerManager().updateNodeVisibility(node); // Add a new element for this level _visibilityStack.push(nodeIsVisible); @@ -153,13 +163,15 @@ class UpdateNodeVisibilityWalker : return true; } - void post(const INodePtr& node) { + void post(const INodePtr& node) + { // Is this child visible? bool childIsVisible = _visibilityStack.top(); _visibilityStack.pop(); - if (childIsVisible) { + if (childIsVisible) + { // Show the node, regardless whether it was hidden before // otherwise the parent would hide the visible children as well node->disable(Node::eLayered); @@ -171,7 +183,8 @@ class UpdateNodeVisibilityWalker : Node_setSelected(node, false); } - if (childIsVisible && !_visibilityStack.empty()) { + if (childIsVisible && !_visibilityStack.empty()) + { // The child was visible, set this parent to true _visibilityStack.top() = true; } @@ -182,13 +195,20 @@ class UpdateNodeVisibilityWalker : * greebo: This method inserts the given node into the given container * and ensures that the container's layer visibility is updated. */ -inline void addNodeToContainer(const INodePtr& node, const INodePtr& container) { +inline void addNodeToContainer(const INodePtr& node, const INodePtr& container) +{ // Insert the child container->addChildNode(node); - // Ensure that worldspawn is visible - UpdateNodeVisibilityWalker walker; - container->traverse(walker); + // If the container is already connected to a root, check the layer visibility + auto rootNode = container->getRootNode(); + + if (rootNode) + { + // Ensure that worldspawn is visible + UpdateNodeVisibilityWalker walker(rootNode); + container->traverse(walker); + } } } // namespace scene diff --git a/radiant/brush/BrushModule.cpp b/radiant/brush/BrushModule.cpp index 7fb4c2b999..15b383115d 100644 --- a/radiant/brush/BrushModule.cpp +++ b/radiant/brush/BrushModule.cpp @@ -70,8 +70,11 @@ scene::INodePtr BrushModuleImpl::createBrush() { scene::INodePtr node = std::make_shared(); - // Move it to the active layer - node->moveToLayer(GlobalLayerSystem().getActiveLayer()); + if (GlobalMapModule().getRoot()) + { + // All brushes are created in the active layer by default + node->moveToLayer(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); + } return node; } diff --git a/radiant/entity/EntityCreator.cpp b/radiant/entity/EntityCreator.cpp index c3efbff2ee..1a9c5388dc 100644 --- a/radiant/entity/EntityCreator.cpp +++ b/radiant/entity/EntityCreator.cpp @@ -76,8 +76,11 @@ IEntityNodePtr Doom3EntityCreator::createEntity(const IEntityClassPtr& eclass) { IEntityNodePtr node = createNodeForEntity(eclass); - // All entities are created in the active layer by default - node->moveToLayer(GlobalLayerSystem().getActiveLayer()); + if (GlobalMapModule().getRoot()) + { + // All entities are created in the active layer by default + node->moveToLayer(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); + } node->getEntity().setKeyValue("classname", eclass->getName()); diff --git a/radiant/layers/LayerCommandTarget.cpp b/radiant/layers/LayerCommandTarget.cpp index cd4f4aa074..9d98a30d5f 100644 --- a/radiant/layers/LayerCommandTarget.cpp +++ b/radiant/layers/LayerCommandTarget.cpp @@ -1,6 +1,7 @@ #include "LayerCommandTarget.h" #include "ieventmanager.h" +#include "imap.h" #include "icommandsystem.h" #include "LayerManager.h" #include "string/string.h" @@ -48,22 +49,50 @@ LayerCommandTarget::LayerCommandTarget(int layerID) : ); } -void LayerCommandTarget::addSelectionToLayer(const cmd::ArgumentList& args) { +void LayerCommandTarget::addSelectionToLayer(const cmd::ArgumentList& args) +{ + if (!GlobalMapModule().getRoot()) + { + rError() << "No map loaded, cannot do this." << std::endl; + return; + } + // Pass the call to the LayerSystem - getLayerSystem().addSelectionToLayer(_layerID); + GlobalMapModule().getRoot()->getLayerManager().addSelectionToLayer(_layerID); } -void LayerCommandTarget::moveSelectionToLayer(const cmd::ArgumentList& args) { +void LayerCommandTarget::moveSelectionToLayer(const cmd::ArgumentList& args) +{ + if (!GlobalMapModule().getRoot()) + { + rError() << "No map loaded, cannot do this." << std::endl; + return; + } + // Pass the call to the LayerSystem - getLayerSystem().moveSelectionToLayer(_layerID); + GlobalMapModule().getRoot()->getLayerManager().moveSelectionToLayer(_layerID); } -void LayerCommandTarget::showLayer(const cmd::ArgumentList& args) { - getLayerSystem().setLayerVisibility(_layerID, true); +void LayerCommandTarget::showLayer(const cmd::ArgumentList& args) +{ + if (!GlobalMapModule().getRoot()) + { + rError() << "No map loaded, cannot do this." << std::endl; + return; + } + + GlobalMapModule().getRoot()->getLayerManager().setLayerVisibility(_layerID, true); } -void LayerCommandTarget::hideLayer(const cmd::ArgumentList& args) { - getLayerSystem().setLayerVisibility(_layerID, false); +void LayerCommandTarget::hideLayer(const cmd::ArgumentList& args) +{ + if (!GlobalMapModule().getRoot()) + { + rError() << "No map loaded, cannot do this." << std::endl; + return; + } + + GlobalMapModule().getRoot()->getLayerManager().setLayerVisibility(_layerID, false); } } // namespace scene diff --git a/radiant/layers/LayerInfoFileModule.cpp b/radiant/layers/LayerInfoFileModule.cpp index 56d8d92d48..4ea886629c 100644 --- a/radiant/layers/LayerInfoFileModule.cpp +++ b/radiant/layers/LayerInfoFileModule.cpp @@ -36,10 +36,23 @@ void LayerInfoFileModule::onInfoFileSaveStart() _layerInfoCount = 0; _output.str(std::string()); _output.clear(); + _layerNameBuffer.clear(); } void LayerInfoFileModule::onBeginSaveMap(const scene::IMapRootNodePtr& root) -{} +{ + // Open a "Layers" block + _layerNameBuffer << "\t" << LAYERS << std::endl; + _layerNameBuffer << "\t{" << std::endl; + + // Visit all layers and write them to the stream + root->getLayerManager().foreachLayer([&](int layerId, const std::string& layerName) + { + _layerNameBuffer << "\t\t" << LAYER << " " << layerId << " { " << layerName << " }" << std::endl; + }); + + _layerNameBuffer << "\t}" << std::endl; +} void LayerInfoFileModule::onFinishSaveMap(const scene::IMapRootNodePtr& root) {} @@ -85,7 +98,7 @@ void LayerInfoFileModule::saveNode(const INodePtr& node) void LayerInfoFileModule::writeBlocks(std::ostream& stream) { // Write the layer names block - writeLayerNames(stream); + stream << _layerNameBuffer.str(); // Write the NodeToLayerMapping block stream << "\t" << NODE_TO_LAYER_MAPPING << std::endl; @@ -217,7 +230,7 @@ void LayerInfoFileModule::applyInfoToScene(const IMapRootNodePtr& root, const ma for (const LayerNameMap::value_type& i : _layerNames) { // Create the named layer with the saved ID - GlobalLayerSystem().createLayer(i.second, i.first); + root->getLayerManager().createLayer(i.second, i.first); } // Set the layer mapping iterator to the beginning @@ -270,19 +283,4 @@ void LayerInfoFileModule::onInfoFileLoadFinished() _layerMappings.clear(); } -void LayerInfoFileModule::writeLayerNames(std::ostream& stream) -{ - // Open a "Layers" block - stream << "\t" << LAYERS << std::endl; - stream << "\t{" << std::endl; - - // Visit all layers and write them to the stream - GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName) - { - stream << "\t\t" << LAYER << " " << layerId << " { " << layerName << " }" << std::endl; - }); - - stream << "\t}" << std::endl; -} - } diff --git a/radiant/layers/LayerInfoFileModule.h b/radiant/layers/LayerInfoFileModule.h index 2bb1e3b814..ef5b7c6fb1 100644 --- a/radiant/layers/LayerInfoFileModule.h +++ b/radiant/layers/LayerInfoFileModule.h @@ -15,6 +15,7 @@ class LayerInfoFileModule : // Buffer to hold our output std::stringstream _output; + std::stringstream _layerNameBuffer; // The list of layernames typedef std::map LayerNameMap; diff --git a/radiant/layers/LayerManager.cpp b/radiant/layers/LayerManager.cpp index 41c3c915cb..440f1641fb 100644 --- a/radiant/layers/LayerManager.cpp +++ b/radiant/layers/LayerManager.cpp @@ -35,7 +35,10 @@ namespace LayerManager::LayerManager() : _activeLayer(DEFAULT_LAYER) -{} +{ + // Create the "master" layer with ID DEFAULT_LAYER + createLayer(_(DEFAULT_LAYER_NAME), DEFAULT_LAYER); +} int LayerManager::createLayer(const std::string& name, int layerID) { @@ -260,13 +263,14 @@ void LayerManager::setLayerVisibility(int layerID, bool visible) onLayerVisibilityChanged(); } -void LayerManager::setLayerVisibility(const std::string& layerName, bool visible) { +void LayerManager::setLayerVisibility(const std::string& layerName, bool visible) +{ // Check if the layer already exists int layerID = getLayerID(layerName); - if (layerID == -1) { - rError() << "Could not set layer visibility, name doesn't exist: " - << layerName.c_str() << std::endl; + if (layerID == -1) + { + rError() << "Could not set layer visibility, name doesn't exist: " << layerName << std::endl; return; } @@ -276,7 +280,7 @@ void LayerManager::setLayerVisibility(const std::string& layerName, bool visible void LayerManager::updateSceneGraphVisibility() { - UpdateNodeVisibilityWalker walker; + UpdateNodeVisibilityWalker walker(GlobalSceneGraph().root()); GlobalSceneGraph().root()->traverseChildren(walker); // Redraw @@ -486,109 +490,6 @@ int LayerManager::getLowestUnusedLayerID() return -1; } -// RegisterableModule implementation -const std::string& LayerManager::getName() const -{ - static std::string _name(MODULE_LAYERSYSTEM); - return _name; -} - -const StringSet& LayerManager::getDependencies() const -{ - static StringSet _dependencies; - - if (_dependencies.empty()) - { - _dependencies.insert(MODULE_EVENTMANAGER); - _dependencies.insert(MODULE_COMMANDSYSTEM); - _dependencies.insert(MODULE_MAPINFOFILEMANAGER); - } - - return _dependencies; -} - -void LayerManager::initialiseModule(const ApplicationContext& ctx) -{ - rMessage() << getName() << "::initialiseModule called." << std::endl; - - // Create the "master" layer with ID DEFAULT_LAYER - createLayer(_(DEFAULT_LAYER_NAME)); - - // Add command targets for the first 10 layer IDs here - for (int i = 0; i < 10; i++) - { - _commandTargets.push_back(std::make_shared(i)); - } - - // Register the "create layer" command - GlobalCommandSystem().addCommand("CreateNewLayer", - std::bind(&LayerManager::createLayerCmd, this, std::placeholders::_1), - { cmd::ARGTYPE_STRING | cmd::ARGTYPE_OPTIONAL }); - IEventPtr ev = GlobalEventManager().addCommand("CreateNewLayer", "CreateNewLayer"); - - GlobalMapModule().signal_mapEvent().connect( - sigc::mem_fun(*this, &LayerManager::onMapEvent) - ); - - GlobalMapInfoFileManager().registerInfoFileModule( - std::make_shared() - ); -} - -void LayerManager::createLayerCmd(const cmd::ArgumentList& args) -{ -#if 0 - std::string initialName = !args.empty() ? args[0].getString() : ""; - - while (true) - { - // Query the name of the new layer from the user - std::string layerName; - - if (!initialName.empty()) { - // If we got a layer name passed through the arguments, - // we use this one, but only the first time - layerName = initialName; - initialName.clear(); - } - - if (layerName.empty()) { - try { - layerName = wxutil::Dialog::TextEntryDialog( - _("Enter Name"), - _("Enter Layer Name"), - "", - GlobalMainFrame().getWxTopLevelWindow() - ); - } - catch (wxutil::EntryAbortedException&) { - break; - } - } - - if (layerName.empty()) { - // Wrong name, let the user try again - wxutil::Messagebox::ShowError(_("Cannot create layer with empty name.")); - continue; - } - - // Attempt to create the layer, this will return -1 if the operation fails - int layerID = createLayer(layerName); - - if (layerID != -1) - { - // Success, break the loop - break; - } - else { - // Wrong name, let the user try again - wxutil::Messagebox::ShowError(_("This name already exists.")); - continue; - } - } -#endif -} - void LayerManager::onMapEvent(IMap::MapEvent ev) { if (ev == IMap::MapUnloaded || ev == IMap::MapLoading) @@ -598,13 +499,4 @@ void LayerManager::onMapEvent(IMap::MapEvent ev) } } -// Define the static LayerManager module -module::StaticModule layerManagerModule; - -// Internal accessor method -LayerManager& getLayerSystem() -{ - return *layerManagerModule.getModule(); -} - } // namespace scene diff --git a/radiant/layers/LayerManager.h b/radiant/layers/LayerManager.h index 3ebb1a97a4..1be24006fa 100644 --- a/radiant/layers/LayerManager.h +++ b/radiant/layers/LayerManager.h @@ -129,14 +129,6 @@ class LayerManager : sigc::signal signal_layerVisibilityChanged() override; sigc::signal signal_nodeMembershipChanged() override; - // RegisterableModule implementation - const std::string& getName() const override; - const StringSet& getDependencies() const override; - void initialiseModule(const ApplicationContext& ctx) override; - - // Command target - void createLayerCmd(const cmd::ArgumentList& args); - private: void onMapEvent(IMap::MapEvent ev); @@ -159,7 +151,4 @@ class LayerManager : int getLowestUnusedLayerID(); }; -// Internal accessor, only accessible within this binary -LayerManager& getLayerSystem(); - } // namespace scene diff --git a/radiant/layers/LayerModule.cpp b/radiant/layers/LayerModule.cpp index 5eb7f427eb..8dff9ef5e5 100644 --- a/radiant/layers/LayerModule.cpp +++ b/radiant/layers/LayerModule.cpp @@ -47,11 +47,6 @@ class LayerModule : { rMessage() << getName() << "::initialiseModule called." << std::endl; -#if 0 // TODO - // Create the "master" layer with ID DEFAULT_LAYER - createLayer(_(DEFAULT_LAYER_NAME)); -#endif - // Add command targets for the first 10 layer IDs here for (int i = 0; i < 10; i++) { diff --git a/radiant/layers/LayerUsageBreakdown.cpp b/radiant/layers/LayerUsageBreakdown.cpp index 01ee00f380..a2ee9e81c7 100644 --- a/radiant/layers/LayerUsageBreakdown.cpp +++ b/radiant/layers/LayerUsageBreakdown.cpp @@ -28,6 +28,11 @@ LayerUsageBreakdown LayerUsageBreakdown::CreateFromScene(bool includeHidden) { LayerUsageBreakdown bd; + if (!GlobalMapModule().getRoot()) + { + return bd; + } + InitialiseVector(bd); GlobalSceneGraph().foreachNode([&](const scene::INodePtr& node) @@ -50,6 +55,11 @@ LayerUsageBreakdown LayerUsageBreakdown::CreateFromSelection() { LayerUsageBreakdown bd; + if (!GlobalMapModule().getRoot()) + { + return bd; + } + InitialiseVector(bd); GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node) @@ -69,7 +79,7 @@ void LayerUsageBreakdown::InitialiseVector(LayerUsageBreakdown& bd) // below will fill the vector with zeros bd.resize(0, 0); - GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName) + GlobalMapModule().getRoot()->getLayerManager().foreachLayer([&](int layerId, const std::string& layerName) { if (layerId >= static_cast(bd.size())) { diff --git a/radiant/map/algorithm/Clone.h b/radiant/map/algorithm/Clone.h index ea40d50141..68fc9c6042 100644 --- a/radiant/map/algorithm/Clone.h +++ b/radiant/map/algorithm/Clone.h @@ -50,11 +50,6 @@ class CloneAll : scene::INodePtr cloned = cloneSingleNode(node); - if (cloned && _postCloneCallback) - { - _postCloneCallback(node, cloned); - } - // Insert the cloned node or an empty ptr if not cloneable _path.push(cloned); @@ -72,6 +67,11 @@ class CloneAll : { // Cloning was successful, add to parent _path.parent()->addChildNode(_path.top()); + + if (_postCloneCallback) + { + _postCloneCallback(node, _path.top()); + } } _path.pop(); @@ -90,19 +90,14 @@ inline scene::INodePtr cloneNodeIncludingDescendants(const scene::INodePtr& node { scene::INodePtr clone = cloneSingleNode(node); + CloneAll visitor(clone, callback); + node->traverseChildren(visitor); + if (callback) { callback(node, clone); } - CloneAll visitor(clone, callback); - node->traverseChildren(visitor); - - // Cloned child nodes are assigned the layers of the source nodes - // update the layer visibility flags to make the layers assignemnt take effect - scene::UpdateNodeVisibilityWalker visibilityUpdater; - clone->traverse(visibilityUpdater); - return clone; } diff --git a/radiant/map/algorithm/Import.cpp b/radiant/map/algorithm/Import.cpp index 5a59aece3e..397215095b 100644 --- a/radiant/map/algorithm/Import.cpp +++ b/radiant/map/algorithm/Import.cpp @@ -228,11 +228,17 @@ class EntityMerger : void mergeMap(const scene::INodePtr& node) { + if (!GlobalSceneGraph().root()) + { + rError() << "Cannot merge map, no scenegraph root present." << std::endl; + return; + } + // Discard all layer information found in the data to be merged // We move everything into the active layer { scene::LayerList layers; - layers.insert(GlobalLayerSystem().getActiveLayer()); + layers.insert(GlobalSceneGraph().root()->getLayerManager().getActiveLayer()); scene::AssignNodeToLayersWalker walker(layers); node->traverse(walker); diff --git a/radiant/map/format/portable/PortableMapReader.cpp b/radiant/map/format/portable/PortableMapReader.cpp index 9334ed4fc0..dc1c6b645a 100644 --- a/radiant/map/format/portable/PortableMapReader.cpp +++ b/radiant/map/format/portable/PortableMapReader.cpp @@ -72,7 +72,7 @@ void PortableMapReader::readLayers(const xml::Node& mapNode) { try { - GlobalLayerSystem().reset(); + _importFilter.getRootNode()->getLayerManager().reset(); auto mapLayers = getNamedChild(mapNode, TAG_MAP_LAYERS); @@ -83,7 +83,7 @@ void PortableMapReader::readLayers(const xml::Node& mapNode) auto id = string::convert(layer.getAttributeValue(ATTR_MAP_LAYER_ID)); auto name = layer.getAttributeValue(ATTR_MAP_LAYER_NAME); - GlobalLayerSystem().createLayer(name, id); + _importFilter.getRootNode()->getLayerManager().createLayer(name, id); } } catch (const BadDocumentFormatException& ex) diff --git a/radiant/map/format/portable/PortableMapWriter.cpp b/radiant/map/format/portable/PortableMapWriter.cpp index 68c0a5a817..e9d349c564 100644 --- a/radiant/map/format/portable/PortableMapWriter.cpp +++ b/radiant/map/format/portable/PortableMapWriter.cpp @@ -63,7 +63,7 @@ void PortableMapWriter::beginWriteMap(const scene::IMapRootNodePtr& root, std::o auto layers = _map.createChild(TAG_MAP_LAYERS); // Visit all layers and add a tag for each - GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName) + root->getLayerManager().foreachLayer([&](int layerId, const std::string& layerName) { auto layer = layers.createChild(TAG_MAP_LAYER); diff --git a/radiant/patch/PatchCreators.cpp b/radiant/patch/PatchCreators.cpp index dca975a5f0..97e7240fad 100644 --- a/radiant/patch/PatchCreators.cpp +++ b/radiant/patch/PatchCreators.cpp @@ -2,6 +2,7 @@ #include "ifilter.h" #include "ilayer.h" +#include "imap.h" #include "ieventmanager.h" #include "ipreferencesystem.h" #include "itextstream.h" @@ -24,11 +25,11 @@ scene::INodePtr Doom3PatchCreator::createPatch() // this means that patchDef3 = true in the PatchNode constructor. scene::INodePtr node = std::make_shared(true); - // Determine the layer patches should be created in - int layer = GlobalLayerSystem().getActiveLayer(); - - // Move it to the first visible layer - node->moveToLayer(layer); + if (GlobalMapModule().getRoot()) + { + // All patches are created in the active layer by default + node->moveToLayer(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); + } return node; } @@ -140,11 +141,11 @@ scene::INodePtr Doom3PatchDef2Creator::createPatch() // The PatchNodeDoom3 constructor takes false == patchDef2 scene::INodePtr node = std::make_shared(false); - // Determine the layer patches should be created in - int layer = GlobalLayerSystem().getActiveLayer(); - - // Move it to the first visible layer - node->moveToLayer(layer); + if (GlobalMapModule().getRoot()) + { + // All patches are created in the active layer by default + node->moveToLayer(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); + } return node; } diff --git a/radiant/selection/algorithm/Entity.cpp b/radiant/selection/algorithm/Entity.cpp index 5c177dc737..0c16cef92d 100644 --- a/radiant/selection/algorithm/Entity.cpp +++ b/radiant/selection/algorithm/Entity.cpp @@ -262,7 +262,10 @@ scene::INodePtr createEntityFromSelection(const std::string& name, const Vector3 GlobalSelectionSystem().setSelectedAll(false); // Move the item to the active layer - targetLayers.insert(GlobalLayerSystem().getActiveLayer()); + if (GlobalMapModule().getRoot()) + { + targetLayers.insert(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); + } Node_setSelected(node, true); } @@ -291,10 +294,10 @@ scene::INodePtr createEntityFromSelection(const std::string& name, const Vector3 scene::INodePtr primitive = GlobalSelectionSystem().ultimateSelected(); targetLayers = primitive->getLayers(); } - else - { - // Otherwise move the item to the active layer - targetLayers.insert(GlobalLayerSystem().getActiveLayer()); + // Otherwise move the item to the active layer + else if (GlobalMapModule().getRoot()) + { + targetLayers.insert(GlobalMapModule().getRoot()->getLayerManager().getActiveLayer()); } // Parent the selected primitives to the new node diff --git a/radiant/selection/algorithm/Group.cpp b/radiant/selection/algorithm/Group.cpp index f45805a0ad..4bb8fb9dc7 100644 --- a/radiant/selection/algorithm/Group.cpp +++ b/radiant/selection/algorithm/Group.cpp @@ -100,7 +100,7 @@ void ParentPrimitivesToEntityWalker::reparent() << " primitives." << std::endl; // Update parent node/subgraph visibility after reparenting - scene::UpdateNodeVisibilityWalker updater; + scene::UpdateNodeVisibilityWalker updater(_parent->getRootNode()); // Update the new parent too _parent->traverse(updater); diff --git a/radiant/selection/algorithm/Primitives.cpp b/radiant/selection/algorithm/Primitives.cpp index 2c2ee159fa..341e62be34 100644 --- a/radiant/selection/algorithm/Primitives.cpp +++ b/radiant/selection/algorithm/Primitives.cpp @@ -453,20 +453,18 @@ void surroundWithMonsterclip(const cmd::ArgumentList& args) GlobalSelectionSystem().foreachSelected(visitor); // Retrieve the list with all the found models from the visitor - ModelFinder::ModelList list = visitor.getList(); + auto list = visitor.getList(); - ModelFinder::ModelList::iterator iter; - for (iter = list.begin(); iter != list.end(); ++iter) + for (const auto& model : list) { - // one of the models in the SelectionStack - const scene::INodePtr& node = *iter; - // retrieve the AABB - AABB brushAABB(node->worldAABB()); + AABB brushAABB(model->worldAABB()); // create the brush scene::INodePtr brushNode(GlobalBrushCreator().createBrush()); + brushNode->assignToLayers(model->getLayers()); + if (brushNode != NULL) { scene::addNodeToContainer(brushNode, GlobalMap().findOrInsertWorldspawn()); diff --git a/radiant/selection/algorithm/Transformation.cpp b/radiant/selection/algorithm/Transformation.cpp index 8b1cd8f482..39ae4f0ff2 100644 --- a/radiant/selection/algorithm/Transformation.cpp +++ b/radiant/selection/algorithm/Transformation.cpp @@ -171,6 +171,11 @@ class SelectionCloner : // Insert this node in the root _cloneRoot->addChildNode(clone); + + // Cloned child nodes are assigned the layers of the source nodes + // update the layer visibility flags using the layer manager of the source tree + scene::UpdateNodeVisibilityWalker visibilityUpdater(node->getRootNode()); + clone->traverse(visibilityUpdater); } } diff --git a/radiant/ui/layers/LayerContextMenu.cpp b/radiant/ui/layers/LayerContextMenu.cpp index 5f2772adc2..40b99a4423 100644 --- a/radiant/ui/layers/LayerContextMenu.cpp +++ b/radiant/ui/layers/LayerContextMenu.cpp @@ -1,6 +1,7 @@ #include "LayerContextMenu.h" #include "iuimanager.h" +#include "imap.h" #include "wxutil/menu/IconTextMenuItem.h" #include "layers/LayerManager.h" @@ -21,8 +22,13 @@ void LayerContextMenu::populate() { _sortedLayers.clear(); + if (!GlobalMapModule().getRoot()) + { + return; + } + // Populate the map with all layer names and IDs - scene::getLayerSystem().foreachLayer([&](int layerId, const std::string& layerName) + GlobalMapModule().getRoot()->getLayerManager().foreachLayer([&](int layerId, const std::string& layerName) { _sortedLayers.insert(SortedLayerMap::value_type(layerName, layerId)); }); diff --git a/radiant/ui/layers/LayerControl.cpp b/radiant/ui/layers/LayerControl.cpp index 4c07865a1f..21213c9ede 100644 --- a/radiant/ui/layers/LayerControl.cpp +++ b/radiant/ui/layers/LayerControl.cpp @@ -7,6 +7,7 @@ #include "wxutil/dialog/Dialog.h" #include "wxutil/dialog/MessageBox.h" #include "wxutil/EntryAbortedException.h" +#include "util/ScopedBoolLock.h" #include #include @@ -98,9 +99,14 @@ wxToggleButton* LayerControl::getToggle() void LayerControl::update() { - _updateActive = true; + util::ScopedBoolLock{_updateActive}; - auto& layerSystem = scene::getLayerSystem(); + if (!GlobalMapModule().getRoot()) + { + return; + } + + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); bool layerIsVisible = layerSystem.layerIsVisible(_layerID); _toggle->SetValue(layerIsVisible); @@ -131,8 +137,6 @@ void LayerControl::update() // Clear usage status _statusWidget->SetBackgroundColour(_inactiveColour); - - _updateActive = false; } int LayerControl::getLayerId() const @@ -148,16 +152,24 @@ void LayerControl::updateUsageStatusWidget(std::size_t numUsedObjectsInLayer) void LayerControl::onToggle(wxCommandEvent& ev) { - if (_updateActive) return; + if (_updateActive || !GlobalMapModule().getRoot()) return; - scene::getLayerSystem().setLayerVisibility(_layerID, _toggle->GetValue()); + GlobalMapModule().getRoot()->getLayerManager().setLayerVisibility(_layerID, _toggle->GetValue()); } void LayerControl::onDelete(wxCommandEvent& ev) { + if (!GlobalMapModule().getRoot()) + { + rError() << "Can't delete layer, no map root present" << std::endl; + return; + } + + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); + // Ask the about the deletion std::string msg = _("Do you really want to delete this layer?"); - msg += "\n" + scene::getLayerSystem().getLayerName(_layerID); + msg += "\n" + layerSystem.getLayerName(_layerID); IDialogPtr box = GlobalDialogManager().createMessageBox( _("Confirm Layer Deletion"), msg, IDialog::MESSAGE_ASK @@ -165,14 +177,20 @@ void LayerControl::onDelete(wxCommandEvent& ev) if (box->run() == IDialog::RESULT_YES) { - scene::getLayerSystem().deleteLayer( - scene::getLayerSystem().getLayerName(_layerID) - ); + layerSystem.deleteLayer(layerSystem.getLayerName(_layerID)); } } void LayerControl::onRename(wxCommandEvent& ev) { + if (!GlobalMapModule().getRoot()) + { + rError() << "Can't rename layer, no map root present" << std::endl; + return; + } + + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); + while (true) { // Query the name of the new layer from the user @@ -183,7 +201,7 @@ void LayerControl::onRename(wxCommandEvent& ev) newLayerName = wxutil::Dialog::TextEntryDialog( _("Rename Layer"), _("Enter new Layer Name"), - scene::getLayerSystem().getLayerName(_layerID), + layerSystem.getLayerName(_layerID), _toggle->GetParent() ); } @@ -193,7 +211,7 @@ void LayerControl::onRename(wxCommandEvent& ev) } // Attempt to rename the layer, this will return -1 if the operation fails - bool success = scene::getLayerSystem().renameLayer(_layerID, newLayerName); + bool success = layerSystem.renameLayer(_layerID, newLayerName); if (success) { @@ -211,10 +229,16 @@ void LayerControl::onRename(wxCommandEvent& ev) void LayerControl::onLayerSelect(wxCommandEvent& ev) { + if (!GlobalMapModule().getRoot()) + { + rError() << "Can't select layer, no map root present" << std::endl; + return; + } + // When holding down CTRL the user sets this as active if (wxGetKeyState(WXK_CONTROL)) { - GlobalLayerSystem().setActiveLayer(_layerID); + GlobalMapModule().getRoot()->getLayerManager().setActiveLayer(_layerID); // Update our icon set LayerControlDialog::Instance().refresh(); @@ -232,7 +256,7 @@ void LayerControl::onLayerSelect(wxCommandEvent& ev) } // Set the entire layer to selected - GlobalLayerSystem().setSelected(_layerID, selected); + GlobalMapModule().getRoot()->getLayerManager().setSelected(_layerID, selected); } } // namespace ui diff --git a/radiant/ui/layers/LayerControlDialog.cpp b/radiant/ui/layers/LayerControlDialog.cpp index ee5b7967c0..244d59e301 100644 --- a/radiant/ui/layers/LayerControlDialog.cpp +++ b/radiant/ui/layers/LayerControlDialog.cpp @@ -105,10 +105,15 @@ void LayerControlDialog::refresh() // Remove all previously allocated layercontrols _layerControls.clear(); + if (!GlobalMapModule().getRoot()) + { + return; // no map present, don't add any layer controls + } + std::map sortedControls; // Traverse the layers - scene::getLayerSystem().foreachLayer([&](int layerID, const std::string& layerName) + GlobalMapModule().getRoot()->getLayerManager().foreachLayer([&](int layerID, const std::string& layerName) { // Create a new layercontrol for each visited layer // Store the object in a sorted container @@ -146,6 +151,13 @@ void LayerControlDialog::refresh() void LayerControlDialog::update() { + if (!GlobalMapModule().getRoot()) + { + return; + } + + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); + // Broadcast the update() call for (const LayerControlPtr& control : _layerControls) { @@ -159,9 +171,9 @@ void LayerControlDialog::update() std::size_t numVisible = 0; std::size_t numHidden = 0; - GlobalLayerSystem().foreachLayer([&](int layerID, const std::string& layerName) + layerSystem.foreachLayer([&](int layerID, const std::string& layerName) { - if (GlobalLayerSystem().layerIsVisible(layerID)) + if (layerSystem.layerIsVisible(layerID)) { numVisible++; } @@ -265,19 +277,24 @@ void LayerControlDialog::_preShow() _rescanSelectionOnIdle = true; }); - // Layer creation/addition/removal triggers a refresh - _layersChangedSignal = GlobalLayerSystem().signal_layersChanged().connect( - sigc::mem_fun(this, &LayerControlDialog::refresh)); + if (GlobalMapModule().getRoot()) + { + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); - // Visibility change doesn't repopulate the dialog - _layerVisibilityChangedSignal = GlobalLayerSystem().signal_layerVisibilityChanged().connect( - sigc::mem_fun(this, &LayerControlDialog::update)); + // Layer creation/addition/removal triggers a refresh + _layersChangedSignal = layerSystem.signal_layersChanged().connect( + sigc::mem_fun(this, &LayerControlDialog::refresh)); - // Node membership triggers a selection rescan - _nodeLayerMembershipChangedSignal = GlobalLayerSystem().signal_nodeMembershipChanged().connect([this]() - { - _rescanSelectionOnIdle = true; - }); + // Visibility change doesn't repopulate the dialog + _layerVisibilityChangedSignal = layerSystem.signal_layerVisibilityChanged().connect( + sigc::mem_fun(this, &LayerControlDialog::update)); + + // Node membership triggers a selection rescan + _nodeLayerMembershipChangedSignal = layerSystem.signal_nodeMembershipChanged().connect([this]() + { + _rescanSelectionOnIdle = true; + }); + } _mapEventSignal = GlobalMapModule().signal_mapEvent().connect( sigc::mem_fun(this, &LayerControlDialog::onMapEvent) @@ -299,17 +316,27 @@ void LayerControlDialog::_postHide() void LayerControlDialog::onShowAllLayers(wxCommandEvent& ev) { - GlobalLayerSystem().foreachLayer([&](int layerID, const std::string& layerName) + if (!GlobalMapModule().getRoot()) + { + rError() << "Can't show layers, no map loaded." << std::endl; + return; + } + + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); + + layerSystem.foreachLayer([&](int layerID, const std::string& layerName) { - GlobalLayerSystem().setLayerVisibility(layerID, true); + layerSystem.setLayerVisibility(layerID, true); }); } void LayerControlDialog::onHideAllLayers(wxCommandEvent& ev) { - GlobalLayerSystem().foreachLayer([&](int layerID, const std::string& layerName) + auto& layerSystem = GlobalMapModule().getRoot()->getLayerManager(); + + layerSystem.foreachLayer([&](int layerID, const std::string& layerName) { - GlobalLayerSystem().setLayerVisibility(layerID, false); + layerSystem.setLayerVisibility(layerID, false); }); } diff --git a/radiant/ui/layers/LayerOrthoContextMenuItem.cpp b/radiant/ui/layers/LayerOrthoContextMenuItem.cpp index 705ee0bde7..530cbf9379 100644 --- a/radiant/ui/layers/LayerOrthoContextMenuItem.cpp +++ b/radiant/ui/layers/LayerOrthoContextMenuItem.cpp @@ -8,10 +8,10 @@ namespace ui { - namespace - { - const char* const LAYER_ICON = "layers.png"; - } +namespace +{ + const char* const LAYER_ICON = "layers.png"; +} LayerOrthoContextMenuItem::LayerOrthoContextMenuItem(const std::string& caption, LayerContextMenu::OnSelectionFunc callback) : @@ -27,7 +27,7 @@ LayerOrthoContextMenuItem::LayerOrthoContextMenuItem(const std::string& caption, LayerOrthoContextMenuItem::~LayerOrthoContextMenuItem() { - if (GetMenu() != NULL) + if (GetMenu() != nullptr) { // Destroying a menu item doesn't de-register it from the parent menu // To prevent double-deletions, we de-register the item on our own @@ -56,20 +56,39 @@ void LayerOrthoContextMenuItem::preShow() void LayerOrthoContextMenuItem::AddToLayer(int layerID) { - GlobalLayerSystem().addSelectionToLayer(layerID); - GlobalMap().setModified(true); + DoWithMapLayerManager([=](scene::ILayerManager& manager) + { + manager.addSelectionToLayer(layerID); + GlobalMap().setModified(true); + }); } void LayerOrthoContextMenuItem::MoveToLayer(int layerID) { - GlobalLayerSystem().moveSelectionToLayer(layerID); - GlobalMap().setModified(true); + DoWithMapLayerManager([=](scene::ILayerManager& manager) + { + manager.moveSelectionToLayer(layerID); + GlobalMap().setModified(true); + }); } void LayerOrthoContextMenuItem::RemoveFromLayer(int layerID) { - GlobalLayerSystem().removeSelectionFromLayer(layerID); - GlobalMap().setModified(true); + DoWithMapLayerManager([=](scene::ILayerManager& manager) + { + manager.removeSelectionFromLayer(layerID); + GlobalMap().setModified(true); + }); +} + +void LayerOrthoContextMenuItem::DoWithMapLayerManager(const std::function& func) +{ + if (!GlobalMapModule().getRoot()) + { + return; + } + + func(GlobalMapModule().getRoot()->getLayerManager()); } } // namespace diff --git a/radiant/ui/layers/LayerOrthoContextMenuItem.h b/radiant/ui/layers/LayerOrthoContextMenuItem.h index d7f283fb4c..9bd4a913d3 100644 --- a/radiant/ui/layers/LayerOrthoContextMenuItem.h +++ b/radiant/ui/layers/LayerOrthoContextMenuItem.h @@ -1,6 +1,7 @@ #pragma once #include "imenu.h" +#include "ilayer.h" #include #include "LayerContextMenu.h" #include "wxutil/menu/IconTextMenuItem.h" @@ -37,6 +38,9 @@ class LayerOrthoContextMenuItem : static void AddToLayer(int layerID); static void MoveToLayer(int layerID); static void RemoveFromLayer(int layerID); + +private: + static void DoWithMapLayerManager(const std::function& func); }; typedef std::shared_ptr LayerOrthoContextMenuItemPtr; diff --git a/radiant/ui/mapinfo/LayerInfoTab.cpp b/radiant/ui/mapinfo/LayerInfoTab.cpp index 1172e5ebcd..6c59015e2b 100644 --- a/radiant/ui/mapinfo/LayerInfoTab.cpp +++ b/radiant/ui/mapinfo/LayerInfoTab.cpp @@ -51,12 +51,19 @@ void LayerInfoTab::populateTab() _treeView->AppendTextColumn(_("Node Count"), _columns.nodeCount.getColumnIndex(), wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT, wxDATAVIEW_COL_SORTABLE); + + GetSizer()->Add(_treeView, 1, wxEXPAND | wxALL, 12); + + if (!GlobalMapModule().getRoot()) + { + return; // stop here if we don't have a map loaded + } // Calculate the node histogram scene::LayerUsageBreakdown bd = scene::LayerUsageBreakdown::CreateFromScene(true); // Populate the liststore with the layer-to-nodecount information - GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName) + GlobalMapModule().getRoot()->getLayerManager().foreachLayer([&](int layerId, const std::string& layerName) { if (layerId >= static_cast(bd.size())) return; @@ -67,8 +74,6 @@ void LayerInfoTab::populateTab() row.SendItemAdded(); }); - - GetSizer()->Add(_treeView, 1, wxEXPAND | wxALL, 12); } } // namespace ui