File: EntityNode.h

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 (286 lines) | stat: -rw-r--r-- 9,931 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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#pragma once

#include <sigc++/connection.h>
#include "ientity.h"
#include "inamespace.h"
#include "icomparablenode.h"
#include "Bounded.h"

#include "scene/SelectableNode.h"
#include "transformlib.h"

#include "NamespaceManager.h"
#include "target/TargetableNode.h"
#include "NameKey.h"
#include "ColourKey.h"
#include "ModelKey.h"
#include "ShaderParms.h"
#include "OriginKey.h"

#include "KeyObserverMap.h"
#include "RenderableEntityName.h"
#include "RenderableObjectCollection.h"

namespace entity
{

const Vector4 INACTIVE_ENTITY_COLOUR(0.73, 0.73, 0.73, 1);

class EntityNode;
typedef std::shared_ptr<EntityNode> EntityNodePtr;

/**
 * greebo: This is the common base class of all map entities.
 */
class EntityNode :
	public IEntityNode,
	public scene::SelectableNode, // derives from scene::Node
	public SelectionTestable,
	public Namespaced,
	public TargetableNode,
	public Transformable,
    public scene::IComparableNode
{
protected:
	// The entity class
	IEntityClassPtr _eclass;

	// The actual entity (which contains the key/value pairs)
	SpawnArgs _spawnArgs;

    // Transformation applied to this node and its children
    Matrix4 _localToParent = Matrix4::getIdentity();

	// The class taking care of all the namespace-relevant stuff
	NamespaceManager _namespaceManager;

    // Observes the "origin" keyvalue
    OriginKey _originKey;

    // Points to the origin value of this entity, is also kept up to date
    // during transformations. Used to render the entity name at the correct position.
    Vector3 _originTransformed;

	// A helper class observing the "name" keyvalue
	// Used for rendering the name and as Nameable implementation
	NameKey _nameKey;

	// The renderable, using the NameKey helper class to retrieve the name
	RenderableEntityName _renderableName;

	// The keyobserver watching over the "_color" keyvalue
	ColourKey _colourKey;

	// Model child node handling helper
	ModelKey _modelKey;

	// A helper class managing the collection of KeyObservers attached to the SpawnArgs
	KeyObserverMap _keyObservers;

	// Helper class observing the "shaderParmNN" spawnargs and caching their values
	ShaderParms _shaderParms;

	// This entity's main direction, usually determined by the angle/rotation keys
	Vector3 _direction;

	// The coloured shaders as determined by the entityclass

	ShaderPtr _fillShader; // cam only
	ShaderPtr _wireShader; // ortho only
	ShaderPtr _colourShader; // cam+ortho view
    ShaderPtr _inactiveShader; // inactive rendering
	ITextRenderer::Ptr _textRenderer; // for name rendering

	sigc::connection _eclassChangedConn;

    // List of attached sub-entities that we will submit for rendering (but are
    // otherwise non-interactable).
    //
    // Although scene::Node already has the ability to store children, this is a
    // separate list of entity nodes for two reasons: (1) there is a lot of
    // other code which walks the scene graph for various reasons (e.g. map
    // saving), and I don't want to have to audit the entire codebase to make
    // sure that everything will play nicely with entities as children of other
    // entities, and (2) storing entity node pointers instead of generic node
    // pointers avoids some extra dynamic_casting.
    using AttachedEntity = std::pair<IEntityNodePtr, Vector3 /* offset */>;
    using AttachedEntities = std::list<AttachedEntity>;
    AttachedEntities _attachedEnts;

    // Whether this entity has registered itself to a render system
    bool _isAttachedToRenderSystem;

    // The list of renderable objects attached to this IRenderEntity
    // Used in lighting render mode to enumerate surfaces by entity
    RenderableObjectCollection _renderObjects;

    bool _isShadowCasting;

protected:
	// The Constructor needs the eclass
	EntityNode(const IEntityClassPtr& eclass);

	// Copy constructor
	EntityNode(const EntityNode& other);

public:
	virtual ~EntityNode();

	// IEntityNode implementation
	Entity& getEntity() override;
	virtual void refreshModel() override;
    virtual void transformChanged() override;

	// RenderEntity implementation
    virtual std::string getEntityName() const override;
	virtual float getShaderParm(int parmNum) const override;
	virtual const Vector3& getDirection() const override;

    virtual void addRenderable(const render::IRenderableObject::Ptr& object, Shader* shader) override;
    virtual void removeRenderable(const render::IRenderableObject::Ptr& object) override;
    virtual void foreachRenderable(const ObjectVisitFunction& functor) override;
    virtual void foreachRenderableTouchingBounds(const AABB& bounds,
        const ObjectVisitFunction& functor) override;
    virtual bool isShadowCasting() const override;

    // IMatrixTransform implementation
    Matrix4 localToParent() const override { return _localToParent; }
    void setLocalToParent(const Matrix4& localToParent) override
    {
        _localToParent = localToParent;
    }

    // IComparableNode implementation
    std::string getFingerprint() override;

	// SelectionTestable implementation
	virtual void testSelect(Selector& selector, SelectionTest& test) override;

	// Namespaced implementation
	// Gets/sets the namespace of this named object
	std::string getName() const override;
	void setNamespace(INamespace* space) override;
	INamespace* getNamespace() const override;
	void connectNameObservers() override;
	void disconnectNameObservers() override;
	void changeName(const std::string& newName) override;

	void attachNames() override;
	void detachNames() override;

	virtual void onInsertIntoScene(scene::IMapRootNode& root) override;
	virtual void onRemoveFromScene(scene::IMapRootNode& root) override;

	// Sets/clears render entity references on child nodes
	virtual void onChildAdded(const scene::INodePtr& child) override;
	virtual void onChildRemoved(const scene::INodePtr& child) override;

	virtual std::string name() const override;
	Type getNodeType() const override;

	// Renderable implementation, can be overridden by subclasses
	virtual void onPreRender(const VolumeTest& volume) override;
	virtual void renderHighlights(IRenderableCollector& collector, const VolumeTest& volume) override;
	virtual void setRenderSystem(const RenderSystemPtr& renderSystem) override;
	virtual std::size_t getHighlightFlags() override;

	// IEntityNode implementation
    void observeKey(const std::string& key, KeyObserverFunc func) override;
    void foreachAttachment(const std::function<void(const IEntityNodePtr&)>& functor) override;

	ModelKey& getModelKey(); // needed by the Doom3Group class, could be a fixme
    const ModelKey& getModelKey() const;

	const ShaderPtr& getWireShader() const override;
	const ShaderPtr& getColourShader() const override;
	const ShaderPtr& getFillShader() const;
    virtual Vector4 getEntityColour() const override;

	virtual void onPostUndo() override;
	virtual void onPostRedo() override;

    // Optional implementation: gets invoked by the EntityModule when the settings are changing
    virtual void onEntitySettingsChanged();

    void onVisibilityChanged(bool isVisibleNow) override;

    // Returns the current world origin of this entity (also up to date during transformations)
    virtual const Vector3& getWorldPosition() const = 0;

    void setRenderState(RenderState state) override;

protected:
    const ShaderPtr& getInactiveShader();

    virtual void onModelKeyChanged(const std::string& value);

    // Invoked when the colour key has changed its value
    virtual void onColourKeyChanged(const std::string& value)
    {}

	/**
	 * greebo: construct() does the necessary setup, connects keyobservers, etc.
	 * This is called by the static constructors - it seems awkward but is necessary
	 * since the std::shared_from_this() is not working when the object is not fully
	 * constructed yet.
	 * Subclasses must make sure to have this base method called if they override this.
	 */
	virtual void construct();

    // Called after cloning and construct to perform additional setup
    virtual void constructClone(const EntityNode& original);

	// Signal method to be overridden by subclasses.
	// Don't forget to call the base class implementation as this will
	// reload the entity key values and notify observers
	virtual void onEntityClassChanged();

private:
	// Routine used by the destructor, should be non-virtual
	void destruct();

	// Private function target - wraps to virtual protected signal
	void _modelKeyChanged(const std::string& value);
    void _originKeyChanged();
    void _colourKeyChanged(const std::string& value);
    void _onNoShadowsSettingsChanged(const std::string& value);

    void acquireShaders();
    void acquireShaders(const RenderSystemPtr& renderSystem);

    // Create entity nodes for all attached entities
    void createAttachedEntities();

    // Render all attached entities
    template <typename RenderFunc> void renderAttachments(const RenderFunc& func) const
    {
        for (auto& [entityNode, offset]: _attachedEnts)
        {
            // Before rendering the attached entity, ensure its offset is correct
            entityNode->setLocalToParent(Matrix4::getTranslation(offset));

            // Attached entities might themselves have child nodes (e.g. func_static
            // which has its model as a child node), so we must traverse() the
            // attached entities, not just render them alone
            struct ChildRenderer : public scene::NodeVisitor
            {
                RenderFunc _func;
                ChildRenderer(const RenderFunc& f): _func(f)
                {}

                bool pre(const scene::INodePtr& node)
                {
                    _func(node);
                    return true;
                }
            };
            ChildRenderer cr(func);
            entityNode->traverse(cr);
        }
    }

    void attachToRenderSystem();
    void detachFromRenderSystem();
};

} // namespace entity