Merge pull request #359 from SHADE-DP/SP3-20-UI-System

Moved UIRoutines call order. Call FinalizeChanges. Fixed UI Button Events.
This commit is contained in:
XiaoQiDigipen 2023-02-23 14:00:50 +08:00 committed by GitHub
commit 79433bcba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 242 additions and 7 deletions

View File

@ -11,8 +11,9 @@ public class ChangeSceneButton : Script
UIElement ui = GetComponent<UIElement>(); UIElement ui = GetComponent<UIElement>();
if (ui != null) if (ui != null)
{ {
ui.OnClick.RegisterAction(() => ui.OnRelease.RegisterAction(() =>
{ {
if (sceneID != 0) if (sceneID != 0)
{ {
Audio.PlaySFXOnce2D("event:/UI/success"); Audio.PlaySFXOnce2D("event:/UI/success");

View File

@ -132,16 +132,19 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>(); SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::GizmosDrawRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::PrepareRenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
//SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>(); //SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::AddUIComponentRoutine>(); SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::AddUIComponentRoutine>();
SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateCanvasMatrixRoutine>(); SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateCanvasMatrixRoutine>();
SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateUIMatrixRoutine>(); SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateUIMatrixRoutine>();
SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateButtonsRoutine>(); SHSystemManager::RegisterRoutine<SHUISystem, SHUISystem::UpdateButtonsRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::GizmosDrawRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::PrepareRenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>(); SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
#ifdef SHEDITOR #ifdef SHEDITOR

View File

@ -369,6 +369,27 @@ namespace SHADE
return eventData->handle; return eventData->handle;
} }
SHEventHandle SHScriptEngine::onUIElementReleased(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHButtonClickEvent>*>(eventPtr.get());
csUIElementOnReleased(eventData->data->EID);
return eventData->handle;
}
SHEventHandle SHScriptEngine::onUIElementOnHoverEntered(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHButtonClickEvent>*>(eventPtr.get());
csUIElementOnHoverEntered(eventData->data->EID);
return eventData->handle;
}
SHEventHandle SHScriptEngine::onUIElementOnHoverExited(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHButtonClickEvent>*>(eventPtr.get());
csUIElementOnHoverExited(eventData->data->EID);
return eventData->handle;
}
SHEventHandle SHScriptEngine::onSceneNodeChildrenAdded(SHEventPtr eventPtr) SHEventHandle SHScriptEngine::onSceneNodeChildrenAdded(SHEventPtr eventPtr)
{ {
auto eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphAddChildEvent>*>(eventPtr.get()); auto eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphAddChildEvent>*>(eventPtr.get());
@ -539,6 +560,24 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".UIElement", DEFAULT_CSHARP_NAMESPACE + ".UIElement",
"OnClicked" "OnClicked"
); );
csUIElementOnReleased = dotNet.GetFunctionPtr<CsEventRelayFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".UIElement",
"OnReleased"
);
csUIElementOnHoverEntered = dotNet.GetFunctionPtr<CsEventRelayFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".UIElement",
"OnHoverEntered"
);
csUIElementOnHoverExited = dotNet.GetFunctionPtr<CsEventRelayFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".UIElement",
"OnHoverExited"
);
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr> csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
@ -608,6 +647,21 @@ namespace SHADE
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onUIElementClicked) std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onUIElementClicked)
}; };
SHEventManager::SubscribeTo(SH_BUTTON_CLICK_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(clickedUIElementEventReceiver)); SHEventManager::SubscribeTo(SH_BUTTON_CLICK_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(clickedUIElementEventReceiver));
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> releasedUIElementEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onUIElementReleased)
};
SHEventManager::SubscribeTo(SH_BUTTON_RELEASE_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(releasedUIElementEventReceiver));
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> hoverEnterUIElementEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onUIElementOnHoverEntered)
};
SHEventManager::SubscribeTo(SH_BUTTON_HOVER_ENTER_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(hoverEnterUIElementEventReceiver));
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> hoverExitedUIElementEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onUIElementOnHoverExited)
};
SHEventManager::SubscribeTo(SH_BUTTON_HOVER_EXIT_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(hoverExitedUIElementEventReceiver));
/* SceneGraph */ /* SceneGraph */
// Register for SceneNode child added event // Register for SceneNode child added event

View File

@ -292,6 +292,9 @@ namespace SHADE
CsEventRelayFuncPtr csSceneNodeChildrenChanged = nullptr; CsEventRelayFuncPtr csSceneNodeChildrenChanged = nullptr;
CsEventRelayFuncPtr csUIElementOnRemoved = nullptr; CsEventRelayFuncPtr csUIElementOnRemoved = nullptr;
CsEventRelayFuncPtr csUIElementOnClicked = nullptr; CsEventRelayFuncPtr csUIElementOnClicked = nullptr;
CsEventRelayFuncPtr csUIElementOnReleased = nullptr;
CsEventRelayFuncPtr csUIElementOnHoverEntered = nullptr;
CsEventRelayFuncPtr csUIElementOnHoverExited = nullptr;
// - Editor // - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
CsFuncPtr csEditorUndo = nullptr; CsFuncPtr csEditorUndo = nullptr;
@ -306,6 +309,9 @@ namespace SHADE
SHEventHandle onColliderComponentRemoved(SHEventPtr eventPtr); SHEventHandle onColliderComponentRemoved(SHEventPtr eventPtr);
SHEventHandle onUIElementRemoved(SHEventPtr eventPtr); SHEventHandle onUIElementRemoved(SHEventPtr eventPtr);
SHEventHandle onUIElementClicked(SHEventPtr eventPtr); SHEventHandle onUIElementClicked(SHEventPtr eventPtr);
SHEventHandle onUIElementReleased(SHEventPtr eventPtr);
SHEventHandle onUIElementOnHoverEntered(SHEventPtr eventPtr);
SHEventHandle onUIElementOnHoverExited(SHEventPtr eventPtr);
SHEventHandle onSceneNodeChildrenAdded(SHEventPtr eventPtr); SHEventHandle onSceneNodeChildrenAdded(SHEventPtr eventPtr);
SHEventHandle onSceneNodeChildrenRemoved(SHEventPtr eventPtr); SHEventHandle onSceneNodeChildrenRemoved(SHEventPtr eventPtr);
SHEventHandle onSceneDestroyed(SHEventPtr eventPtr); SHEventHandle onSceneDestroyed(SHEventPtr eventPtr);

View File

@ -204,6 +204,7 @@ namespace SHADE
SHButtonClickEvent clickEvent; SHButtonClickEvent clickEvent;
clickEvent.EID = comp.GetEID(); clickEvent.EID = comp.GetEID();
SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_HOVER_ENTER_EVENT); SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_HOVER_ENTER_EVENT);
//SHLOG_INFO("C++ BROADCASTED HOVER ENTER EVENT EID: {}", clickEvent.EID);
} }
comp.isHovered = true; comp.isHovered = true;
@ -313,6 +314,7 @@ namespace SHADE
auto material = renderable->GetModifiableMaterial(); auto material = renderable->GetModifiableMaterial();
comp.currentTexture = textureID; comp.currentTexture = textureID;
material->SetProperty("data.textureIndex", SHResourceManager::LoadOrGet<SHTexture>(textureID)); material->SetProperty("data.textureIndex", SHResourceManager::LoadOrGet<SHTexture>(textureID));
loadTexture = true;
} }
@ -367,6 +369,7 @@ namespace SHADE
auto material = renderable->GetModifiableMaterial(); auto material = renderable->GetModifiableMaterial();
comp.currentTexture = textureID; comp.currentTexture = textureID;
material->SetProperty("data.textureIndex", SHResourceManager::LoadOrGet<SHTexture>(textureID)); material->SetProperty("data.textureIndex", SHResourceManager::LoadOrGet<SHTexture>(textureID));
loadTexture = true;
} }
@ -390,6 +393,11 @@ namespace SHADE
if (SHSceneManager::CheckNodeAndComponentsActive<SHToggleButtonComponent>(comp.GetEID())) if (SHSceneManager::CheckNodeAndComponentsActive<SHToggleButtonComponent>(comp.GetEID()))
system->UpdateToggleButtonComponent(comp); system->UpdateToggleButtonComponent(comp);
} }
if (system->loadTexture == true)
{
system->loadTexture = false;
SHResourceManager::FinaliseChanges();
}
} }
SHVec2 SHUISystem::CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept SHVec2 SHUISystem::CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept

View File

@ -68,6 +68,8 @@ namespace SHADE
private: private:
bool loadTexture{false};
void UpdateUIComponent(SHUIComponent& comp) noexcept; void UpdateUIComponent(SHUIComponent& comp) noexcept;
void UpdateButtonComponent(SHButtonComponent& comp) noexcept; void UpdateButtonComponent(SHButtonComponent& comp) noexcept;
void UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept; void UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept;

View File

@ -28,6 +28,18 @@ namespace SHADE
: Component(entity) : Component(entity)
{} {}
void UIElement::ClearStaticEventData()
{
if (onClickEventMap != nullptr)
onClickEventMap->Clear();
if (onReleasedEventMap != nullptr)
onReleasedEventMap->Clear();
if (onHoverEnterEventMap != nullptr)
onHoverEnterEventMap->Clear();
if (onHoverExitEventMap != nullptr)
onHoverExitEventMap->Clear();
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Properties */ /* Properties */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -48,6 +60,57 @@ namespace SHADE
// Return the event // Return the event
return onClickEventMap[owner.EntityId]; return onClickEventMap[owner.EntityId];
} }
CallbackEvent^ UIElement::OnRelease::get()
{
// Create map if it wasn't before
if (onReleasedEventMap == nullptr)
{
onReleasedEventMap = gcnew System::Collections::Generic::Dictionary<Entity, CallbackEvent ^>();
}
// Create event if it wasn't before
if (!onReleasedEventMap->ContainsKey(owner.EntityId))
{
onReleasedEventMap->Add(owner.EntityId, gcnew CallbackEvent());
}
// Return the event
return onReleasedEventMap[owner.EntityId];
}
CallbackEvent^ UIElement::OnHoverEnter::get()
{
// Create map if it wasn't before
if (onHoverEnterEventMap == nullptr)
{
onHoverEnterEventMap = gcnew System::Collections::Generic::Dictionary<Entity, CallbackEvent ^>();
}
// Create event if it wasn't before
if (!onHoverEnterEventMap->ContainsKey(owner.EntityId))
{
onHoverEnterEventMap->Add(owner.EntityId, gcnew CallbackEvent());
}
// Return the event
return onHoverEnterEventMap[owner.EntityId];
}
CallbackEvent^ UIElement::OnHoverExit::get()
{
// Create map if it wasn't before
if (onHoverExitEventMap == nullptr)
{
onHoverExitEventMap = gcnew System::Collections::Generic::Dictionary<Entity, CallbackEvent ^>();
}
// Create event if it wasn't before
if (!onHoverExitEventMap->ContainsKey(owner.EntityId))
{
onHoverExitEventMap->Add(owner.EntityId, gcnew CallbackEvent());
}
// Return the event
return onHoverExitEventMap[owner.EntityId];
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Event Handling Functions */ /* Event Handling Functions */
@ -60,6 +123,18 @@ namespace SHADE
{ {
onClickEventMap->Remove(entity); onClickEventMap->Remove(entity);
} }
if (onReleasedEventMap != nullptr && onReleasedEventMap->ContainsKey(entity))
{
onReleasedEventMap->Remove(entity);
}
if (onHoverEnterEventMap != nullptr && onHoverEnterEventMap->ContainsKey(entity))
{
onHoverEnterEventMap->Remove(entity);
}
if (onHoverExitEventMap != nullptr && onHoverExitEventMap->ContainsKey(entity))
{
onHoverExitEventMap->Remove(entity);
}
SAFE_NATIVE_CALL_END("UIElement.OnComponentRemoved") SAFE_NATIVE_CALL_END("UIElement.OnComponentRemoved")
} }
void UIElement::OnClicked(EntityID entity) void UIElement::OnClicked(EntityID entity)
@ -72,4 +147,34 @@ namespace SHADE
} }
SAFE_NATIVE_CALL_END("UIElement.OnClicked") SAFE_NATIVE_CALL_END("UIElement.OnClicked")
} }
void UIElement::OnReleased(EntityID entity)
{
SAFE_NATIVE_CALL_BEGIN
// Remove the event if it contained an event
if (onReleasedEventMap != nullptr && onReleasedEventMap->ContainsKey(entity))
{
onReleasedEventMap[entity]->Invoke();
}
SAFE_NATIVE_CALL_END("UIElement.OnReleased")
}
void UIElement::OnHoverEntered(EntityID entity)
{
SAFE_NATIVE_CALL_BEGIN
// Remove the event if it contained an event
if (onHoverEnterEventMap != nullptr && onHoverEnterEventMap->ContainsKey(entity))
{
onHoverEnterEventMap[entity]->Invoke();
}
SAFE_NATIVE_CALL_END("UIElement.OnHoverEntered")
}
void UIElement::OnHoverExited(EntityID entity)
{
SAFE_NATIVE_CALL_BEGIN
// Remove the event if it contained an event
if (onHoverExitEventMap != nullptr && onHoverExitEventMap->ContainsKey(entity))
{
onHoverExitEventMap[entity]->Invoke();
}
SAFE_NATIVE_CALL_END("UIElement.OnHoverExited")
}
} }

View File

@ -50,6 +50,37 @@ namespace SHADE
{ {
CallbackEvent^ get(); CallbackEvent^ get();
} }
/// <summary>
/// Event that is raised when this UIElement is released.
/// </summary>
property CallbackEvent^ OnRelease
{
CallbackEvent^ get();
}
/// <summary>
/// Event that is raised on the first frame when this UIElement is hovered over.
/// </summary>
property CallbackEvent^ OnHoverEnter
{
CallbackEvent^ get();
}
/// <summary>
/// Event that is raised on the first frame when this UIElement is no longer
/// hovered over.
/// </summary>
property CallbackEvent^ OnHoverExit
{
CallbackEvent^ get();
}
internal:
/*-----------------------------------------------------------------------------*/
/* Static Clear Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Disposes static event data which may contains data from SHADE_Scripting.
/// </summary>
static void ClearStaticEventData();
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -65,11 +96,32 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="entity">The entity which was clicked.</param> /// <param name="entity">The entity which was clicked.</param>
static void OnClicked(EntityID entity); static void OnClicked(EntityID entity);
/// <summary>
/// To be called from native code when this component is released from clicking.
/// </summary>
/// <param name="entity">The entity which was clicked.</param>
static void OnReleased(EntityID entity);
/// <summary>
/// To be called from native code on the first frame that this component is
/// hovered on.
/// </summary>
/// <param name="entity">The entity which was clicked.</param>
static void OnHoverEntered(EntityID entity);
/// <summary>
/// To be called from native code on the first frame that this component is
/// no longer hovered on.
/// </summary>
/// <param name="entity">The entity which was clicked.</param>
static void OnHoverExited(EntityID entity);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Static Data Members */ /* Static Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
// As these hold references to code in SHADE_Scripting, we must remember to dispose of them when changing scenes
static System::Collections::Generic::Dictionary<Entity, CallbackEvent^>^ onClickEventMap; static System::Collections::Generic::Dictionary<Entity, CallbackEvent^>^ onClickEventMap;
static System::Collections::Generic::Dictionary<Entity, CallbackEvent^>^ onReleasedEventMap;
static System::Collections::Generic::Dictionary<Entity, CallbackEvent^>^ onHoverEnterEventMap;
static System::Collections::Generic::Dictionary<Entity, CallbackEvent^>^ onHoverExitEventMap;
}; };
} }

View File

@ -51,7 +51,7 @@ namespace SHADE
/// specified Component. /// specified Component.
/// </returns> /// </returns>
generic<typename T> where T : BaseComponent generic<typename T> where T : BaseComponent
static T GetComponent(EntityID entity); static T GetComponent(EntityID entity);
/// <summary> /// <summary>
/// Retrieves the first Component from the specified GameObject's children that /// Retrieves the first Component from the specified GameObject's children that
/// matches the specified type. /// matches the specified type.

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Utility/Convert.hxx" #include "Utility/Convert.hxx"
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "Scripts/ScriptStore.hxx" #include "Scripts/ScriptStore.hxx"
#include "Components/UIElement.hxx"
namespace SHADE namespace SHADE
{ {
@ -43,6 +44,9 @@ namespace SHADE
oss << "[EngineInterface] Unloading " << Convert::ToNative(ManagedLibraryName) << ".dll"; oss << "[EngineInterface] Unloading " << Convert::ToNative(ManagedLibraryName) << ".dll";
ScriptStore::Exit(); ScriptStore::Exit();
// Unload static data of components that have access to the assembly
UIElement::ClearStaticEventData();
// Unload the script // Unload the script
scriptContext->Unload(); scriptContext->Unload();
scriptContext = nullptr; scriptContext = nullptr;