Skip to content

Commit

Permalink
#5584: Migrate entity name rendering. Everything except the colour is…
Browse files Browse the repository at this point in the history
… working.

Added OriginKey member to EntityNode - all subclasses need to be adjusted now to use the same observer.
  • Loading branch information
codereader committed Jan 24, 2022
1 parent a93973d commit 3393128
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 98 deletions.
8 changes: 8 additions & 0 deletions libs/render/RenderableText.h
Expand Up @@ -62,6 +62,9 @@ class RenderableText :
{
_slot = _renderer->addText(*this);
}

// Subclasses should get a chance to update the data now
onUpdate();
}

void clear()
Expand Down Expand Up @@ -102,6 +105,11 @@ class RenderableText :
_colour = colour;
}

protected:
// Optional update routine to be implemented by subclasses, invoked at the end of the public update()
virtual void onUpdate()
{}

private:
// Removes the text from the attached renderer. Does nothing if no text has been added.
void removeTextFromRenderer()
Expand Down
56 changes: 42 additions & 14 deletions radiantcore/entity/EntityNode.cpp
Expand Up @@ -19,8 +19,9 @@ EntityNode::EntityNode(const IEntityClassPtr& eclass) :
_eclass(eclass),
_spawnArgs(_eclass),
_namespaceManager(_spawnArgs),
_originKey(std::bind(&EntityNode::_originKeyChanged, this)),
_nameKey(_spawnArgs),
_renderableName(_nameKey),
_renderableName(_nameKey, _originKey.get()),
_modelKey(*this),
_keyObservers(_spawnArgs),
_shaderParms(_keyObservers, _colourKey),
Expand All @@ -39,8 +40,9 @@ EntityNode::EntityNode(const EntityNode& other) :
_spawnArgs(other._spawnArgs),
_localToParent(other._localToParent),
_namespaceManager(_spawnArgs),
_originKey(std::bind(&EntityNode::_originKeyChanged, this)),
_nameKey(_spawnArgs),
_renderableName(_nameKey),
_renderableName(_nameKey, _originKey.get()),
_modelKey(*this),
_keyObservers(_spawnArgs),
_shaderParms(_keyObservers, _colourKey),
Expand All @@ -63,14 +65,16 @@ void EntityNode::construct()
TargetableNode::construct();

// Observe basic keys
static_assert(std::is_base_of<sigc::trackable, NameKey>::value);
static_assert(std::is_base_of<sigc::trackable, ColourKey>::value);
static_assert(std::is_base_of_v<sigc::trackable, NameKey>);
static_assert(std::is_base_of_v<sigc::trackable, ColourKey>);
static_assert(std::is_base_of_v<sigc::trackable, OriginKey>);
observeKey("origin", sigc::mem_fun(_originKey, &OriginKey::onKeyValueChanged));
observeKey("name", sigc::mem_fun(_nameKey, &NameKey::onKeyValueChanged));
observeKey("_color", sigc::mem_fun(_colourKey, &ColourKey::onKeyValueChanged));

// Observe model-related keys
static_assert(std::is_base_of<sigc::trackable, EntityNode>::value);
static_assert(std::is_base_of<sigc::trackable, ModelKey>::value);
static_assert(std::is_base_of_v<sigc::trackable, EntityNode>);
static_assert(std::is_base_of_v<sigc::trackable, ModelKey>);
observeKey("model", sigc::mem_fun(this, &EntityNode::_modelKeyChanged));
observeKey("skin", sigc::mem_fun(_modelKey, &ModelKey::skinChanged));

Expand Down Expand Up @@ -333,7 +337,7 @@ void EntityNode::onChildRemoved(const scene::INodePtr& child)

std::string EntityNode::name() const
{
return _nameKey.name();
return _nameKey.getName();
}

scene::INode::Type EntityNode::getNodeType() const
Expand All @@ -346,6 +350,18 @@ bool EntityNode::isOriented() const
return true;
}

void EntityNode::onPreRender(const VolumeTest& volume)
{
if (EntitySettings::InstancePtr()->getRenderEntityNames())
{
_renderableName.update(_textRenderer);
}
else
{
_renderableName.clear();
}
}

void EntityNode::renderSolid(IRenderableCollector& collector,
const VolumeTest& volume) const
{
Expand All @@ -358,13 +374,6 @@ void EntityNode::renderSolid(IRenderableCollector& collector,
void EntityNode::renderWireframe(IRenderableCollector& collector,
const VolumeTest& volume) const
{
// Submit renderable text name if required
if (EntitySettings::InstancePtr()->getRenderEntityNames())
{
collector.addRenderable(*getWireShader(), _renderableName,
localToWorld());
}

// Render any attached entities
renderAttachments(
[&](const scene::INodePtr& n) { n->renderWireframe(collector, volume); }
Expand Down Expand Up @@ -395,12 +404,14 @@ void EntityNode::acquireShaders(const RenderSystemPtr& renderSystem)
_fillShader = renderSystem->capture(_spawnArgs.getEntityClass()->getFillShader());
_wireShader = renderSystem->capture(_spawnArgs.getEntityClass()->getWireShader());
_colourShader = renderSystem->capture(_spawnArgs.getEntityClass()->getColourShader());
_textRenderer = renderSystem->captureTextRenderer(IGLFont::Style::Sans, 14);
}
else
{
_fillShader.reset();
_wireShader.reset();
_colourShader.reset();
_textRenderer.reset();
}
}

Expand Down Expand Up @@ -450,6 +461,11 @@ void EntityNode::_modelKeyChanged(const std::string& value)
onModelKeyChanged(value);
}

void EntityNode::_originKeyChanged()
{
_renderableName.queueUpdate();
}

const ShaderPtr& EntityNode::getWireShader() const
{
return _wireShader;
Expand Down Expand Up @@ -492,4 +508,16 @@ void EntityNode::onPostRedo()
});
}

void EntityNode::onEntitySettingsChanged()
{
if (EntitySettings::InstancePtr()->getRenderEntityNames())
{
_renderableName.queueUpdate();
}
else
{
_renderableName.clear();
}
}

} // namespace entity
15 changes: 11 additions & 4 deletions radiantcore/entity/EntityNode.h
Expand Up @@ -15,8 +15,10 @@
#include "ColourKey.h"
#include "ModelKey.h"
#include "ShaderParms.h"
#include "OriginKey.h"

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

namespace entity
{
Expand Down Expand Up @@ -49,12 +51,15 @@ class EntityNode :
// The class taking care of all the namespace-relevant stuff
NamespaceManager _namespaceManager;

// Observes the "origin" keyvalue
OriginKey _originKey;

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

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

// The keyobserver watching over the "_color" keyvalue
ColourKey _colourKey;
Expand All @@ -76,6 +81,7 @@ class EntityNode :
ShaderPtr _fillShader; // cam only
ShaderPtr _wireShader; // ortho only
ShaderPtr _colourShader; // cam+ortho view
ITextRenderer::Ptr _textRenderer; // for name rendering

sigc::connection _eclassChangedConn;

Expand Down Expand Up @@ -145,6 +151,7 @@ class EntityNode :

// Renderable implementation, can be overridden by subclasses
virtual bool isOriented() const override;
virtual void onPreRender(const VolumeTest& volume) override;
virtual void renderSolid(IRenderableCollector& collector, const VolumeTest& volume) const override;
virtual void renderWireframe(IRenderableCollector& collector, const VolumeTest& volume) const override;
virtual void renderHighlights(IRenderableCollector& collector, const VolumeTest& volume) override;
Expand All @@ -166,8 +173,7 @@ class EntityNode :
virtual void onPostRedo() override;

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

protected:
virtual void onModelKeyChanged(const std::string& value);
Expand Down Expand Up @@ -195,6 +201,7 @@ class EntityNode :

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

void acquireShaders();
void acquireShaders(const RenderSystemPtr& renderSystem);
Expand Down
77 changes: 18 additions & 59 deletions radiantcore/entity/NameKey.h
@@ -1,89 +1,48 @@
/*
Copyright (C) 2001-2006, William Joseph.
All Rights Reserved.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#if !defined(INCLUDED_NAMEDENTITY_H)
#define INCLUDED_NAMEDENTITY_H

#include "entitylib.h"
#pragma once

#include "ieclass.h"
#include "ientity.h"
#include "SpawnArgs.h"

namespace entity {
namespace entity
{

class NameKey :
public KeyObserver
{
// The reference to the spawnarg structure
SpawnArgs& m_entity;
SpawnArgs& _entity;

// Cached "name" keyvalue
std::string _name;

sigc::signal<void> _sigNameChanged;

public:
NameKey(SpawnArgs& entity) :
m_entity(entity)
NameKey(SpawnArgs& entity) :
_entity(entity)
{}

std::string name() const
std::string getName() const
{
if (_name.empty())
{
return m_entity.getEntityClass()->getName();
return _entity.getEntityClass()->getName();
}
return _name;
}

void onKeyValueChanged(const std::string& value)
{
_name = value;
}
};

class RenderableNameKey :
public OpenGLRenderable
{
const NameKey& _nameKey;

// The origin (local entity coordinates)
Vector3 _origin;

public:
RenderableNameKey(const NameKey& nameKey) :
_nameKey(nameKey),
_origin(0,0,0)
{}

// We render in local coordinates of the owning entity node
void render(const RenderInfo& info) const
{
glRasterPos3dv(_origin);
GlobalOpenGL().drawString(_nameKey.name());
_sigNameChanged.emit();
}

void setOrigin(const Vector3& origin)
{
_origin = origin;
}
sigc::signal<void>& signal_nameChanged()
{
return _sigNameChanged;
}
};

} // namespace entity

#endif
} // namespace
52 changes: 52 additions & 0 deletions radiantcore/entity/RenderableEntityName.h
@@ -0,0 +1,52 @@
#pragma once

#include <sigc++/trackable.h>
#include <sigc++/functors/mem_fun.h>
#include "math/Matrix4.h"
#include "render/RenderableText.h"
#include "NameKey.h"

namespace entity
{

class RenderableEntityName :
public render::RenderableText,
public sigc::trackable
{
NameKey& _nameKey;

// The origin in world coordinates
const Vector3& _entityOrigin;

bool _needsUpdate;

public:
RenderableEntityName(NameKey& nameKey, const Vector3& entityOrigin) :
_nameKey(nameKey),
_entityOrigin(entityOrigin),
_needsUpdate(true)
{
// Queue an update once the name changes
_nameKey.signal_nameChanged().connect(
sigc::mem_fun(*this, &RenderableEntityName::queueUpdate)
);
}

void queueUpdate()
{
_needsUpdate = true;
}

protected:
void onUpdate() override
{
if (!_needsUpdate) return;

_needsUpdate = false;

setText(_nameKey.getName());
setWorldPosition(_entityOrigin);
}
};

}

0 comments on commit 3393128

Please sign in to comment.