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
|