Browse Source

Change ElementInstancer to NodeInstancer

Several breaking changes, mainly for custom elements:

- ElementInstancer renamed to NodeInstancer, and changes to function names and signatures.
- Associated Factory functions changed as well.
Michael Ragazzon 1 month ago
parent
commit
0ac88ea3d6
50 changed files with 374 additions and 411 deletions
  1. 1 1
      Include/RmlUi/Core.h
  2. 0 10
      Include/RmlUi/Core/Element.h
  3. 9 11
      Include/RmlUi/Core/Factory.h
  4. 10 0
      Include/RmlUi/Core/Node.h
  5. 30 35
      Include/RmlUi/Core/NodeInstancer.h
  6. 1 1
      Include/RmlUi/Core/Types.h
  7. 1 1
      Samples/basic/drag/src/Inventory.cpp
  8. 2 2
      Samples/invaders/src/main.cpp
  9. 4 4
      Samples/lua_invaders/src/ElementGameInstancer.cpp
  10. 5 6
      Samples/lua_invaders/src/ElementGameInstancer.h
  11. 1 1
      Samples/lua_invaders/src/LuaInterface.cpp
  12. 1 2
      Samples/tutorial/drag/src/Inventory.cpp
  13. 2 2
      Source/Core/CMakeLists.txt
  14. 12 12
      Source/Core/Context.cpp
  15. 3 3
      Source/Core/Core.cpp
  16. 7 4
      Source/Core/DataViewDefault.cpp
  17. 7 30
      Source/Core/Element.cpp
  18. 2 2
      Source/Core/ElementDocument.cpp
  19. 2 3
      Source/Core/ElementScroll.cpp
  20. 1 1
      Source/Core/Elements/ElementProgress.cpp
  21. 12 12
      Source/Core/Elements/ElementTabSet.cpp
  22. 1 2
      Source/Core/Elements/InputTypeButton.cpp
  23. 1 2
      Source/Core/Elements/InputTypeSubmit.cpp
  24. 4 4
      Source/Core/Elements/WidgetDropDown.cpp
  25. 14 11
      Source/Core/Elements/WidgetSlider.cpp
  26. 3 3
      Source/Core/Elements/WidgetTextInput.cpp
  27. 8 11
      Source/Core/Elements/XMLNodeHandlerSelect.cpp
  28. 13 16
      Source/Core/Elements/XMLNodeHandlerTabSet.cpp
  29. 2 4
      Source/Core/Elements/XMLNodeHandlerTextArea.cpp
  30. 55 57
      Source/Core/Factory.cpp
  31. 20 0
      Source/Core/Node.cpp
  32. 23 23
      Source/Core/NodeInstancer.cpp
  33. 4 4
      Source/Core/WidgetScroll.cpp
  34. 2 6
      Source/Core/XMLNodeHandlerDefault.cpp
  35. 9 9
      Source/Debugger/DebuggerPlugin.cpp
  36. 1 1
      Source/Debugger/DebuggerPlugin.h
  37. 4 4
      Source/Lottie/LottiePlugin.cpp
  38. 6 6
      Source/Lua/CMakeLists.txt
  39. 1 1
      Source/Lua/Interpreter.cpp
  40. 6 11
      Source/Lua/LuaDocumentNodeInstancer.cpp
  41. 7 12
      Source/Lua/LuaDocumentNodeInstancer.h
  42. 21 21
      Source/Lua/LuaNodeInstancer.cpp
  43. 13 17
      Source/Lua/LuaNodeInstancer.h
  44. 5 5
      Source/Lua/LuaPlugin.cpp
  45. 2 2
      Source/Lua/LuaPlugin.h
  46. 17 17
      Source/Lua/NodeInstancer.cpp
  47. 10 10
      Source/Lua/NodeInstancer.h
  48. 4 4
      Source/Lua/RmlUi.cpp
  49. 4 4
      Source/SVG/SVGPlugin.cpp
  50. 1 1
      Tests/Source/UnitTests/PropertySpecification.cpp

+ 1 - 1
Include/RmlUi/Core.h

@@ -47,7 +47,6 @@
 #include "Core/EffectSpecification.h"
 #include "Core/Element.h"
 #include "Core/ElementDocument.h"
-#include "Core/ElementInstancer.h"
 #include "Core/ElementScroll.h"
 #include "Core/ElementText.h"
 #include "Core/ElementUtilities.h"
@@ -71,6 +70,7 @@
 #include "Core/Mesh.h"
 #include "Core/MeshUtilities.h"
 #include "Core/Node.h"
+#include "Core/NodeInstancer.h"
 #include "Core/NumericValue.h"
 #include "Core/Plugin.h"
 #include "Core/PropertiesIteratorView.h"

+ 0 - 10
Include/RmlUi/Core/Element.h

@@ -49,7 +49,6 @@ namespace Rml {
 class Context;
 class DataModel;
 class Decorator;
-class ElementInstancer;
 class EventDispatcher;
 class EventListener;
 class ElementBackgroundBorder;
@@ -579,10 +578,6 @@ public:
 	DataModel* GetDataModel() const;
 	//@}
 
-	/// Sets the instancer to use for releasing this element.
-	/// @param[in] instancer Instancer to set on this element.
-	void SetInstancer(ElementInstancer* instancer);
-
 	/// Called when an emitted event propagates to this element, for event types with default actions.
 	/// Note: See 'EventSpecification' for the events that call this function and during which phase.
 	/// @param[in] event The event to process.
@@ -653,8 +648,6 @@ protected:
 
 	void OnStyleSheetChangeRecursive();
 
-	void Release() override;
-
 private:
 	void OnChildNodeAdd(Node* child, bool dom_node) override;
 	void OnChildNodeRemove(Node* child, bool dom_node) override;
@@ -734,9 +727,6 @@ private:
 	// The optional, unique ID of this object.
 	String id;
 
-	// Instancer that created us, used for destruction.
-	ElementInstancer* instancer;
-
 	// Currently focused child object
 	Element* focus;
 

+ 9 - 11
Include/RmlUi/Core/Factory.h

@@ -42,7 +42,7 @@ class Decorator;
 class DecoratorInstancer;
 class Element;
 class ElementDocument;
-class ElementInstancer;
+class NodeInstancer;
 class Event;
 class EventInstancer;
 class EventListener;
@@ -87,18 +87,16 @@ public:
 	/// @param[in] name Name of the instancer; elements with this as their tag will use this instancer.
 	/// @param[in] instancer The instancer to call when the tag is encountered.
 	/// @lifetime The instancer must be kept alive until after the call to Rml::Shutdown.
-	static void RegisterElementInstancer(const String& name, ElementInstancer* instancer);
+	static void RegisterNodeInstancer(const String& name, NodeInstancer* instancer);
 	/// Returns the element instancer for the specified tag.
 	/// @param[in] tag Name of the tag to get the instancer for.
 	/// @return The requested element instancer, or nullptr if no such instancer is registered.
-	static ElementInstancer* GetElementInstancer(const String& tag);
-	/// Instances a single element.
-	/// @param[in] parent The parent of the new element, or nullptr for a root tag.
-	/// @param[in] instancer The name of the instancer to create the element with.
-	/// @param[in] tag The tag of the element to be instanced.
-	/// @param[in] attributes The attributes to instance the element with.
-	/// @return The instanced element, or nullptr if the instancing failed.
-	static ElementPtr InstanceElement(Element* parent, const String& instancer, const String& tag, const XMLAttributes& attributes);
+	static NodeInstancer* GetNodeInstancer(const String& tag);
+	/// Instances a single node.
+	/// @param[in] instancer The name of the instancer to create the node with.
+	/// @param[in] tag The tag of the node to be instanced.
+	/// @return The instanced node, or nullptr if the instancing failed.
+	static NodePtr InstanceNode(const String& instancer, const String& tag);
 
 	/// Instances a text element containing a string.
 	/// More than one element may be instanced if the string contains RML or RML is introduced during translation.
@@ -116,7 +114,7 @@ public:
 	/// @param[in] stream The stream to instance from.
 	/// @param[in] document_base_tag The tag used to wrap the document, eg. 'rml'.
 	/// @return The instanced document, or nullptr if an error occurred.
-	static ElementPtr InstanceDocumentStream(Context* context, Stream* stream, const String& document_base_tag);
+	static NodePtr InstanceDocumentStream(Context* context, Stream* stream, const String& document_base_tag);
 
 	/// Registers a non-owning pointer to an instancer that will be used to instance decorators.
 	/// @param[in] name The name of the decorator the instancer will be called for.

+ 10 - 0
Include/RmlUi/Core/Node.h

@@ -38,6 +38,7 @@ namespace Rml {
 class Context;
 class Element;
 class ElementDocument;
+class NodeInstancer;
 using OwnedNodeList = Vector<NodePtr>;
 
 /**
@@ -277,9 +278,16 @@ public:
 		return NodeChildReverseRange<T>(this, include_non_dom_elements);
 	}
 
+	/// Sets the instancer to use for releasing this node.
+	/// @param[in] instancer Instancer to set on this node.
+	void SetInstancer(NodeInstancer* instancer);
+
 protected:
 	Node();
 
+	NodeInstancer* GetInstancer() const;
+	void Release() override;
+
 	void SetOwnerDocument(ElementDocument* document);
 
 	virtual void OnChildNodeAdd(Node* child, bool dom_node);
@@ -289,6 +297,8 @@ protected:
 private:
 	void SetParent(Node* new_parent);
 
+	NodeInstancer* instancer = nullptr;
+
 	Node* parent = nullptr;
 	ElementDocument* owner_document = nullptr;
 

+ 30 - 35
Include/RmlUi/Core/ElementInstancer.h → Include/RmlUi/Core/NodeInstancer.h

@@ -26,8 +26,8 @@
  *
  */
 
-#ifndef RMLUI_CORE_ELEMENTINSTANCER_H
-#define RMLUI_CORE_ELEMENTINSTANCER_H
+#ifndef RMLUI_CORE_NODEINSTANCER_H
+#define RMLUI_CORE_NODEINSTANCER_H
 
 #include "Element.h"
 #include "Header.h"
@@ -37,36 +37,31 @@
 
 namespace Rml {
 
-class Element;
+class Node;
 
 /**
-    An element instancer provides a method for allocating
-    and deallocating elements.
+    A node instancer provides a method for allocating and deallocating elements.
 
-    It is important at the same instancer that allocated
-    the element releases it. This ensures there are no
-    issues with memory from different DLLs getting mixed up.
+    It is important at the same instancer that allocated the node releases it. This ensures that the node is constructed
+    and freed from the same allocator.
 
-    The returned element is a unique pointer. When this is
-    destroyed, it will call	ReleaseElement on the instancer
-    in which it was instanced.
+    The returned element is a unique pointer. When this is destroyed, it will call ReleaseElement on the instancer in
+    which it was instanced.
 
     @author Lloyd Weehuizen
  */
 
-class RMLUICORE_API ElementInstancer : public NonCopyMoveable {
+class RMLUICORE_API NodeInstancer : public NonCopyMoveable {
 public:
-	virtual ~ElementInstancer();
+	virtual ~NodeInstancer();
 
 	/// Instances an element given the tag name and attributes.
-	/// @param[in] parent The element the new element is destined to be parented to.
 	/// @param[in] tag The tag of the element to instance.
-	/// @param[in] attributes Dictionary of attributes.
 	/// @return A unique pointer to the instanced element.
-	virtual ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) = 0;
+	virtual NodePtr InstanceNode(const String& tag) = 0;
 	/// Releases an element instanced by this instancer.
-	/// @param[in] element The element to release.
-	virtual void ReleaseElement(Element* element) = 0;
+	/// @param[in] node The element to release.
+	virtual void ReleaseNode(Node* node) = 0;
 };
 
 /**
@@ -75,11 +70,11 @@ public:
     pool for allocations.
  */
 
-class RMLUICORE_API ElementInstancerElement : public ElementInstancer {
+class RMLUICORE_API NodeInstancerElement : public NodeInstancer {
 public:
-	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
-	void ReleaseElement(Element* element) override;
-	~ElementInstancerElement();
+	NodePtr InstanceNode(const String& tag) override;
+	void ReleaseNode(Node* node) override;
+	~NodeInstancerElement();
 };
 
 /**
@@ -88,10 +83,10 @@ public:
     pool for allocations.
  */
 
-class RMLUICORE_API ElementInstancerText : public ElementInstancer {
+class RMLUICORE_API NodeInstancerText : public NodeInstancer {
 public:
-	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
-	void ReleaseElement(Element* element) override;
+	NodePtr InstanceNode(const String& tag) override;
+	void ReleaseNode(Node* node) override;
 };
 
 /**
@@ -100,26 +95,26 @@ public:
  */
 
 template <typename T>
-class ElementInstancerGeneric : public ElementInstancer {
+class NodeInstancerGeneric : public NodeInstancer {
 public:
-	virtual ~ElementInstancerGeneric() {}
+	virtual ~NodeInstancerGeneric() {}
 
-	ElementPtr InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/) override
+	NodePtr InstanceNode(const String& tag) override
 	{
-		RMLUI_ZoneScopedN("ElementGenericInstance");
-		return ElementPtr(new T(tag));
+		RMLUI_ZoneScopedN("InstanceNodeGeneric");
+		return NodePtr(new T(tag));
 	}
 
-	void ReleaseElement(Element* element) override
+	void ReleaseNode(Node* node) override
 	{
-		RMLUI_ZoneScopedN("ElementGenericRelease");
-		delete element;
+		RMLUI_ZoneScopedN("ReleaseNodeGeneric");
+		delete node;
 	}
 };
 
 namespace Detail {
-	void InitializeElementInstancerPools();
-	void ShutdownElementInstancerPools();
+	void InitializeNodeInstancerPools();
+	void ShutdownNodeInstancerPools();
 } // namespace Detail
 
 } // namespace Rml

+ 1 - 1
Include/RmlUi/Core/Types.h

@@ -77,8 +77,8 @@ using Matrix4f = RMLUI_MATRIX4_TYPE;
 
 // Common classes
 class Node;
+class NodeInstancer;
 class Element;
-class ElementInstancer;
 class ElementAnimation;
 class RenderManager;
 class Texture;

+ 1 - 1
Samples/basic/drag/src/Inventory.cpp

@@ -63,6 +63,6 @@ void Inventory::AddItem(const Rml::String& name)
 		return;
 
 	// Create the new 'icon' element.
-	Rml::Element* icon = content->AppendChild(Rml::Factory::InstanceElement(content, "icon", "icon", Rml::XMLAttributes()));
+	Rml::Element* icon = content->AppendChild(Rml::As<Rml::ElementPtr>(Rml::Factory::InstanceNode("icon", "icon")));
 	icon->SetInnerRML(name);
 }

+ 2 - 2
Samples/invaders/src/main.cpp

@@ -87,8 +87,8 @@ int main(int /*argc*/, char** /*argv*/)
 	Shell::LoadFonts();
 
 	// Register Invader's custom element and decorator instancers.
-	Rml::ElementInstancerGeneric<ElementGame> element_instancer_game;
-	Rml::Factory::RegisterElementInstancer("game", &element_instancer_game);
+	Rml::NodeInstancerGeneric<ElementGame> element_instancer_game;
+	Rml::Factory::RegisterNodeInstancer("game", &element_instancer_game);
 
 	DecoratorInstancerStarfield decorator_instancer_starfield;
 	DecoratorInstancerDefender decorator_instancer_defender;

+ 4 - 4
Samples/lua_invaders/src/ElementGameInstancer.cpp

@@ -3,12 +3,12 @@
 
 ElementGameInstancer::~ElementGameInstancer() {}
 
-Rml::ElementPtr ElementGameInstancer::InstanceElement(Rml::Element* /*parent*/, const Rml::String& tag, const Rml::XMLAttributes& /*attributes*/)
+Rml::NodePtr ElementGameInstancer::InstanceNode(const Rml::String& tag)
 {
-	return Rml::ElementPtr(new ElementGame(tag));
+	return Rml::NodePtr(new ElementGame(tag));
 }
 
-void ElementGameInstancer::ReleaseElement(Rml::Element* element)
+void ElementGameInstancer::ReleaseNode(Rml::Node* node)
 {
-	delete element;
+	delete node;
 }

+ 5 - 6
Samples/lua_invaders/src/ElementGameInstancer.h

@@ -1,20 +1,19 @@
 #ifndef RMLUI_LUAINVADERS_ELEMENTGAMEINSTANCER_H
 #define RMLUI_LUAINVADERS_ELEMENTGAMEINSTANCER_H
 
-#include <RmlUi/Core/ElementInstancer.h>
+#include <RmlUi/Core/NodeInstancer.h>
 
-class ElementGameInstancer : public Rml::ElementInstancer {
+class ElementGameInstancer : public Rml::NodeInstancer {
 public:
 	virtual ~ElementGameInstancer();
 
 	/// Instances an element given the tag name and attributes
 	/// @param tag Name of the element to instance
-	/// @param attributes vector of name value pairs
-	Rml::ElementPtr InstanceElement(Rml::Element* parent, const Rml::String& tag, const Rml::XMLAttributes& attributes) override;
+	Rml::NodePtr InstanceNode(const Rml::String& tag) override;
 
 	/// Releases the given element
-	/// @param element to release
-	void ReleaseElement(Rml::Element* element) override;
+	/// @param node to release
+	void ReleaseNode(Rml::Node* node) override;
 };
 
 #endif

+ 1 - 1
Samples/lua_invaders/src/LuaInterface.cpp

@@ -27,7 +27,7 @@ static ElementGameInstancer game_instancer;
 void LuaInterface::Initialise(lua_State* L)
 {
 	InitGame(L);
-	Rml::Factory::RegisterElementInstancer("game", &game_instancer);
+	Rml::Factory::RegisterNodeInstancer("game", &game_instancer);
 }
 
 void LuaInterface::InitGame(lua_State* L)

+ 1 - 2
Samples/tutorial/drag/src/Inventory.cpp

@@ -29,7 +29,6 @@ void Inventory::AddItem(const Rml::String& name)
 		return;
 
 	// Create the new 'icon' element.
-	Rml::ElementPtr icon = Rml::Factory::InstanceElement(content, "icon", "icon", Rml::XMLAttributes());
+	Rml::Element* icon = content->AppendChild(Rml::As<Rml::ElementPtr>(Rml::Factory::InstanceNode("icon", "icon")));
 	icon->SetInnerRML(name);
-	content->AppendChild(std::move(icon));
 }

+ 2 - 2
Source/Core/CMakeLists.txt

@@ -72,7 +72,6 @@ add_library(rmlui_core
 	ElementEffects.h
 	ElementHandle.cpp
 	ElementHandle.h
-	ElementInstancer.cpp
 	ElementMeta.cpp
 	ElementMeta.h
 	ElementScroll.cpp
@@ -125,6 +124,7 @@ add_library(rmlui_core
 	Memory.h
 	MeshUtilities.cpp
 	Node.cpp
+	NodeInstancer.cpp
 	ObserverPtr.cpp
 	Plugin.cpp
 	PluginRegistry.cpp
@@ -263,7 +263,6 @@ target_sources(rmlui_core PRIVATE
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Element.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Element.inl"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/ElementDocument.h"
-	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/ElementInstancer.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/ElementScroll.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Elements/ElementForm.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Elements/ElementFormControl.h"
@@ -297,6 +296,7 @@ target_sources(rmlui_core PRIVATE
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Mesh.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/MeshUtilities.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Node.h"
+	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/NodeInstancer.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/NumericValue.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/ObserverPtr.h"
 	"${PROJECT_SOURCE_DIR}/Include/RmlUi/Core/Platform.h"

+ 12 - 12
Source/Core/Context.cpp

@@ -88,12 +88,12 @@ Context::Context(const String& name, RenderManager* render_manager, TextInputHan
 {
 	instancer = nullptr;
 
-	root = Factory::InstanceElement(nullptr, "*", "#root", XMLAttributes());
+	root = As<ElementPtr>(Factory::InstanceNode("*", "#root"));
 	root->SetId(name);
 	root->SetOffset(Vector2f(0, 0), nullptr);
 	root->SetProperty(PropertyId::ZIndex, Property(0, Unit::NUMBER));
 
-	cursor_proxy = Factory::InstanceElement(nullptr, documents_base_tag, documents_base_tag, XMLAttributes());
+	cursor_proxy = As<ElementPtr>(Factory::InstanceNode(documents_base_tag, documents_base_tag));
 	ElementDocument* cursor_proxy_document = rmlui_dynamic_cast<ElementDocument*>(cursor_proxy.get());
 	RMLUI_ASSERT(cursor_proxy_document);
 	cursor_proxy_document->context = this;
@@ -266,24 +266,24 @@ bool Context::Render()
 
 ElementDocument* Context::CreateDocument(const String& instancer_name)
 {
-	ElementPtr element = Factory::InstanceElement(nullptr, instancer_name, documents_base_tag, XMLAttributes());
-	if (!element)
+	NodePtr node = Factory::InstanceNode(instancer_name, documents_base_tag);
+	if (!node)
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document on instancer_name '%s', instancer returned nullptr.", instancer_name.c_str());
 		return nullptr;
 	}
 
-	ElementDocument* document = rmlui_dynamic_cast<ElementDocument*>(element.get());
+	ElementDocument* document = rmlui_dynamic_cast<ElementDocument*>(node.get());
 	if (!document)
 	{
 		Log::Message(Log::LT_ERROR,
 			"Failed to instance document on instancer_name '%s', Found type '%s', was expecting derivative of ElementDocument.",
-			instancer_name.c_str(), rmlui_type_name(*element));
+			instancer_name.c_str(), rmlui_type_name(*node));
 		return nullptr;
 	}
 
 	document->context = this;
-	root->AppendChild(std::move(element));
+	root->AppendChild(std::move(node));
 
 	PluginRegistry::NotifyDocumentLoad(document);
 
@@ -307,16 +307,16 @@ ElementDocument* Context::LoadDocument(Stream* stream)
 	DebugVerifyLocaleSetting();
 	PluginRegistry::NotifyDocumentOpen(this, stream->GetSourceURL().GetURL());
 
-	ElementPtr element = Factory::InstanceDocumentStream(this, stream, GetDocumentsBaseTag());
-	if (!element)
+	NodePtr node = Factory::InstanceDocumentStream(this, stream, GetDocumentsBaseTag());
+	if (!node)
 		return nullptr;
 
-	ElementDocument* document = rmlui_static_cast<ElementDocument*>(element.get());
+	ElementDocument* document = rmlui_static_cast<ElementDocument*>(node.get());
 
-	root->AppendChild(std::move(element));
+	root->AppendChild(std::move(node));
 
 	// The 'load' event is fired before updating the document, because the user might
-	// need to initalize things before running an update. The drawback is that computed
+	// need to initialize things before running an update. The drawback is that computed
 	// values and layouting are not performed yet, resulting in default values when
 	// querying such information in the event handler.
 	PluginRegistry::NotifyDocumentLoad(document);

+ 3 - 3
Source/Core/Core.cpp

@@ -29,10 +29,10 @@
 #include "../../Include/RmlUi/Core/Core.h"
 #include "../../Include/RmlUi/Core/Context.h"
 #include "../../Include/RmlUi/Core/Element.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/Factory.h"
 #include "../../Include/RmlUi/Core/FileInterface.h"
 #include "../../Include/RmlUi/Core/FontEngineInterface.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/Plugin.h"
 #include "../../Include/RmlUi/Core/RenderInterface.h"
 #include "../../Include/RmlUi/Core/RenderManager.h"
@@ -92,7 +92,7 @@ static bool initialised = false;
 
 static void InitializeMemoryPools()
 {
-	Detail::InitializeElementInstancerPools();
+	Detail::InitializeNodeInstancerPools();
 	ElementMetaPool::Initialize();
 	LayoutPools::Initialize();
 }
@@ -100,7 +100,7 @@ static void ReleaseMemoryPools()
 {
 	LayoutPools::Shutdown();
 	ElementMetaPool::Shutdown();
-	Detail::ShutdownElementInstancerPools();
+	Detail::ShutdownNodeInstancerPools();
 }
 
 #ifndef RMLUI_VERSION

+ 7 - 4
Source/Core/DataViewDefault.cpp

@@ -536,7 +536,10 @@ bool DataViewFor::Update(DataModel& model)
 	{
 		if (i >= num_elements)
 		{
-			ElementPtr new_element_ptr = Factory::InstanceElement(nullptr, element->GetTagName(), element->GetTagName(), attributes);
+			NodePtr new_node_ptr = Factory::InstanceNode(element->GetTagName(), element->GetTagName());
+			Element* new_element = rmlui_dynamic_cast<Element*>(new_node_ptr.get());
+			RMLUI_ASSERT(new_element);
+			new_element->SetAttributes(attributes);
 
 			DataAddress iterator_address;
 			iterator_address.reserve(container_address.size() + 1);
@@ -545,10 +548,10 @@ bool DataViewFor::Update(DataModel& model)
 
 			DataAddress iterator_index_address = {{"literal"}, {"int"}, {i}};
 
-			model.InsertAlias(new_element_ptr.get(), iterator_name, std::move(iterator_address));
-			model.InsertAlias(new_element_ptr.get(), iterator_index_name, std::move(iterator_index_address));
+			model.InsertAlias(new_element, iterator_name, std::move(iterator_address));
+			model.InsertAlias(new_element, iterator_index_name, std::move(iterator_index_address));
 
-			Element* new_element = element->GetParentNode()->InsertBefore(std::move(new_element_ptr), element);
+			element->GetParentNode()->InsertBefore(std::move(new_node_ptr), element);
 			elements.push_back(new_element);
 
 			const String* rml_contents = RMLContents();

+ 7 - 30
Source/Core/Element.cpp

@@ -31,11 +31,11 @@
 #include "../../Include/RmlUi/Core/Core.h"
 #include "../../Include/RmlUi/Core/Dictionary.h"
 #include "../../Include/RmlUi/Core/ElementDocument.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/ElementScroll.h"
 #include "../../Include/RmlUi/Core/ElementUtilities.h"
 #include "../../Include/RmlUi/Core/Factory.h"
 #include "../../Include/RmlUi/Core/Math.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/Profiling.h"
 #include "../../Include/RmlUi/Core/PropertiesIteratorView.h"
 #include "../../Include/RmlUi/Core/PropertyDefinition.h"
@@ -98,9 +98,8 @@ Element::Element(const String& tag) :
 	dirty_child_definitions(false), dirty_animation(false), dirty_transition(false), dirty_transform(false), dirty_perspective(false), tag(tag),
 	relative_offset_base(0, 0), relative_offset_position(0, 0), absolute_offset(0, 0), scroll_offset(0, 0)
 {
-	RMLUI_ASSERT(tag == StringUtilities::ToLower(tag));
+	RMLUI_ASSERT(tag == StringUtilities::ToLower(String(tag)));
 	focus = nullptr;
-	instancer = nullptr;
 	offset_parent = nullptr;
 
 	clip_area = BoxArea::Padding;
@@ -233,19 +232,15 @@ void Element::Render()
 
 ElementPtr Element::Clone() const
 {
-	ElementPtr clone;
+	NodeInstancer* instancer = GetInstancer();
+	RMLUI_ASSERT(instancer);
 
-	if (instancer)
-	{
-		clone = instancer->InstanceElement(nullptr, GetTagName(), attributes);
-		if (clone)
-			clone->SetInstancer(instancer);
-	}
-	else
-		clone = Factory::InstanceElement(nullptr, GetTagName(), GetTagName(), attributes);
+	ElementPtr clone = As<ElementPtr>(instancer->InstanceNode(tag));
 
 	if (clone)
 	{
+		clone->SetInstancer(instancer);
+
 		// Copy over the attributes. The 'style' and 'class' attributes are skipped because inline styles and class names are copied manually below.
 		// This is necessary in case any properties or classes have been set manually, in which case the 'style' and 'class' attributes are out of
 		// sync with the used style and active classes.
@@ -1493,16 +1488,6 @@ DataModel* Element::GetDataModel() const
 	return data_model;
 }
 
-void Element::SetInstancer(ElementInstancer* _instancer)
-{
-	// Only record the first instancer being set as some instancers call other instancers to do their dirty work, in
-	// which case we don't want to update the lowest level instancer.
-	if (!instancer)
-	{
-		instancer = _instancer;
-	}
-}
-
 void Element::ForceLocalStackingContext()
 {
 	local_stacking_context_forced = true;
@@ -1953,14 +1938,6 @@ void Element::SetDataModel(DataModel* new_data_model)
 		child->SetDataModel(new_data_model);
 }
 
-void Element::Release()
-{
-	if (instancer)
-		instancer->ReleaseElement(this);
-	else
-		Log::Message(Log::LT_WARNING, "Leak detected: element %s not instanced via RmlUi Factory. Unable to release.", GetAddress().c_str());
-}
-
 void Element::OnChildNodeAdd(Node* child_node, bool dom_node)
 {
 	Element* child = AsIf<Element*>(child_node);

+ 2 - 2
Source/Core/ElementDocument.cpp

@@ -338,7 +338,7 @@ void ElementDocument::ReloadStyleSheet()
 
 	Factory::ClearStyleSheetCache();
 	Factory::ClearTemplateCache();
-	ElementPtr temp_doc = Factory::InstanceDocumentStream(nullptr, stream.get(), context->GetDocumentsBaseTag());
+	NodePtr temp_doc = Factory::InstanceDocumentStream(nullptr, stream.get(), context->GetDocumentsBaseTag());
 	if (!temp_doc)
 	{
 		Log::Message(Log::LT_WARNING, "Failed to reload style sheet, could not instance document: %s", source_url.c_str());
@@ -469,7 +469,7 @@ void ElementDocument::Close()
 
 ElementPtr ElementDocument::CreateElement(const String& name)
 {
-	return Factory::InstanceElement(nullptr, name, name, XMLAttributes());
+	return As<ElementPtr>(Factory::InstanceNode(name, name));
 }
 
 ElementPtr ElementDocument::CreateTextNode(const String& text)

+ 2 - 3
Source/Core/ElementScroll.cpp

@@ -217,8 +217,7 @@ bool ElementScroll::CreateScrollbar(Orientation orientation)
 	if (scrollbars[orientation].element && scrollbars[orientation].widget)
 		return true;
 
-	ElementPtr scrollbar_element =
-		Factory::InstanceElement(element, "*", orientation == VERTICAL ? "scrollbarvertical" : "scrollbarhorizontal", XMLAttributes());
+	ElementPtr scrollbar_element = As<ElementPtr>(Factory::InstanceNode("*", orientation == VERTICAL ? "scrollbarvertical" : "scrollbarhorizontal"));
 	scrollbars[orientation].element = scrollbar_element.get();
 	scrollbars[orientation].element->SetProperty(PropertyId::Clip, Property(1, Unit::NUMBER));
 	scrollbars[orientation].element->SetProperty(PropertyId::Drag, Property(Style::Drag::Block));
@@ -238,7 +237,7 @@ bool ElementScroll::CreateCorner()
 	if (corner != nullptr)
 		return true;
 
-	ElementPtr corner_element = Factory::InstanceElement(element, "*", "scrollbarcorner", XMLAttributes());
+	ElementPtr corner_element = As<ElementPtr>(Factory::InstanceNode("*", "scrollbarcorner"));
 	corner = corner_element.get();
 	corner->SetProperty(PropertyId::Clip, Property(1, Unit::NUMBER));
 	corner->SetProperty(PropertyId::Drag, Property(Style::Drag::Block));

+ 1 - 1
Source/Core/Elements/ElementProgress.cpp

@@ -49,7 +49,7 @@ ElementProgress::ElementProgress(const String& tag) :
 	geometry_dirty = false;
 
 	// Add the fill element as a non-DOM element.
-	ElementPtr fill_element = Factory::InstanceElement(this, "*", "fill", XMLAttributes());
+	ElementPtr fill_element = As<ElementPtr>(Factory::InstanceNode("*", "fill"));
 	RMLUI_ASSERT(fill_element);
 	fill = AppendChild(std::move(fill_element), false);
 }

+ 12 - 12
Source/Core/Elements/ElementTabSet.cpp

@@ -41,14 +41,14 @@ ElementTabSet::~ElementTabSet() {}
 
 void ElementTabSet::SetTab(int tab_index, const String& rml)
 {
-	ElementPtr element = Factory::InstanceElement(nullptr, "*", "tab", XMLAttributes());
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode("*", "tab"));
 	Factory::InstanceElementText(element.get(), rml);
 	SetTab(tab_index, std::move(element));
 }
 
 void ElementTabSet::SetPanel(int tab_index, const String& rml)
 {
-	ElementPtr element = Factory::InstanceElement(nullptr, "*", "panel", XMLAttributes());
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode("*", "panel"));
 	Factory::InstanceElementText(element.get(), rml);
 	SetPanel(tab_index, std::move(element));
 }
@@ -113,16 +113,16 @@ void ElementTabSet::SetActiveTab(int tab_index)
 		Element* old_window = windows->GetChild(active_tab);
 		Element* new_window = windows->GetChild(tab_index);
 
-        if (old_window)
-        {
-            old_window->SetPseudoClass("selected", false);
+		if (old_window)
+		{
+			old_window->SetPseudoClass("selected", false);
 			old_window->SetProperty(PropertyId::Display, Property(Style::Display::None));
-        }
+		}
 		if (new_window)
-        {
-            new_window->SetPseudoClass("selected", true);
+		{
+			new_window->SetPseudoClass("selected", true);
 			new_window->RemoveProperty(PropertyId::Display);
-        }
+		}
 
 		active_tab = tab_index;
 
@@ -188,10 +188,10 @@ void ElementTabSet::OnChildAdd(Element* child)
 
 		// Make the new element visible if its the active tab
 		if (child->GetParentNode()->GetChild(active_tab) == child)
-        {
+		{
 			child->SetPseudoClass("selected", true);
 			child->RemoveProperty(PropertyId::Display);
-        }
+		}
 	}
 }
 
@@ -205,7 +205,7 @@ Element* ElementTabSet::GetChildByTag(const String& tag)
 	}
 
 	// If it doesn't exist, create it
-	ElementPtr element = Factory::InstanceElement(this, "*", tag, XMLAttributes());
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode("*", tag));
 	Element* result = AppendChild(std::move(element));
 	return result;
 }

+ 1 - 2
Source/Core/Elements/InputTypeButton.cpp

@@ -49,8 +49,7 @@ bool InputTypeButton::OnAttributeChange(const ElementAttributes& changed_attribu
 	{
 		auto value = element->GetAttribute<String>("value", "");
 		if (!value.empty() && !value_element)
-			value_element =
-				rmlui_static_cast<ElementText*>(element->AppendChild(Factory::InstanceElement(element, "#text", "", XMLAttributes()), true));
+			value_element = rmlui_static_cast<ElementText*>(element->AppendChild(Factory::InstanceNode("#text", "#text"), true));
 
 		if (value_element)
 			value_element->SetText(value);

+ 1 - 2
Source/Core/Elements/InputTypeSubmit.cpp

@@ -48,8 +48,7 @@ bool InputTypeSubmit::OnAttributeChange(const ElementAttributes& changed_attribu
 	{
 		auto value = element->GetAttribute<String>("value", "");
 		if (!value.empty() && !value_element)
-			value_element =
-				rmlui_static_cast<ElementText*>(element->AppendChild(Factory::InstanceElement(element, "#text", "", XMLAttributes()), true));
+			value_element = rmlui_static_cast<ElementText*>(element->AppendChild(Factory::InstanceNode("#text", "#text"), true));
 
 		if (value_element)
 			value_element->SetText(value);

+ 4 - 4
Source/Core/Elements/WidgetDropDown.cpp

@@ -47,9 +47,9 @@ WidgetDropDown::WidgetDropDown(ElementFormControl* element)
 	parent_element = element;
 
 	// Create the button and selection elements.
-	button_element = parent_element->AppendChild(Factory::InstanceElement(parent_element, "*", "selectarrow", XMLAttributes()), false);
-	value_element = parent_element->AppendChild(Factory::InstanceElement(parent_element, "*", "selectvalue", XMLAttributes()), false);
-	selection_element = parent_element->AppendChild(Factory::InstanceElement(parent_element, "*", "selectbox", XMLAttributes()), false);
+	button_element = parent_element->AppendChild(As<ElementPtr>(Factory::InstanceNode("*", "selectarrow")), false);
+	value_element = parent_element->AppendChild(As<ElementPtr>(Factory::InstanceNode("*", "selectvalue")), false);
+	selection_element = parent_element->AppendChild(As<ElementPtr>(Factory::InstanceNode("*", "selectbox")), false);
 
 	value_element->SetProperty(PropertyId::OverflowX, Property(Style::Overflow::Hidden));
 	value_element->SetProperty(PropertyId::OverflowY, Property(Style::Overflow::Hidden));
@@ -380,7 +380,7 @@ int WidgetDropDown::GetSelection() const
 
 int WidgetDropDown::AddOption(const String& rml, const String& option_value, int before, bool select, bool selectable)
 {
-	ElementPtr element = Factory::InstanceElement(selection_element, "*", "option", XMLAttributes());
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode("*", "option"));
 	element->SetInnerRML(rml);
 
 	element->SetAttribute("value", option_value);

+ 14 - 11
Source/Core/Elements/WidgetSlider.cpp

@@ -95,11 +95,11 @@ WidgetSlider::~WidgetSlider()
 bool WidgetSlider::Initialise()
 {
 	// Create all of our child elements as standard elements, and abort if we can't create them.
-	ElementPtr track_element = Factory::InstanceElement(parent, "*", "slidertrack", XMLAttributes());
-	ElementPtr bar_element = Factory::InstanceElement(parent, "*", "sliderbar", XMLAttributes());
-	ElementPtr progress_element = Factory::InstanceElement(parent, "*", "sliderprogress", XMLAttributes());
-	ElementPtr arrow0_element = Factory::InstanceElement(parent, "*", "sliderarrowdec", XMLAttributes());
-	ElementPtr arrow1_element = Factory::InstanceElement(parent, "*", "sliderarrowinc", XMLAttributes());
+	ElementPtr track_element = As<ElementPtr>(Factory::InstanceNode("*", "slidertrack"));
+	ElementPtr bar_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderbar"));
+	ElementPtr progress_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderprogress"));
+	ElementPtr arrow0_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderarrowdec"));
+	ElementPtr arrow1_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderarrowinc"));
 
 	if (!track_element || !bar_element || !progress_element || !arrow0_element || !arrow1_element)
 		return false;
@@ -373,11 +373,11 @@ void WidgetSlider::FormatProgress()
 	progress_box.SetContent(progress_box_content);
 	progress->SetBox(progress_box);
 
-        Vector2f offset = track->GetRelativeOffset();
-        offset.x += progress->GetBox().GetEdge(BoxArea::Margin, BoxEdge::Left);
-        offset.y += progress->GetBox().GetEdge(BoxArea::Margin, BoxEdge::Top);
+	Vector2f offset = track->GetRelativeOffset();
+	offset.x += progress->GetBox().GetEdge(BoxArea::Margin, BoxEdge::Left);
+	offset.y += progress->GetBox().GetEdge(BoxArea::Margin, BoxEdge::Top);
 
-        progress->SetOffset(offset, parent);
+	progress->SetOffset(offset, parent);
 
 	ResizeProgress();
 }
@@ -600,9 +600,12 @@ void WidgetSlider::ResizeProgress()
 	Box progress_box = progress->GetBox();
 	Vector2f new_size = progress_box.GetSize();
 
-	if (orientation == VERTICAL) {
+	if (orientation == VERTICAL)
+	{
 		new_size.y = bar->GetOffsetTop();
-	} else {
+	}
+	else
+	{
 		new_size.x = bar->GetOffsetLeft();
 	}
 

+ 3 - 3
Source/Core/Elements/WidgetTextInput.cpp

@@ -203,9 +203,9 @@ WidgetTextInput::WidgetTextInput(ElementFormControl* _parent)
 	parent->AddEventListener(EventId::Dblclick, this, true);
 	parent->AddEventListener(EventId::Drag, this, true);
 
-	ElementPtr unique_text = Factory::InstanceElement(parent, "#text", "#text", XMLAttributes());
+	NodePtr unique_text = Factory::InstanceNode("#text", "#text");
 	text_element = rmlui_dynamic_cast<ElementText*>(unique_text.get());
-	ElementPtr unique_selected_text = Factory::InstanceElement(parent, "#text", "#text", XMLAttributes());
+	NodePtr unique_selected_text = Factory::InstanceNode("#text", "#text");
 	selected_text_element = rmlui_dynamic_cast<ElementText*>(unique_selected_text.get());
 	if (text_element)
 	{
@@ -217,7 +217,7 @@ WidgetTextInput::WidgetTextInput(ElementFormControl* _parent)
 	}
 
 	// Create the dummy selection element.
-	ElementPtr unique_selection = Factory::InstanceElement(parent, "#selection", "selection", XMLAttributes());
+	NodePtr unique_selection = Factory::InstanceNode("#selection", "selection");
 	if (ElementTextSelection* text_selection_element = rmlui_dynamic_cast<ElementTextSelection*>(unique_selection.get()))
 	{
 		selection_element = text_selection_element;

+ 8 - 11
Source/Core/Elements/XMLNodeHandlerSelect.cpp

@@ -48,27 +48,24 @@ Element* XMLNodeHandlerSelect::ElementStart(XMLParser* parser, const String& nam
 		parser->PushHandler("select");
 
 		// Attempt to instance the tabset
-		ElementPtr element = Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
-		ElementFormControlSelect* select_element = rmlui_dynamic_cast<ElementFormControlSelect*>(element.get());
-		if (!select_element)
-		{
-			Log::Message(Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
-			return nullptr;
-		}
+		NodePtr node = Factory::InstanceNode(name, name);
+		ElementFormControlSelect* select_element = rmlui_static_cast<ElementFormControlSelect*>(node.get());
+		select_element->SetAttributes(attributes);
 
 		// Add the Select element into the document
-		Element* result = parser->GetParseFrame()->element->AppendChild(std::move(element));
+		parser->GetParseFrame()->element->AppendChild(std::move(node));
 
-		return result;
+		return select_element;
 	}
 	else if (name == "option")
 	{
 		// Call default element handler for all children.
 		parser->PushDefaultHandler();
 
-		ElementPtr option_element = Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
-		Element* result = nullptr;
+		ElementPtr option_element = As<ElementPtr>(Factory::InstanceNode(name, name));
+		option_element->SetAttributes(attributes);
 
+		Element* result = nullptr;
 		ElementFormControlSelect* select_element = rmlui_dynamic_cast<ElementFormControlSelect*>(parser->GetParseFrame()->element);
 		if (select_element)
 		{

+ 13 - 16
Source/Core/Elements/XMLNodeHandlerTabSet.cpp

@@ -47,28 +47,28 @@ Element* XMLNodeHandlerTabSet::ElementStart(XMLParser* parser, const String& nam
 		// Call this node handler for all children
 		parser->PushHandler("tabset");
 
-		// Attempt to instance the tabset
-		ElementPtr element = Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
-		ElementTabSet* tabset = rmlui_dynamic_cast<ElementTabSet*>(element.get());
+		NodePtr Node = Factory::InstanceNode(name, name);
+		ElementTabSet* tabset = rmlui_dynamic_cast<ElementTabSet*>(Node.get());
 		if (!tabset)
 		{
 			Log::Message(Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
 			return nullptr;
 		}
+		tabset->SetAttributes(attributes);
 
-		// Add the TabSet into the document
-		Element* result = parser->GetParseFrame()->element->AppendChild(std::move(element));
+		parser->GetParseFrame()->element->AppendChild(std::move(Node));
 
-		return result;
+		return tabset;
 	}
 	else if (name == "tab")
 	{
 		// Call default element handler for all children.
 		parser->PushDefaultHandler();
 
-		ElementPtr tab_element = Factory::InstanceElement(parser->GetParseFrame()->element, "*", "tab", attributes);
-		Element* result = nullptr;
+		ElementPtr tab_element = As<ElementPtr>(Factory::InstanceNode("*", "tab"));
+		tab_element->SetAttributes(attributes);
 
+		Element* result = nullptr;
 		ElementTabSet* tabset = rmlui_dynamic_cast<ElementTabSet*>(parser->GetParseFrame()->element);
 		if (tabset)
 		{
@@ -83,9 +83,10 @@ Element* XMLNodeHandlerTabSet::ElementStart(XMLParser* parser, const String& nam
 		// Call default element handler for all children.
 		parser->PushDefaultHandler();
 
-		ElementPtr panel_element = Factory::InstanceElement(parser->GetParseFrame()->element, "*", "panel", attributes);
-		Element* result = nullptr;
+		ElementPtr panel_element = As<ElementPtr>(Factory::InstanceNode("*", "panel"));
+		panel_element->SetAttributes(attributes);
 
+		Element* result = nullptr;
 		ElementTabSet* tabset = rmlui_dynamic_cast<ElementTabSet*>(parser->GetParseFrame()->element);
 		if (tabset)
 		{
@@ -103,12 +104,8 @@ Element* XMLNodeHandlerTabSet::ElementStart(XMLParser* parser, const String& nam
 
 		Element* parent = parser->GetParseFrame()->element;
 
-		ElementPtr element = Factory::InstanceElement(parent, name, name, attributes);
-		if (!element)
-		{
-			Log::Message(Log::LT_ERROR, "Instancer failed to create element for tag %s.", name.c_str());
-			return nullptr;
-		}
+		ElementPtr element = As<ElementPtr>(Factory::InstanceNode(name, name));
+		element->SetAttributes(attributes);
 
 		parent->AppendChild(std::move(element));
 

+ 2 - 4
Source/Core/Elements/XMLNodeHandlerTextArea.cpp

@@ -44,12 +44,10 @@ Element* XMLNodeHandlerTextArea::ElementStart(XMLParser* parser, const String& n
 	ElementFormControlTextArea* text_area = rmlui_dynamic_cast<ElementFormControlTextArea*>(parser->GetParseFrame()->element);
 	if (!text_area)
 	{
-		ElementPtr new_element = Factory::InstanceElement(parser->GetParseFrame()->element, name, name, attributes);
-		if (!new_element)
-			return nullptr;
+		ElementPtr new_element = As<ElementPtr>(Factory::InstanceNode(name, name));
+		new_element->SetAttributes(attributes);
 
 		Element* result = parser->GetParseFrame()->element->AppendChild(std::move(new_element));
-
 		return result;
 	}
 

+ 55 - 57
Source/Core/Factory.cpp

@@ -31,7 +31,6 @@
 #include "../../Include/RmlUi/Core/ContextInstancer.h"
 #include "../../Include/RmlUi/Core/Core.h"
 #include "../../Include/RmlUi/Core/ElementDocument.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/ElementText.h"
 #include "../../Include/RmlUi/Core/ElementUtilities.h"
 #include "../../Include/RmlUi/Core/Elements/ElementForm.h"
@@ -41,6 +40,7 @@
 #include "../../Include/RmlUi/Core/Elements/ElementProgress.h"
 #include "../../Include/RmlUi/Core/Elements/ElementTabSet.h"
 #include "../../Include/RmlUi/Core/EventListenerInstancer.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/StreamMemory.h"
 #include "../../Include/RmlUi/Core/StyleSheet.h"
 #include "../../Include/RmlUi/Core/StyleSheetContainer.h"
@@ -91,23 +91,23 @@ struct DefaultInstancers {
 	UniquePtr<EventInstancer> event_default;
 
 	// Basic elements
-	ElementInstancerElement element_default;
-	ElementInstancerText element_text;
-	ElementInstancerGeneric<ElementImage> element_img;
-	ElementInstancerGeneric<ElementHandle> element_handle;
-	ElementInstancerGeneric<ElementDocument> element_body;
+	NodeInstancerElement element_default;
+	NodeInstancerText element_text;
+	NodeInstancerGeneric<ElementImage> element_img;
+	NodeInstancerGeneric<ElementHandle> element_handle;
+	NodeInstancerGeneric<ElementDocument> element_body;
 
 	// Control elements
-	ElementInstancerGeneric<ElementForm> form;
-	ElementInstancerGeneric<ElementFormControlInput> input;
-	ElementInstancerGeneric<ElementFormControlSelect> select;
-	ElementInstancerGeneric<ElementLabel> element_label;
+	NodeInstancerGeneric<ElementForm> form;
+	NodeInstancerGeneric<ElementFormControlInput> input;
+	NodeInstancerGeneric<ElementFormControlSelect> select;
+	NodeInstancerGeneric<ElementLabel> element_label;
 
-	ElementInstancerGeneric<ElementFormControlTextArea> textarea;
-	ElementInstancerGeneric<ElementTextSelection> selection;
-	ElementInstancerGeneric<ElementTabSet> tabset;
+	NodeInstancerGeneric<ElementFormControlTextArea> textarea;
+	NodeInstancerGeneric<ElementTextSelection> selection;
+	NodeInstancerGeneric<ElementTabSet> tabset;
 
-	ElementInstancerGeneric<ElementProgress> progress;
+	NodeInstancerGeneric<ElementProgress> progress;
 
 	// Decorators
 	DecoratorTextInstancer decorator_text;
@@ -157,7 +157,7 @@ struct DefaultInstancers {
 
 struct FactoryData {
 	DefaultInstancers default_instancers;
-	UnorderedMap<String, ElementInstancer*> element_instancers;
+	UnorderedMap<String, NodeInstancer*> element_instancers;
 	UnorderedMap<String, DecoratorInstancer*> decorator_instancers;
 	UnorderedMap<String, FilterInstancer*> filter_instancers;
 	UnorderedMap<String, FontEffectInstancer*> font_effect_instancers;
@@ -201,24 +201,24 @@ void Factory::Initialise()
 		event_listener_instancer = nullptr;
 
 	// Basic element instancers
-	RegisterElementInstancer("*", &default_instancers.element_default);
-	RegisterElementInstancer("img", &default_instancers.element_img);
-	RegisterElementInstancer("#text", &default_instancers.element_text);
-	RegisterElementInstancer("handle", &default_instancers.element_handle);
-	RegisterElementInstancer("body", &default_instancers.element_body);
+	RegisterNodeInstancer("*", &default_instancers.element_default);
+	RegisterNodeInstancer("img", &default_instancers.element_img);
+	RegisterNodeInstancer("#text", &default_instancers.element_text);
+	RegisterNodeInstancer("handle", &default_instancers.element_handle);
+	RegisterNodeInstancer("body", &default_instancers.element_body);
 
 	// Control element instancers
-	RegisterElementInstancer("form", &default_instancers.form);
-	RegisterElementInstancer("input", &default_instancers.input);
-	RegisterElementInstancer("select", &default_instancers.select);
-	RegisterElementInstancer("label", &default_instancers.element_label);
+	RegisterNodeInstancer("form", &default_instancers.form);
+	RegisterNodeInstancer("input", &default_instancers.input);
+	RegisterNodeInstancer("select", &default_instancers.select);
+	RegisterNodeInstancer("label", &default_instancers.element_label);
 
-	RegisterElementInstancer("textarea", &default_instancers.textarea);
-	RegisterElementInstancer("#selection", &default_instancers.selection);
-	RegisterElementInstancer("tabset", &default_instancers.tabset);
+	RegisterNodeInstancer("textarea", &default_instancers.textarea);
+	RegisterNodeInstancer("#selection", &default_instancers.selection);
+	RegisterNodeInstancer("tabset", &default_instancers.tabset);
 
-	RegisterElementInstancer("progress", &default_instancers.progress);
-	RegisterElementInstancer("progressbar", &default_instancers.progress);
+	RegisterNodeInstancer("progress", &default_instancers.progress);
+	RegisterNodeInstancer("progressbar", &default_instancers.progress);
 
 	// Decorator instancers
 	RegisterDecoratorInstancer("text", &default_instancers.decorator_text);
@@ -320,12 +320,12 @@ ContextPtr Factory::InstanceContext(const String& name, RenderManager* render_ma
 	return new_context;
 }
 
-void Factory::RegisterElementInstancer(const String& name, ElementInstancer* instancer)
+void Factory::RegisterNodeInstancer(const String& name, NodeInstancer* instancer)
 {
 	factory_data->element_instancers[StringUtilities::ToLower(name)] = instancer;
 }
 
-ElementInstancer* Factory::GetElementInstancer(const String& tag)
+NodeInstancer* Factory::GetNodeInstancer(const String& tag)
 {
 	auto instancer_iterator = factory_data->element_instancers.find(tag);
 	if (instancer_iterator == factory_data->element_instancers.end())
@@ -338,17 +338,18 @@ ElementInstancer* Factory::GetElementInstancer(const String& tag)
 	return instancer_iterator->second;
 }
 
-ElementPtr Factory::InstanceElement(Element* parent, const String& instancer_name, const String& tag, const XMLAttributes& attributes)
+NodePtr Factory::InstanceNode(const String& instancer_name, const String& tag)
 {
-	if (ElementInstancer* instancer = GetElementInstancer(instancer_name))
+	if (NodeInstancer* instancer = GetNodeInstancer(instancer_name))
 	{
-		if (ElementPtr element = instancer->InstanceElement(parent, tag, attributes))
+		if (NodePtr node = instancer->InstanceNode(tag))
 		{
-			element->SetInstancer(instancer);
-			element->SetAttributes(attributes);
+			node->SetInstancer(instancer);
 
-			PluginRegistry::NotifyElementCreate(element.get());
-			return element;
+			if (Element* element = rmlui_dynamic_cast<Element*>(node.get()))
+				PluginRegistry::NotifyElementCreate(element);
+
+			return node;
 		}
 	}
 
@@ -412,36 +413,33 @@ bool Factory::InstanceElementText(Element* parent, const String& in_text)
 	{
 		RMLUI_ZoneScopedNC("InstanceText", 0x8FBC8F);
 
-		// Attempt to instance the element.
-		XMLAttributes attributes;
-
-		// If we have curly brackets in the text, we tag the element so that the appropriate data view (DataViewText) is constructed.
-		if (has_data_expression)
-			attributes.emplace("data-text", Variant());
-
-		ElementPtr element = Factory::InstanceElement(parent, "#text", "#text", attributes);
-		if (!element)
+		NodePtr node = Factory::InstanceNode("#text", "#text");
+		if (!node)
 		{
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s', instancer returned nullptr.", text.c_str());
 			return false;
 		}
 
 		// Assign the element its text value.
-		ElementText* text_element = rmlui_dynamic_cast<ElementText*>(element.get());
+		ElementText* text_element = rmlui_dynamic_cast<ElementText*>(node.get());
 		if (!text_element)
 		{
 			Log::Message(Log::LT_ERROR, "Failed to instance text element '%s'. Found type '%s', was expecting a derivative of ElementText.",
-				text.c_str(), rmlui_type_name(*element));
+				text.c_str(), rmlui_type_name(*node));
 			return false;
 		}
 
+		// If we have curly brackets in the text, tag the element so that the appropriate data view (DataViewText) is constructed.
+		if (has_data_expression)
+			text_element->SetAttributes(ElementAttributes{{"data-text", Variant()}});
+
 		// Unescape any escaped entities or unicode symbols
 		text = StringUtilities::DecodeRml(text);
 
 		text_element->SetText(text);
 
 		// Add to active node.
-		parent->AppendChild(std::move(element));
+		parent->AppendChild(std::move(node));
 	}
 
 	return true;
@@ -454,31 +452,31 @@ bool Factory::InstanceElementStream(Element* parent, Stream* stream)
 	return true;
 }
 
-ElementPtr Factory::InstanceDocumentStream(Context* context, Stream* stream, const String& document_base_tag)
+NodePtr Factory::InstanceDocumentStream(Context* context, Stream* stream, const String& document_base_tag)
 {
 	RMLUI_ZoneScoped;
 
-	ElementPtr element = Factory::InstanceElement(nullptr, document_base_tag, document_base_tag, XMLAttributes());
-	if (!element)
+	NodePtr node = Factory::InstanceNode(document_base_tag, document_base_tag);
+	if (!node)
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document, instancer returned nullptr.");
 		return nullptr;
 	}
 
-	ElementDocument* document = rmlui_dynamic_cast<ElementDocument*>(element.get());
+	ElementDocument* document = rmlui_dynamic_cast<ElementDocument*>(node.get());
 	if (!document)
 	{
 		Log::Message(Log::LT_ERROR, "Failed to instance document element. Found type '%s', was expecting derivative of ElementDocument.",
-			rmlui_type_name(*element));
+			rmlui_type_name(*node));
 		return nullptr;
 	}
 
 	document->context = context;
 
-	XMLParser parser(element.get());
+	XMLParser parser(document);
 	parser.Parse(stream);
 
-	return element;
+	return node;
 }
 
 void Factory::RegisterDecoratorInstancer(const String& name, DecoratorInstancer* instancer)

+ 20 - 0
Source/Core/Node.cpp

@@ -30,6 +30,7 @@
 #include "../../Include/RmlUi/Core/Context.h"
 #include "../../Include/RmlUi/Core/Element.h"
 #include "../../Include/RmlUi/Core/ElementDocument.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include <iterator>
 
 namespace Rml {
@@ -238,6 +239,25 @@ RenderManager* Node::GetRenderManager() const
 	return nullptr;
 }
 
+void Node::SetInstancer(NodeInstancer* new_instancer)
+{
+	RMLUI_ASSERT(!instancer && new_instancer);
+	instancer = new_instancer;
+}
+
+NodeInstancer* Node::GetInstancer() const
+{
+	return instancer;
+}
+
+void Node::Release()
+{
+	if (instancer)
+		instancer->ReleaseNode(this);
+	else
+		Log::Message(Log::LT_WARNING, "Leak detected: Node (%s) not instanced via RmlUi Factory. Unable to release.", rmlui_type_name(*this));
+}
+
 void Node::SetOwnerDocument(ElementDocument* document)
 {
 	if (owner_document && !document)

+ 23 - 23
Source/Core/ElementInstancer.cpp → Source/Core/NodeInstancer.cpp

@@ -26,7 +26,7 @@
  *
  */
 
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/ElementText.h"
 #include "ControlledLifetimeResource.h"
 #include "Pool.h"
@@ -34,63 +34,63 @@
 
 namespace Rml {
 
-ElementInstancer::~ElementInstancer() {}
+NodeInstancer::~NodeInstancer() {}
 
-struct ElementInstancerPools {
+struct NodeInstancerPools {
 	Pool<Element> pool_element{200, true};
 	Pool<ElementText> pool_text_default{200, true};
 
 	bool IsEmpty() const { return pool_element.GetNumAllocatedObjects() == 0 && pool_text_default.GetNumAllocatedObjects() == 0; }
 };
-static ControlledLifetimeResource<ElementInstancerPools> element_instancer_pools;
+static ControlledLifetimeResource<NodeInstancerPools> node_instancer_pools;
 
-ElementPtr ElementInstancerElement::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
+NodePtr NodeInstancerElement::InstanceNode(const String& tag)
 {
-	Element* ptr = element_instancer_pools->pool_element.AllocateAndConstruct(tag);
-	return ElementPtr(ptr);
+	Element* ptr = node_instancer_pools->pool_element.AllocateAndConstruct(tag);
+	return NodePtr(ptr);
 }
 
-void ElementInstancerElement::ReleaseElement(Element* element)
+void NodeInstancerElement::ReleaseNode(Node* node)
 {
-	element_instancer_pools->pool_element.DestroyAndDeallocate(element);
+	node_instancer_pools->pool_element.DestroyAndDeallocate(rmlui_static_cast<Element*>(node));
 }
 
-ElementInstancerElement::~ElementInstancerElement()
+NodeInstancerElement::~NodeInstancerElement()
 {
-	int num_elements = element_instancer_pools->pool_element.GetNumAllocatedObjects();
+	int num_elements = node_instancer_pools->pool_element.GetNumAllocatedObjects();
 	if (num_elements > 0)
 	{
 		Log::Message(Log::LT_WARNING, "--- Found %d leaked element(s) ---", num_elements);
 
-		for (auto it = element_instancer_pools->pool_element.Begin(); it; ++it)
+		for (auto it = node_instancer_pools->pool_element.Begin(); it; ++it)
 			Log::Message(Log::LT_WARNING, "    %s", it->GetAddress().c_str());
 
 		Log::Message(Log::LT_WARNING, "------");
 	}
 }
 
-ElementPtr ElementInstancerText::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
+NodePtr NodeInstancerText::InstanceNode(const String& tag)
 {
-	ElementText* ptr = element_instancer_pools->pool_text_default.AllocateAndConstruct(tag);
-	return ElementPtr(static_cast<Element*>(ptr));
+	ElementText* ptr = node_instancer_pools->pool_text_default.AllocateAndConstruct(tag);
+	return NodePtr(ptr);
 }
 
-void ElementInstancerText::ReleaseElement(Element* element)
+void NodeInstancerText::ReleaseNode(Node* node)
 {
-	element_instancer_pools->pool_text_default.DestroyAndDeallocate(rmlui_static_cast<ElementText*>(element));
+	node_instancer_pools->pool_text_default.DestroyAndDeallocate(rmlui_static_cast<ElementText*>(node));
 }
 
-void Detail::InitializeElementInstancerPools()
+void Detail::InitializeNodeInstancerPools()
 {
-	element_instancer_pools.InitializeIfEmpty();
+	node_instancer_pools.InitializeIfEmpty();
 }
 
-void Detail::ShutdownElementInstancerPools()
+void Detail::ShutdownNodeInstancerPools()
 {
-	if (element_instancer_pools->IsEmpty())
-		element_instancer_pools.Shutdown();
+	if (node_instancer_pools->IsEmpty())
+		node_instancer_pools.Shutdown();
 	else
-		element_instancer_pools.Leak();
+		node_instancer_pools.Leak();
 }
 
 } // namespace Rml

+ 4 - 4
Source/Core/WidgetScroll.cpp

@@ -109,10 +109,10 @@ bool WidgetScroll::Initialise(Orientation _orientation)
 	orientation = _orientation;
 
 	// Create all of our child elements as standard elements, and abort if we can't create them.
-	ElementPtr track_element = Factory::InstanceElement(parent, "*", "slidertrack", XMLAttributes());
-	ElementPtr bar_element = Factory::InstanceElement(parent, "*", "sliderbar", XMLAttributes());
-	ElementPtr arrow0_element = Factory::InstanceElement(parent, "*", "sliderarrowdec", XMLAttributes());
-	ElementPtr arrow1_element = Factory::InstanceElement(parent, "*", "sliderarrowinc", XMLAttributes());
+	ElementPtr track_element = As<ElementPtr>(Factory::InstanceNode("*", "slidertrack"));
+	ElementPtr bar_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderbar"));
+	ElementPtr arrow0_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderarrowdec"));
+	ElementPtr arrow1_element = As<ElementPtr>(Factory::InstanceNode("*", "sliderarrowinc"));
 
 	if (!track_element || !bar_element || !arrow0_element || !arrow1_element)
 	{

+ 2 - 6
Source/Core/XMLNodeHandlerDefault.cpp

@@ -49,12 +49,8 @@ Element* XMLNodeHandlerDefault::ElementStart(XMLParser* parser, const String& na
 	Element* parent = parser->GetParseFrame()->element;
 
 	// Attempt to instance the element with the instancer
-	ElementPtr element = Factory::InstanceElement(parent, name, name, attributes);
-	if (!element)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to create element for tag %s, instancer returned nullptr.", name.c_str());
-		return nullptr;
-	}
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode(name, name));
+	element->SetAttributes(attributes);
 
 	// Move and append the element to the parent
 	Element* result = parent->AppendChild(std::move(element));

+ 9 - 9
Source/Debugger/DebuggerPlugin.cpp

@@ -29,9 +29,9 @@
 #include "DebuggerPlugin.h"
 #include "../../Include/RmlUi/Core/Context.h"
 #include "../../Include/RmlUi/Core/Core.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/ElementUtilities.h"
 #include "../../Include/RmlUi/Core/Factory.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/Types.h"
 #include "DebuggerSystemInterface.h"
 #include "ElementContextHook.h"
@@ -88,8 +88,8 @@ bool DebuggerPlugin::Initialise(Context* context)
 		return false;
 	}
 
-	hook_element_instancer = MakeUnique<ElementInstancerGeneric<ElementContextHook>>();
-	Factory::RegisterElementInstancer("debug-hook", hook_element_instancer.get());
+	hook_element_instancer = MakeUnique<NodeInstancerGeneric<ElementContextHook>>();
+	Factory::RegisterNodeInstancer("debug-hook", hook_element_instancer.get());
 
 	return true;
 }
@@ -274,8 +274,8 @@ bool DebuggerPlugin::LoadFont()
 
 bool DebuggerPlugin::LoadMenuElement()
 {
-	debug_document_instancer = MakeUnique<ElementInstancerGeneric<ElementDebugDocument>>();
-	Factory::RegisterElementInstancer("debug-document", debug_document_instancer.get());
+	debug_document_instancer = MakeUnique<NodeInstancerGeneric<ElementDebugDocument>>();
+	Factory::RegisterNodeInstancer("debug-document", debug_document_instancer.get());
 	menu_element = host_context->CreateDocument("debug-document");
 	if (!menu_element)
 		return false;
@@ -312,8 +312,8 @@ bool DebuggerPlugin::LoadMenuElement()
 
 bool DebuggerPlugin::LoadInfoElement()
 {
-	info_element_instancer = MakeUnique<ElementInstancerGeneric<ElementInfo>>();
-	Factory::RegisterElementInstancer("debug-info", info_element_instancer.get());
+	info_element_instancer = MakeUnique<NodeInstancerGeneric<ElementInfo>>();
+	Factory::RegisterNodeInstancer("debug-info", info_element_instancer.get());
 	info_element = rmlui_dynamic_cast<ElementInfo*>(host_context->CreateDocument("debug-info"));
 	if (!info_element)
 		return false;
@@ -333,8 +333,8 @@ bool DebuggerPlugin::LoadInfoElement()
 
 bool DebuggerPlugin::LoadLogElement()
 {
-	log_element_instancer = MakeUnique<ElementInstancerGeneric<ElementLog>>();
-	Factory::RegisterElementInstancer("debug-log", log_element_instancer.get());
+	log_element_instancer = MakeUnique<NodeInstancerGeneric<ElementLog>>();
+	Factory::RegisterNodeInstancer("debug-log", log_element_instancer.get());
 	log_element = rmlui_dynamic_cast<ElementLog*>(host_context->CreateDocument("debug-log"));
 	if (!log_element)
 		return false;

+ 1 - 1
Source/Debugger/DebuggerPlugin.h

@@ -119,7 +119,7 @@ private:
 	Rml::SystemInterface* application_interface;
 	UniquePtr<DebuggerSystemInterface> log_interface;
 
-	UniquePtr<ElementInstancer> hook_element_instancer, debug_document_instancer, info_element_instancer, log_element_instancer;
+	UniquePtr<NodeInstancer> hook_element_instancer, debug_document_instancer, info_element_instancer, log_element_instancer;
 
 	bool render_outlines;
 

+ 4 - 4
Source/Lottie/LottiePlugin.cpp

@@ -27,9 +27,9 @@
  */
 
 #include "../../Include/RmlUi/Core/Core.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/Factory.h"
 #include "../../Include/RmlUi/Core/Log.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/Plugin.h"
 #include "../../Include/RmlUi/Lottie/ElementLottie.h"
 
@@ -40,9 +40,9 @@ namespace Lottie {
 	public:
 		void OnInitialise() override
 		{
-			instancer = MakeUnique<ElementInstancerGeneric<ElementLottie>>();
+			instancer = MakeUnique<NodeInstancerGeneric<ElementLottie>>();
 
-			Factory::RegisterElementInstancer("lottie", instancer.get());
+			Factory::RegisterNodeInstancer("lottie", instancer.get());
 
 			Log::Message(Log::LT_INFO, "Lottie plugin initialised.");
 		}
@@ -52,7 +52,7 @@ namespace Lottie {
 		int GetEventClasses() override { return Plugin::EVT_BASIC; }
 
 	private:
-		UniquePtr<ElementInstancerGeneric<ElementLottie>> instancer;
+		UniquePtr<NodeInstancerGeneric<ElementLottie>> instancer;
 	};
 
 	void Initialise()

+ 6 - 6
Source/Lua/CMakeLists.txt

@@ -15,8 +15,8 @@ add_library(rmlui_lua
 	ElementAttributesProxy.h
 	ElementChildNodesProxy.cpp
 	ElementChildNodesProxy.h
-	ElementInstancer.cpp
-	ElementInstancer.h
+	NodeInstancer.cpp
+	NodeInstancer.h
 	ElementStyleProxy.cpp
 	ElementStyleProxy.h
 	ElementText.cpp
@@ -35,10 +35,10 @@ add_library(rmlui_lua
 	LuaDataModel.h
 	LuaDocument.cpp
 	LuaDocument.h
-	LuaDocumentElementInstancer.cpp
-	LuaDocumentElementInstancer.h
-	LuaElementInstancer.cpp
-	LuaElementInstancer.h
+	LuaDocumentNodeInstancer.cpp
+	LuaDocumentNodeInstancer.h
+	LuaNodeInstancer.cpp
+	LuaNodeInstancer.h
 	LuaEventListener.cpp
 	LuaEventListener.h
 	LuaEventListenerInstancer.cpp

+ 1 - 1
Source/Lua/Interpreter.cpp

@@ -26,7 +26,7 @@
  *
  */
 
-#include "LuaDocumentElementInstancer.h"
+#include "LuaDocumentNodeInstancer.h"
 #include "LuaEventListenerInstancer.h"
 #include "LuaPlugin.h"
 #include <RmlUi/Core/Core.h>

+ 6 - 11
Source/Lua/LuaDocumentElementInstancer.cpp → Source/Lua/LuaDocumentNodeInstancer.cpp

@@ -26,25 +26,20 @@
  *
  */
 
-#include "LuaDocumentElementInstancer.h"
+#include "LuaDocumentNodeInstancer.h"
 #include "LuaDocument.h"
 
 namespace Rml {
 namespace Lua {
 
-/// Instances an element given the tag name and attributes.
-/// @param[in] parent The element the new element is destined to be parented to.
-/// @param[in] tag The tag of the element to instance.
-/// @param[in] attributes Dictionary of attributes.
-ElementPtr LuaDocumentElementInstancer::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
+NodePtr LuaDocumentNodeInstancer::InstanceNode(const String& tag)
 {
-	return ElementPtr(new LuaDocument(tag));
+	return NodePtr(new LuaDocument(tag));
 }
-/// Releases an element instanced by this instancer.
-/// @param[in] element The element to release.
-void LuaDocumentElementInstancer::ReleaseElement(Element* element)
+
+void LuaDocumentNodeInstancer::ReleaseNode(Node* node)
 {
-	delete element;
+	delete node;
 }
 
 } // namespace Lua

+ 7 - 12
Source/Lua/LuaDocumentElementInstancer.h → Source/Lua/LuaDocumentNodeInstancer.h

@@ -26,23 +26,18 @@
  *
  */
 
-#ifndef RMLUI_LUA_LUADOCUMENTELEMENTINSTANCER_H
-#define RMLUI_LUA_LUADOCUMENTELEMENTINSTANCER_H
+#ifndef RMLUI_LUA_LUADOCUMENTNODEINSTANCER_H
+#define RMLUI_LUA_LUADOCUMENTNODEINSTANCER_H
 
-#include <RmlUi/Core/ElementInstancer.h>
+#include <RmlUi/Core/NodeInstancer.h>
 
 namespace Rml {
 namespace Lua {
 
-class LuaDocumentElementInstancer : public ::Rml::ElementInstancer {
-	/// Instances an element given the tag name and attributes.
-	/// @param[in] parent The element the new element is destined to be parented to.
-	/// @param[in] tag The tag of the element to instance.
-	/// @param[in] attributes Dictionary of attributes.
-	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
-	/// Releases an element instanced by this instancer.
-	/// @param[in] element The element to release.
-	void ReleaseElement(Element* element) override;
+class LuaDocumentNodeInstancer : public ::Rml::NodeInstancer {
+public:
+	NodePtr InstanceNode(const String& tag) override;
+	void ReleaseNode(Node* node) override;
 };
 
 } // namespace Lua

+ 21 - 21
Source/Lua/LuaElementInstancer.cpp → Source/Lua/LuaNodeInstancer.cpp

@@ -26,7 +26,7 @@
  *
  */
 
-#include "LuaElementInstancer.h"
+#include "LuaNodeInstancer.h"
 #include <RmlUi/Core/Log.h>
 #include <RmlUi/Core/Platform.h>
 #include <RmlUi/Lua/Interpreter.h>
@@ -34,56 +34,56 @@
 
 namespace Rml {
 namespace Lua {
-// This will be called from ElementInstancernew
-LuaElementInstancer::LuaElementInstancer(lua_State* L) : ElementInstancer(), ref_InstanceElement(LUA_NOREF)
+// This will be called from NodeInstancernew
+LuaNodeInstancer::LuaNodeInstancer(lua_State* L) : ref_InstanceNode(LUA_NOREF)
 {
 	if (lua_type(L, 1) != LUA_TFUNCTION && !lua_isnoneornil(L, 1))
 	{
-		Log::Message(Log::LT_ERROR, "The argument to ElementInstancer.new has to be a function or nil. You passed in a %s.", luaL_typename(L, 1));
+		Log::Message(Log::LT_ERROR, "The argument to NodeInstancer.new has to be a function or nil. You passed in a %s.", luaL_typename(L, 1));
 		return;
 	}
-	PushFunctionsTable(L); // top of the table is now ELEMENTINSTANCERFUNCTIONS table
+	PushFunctionsTable(L); // top of the table is now NODEINSTANCERFUNCTIONS table
 	lua_pushvalue(L, 1);   // copy of the function
-	ref_InstanceElement = luaL_ref(L, -2);
-	lua_pop(L, 1);         // pop the ELEMENTINSTANCERFUNCTIONS table
+	ref_InstanceNode = luaL_ref(L, -2);
+	lua_pop(L, 1);         // pop the NODEINSTANCERFUNCTIONS table
 }
 
-ElementPtr LuaElementInstancer::InstanceElement(Element* /*parent*/, const String& tag, const XMLAttributes& /*attributes*/)
+NodePtr LuaNodeInstancer::InstanceNode(const String& tag)
 {
 	lua_State* L = Interpreter::GetLuaState();
 	int top = lua_gettop(L);
-	ElementPtr ret = nullptr;
-	if (ref_InstanceElement != LUA_REFNIL && ref_InstanceElement != LUA_NOREF)
+	NodePtr ret = nullptr;
+	if (ref_InstanceNode != LUA_REFNIL && ref_InstanceNode != LUA_NOREF)
 	{
 		PushFunctionsTable(L);
-		lua_rawgeti(L, -1, ref_InstanceElement); // push the function
-		lua_pushstring(L, tag.c_str());          // push the tag
-		Interpreter::ExecuteCall(1, 1);          // we pass in a string, and we want to get an Element back
-		ret = std::move(*LuaType<ElementPtr>::check(L, -1));
+		lua_rawgeti(L, -1, ref_InstanceNode); // push the function
+		lua_pushstring(L, tag.c_str());       // push the tag
+		Interpreter::ExecuteCall(1, 1);       // we pass in a string, and we want to get a Node back
+		ret = std::move(*LuaType<NodePtr>::check(L, -1));
 	}
 	else
 	{
-		Log::Message(Log::LT_WARNING, "Attempt to call the function for ElementInstancer.InstanceElement, the function does not exist.");
+		Log::Message(Log::LT_WARNING, "Attempt to call the function for NodeInstancer.InstanceNode, the function does not exist.");
 	}
 	lua_settop(L, top);
 	return ret;
 }
 
-void LuaElementInstancer::ReleaseElement(Element* element)
+void LuaNodeInstancer::ReleaseNode(Node* node)
 {
-	delete element;
+	delete node;
 }
 
-void LuaElementInstancer::PushFunctionsTable(lua_State* L)
+void LuaNodeInstancer::PushFunctionsTable(lua_State* L)
 {
 	// make sure there is an area to save the function
-	lua_getglobal(L, "ELEMENTINSTANCERFUNCTIONS");
+	lua_getglobal(L, "NODEINSTANCERFUNCTIONS");
 	if (lua_isnoneornil(L, -1))
 	{
 		lua_newtable(L);
-		lua_setglobal(L, "ELEMENTINSTANCERFUNCTIONS");
+		lua_setglobal(L, "NODEINSTANCERFUNCTIONS");
 		lua_pop(L, 1); // pop the unsucessful getglobal
-		lua_getglobal(L, "ELEMENTINSTANCERFUNCTIONS");
+		lua_getglobal(L, "NODEINSTANCERFUNCTIONS");
 	}
 }
 

+ 13 - 17
Source/Lua/LuaElementInstancer.h → Source/Lua/LuaNodeInstancer.h

@@ -26,31 +26,27 @@
  *
  */
 
-#ifndef RMLUI_LUA_LUAELEMENTINSTANCER_H
-#define RMLUI_LUA_LUAELEMENTINSTANCER_H
+#ifndef RMLUI_LUA_LUANODEINSTANCER_H
+#define RMLUI_LUA_LUANODEINSTANCER_H
 
 #include <RmlUi/Core/Element.h>
-#include <RmlUi/Core/ElementInstancer.h>
+#include <RmlUi/Core/NodeInstancer.h>
 #include <RmlUi/Lua/IncludeLua.h>
 
 namespace Rml {
 namespace Lua {
 
-class LuaElementInstancer : public ::Rml::ElementInstancer {
+class LuaNodeInstancer : public ::Rml::NodeInstancer {
 public:
-	LuaElementInstancer(lua_State* L);
-	/// Instances an element given the tag name and attributes.
-	/// @param[in] parent The element the new element is destined to be parented to.
-	/// @param[in] tag The tag of the element to instance.
-	/// @param[in] attributes Dictionary of attributes.
-	ElementPtr InstanceElement(Element* parent, const String& tag, const XMLAttributes& attributes) override;
-	/// Releases an element instanced by this instancer.
-	/// @param[in] element The element to release.
-	void ReleaseElement(Element* element) override;
-
-	int ref_InstanceElement;
-
-	// Pushes on to the top of the stack the table named EVENTINSTNACERFUNCTIONS
+	LuaNodeInstancer(lua_State* L);
+
+	NodePtr InstanceNode(const String& tag) override;
+
+	void ReleaseNode(Node* node) override;
+
+	int ref_InstanceNode;
+
+	// Pushes on to the top of the stack the table named NODEINSTANCERFUNCTIONS
 	void PushFunctionsTable(lua_State* L);
 };
 

+ 5 - 5
Source/Lua/LuaPlugin.cpp

@@ -27,7 +27,7 @@
  */
 
 #include "LuaPlugin.h"
-#include "LuaDocumentElementInstancer.h"
+#include "LuaDocumentNodeInstancer.h"
 #include "LuaEventListenerInstancer.h"
 #include "RmlUi.h"
 #include <RmlUi/Core/Factory.h>
@@ -45,13 +45,13 @@
 #include "Element.h"
 #include "ElementAttributesProxy.h"
 #include "ElementChildNodesProxy.h"
-#include "ElementInstancer.h"
 #include "ElementStyleProxy.h"
 #include "ElementText.h"
 #include "Event.h"
 #include "EventParametersProxy.h"
 #include "GlobalLuaFunctions.h"
 #include "Log.h"
+#include "NodeInstancer.h"
 #include "RmlUiContextsProxy.h"
 #include "Vector2f.h"
 #include "Vector2i.h"
@@ -100,9 +100,9 @@ void LuaPlugin::OnInitialise()
 	}
 	RegisterTypes();
 
-	lua_document_element_instancer = new LuaDocumentElementInstancer();
+	lua_document_element_instancer = new LuaDocumentNodeInstancer();
 	lua_event_listener_instancer = new LuaEventListenerInstancer();
-	Factory::RegisterElementInstancer("body", lua_document_element_instancer);
+	Factory::RegisterNodeInstancer("body", lua_document_element_instancer);
 	Factory::RegisterEventListenerInstancer(lua_event_listener_instancer);
 }
 
@@ -140,7 +140,7 @@ static void RegisterTypes()
 	LuaType<Event>::Register(L);
 	LuaType<Context>::Register(L);
 	LuaType<LuaRmlUi>::Register(L);
-	LuaType<ElementInstancer>::Register(L);
+	LuaType<NodeInstancer>::Register(L);
 	// Proxy tables
 	LuaType<ContextDocumentsProxy>::Register(L);
 	LuaType<EventParametersProxy>::Register(L);

+ 2 - 2
Source/Lua/LuaPlugin.h

@@ -37,7 +37,7 @@ typedef struct lua_State lua_State;
 namespace Rml {
 namespace Lua {
 
-class LuaDocumentElementInstancer;
+class LuaDocumentNodeInstancer;
 class LuaEventListenerInstancer;
 
 /**
@@ -59,7 +59,7 @@ private:
 
 	void OnShutdown() override;
 
-	LuaDocumentElementInstancer* lua_document_element_instancer = nullptr;
+	LuaDocumentNodeInstancer* lua_document_element_instancer = nullptr;
 	LuaEventListenerInstancer* lua_event_listener_instancer = nullptr;
 	bool owns_lua_state = false;
 };

+ 17 - 17
Source/Lua/ElementInstancer.cpp → Source/Lua/NodeInstancer.cpp

@@ -26,56 +26,56 @@
  *
  */
 
-#include "ElementInstancer.h"
+#include "NodeInstancer.h"
 
 namespace Rml {
 namespace Lua {
 template <>
-void ExtraInit<ElementInstancer>(lua_State* L, int metatable_index)
+void ExtraInit<NodeInstancer>(lua_State* L, int metatable_index)
 {
-	lua_pushcfunction(L, ElementInstancernew);
+	lua_pushcfunction(L, NodeInstancernew);
 	lua_setfield(L, metatable_index - 1, "new");
 }
 
 // method
-int ElementInstancernew(lua_State* L)
+int NodeInstancernew(lua_State* L)
 {
-	LuaElementInstancer* lei = new LuaElementInstancer(L);
-	LuaType<ElementInstancer>::push(L, lei, true);
+	LuaNodeInstancer* lei = new LuaNodeInstancer(L);
+	LuaType<NodeInstancer>::push(L, lei, true);
 	return 1;
 }
 
 // setter
-int ElementInstancerSetAttrInstanceElement(lua_State* L)
+int NodeInstancerSetAttrInstanceNode(lua_State* L)
 {
-	LuaElementInstancer* lei = (LuaElementInstancer*)LuaType<ElementInstancer>::check(L, 1);
+	LuaNodeInstancer* lei = (LuaNodeInstancer*)LuaType<NodeInstancer>::check(L, 1);
 	RMLUI_CHECK_OBJ(lei);
 
 	if (lua_type(L, 2) != LUA_TFUNCTION)
 	{
-		Log::Message(Log::LT_ERROR, "The argument to ElementInstancer.InstanceElement must be a function. You passed in a %s.", luaL_typename(L, 2));
+		Log::Message(Log::LT_ERROR, "The argument to NodeInstancer.InstanceNode must be a function. You passed in a %s.", luaL_typename(L, 2));
 		return 0;
 	}
-	lei->PushFunctionsTable(L); // top of the stack is now ELEMENTINSTANCERFUNCTIONS table
+	lei->PushFunctionsTable(L); // top of the stack is now NODEINSTANCERFUNCTIONS table
 	lua_pushvalue(L, 2);        // copy of the function
-	lei->ref_InstanceElement = luaL_ref(L, -2);
-	lua_pop(L, 1);              // pop the ELEMENTINSTANCERFUNCTIONS table
+	lei->ref_InstanceNode = luaL_ref(L, -2);
+	lua_pop(L, 1);              // pop the NODEINSTANCERFUNCTIONS table
 	return 0;
 }
 
-RegType<ElementInstancer> ElementInstancerMethods[] = {
+RegType<NodeInstancer> NodeInstancerMethods[] = {
 	{nullptr, nullptr},
 };
 
-luaL_Reg ElementInstancerGetters[] = {
+luaL_Reg NodeInstancerGetters[] = {
 	{nullptr, nullptr},
 };
 
-luaL_Reg ElementInstancerSetters[] = {
-	RMLUI_LUASETTER(ElementInstancer, InstanceElement),
+luaL_Reg NodeInstancerSetters[] = {
+	RMLUI_LUASETTER(NodeInstancer, InstanceNode),
 	{nullptr, nullptr},
 };
 
-RMLUI_LUATYPE_DEFINE(ElementInstancer)
+RMLUI_LUATYPE_DEFINE(NodeInstancer)
 } // namespace Lua
 } // namespace Rml

+ 10 - 10
Source/Lua/ElementInstancer.h → Source/Lua/NodeInstancer.h

@@ -26,27 +26,27 @@
  *
  */
 
-#ifndef RMLUI_LUA_ELEMENTINSTANCER_H
-#define RMLUI_LUA_ELEMENTINSTANCER_H
+#ifndef RMLUI_LUA_NODEINSTANCER_H
+#define RMLUI_LUA_NODEINSTANCER_H
 
-#include "LuaElementInstancer.h"
+#include "LuaNodeInstancer.h"
 #include <RmlUi/Lua/IncludeLua.h>
 #include <RmlUi/Lua/LuaType.h>
 
 namespace Rml {
 namespace Lua {
 template <>
-void ExtraInit<ElementInstancer>(lua_State* L, int metatable_index);
+void ExtraInit<NodeInstancer>(lua_State* L, int metatable_index);
 // method
-int ElementInstancernew(lua_State* L);
+int NodeInstancernew(lua_State* L);
 // setter
-int ElementInstancerSetAttrInstanceElement(lua_State* L);
+int NodeInstancerSetAttrInstanceNode(lua_State* L);
 
-extern RegType<ElementInstancer> ElementInstancerMethods[];
-extern luaL_Reg ElementInstancerGetters[];
-extern luaL_Reg ElementInstancerSetters[];
+extern RegType<NodeInstancer> NodeInstancerMethods[];
+extern luaL_Reg NodeInstancerGetters[];
+extern luaL_Reg NodeInstancerSetters[];
 
-RMLUI_LUATYPE_DECLARE(ElementInstancer)
+RMLUI_LUATYPE_DECLARE(NodeInstancer)
 } // namespace Lua
 } // namespace Rml
 #endif

+ 4 - 4
Source/Lua/RmlUi.cpp

@@ -27,8 +27,8 @@
  */
 
 #include "RmlUi.h"
-#include "ElementInstancer.h"
-#include "LuaElementInstancer.h"
+#include "LuaNodeInstancer.h"
+#include "NodeInstancer.h"
 #include "RmlUiContextsProxy.h"
 #include <RmlUi/Core/Core.h>
 #include <RmlUi/Core/Factory.h>
@@ -91,9 +91,9 @@ int LuaRmlUiLoadFontFace(lua_State* L, LuaRmlUi* /*obj*/)
 int LuaRmlUiRegisterTag(lua_State* L, LuaRmlUi* /*obj*/)
 {
 	const char* tag = luaL_checkstring(L, 1);
-	LuaElementInstancer* lei = (LuaElementInstancer*)LuaType<ElementInstancer>::check(L, 2);
+	LuaNodeInstancer* lei = (LuaNodeInstancer*)LuaType<NodeInstancer>::check(L, 2);
 	RMLUI_CHECK_OBJ(lei);
-	Factory::RegisterElementInstancer(tag, lei);
+	Factory::RegisterNodeInstancer(tag, lei);
 	return 0;
 }
 

+ 4 - 4
Source/SVG/SVGPlugin.cpp

@@ -27,9 +27,9 @@
  */
 
 #include "../../Include/RmlUi/Core/Core.h"
-#include "../../Include/RmlUi/Core/ElementInstancer.h"
 #include "../../Include/RmlUi/Core/Factory.h"
 #include "../../Include/RmlUi/Core/Log.h"
+#include "../../Include/RmlUi/Core/NodeInstancer.h"
 #include "../../Include/RmlUi/Core/Plugin.h"
 #include "../../Include/RmlUi/SVG/ElementSVG.h"
 #include "DecoratorSVG.h"
@@ -45,8 +45,8 @@ namespace SVG {
 		{
 			SVGCache::Initialize();
 
-			element_instancer = MakeUnique<ElementInstancerGeneric<ElementSVG>>();
-			Factory::RegisterElementInstancer("svg", element_instancer.get());
+			element_instancer = MakeUnique<NodeInstancerGeneric<ElementSVG>>();
+			Factory::RegisterNodeInstancer("svg", element_instancer.get());
 
 			decorator_instancer = MakeUnique<DecoratorSVGInstancer>();
 			Factory::RegisterDecoratorInstancer("svg", decorator_instancer.get());
@@ -66,7 +66,7 @@ namespace SVG {
 		int GetEventClasses() override { return Plugin::EVT_BASIC; }
 
 	private:
-		UniquePtr<ElementInstancerGeneric<ElementSVG>> element_instancer;
+		UniquePtr<NodeInstancerGeneric<ElementSVG>> element_instancer;
 		UniquePtr<DecoratorSVGInstancer> decorator_instancer;
 	};
 

+ 1 - 1
Tests/Source/UnitTests/PropertySpecification.cpp

@@ -344,7 +344,7 @@ TEST_CASE("PropertyParser.InvalidShorthands")
 	SetSystemInterface(&system_interface);
 	Rml::Initialise();
 
-	ElementPtr element = Factory::InstanceElement(nullptr, "*", "div", {});
+	ElementPtr element = As<ElementPtr>(Factory::InstanceNode("*", "div"));
 
 	struct TestCase {
 		bool expected_result;