File: Models.cpp

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (169 lines) | stat: -rw-r--r-- 3,658 bytes parent folder | download | duplicates (3)
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;
}

}

}