1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
#include "Models.h"
#include <set>
#include "i18n.h"
#include "inode.h"
#include "iselection.h"
#include "ientity.h"
#include "imodel.h"
#include "imodelcache.h"
#include "iscenegraph.h"
#include "messages/ScopedLongRunningOperation.h"
namespace map
{
namespace algorithm
{
class ModelFinder :
public selection::SelectionSystem::Visitor,
public scene::NodeVisitor
{
public:
typedef std::set<IEntityNodePtr> Entities;
typedef std::set<std::string> ModelPaths;
private:
// All the model path of the selected modelnodes
mutable ModelPaths _modelNames;
// All the selected entities with modelnodes as child
mutable Entities _entities;
public:
bool pre(const scene::INodePtr& node)
{
model::ModelNodePtr model = Node_getModel(node);
if (model)
{
_modelNames.insert(model->getIModel().getModelPath());
IEntityNodePtr ent = std::dynamic_pointer_cast<IEntityNode>(node->getParent());
if (ent)
{
_entities.insert(ent);
}
return false;
}
return true;
}
void visit(const scene::INodePtr& node) const
{
node->traverse(*const_cast<ModelFinder*>(this));
}
const Entities& getEntities() const
{
return _entities;
}
const ModelPaths& getModelPaths() const
{
return _modelNames;
}
};
class ModelRefreshWalker :
public scene::NodeVisitor
{
public:
bool pre(const scene::INodePtr& node)
{
IEntityNodePtr entity = std::dynamic_pointer_cast<IEntityNode>(node);
if (entity)
{
entity->refreshModel();
return false;
}
return true;
}
};
void refreshModels(bool blockScreenUpdates)
{
std::unique_ptr<radiant::ScopedLongRunningOperation> blocker;
if (blockScreenUpdates)
{
// Disable screen updates for the scope of this function
blocker.reset(new radiant::ScopedLongRunningOperation(_("Reloading Models")));
}
// Clear the model cache
GlobalModelCache().clear();
// Update all model nodes
ModelRefreshWalker walker;
GlobalSceneGraph().root()->traverse(walker);
// Send the signal to the UI
GlobalModelCache().signal_modelsReloaded().emit();
}
void refreshSelectedModels(bool blockScreenUpdates)
{
std::unique_ptr<radiant::ScopedLongRunningOperation> blocker;
if (blockScreenUpdates)
{
// Disable screen updates for the scope of this function
blocker.reset(new radiant::ScopedLongRunningOperation(_("Reloading Models")));
}
// Find all models in the current selection
ModelFinder walker;
GlobalSelectionSystem().foreachSelected(walker);
// Remove the selected models from the cache
ModelFinder::ModelPaths models = walker.getModelPaths();
for (const std::string& modelPath : models)
{
GlobalModelCache().removeModel(modelPath);
}
// Traverse the entities and submit a refresh call
ModelFinder::Entities entities = walker.getEntities();
for (const IEntityNodePtr& entityNode : entities)
{
entityNode->refreshModel();
}
}
// Reloads all entities with their model spawnarg referencing the given model path.
// The given model path denotes a VFS path, i.e. it is mod/game-relative
void refreshModelsByPath(const std::string& relativeModelPath)
{
std::size_t refreshedEntityCount = 0;
GlobalModelCache().removeModel(relativeModelPath);
GlobalMapModule().getRoot()->foreachNode([&](const scene::INodePtr& node)
{
auto entity = std::dynamic_pointer_cast<IEntityNode>(node);
if (entity && entity->getEntity().getKeyValue("model") == relativeModelPath)
{
entity->refreshModel();
++refreshedEntityCount;
}
return true;
});
rMessage() << "Refreshed " << refreshedEntityCount << " entities using the model " << relativeModelPath << std::endl;
}
}
}
|