Started to expose DOM to C# API with support for custom nodes. Currently crash when doing FindNodeByID<T>
This commit is contained in:
@@ -98,7 +98,6 @@ Ref<Model> ResourceLoader::LoadModel(const std::string& path)
|
||||
Ref<UIResource> ResourceLoader::LoadUI(const std::string& path)
|
||||
{
|
||||
auto uiResource = CreateRef<UIResource>(path);
|
||||
uiResource->ID = UUID();
|
||||
return uiResource;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ UIResource::UIResource(const std::string& path) :
|
||||
inputManager = new MyInputManager(*Engine::GetCurrentWindow());
|
||||
}
|
||||
|
||||
canvas = CanvasParser::Get().Parse(FileSystem::RelativeToAbsolute(path));
|
||||
canvas = Canvas::New();
|
||||
canvas->uuid = this->ID;
|
||||
canvas = CanvasParser::Get().Parse(canvas, FileSystem::RelativeToAbsolute(path));
|
||||
canvas->SetInputManager(inputManager);
|
||||
canvas->ComputeLayout(defaultSize);
|
||||
}
|
||||
@@ -65,7 +67,7 @@ void UIResource::Reload()
|
||||
return;
|
||||
}
|
||||
|
||||
canvas = CanvasParser::Get().Parse(FileSystem::RelativeToAbsolute(filePath));
|
||||
canvas = CanvasParser::Get().Parse(canvas, FileSystem::RelativeToAbsolute(filePath));
|
||||
if (canvas)
|
||||
{
|
||||
canvas->SetInputManager(inputManager);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Nuake
|
||||
void Reload();
|
||||
|
||||
Ref<Texture> GetOutputTexture() const;
|
||||
Ref<NuakeUI::Canvas> GetCanvas() { return canvas; }
|
||||
|
||||
private:
|
||||
Ref<NuakeUI::Canvas> canvas;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Nuake
|
||||
// Instantiate UI widgets
|
||||
for (auto& uiWidget : CanvasParser::Get().GetAllCustomWidgetInstance())
|
||||
{
|
||||
scriptingEngineNet.RegisterCustomWidgetInstance(uiWidget.first, uiWidget.second);
|
||||
scriptingEngineNet.RegisterCustomWidgetInstance(uiWidget.first.first, uiWidget.first.second, uiWidget.second);
|
||||
}
|
||||
|
||||
// Call OnInit on entity script instances
|
||||
@@ -84,10 +84,11 @@ namespace Nuake
|
||||
// Call OnInit on UI widgets
|
||||
for (auto& widget : CanvasParser::Get().GetAllCustomWidgetInstance())
|
||||
{
|
||||
const UUID& widgetInstanceUUID = widget.first;
|
||||
if (scriptingEngineNet.HasCustomWidgetInstance(widgetInstanceUUID))
|
||||
const UUID& canvasInstanceUUID = widget.first.first;
|
||||
const UUID& widgetInstanceUUID = widget.first.second;
|
||||
if (scriptingEngineNet.HasCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID))
|
||||
{
|
||||
auto widgetInstance = scriptingEngineNet.GetCustomWidgetInstance(widgetInstanceUUID);
|
||||
auto widgetInstance = scriptingEngineNet.GetCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID);
|
||||
widgetInstance.InvokeMethod("OnInit");
|
||||
}
|
||||
}
|
||||
@@ -157,6 +158,17 @@ namespace Nuake
|
||||
scriptInstance.InvokeMethod("OnUpdate", ts.GetSeconds());
|
||||
}
|
||||
|
||||
for (auto& widget : CanvasParser::Get().GetAllCustomWidgetInstance())
|
||||
{
|
||||
const UUID& canvasInstanceUUID = widget.first.first;
|
||||
const UUID& widgetInstanceUUID = widget.first.second;
|
||||
if (scriptingEngineNet.HasCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID))
|
||||
{
|
||||
auto widgetInstance = scriptingEngineNet.GetCustomWidgetInstance(canvasInstanceUUID, widgetInstanceUUID);
|
||||
widgetInstance.InvokeMethod("OnTick", ts.GetSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
DispatchPhysicCallbacks();
|
||||
}
|
||||
|
||||
|
||||
123
Nuake/src/Scripting/NetModules/UINetAPI.cpp
Normal file
123
Nuake/src/Scripting/NetModules/UINetAPI.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "UINetAPI.h"
|
||||
#include "src/Core/Core.h"
|
||||
#include <src/Resource/ResourceManager.h>
|
||||
#include <src/Resource/UI.h>
|
||||
#include "src/Resource/UUID.h"
|
||||
#include "src/UI/Nodes/Canvas.h"
|
||||
#include "src/UI/Nodes/Text.h"
|
||||
|
||||
#include <Coral/String.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
UUID UUIDFromString(const std::string& input)
|
||||
{
|
||||
return std::stoull(input);
|
||||
}
|
||||
|
||||
uint64_t FindChildByIDIcall(const Coral::String& canvasUUID, const Coral::String& id, const Coral::String& id2)
|
||||
{
|
||||
if (!ResourceManager::IsResourceLoaded(UUIDFromString(canvasUUID)))
|
||||
{
|
||||
Logger::Log("Error finding child, canvas is not loaded.", ".net/ui", CRITICAL);
|
||||
return UUID(0);
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceManager::GetResource<UIResource>(UUIDFromString(canvasUUID));
|
||||
Ref<Canvas> canvas = uiResource->GetCanvas();
|
||||
if(Ref<Node> searchNode = canvas->GetNodeByUUID(UUIDFromString(id));
|
||||
searchNode != nullptr)
|
||||
{
|
||||
Ref<Node> foundNode;
|
||||
if (foundNode->FindChildByID(id2, foundNode))
|
||||
{
|
||||
return foundNode->GetScriptingID();
|
||||
}
|
||||
}
|
||||
|
||||
return UUID(0);
|
||||
}
|
||||
|
||||
bool HasNativeInstanceICall(const Coral::String& canvasUUID, const Coral::String& nodeUUID, const Coral::String& nodeUUID2)
|
||||
{
|
||||
if (!ResourceManager::IsResourceLoaded(UUIDFromString(canvasUUID)))
|
||||
{
|
||||
Logger::Log("Error finding child, canvas is not loaded." + std::string(canvasUUID), ".net/ui", CRITICAL);
|
||||
return UUID(0);
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceManager::GetResource<UIResource>(UUIDFromString(canvasUUID));
|
||||
Ref<Canvas> canvas = uiResource->GetCanvas();
|
||||
if (Ref<Node> node = canvas->GetNodeByUUID(UUIDFromString(nodeUUID));
|
||||
node != nullptr)
|
||||
{
|
||||
if (ScriptingEngineNet::Get().HasCustomWidgetInstance(UUIDFromString(canvasUUID), UUIDFromString(nodeUUID)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Coral::ManagedObject GetNativeInstanceNodeICall(const Coral::String& canvasUUID, const Coral::String& nodeUUID)
|
||||
{
|
||||
if (!ResourceManager::IsResourceLoaded(UUIDFromString(canvasUUID)))
|
||||
{
|
||||
Logger::Log("Error getting native instance of UI node, canvas is not loaded.", ".net/ui", CRITICAL);
|
||||
return Coral::ManagedObject();
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceManager::GetResource<UIResource>(UUIDFromString(canvasUUID));
|
||||
Ref<Canvas> canvas = uiResource->GetCanvas();
|
||||
if(ScriptingEngineNet::Get().HasCustomWidgetInstance(UUIDFromString(canvasUUID), UUIDFromString(nodeUUID)))
|
||||
{
|
||||
return ScriptingEngineNet::Get().GetCustomWidgetInstance(UUIDFromString(canvasUUID), UUIDFromString(nodeUUID));
|
||||
}
|
||||
|
||||
Logger::Log("Error getting native instance of UI node, custom widget doesnt have an instance", ".net/ui", CRITICAL);
|
||||
return Coral::ManagedObject();
|
||||
}
|
||||
|
||||
Coral::String GetTextNodeTextICall(const Coral::String& canvasUUID, const Coral::String& nodeUUID)
|
||||
{
|
||||
if(!ResourceManager::IsResourceLoaded(UUIDFromString(canvasUUID)))
|
||||
{
|
||||
Logger::Log("Error getting native instance of UI node, canvas is not loaded.", ".net/ui", CRITICAL);
|
||||
return Coral::String::New("");
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceManager::GetResource<UIResource>(UUIDFromString(canvasUUID));
|
||||
Ref<Canvas> canvas = uiResource->GetCanvas();
|
||||
Ref<Text> textNode = std::static_pointer_cast<NuakeUI::Text>(canvas->GetNodeByUUID(UUIDFromString(nodeUUID)));
|
||||
return Coral::String::New(textNode->GetText());
|
||||
}
|
||||
|
||||
void SetTextNodeTextICall(const Coral::String& canvasUUID, const Coral::String& nodeUUID, Coral::String newText)
|
||||
{
|
||||
if (!ResourceManager::IsResourceLoaded(UUIDFromString(canvasUUID)))
|
||||
{
|
||||
Logger::Log("Error getting native instance of UI node, canvas is not loaded.", ".net/ui", CRITICAL);
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<UIResource> uiResource = ResourceManager::GetResource<UIResource>(UUIDFromString(canvasUUID));
|
||||
Ref<Canvas> canvas = uiResource->GetCanvas();
|
||||
Ref<Text> textNode = std::static_pointer_cast<NuakeUI::Text>(canvas->GetNodeByUUID(UUIDFromString(nodeUUID)));
|
||||
textNode->SetText(newText);
|
||||
}
|
||||
|
||||
void UINetAPI::RegisterMethods()
|
||||
{
|
||||
RegisterMethod("Node.FindChildByIDICall", &FindChildByIDIcall);
|
||||
RegisterMethod("Node.HasNativeInstanceICall", &HasNativeInstanceICall);
|
||||
RegisterMethod("Node.GetNativeInstanceNodeICall", &GetNativeInstanceNodeICall);
|
||||
|
||||
RegisterMethod("TextNode.GetTextNodeTextICall", &GetTextNodeTextICall);
|
||||
RegisterMethod("TextNode.SetTextNodeTextICall", &SetTextNodeTextICall);
|
||||
}
|
||||
15
Nuake/src/Scripting/NetModules/UINetAPI.h
Normal file
15
Nuake/src/Scripting/NetModules/UINetAPI.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "NetAPIModule.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
|
||||
class UINetAPI : public NetAPIModule
|
||||
{
|
||||
public:
|
||||
virtual const std::string GetModuleName() const override { return "UI"; }
|
||||
|
||||
virtual void RegisterMethods() override;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "NetModules/EngineNetAPI.h"
|
||||
#include "NetModules/InputNetAPI.h"
|
||||
#include "NetModules/SceneNetAPI.h"
|
||||
#include "NetModules/UINetAPI.h"
|
||||
|
||||
#include <src/Scene/Components/BSPBrushComponent.h>
|
||||
|
||||
@@ -53,7 +54,8 @@ namespace Nuake
|
||||
{
|
||||
CreateRef<EngineNetAPI>(),
|
||||
CreateRef<InputNetAPI>(),
|
||||
CreateRef<SceneNetAPI>()
|
||||
CreateRef<SceneNetAPI>(),
|
||||
CreateRef<UINetAPI>()
|
||||
};
|
||||
|
||||
for (auto& m : modules)
|
||||
@@ -289,7 +291,7 @@ namespace Nuake
|
||||
return uiWidgets[widgetName];
|
||||
}
|
||||
|
||||
void ScriptingEngineNet::RegisterCustomWidgetInstance(const UUID& uuid, const std::string& widgetTypeName)
|
||||
void ScriptingEngineNet::RegisterCustomWidgetInstance(const UUID& canvasUUID, const UUID& nodeUUID, const std::string& widgetTypeName)
|
||||
{
|
||||
if (uiWidgets.find(widgetTypeName) == uiWidgets.end())
|
||||
{
|
||||
@@ -301,24 +303,25 @@ namespace Nuake
|
||||
}
|
||||
|
||||
auto classInstance = uiWidgets[widgetTypeName].coralType->CreateInstance();
|
||||
classInstance.SetPropertyValue("ID", uuid);
|
||||
widgetUUIDToManagedObjects[uuid] = classInstance;
|
||||
classInstance.SetFieldValue("CanvasUUID", Coral::String::New(std::to_string(canvasUUID)));
|
||||
classInstance.SetFieldValue("UUID", Coral::String::New(std::to_string(nodeUUID)));
|
||||
widgetUUIDToManagedObjects[std::make_pair(canvasUUID, nodeUUID)] = classInstance;
|
||||
}
|
||||
|
||||
bool ScriptingEngineNet::HasCustomWidgetInstance(const UUID& uuid)
|
||||
bool ScriptingEngineNet::HasCustomWidgetInstance(const UUID& canvasUUID, const UUID& uuid)
|
||||
{
|
||||
return widgetUUIDToManagedObjects.contains(uuid);
|
||||
return widgetUUIDToManagedObjects.contains(std::make_pair(canvasUUID, uuid));
|
||||
}
|
||||
|
||||
Coral::ManagedObject ScriptingEngineNet::GetCustomWidgetInstance(const UUID& uuid)
|
||||
Coral::ManagedObject ScriptingEngineNet::GetCustomWidgetInstance(const UUID& canvasUUID, const UUID& uuid)
|
||||
{
|
||||
if (!HasCustomWidgetInstance(uuid))
|
||||
if (!HasCustomWidgetInstance(canvasUUID, uuid))
|
||||
{
|
||||
Logger::Log("Failed to get custom widget .Net script instance, doesn't exist", ".net", CRITICAL);
|
||||
return Coral::ManagedObject();
|
||||
}
|
||||
|
||||
return widgetUUIDToManagedObjects[uuid];
|
||||
return widgetUUIDToManagedObjects[std::make_pair(canvasUUID, uuid)];
|
||||
}
|
||||
|
||||
std::vector<CompilationError> ScriptingEngineNet::BuildProjectAssembly(Ref<Project> project)
|
||||
|
||||
@@ -102,9 +102,9 @@ namespace Nuake
|
||||
|
||||
bool HasUIWidget(const std::string& widgetName);
|
||||
UIWidgetObject& GetUIWidget(const std::string& widgetName);
|
||||
void RegisterCustomWidgetInstance(const UUID& uuid, const std::string& widgetTypeName);
|
||||
bool HasCustomWidgetInstance(const UUID& uuid);
|
||||
Coral::ManagedObject GetCustomWidgetInstance(const UUID& uuid);
|
||||
void RegisterCustomWidgetInstance(const UUID& canvasUUID, const UUID& nodeUUID, const std::string& widgetTypeName);
|
||||
bool HasCustomWidgetInstance(const UUID& canvasUUID, const UUID& uuid);
|
||||
Coral::ManagedObject GetCustomWidgetInstance(const UUID& canvasUUID, const UUID& uuid);
|
||||
|
||||
std::unordered_map<std::string, NetGameScriptObject> GetBrushEntities() const { return brushEntityTypes; }
|
||||
std::unordered_map<std::string, NetGameScriptObject> GetPointEntities() const { return pointEntityTypes; }
|
||||
@@ -139,7 +139,8 @@ namespace Nuake
|
||||
std::unordered_map<std::string, UIWidgetObject> uiWidgets;
|
||||
|
||||
std::unordered_map<uint32_t, Coral::ManagedObject> entityToManagedObjects;
|
||||
std::unordered_map<UUID, Coral::ManagedObject> widgetUUIDToManagedObjects;
|
||||
std::map<std::pair<UUID, UUID>, Coral::ManagedObject> widgetUUIDToManagedObjects;
|
||||
|
||||
ScriptingEngineNet();
|
||||
~ScriptingEngineNet();
|
||||
|
||||
|
||||
@@ -92,41 +92,52 @@ namespace NuakeUI
|
||||
for (auto& rule : mStyleSheet->Rules)
|
||||
{
|
||||
bool respectSelector = true;
|
||||
|
||||
for (StyleSelector& selector : rule.Selector)
|
||||
{
|
||||
bool foundSelector = false;
|
||||
if (selector.Type == StyleSelectorType::Class)
|
||||
switch (selector.Type)
|
||||
{
|
||||
for (auto& c : node->Classes)
|
||||
case StyleSelectorType::Class:
|
||||
{
|
||||
if (c == selector.Value)
|
||||
foundSelector = true;
|
||||
for (auto& c : node->Classes)
|
||||
{
|
||||
if (c == selector.Value)
|
||||
foundSelector = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (selector.Type == StyleSelectorType::Pseudo)
|
||||
{
|
||||
if (selector.Value == "hover" && node->State == NodeState::Hover)
|
||||
foundSelector = true;
|
||||
if (selector.Value == "active" && node->State == NodeState::Pressed)
|
||||
foundSelector = true;
|
||||
}
|
||||
else if (selector.Type == StyleSelectorType::Id)
|
||||
{
|
||||
if (node->GetID() == selector.Value)
|
||||
foundSelector = true;
|
||||
}
|
||||
else if (selector.Type == StyleSelectorType::Tag)
|
||||
{
|
||||
if (selector.Value == node->GetType())
|
||||
case StyleSelectorType::Pseudo:
|
||||
{
|
||||
foundSelector = true;
|
||||
|
||||
const bool isHover = selector.Value == "hover" && node->State == NodeState::Hover;
|
||||
const bool isActive = selector.Value == "active" && node->State == NodeState::Clicked;
|
||||
if (isHover || isActive)
|
||||
{
|
||||
foundSelector = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StyleSelectorType::Id:
|
||||
{
|
||||
if (selector.Value == node->GetID())
|
||||
{
|
||||
foundSelector = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StyleSelectorType::Tag:
|
||||
{
|
||||
if (selector.Value == node->GetType())
|
||||
{
|
||||
foundSelector = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSelector)
|
||||
{
|
||||
respectSelector = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (respectSelector)
|
||||
@@ -149,6 +160,7 @@ namespace NuakeUI
|
||||
void Canvas::SetRoot(NodePtr root)
|
||||
{
|
||||
mRootNode = root;
|
||||
root->canvasOwner = this;
|
||||
}
|
||||
|
||||
void Canvas::SetInputManager(InputManager* inputManager)
|
||||
@@ -166,4 +178,14 @@ namespace NuakeUI
|
||||
mDirty = true;
|
||||
mStyleSheet = styleSheet;
|
||||
}
|
||||
|
||||
Ref<Node> Canvas::GetNodeByUUID(const UUID& uuid)
|
||||
{
|
||||
if (!nodeCache.contains(uuid))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nodeCache[uuid];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#pragma once
|
||||
#include "Node.h"
|
||||
#include "../InputManager.h"
|
||||
#include "../Styles/StyleSheet.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Resource/UUID.h"
|
||||
#include "src/UI/InputManager.h"
|
||||
#include "src/UI/Styles/StyleSheet.h"
|
||||
|
||||
#include <src/Core/Maths.h>
|
||||
#include "yoga/YGConfig.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace NuakeUI
|
||||
{
|
||||
class Canvas;
|
||||
@@ -14,9 +17,13 @@ namespace NuakeUI
|
||||
|
||||
class Canvas
|
||||
{
|
||||
friend Node;
|
||||
|
||||
private:
|
||||
YGConfigRef mYogaConfig;
|
||||
|
||||
std::map<UUID, Ref<Node>> nodeCache;
|
||||
|
||||
std::string mFilePath = "";
|
||||
|
||||
InputManager* mInputManager;
|
||||
@@ -25,11 +32,16 @@ namespace NuakeUI
|
||||
NodePtr mRootNode;
|
||||
|
||||
bool mDirty;
|
||||
|
||||
|
||||
public:
|
||||
static CanvasPtr New();
|
||||
Canvas();
|
||||
~Canvas();
|
||||
|
||||
UUID uuid = UUID(0);
|
||||
UUID GetUUID() { return uuid; }
|
||||
|
||||
void Tick();
|
||||
void Draw();
|
||||
void ComputeLayout(Vector2 size);
|
||||
@@ -51,5 +63,7 @@ namespace NuakeUI
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Ref<Node> GetNodeByUUID(const UUID& uuid);
|
||||
};
|
||||
}
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#include "NodeState.h"
|
||||
#include "../StringHelper.h"
|
||||
#include "src/UI/Nodes/Canvas.h"
|
||||
|
||||
#include <nanosvg.h>
|
||||
#include <nanosvgrast.h>
|
||||
|
||||
|
||||
namespace NuakeUI
|
||||
{
|
||||
NodePtr Node::New(const std::string id, const std::string& value)
|
||||
@@ -15,7 +17,10 @@ namespace NuakeUI
|
||||
return std::make_shared<Node>(id, value);
|
||||
}
|
||||
|
||||
Node::Node(const std::string& id, const std::string& value) : ID(id)
|
||||
Node::Node(const std::string& id, const std::string& value) :
|
||||
ID(id),
|
||||
Type("div"),
|
||||
canvasOwner(nullptr)
|
||||
{
|
||||
InitializeNode();
|
||||
|
||||
@@ -300,6 +305,14 @@ namespace NuakeUI
|
||||
}
|
||||
}
|
||||
|
||||
void Node::OnClick(InputManager * inputManager)
|
||||
{
|
||||
if (ScriptingEngineNet::Get().HasCustomWidgetInstance(canvasOwner->GetUUID(), scriptingId))
|
||||
{
|
||||
ScriptingEngineNet::Get().GetCustomWidgetInstance(canvasOwner->GetUUID(), scriptingId).InvokeMethod("OnClick");
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::IsMouseHover(float x, float y)
|
||||
{
|
||||
YGNodeRef ygNode = GetYogaNode();
|
||||
@@ -335,8 +348,17 @@ namespace NuakeUI
|
||||
if (!mHasBeenInitialized)
|
||||
InitializeNode();
|
||||
|
||||
if (!canvasOwner)
|
||||
{
|
||||
assert(false && "cannot add a node if it is not part of canvas");
|
||||
}
|
||||
|
||||
child->Parent = this;
|
||||
child->canvasOwner = canvasOwner;
|
||||
Childrens.push_back(child);
|
||||
|
||||
canvasOwner->nodeCache[child->scriptingId] = child;
|
||||
|
||||
uint32_t index = (uint32_t)Childrens.size() - 1;
|
||||
YGNodeInsertChild(this->mNode, child->GetYogaNode(), index);
|
||||
}
|
||||
|
||||
@@ -84,11 +84,13 @@ namespace NuakeUI
|
||||
class Node;
|
||||
class CanvasParser;
|
||||
class Renderer;
|
||||
class Canvas;
|
||||
|
||||
typedef std::shared_ptr<Node> NodePtr;
|
||||
|
||||
class Node
|
||||
{
|
||||
friend NuakeUI::Canvas;
|
||||
friend NuakeUI::CanvasParser;
|
||||
friend NuakeUI::Renderer;
|
||||
|
||||
@@ -97,9 +99,11 @@ namespace NuakeUI
|
||||
UUID scriptingId;
|
||||
|
||||
protected:
|
||||
Canvas* canvasOwner;
|
||||
|
||||
std::string Type = "node";
|
||||
float ScrollDelta = 0.0f;
|
||||
std::string ID = "";
|
||||
std::string Type = "node";
|
||||
Node* Parent = nullptr;
|
||||
std::vector<NodePtr> Childrens = std::vector<NodePtr>();
|
||||
|
||||
@@ -136,13 +140,7 @@ namespace NuakeUI
|
||||
|
||||
void OnMouseHover(InputManager* inputManager) {};
|
||||
void OnMouseExit(InputManager* inputManager) {};
|
||||
void OnClick(InputManager* inputManager)
|
||||
{
|
||||
if (ScriptingEngineNet::Get().HasCustomWidgetInstance(scriptingId))
|
||||
{
|
||||
ScriptingEngineNet::Get().GetCustomWidgetInstance(scriptingId).InvokeMethod("OnClick");
|
||||
}
|
||||
};
|
||||
void OnClick(InputManager* inputManager);
|
||||
void OnTick(InputManager* manager) {};
|
||||
void OnClickReleased(InputManager* inputManager) {};
|
||||
void OnScroll(InputManager* inputManager) {};
|
||||
@@ -152,6 +150,11 @@ namespace NuakeUI
|
||||
scriptingId = uuid;
|
||||
}
|
||||
|
||||
UUID GetScriptingID() const
|
||||
{
|
||||
return scriptingId;
|
||||
}
|
||||
|
||||
bool HasFocus() const;
|
||||
void GrabFocus();
|
||||
void ReleaseFocus();
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace NuakeUI
|
||||
|
||||
Text::Text(const std::string& id, const std::string& text)
|
||||
{
|
||||
Type = "text";
|
||||
ID = id;
|
||||
mNode = YGNodeNew();
|
||||
|
||||
mFont = Renderer::Get().mDefaultFont;
|
||||
|
||||
SetText(text);
|
||||
@@ -40,6 +40,17 @@ namespace NuakeUI
|
||||
Calculate();
|
||||
}
|
||||
|
||||
std::string Text::GetText() const
|
||||
{
|
||||
std::string result = "";
|
||||
for (const auto& line : Lines)
|
||||
{
|
||||
result += line + "\n";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Text::Draw(int z)
|
||||
{
|
||||
const float width = YGNodeLayoutGetWidth(mNode);
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace NuakeUI
|
||||
~Text() = default;
|
||||
|
||||
void SetText(const std::string& text);
|
||||
std::string GetText() const;
|
||||
|
||||
void Calculate() override;
|
||||
void UpdateInput(InputManager* manager) override {};
|
||||
|
||||
@@ -250,12 +250,12 @@ bool CanvasParser::ScanCustomWidgets(tinyxml2::XMLElement* e, NodePtr node)
|
||||
|
||||
// Let's parse the file
|
||||
auto firstNode = doc.FirstChildElement();
|
||||
IterateOverElement(firstNode, node);
|
||||
IterateOverElement(firstNode, node, nodeTypeName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CanvasParser::IterateOverElement(tinyxml2::XMLElement* e, NodePtr node)
|
||||
void CanvasParser::IterateOverElement(tinyxml2::XMLElement* e, NodePtr node, const std::string& customNodeName)
|
||||
{
|
||||
tinyxml2::XMLElement* current = e;
|
||||
while (current)
|
||||
@@ -272,17 +272,18 @@ void CanvasParser::IterateOverElement(tinyxml2::XMLElement* e, NodePtr node)
|
||||
// Let's keep fragments for now as they remove
|
||||
// the need to create a C# class for simple templating.
|
||||
ScanFragment(current, node);
|
||||
bool hasScript = ScanCustomWidgets(current, node);
|
||||
ScanCustomWidgets(current, node);
|
||||
|
||||
// Let's add custom widgets to the DOM.
|
||||
NodePtr newNode = CreateNodeFromXML(current, id);
|
||||
if (newNode)
|
||||
{
|
||||
if (hasScript)
|
||||
if (!customNodeName.empty())
|
||||
{
|
||||
// Allow to link between C# script and node using a UUID
|
||||
UUID scriptingId = UUID();
|
||||
node->SetScriptingID(scriptingId);
|
||||
customWidgetIDs.push_back(std::make_pair(scriptingId, current->Value()));
|
||||
newNode->SetScriptingID(scriptingId);
|
||||
customWidgetIDs.push_back(std::make_pair(std::make_pair(node->canvasOwner->uuid, scriptingId), customNodeName));
|
||||
}
|
||||
|
||||
AddClassesToNode(current, newNode);
|
||||
@@ -301,7 +302,7 @@ void CanvasParser::IterateOverElement(tinyxml2::XMLElement* e, NodePtr node)
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Canvas> CanvasParser::Parse(const std::string& path)
|
||||
Ref<Canvas> CanvasParser::Parse(CanvasPtr canvas, const std::string& path)
|
||||
{
|
||||
customWidgetIDs.clear();
|
||||
|
||||
@@ -327,7 +328,6 @@ Ref<Canvas> CanvasParser::Parse(const std::string& path)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CanvasPtr canvas = Canvas::New();
|
||||
NodePtr root = Node::New("root");
|
||||
|
||||
auto firstNode = doc.FirstChildElement();
|
||||
@@ -348,9 +348,8 @@ Ref<Canvas> CanvasParser::Parse(const std::string& path)
|
||||
}
|
||||
}
|
||||
|
||||
IterateOverElement(firstNode, root);
|
||||
|
||||
canvas->SetRoot(root);
|
||||
IterateOverElement(firstNode, root);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace NuakeUI
|
||||
private:
|
||||
std::map<std::string, refNew> NodeTypes;
|
||||
std::string _parsingPath;
|
||||
std::vector<std::pair<UUID, std::string>> customWidgetIDs;
|
||||
std::vector<std::pair<std::pair<UUID, UUID>, std::string>> customWidgetIDs;
|
||||
|
||||
public:
|
||||
static CanvasParser& Get()
|
||||
@@ -33,6 +33,8 @@ namespace NuakeUI
|
||||
~CanvasParser() = default;
|
||||
|
||||
public:
|
||||
UUID lastCanvasID = UUID(0);
|
||||
|
||||
/// <summary>
|
||||
/// Register a custom node type.
|
||||
/// </summary>
|
||||
@@ -42,16 +44,16 @@ namespace NuakeUI
|
||||
bool HasNodeType(const std::string& name) const;
|
||||
refNew GetNodeType(const std::string& name) const;
|
||||
|
||||
Ref<Canvas> Parse(const std::string& file);
|
||||
Ref<Canvas> Parse(CanvasPtr canvas, const std::string& file);
|
||||
|
||||
std::vector<std::pair<UUID, std::string>> GetAllCustomWidgetInstance() { return customWidgetIDs; }
|
||||
std::vector<std::pair<std::pair<UUID, UUID>, std::string>> GetAllCustomWidgetInstance() { return customWidgetIDs; }
|
||||
|
||||
private:
|
||||
void ScanFragment(tinyxml2::XMLElement* e, NodePtr node);
|
||||
bool ScanCustomWidgets(tinyxml2::XMLElement* e, NodePtr node);
|
||||
|
||||
void WriteValueFromString(std::variant<int, float, bool, std::string, char>& var, const std::string& str);
|
||||
void IterateOverElement(tinyxml2::XMLElement* e, NodePtr node);
|
||||
void IterateOverElement(tinyxml2::XMLElement* e, NodePtr node, const std::string& customNodeName = "");
|
||||
NodePtr CreateNodeFromXML(tinyxml2::XMLElement* xml, const std::string& id = "Node");
|
||||
void AddClassesToNode(tinyxml2::XMLElement* e, NodePtr node);
|
||||
void AddModelIfToNode(tinyxml2::XMLElement* e, NodePtr node);
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace Nuake.Net
|
||||
public bool Playing { get; set; }
|
||||
public int CurrentAnimation { get; set; }
|
||||
|
||||
public void Play(String name)
|
||||
public void Play(string name)
|
||||
{
|
||||
unsafe { PlayIcall(EntityID, name); }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using System;
|
||||
using Coral.Managed;
|
||||
using Coral.Managed.Interop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nuake.Net
|
||||
@@ -63,31 +69,95 @@ namespace Nuake.Net
|
||||
}
|
||||
}
|
||||
|
||||
public class UIWidget
|
||||
public class Node
|
||||
{
|
||||
internal static unsafe delegate*<NativeString, NativeString, NativeString, NativeString, ulong> FindChildByIDICall;
|
||||
internal static unsafe delegate*<NativeString, NativeString, NativeString, bool> HasNativeInstanceICall;
|
||||
internal static unsafe delegate*<NativeString, NativeString, NativeInstance<Node>> GetNativeInstanceNodeICall;
|
||||
|
||||
public string UUID;
|
||||
public string CanvasUUID;
|
||||
|
||||
public string ID { get; set; } = "";
|
||||
public List<string> Classes { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Traverse the DOM starting from this node to find a child from a unique ID
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of node</typeparam>
|
||||
/// <param name="id">Unique id of the node to find</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception">Node not found</exception>
|
||||
public T FindChildByID<T>(string id) where T : Node
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Engine.Log("Calling FindChildByIDICall with params: " + CanvasUUID + " , " + UUID + " , " + id);
|
||||
|
||||
ulong uuid = FindChildByIDICall(CanvasUUID, CanvasUUID, UUID, id);
|
||||
if (uuid == 0)
|
||||
{
|
||||
throw new Exception("Node not found");
|
||||
}
|
||||
|
||||
Node? newNode = null;
|
||||
//if (HasNativeInstanceICall(CanvasUUID, CanvasUUID, UUID))
|
||||
//{
|
||||
// NativeInstance<Node> handle;
|
||||
// unsafe { handle = GetNativeInstanceNodeICall(CanvasUUID, UUID); }
|
||||
// newNode = handle.Get();
|
||||
//}
|
||||
|
||||
if(newNode == null)
|
||||
{
|
||||
newNode = new Node()
|
||||
{
|
||||
UUID = uuid.ToString(),
|
||||
CanvasUUID = CanvasUUID
|
||||
};
|
||||
|
||||
return newNode as T;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TextNode : Node
|
||||
{
|
||||
internal static unsafe delegate*<NativeString, NativeString, NativeString, void> SetTextNodeTextICall;
|
||||
internal static unsafe delegate*<NativeString, NativeString, NativeString> GetTextNodeTextICall;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return GetTextNodeTextICall(this.CanvasUUID, this.UUID).ToString();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
SetTextNodeTextICall(this.CanvasUUID, this.UUID, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UIWidget : Node
|
||||
{
|
||||
public Style Style { get; set; }
|
||||
|
||||
private string HTML;
|
||||
|
||||
protected ulong ID { get; set; }
|
||||
|
||||
public UIWidget()
|
||||
{ }
|
||||
|
||||
protected UIWidget(ulong id)
|
||||
{
|
||||
ID = id;
|
||||
Style = new Style(id);
|
||||
HTML = "";
|
||||
}
|
||||
public UIWidget() { }
|
||||
|
||||
public virtual void OnInit() { }
|
||||
public virtual void OnTick(float dt) { }
|
||||
|
||||
// Events
|
||||
public virtual void OnClick()
|
||||
{
|
||||
|
||||
}
|
||||
public virtual void OnClick() { }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user