Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions addons/core/Configs/Systems/ChimeraSystemsConfig.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
SystemSettings : "{45C53F06BA17238D}configs/Systems/SystemsConfig.conf" {
Systems {
ACE_RenderTargetSystem "{65612DEA1619BAA4}" {
SystemLocation Client
SystemPoints 0x14 0x10
}
ACE_LoadtimeEntityManager "{66ACC8B1AE46C9A6}" {
SystemPoints 0 0x10
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
//------------------------------------------------------------------------------------------------
class ACE_RenderTargetComponentClass : ScriptComponentClass
{
}

//------------------------------------------------------------------------------------------------
//! Component for configuring render target handled by ACE_RenderTargetSystem
class ACE_RenderTargetComponent : ScriptComponent
{
[Attribute(uiwidget: UIWidgets.ResourcePickerThumbnail, desc: "Layout for the render target", params: "layout")]
protected ResourceName m_sLayoutName;

[Attribute(defvalue: "15", desc: "Maximum distance for render target being active [m]")]
protected float m_fRenderDistanceM;
protected float m_fRenderDistanceSq;

[RplProp(onRplName: "OnToggleActive"), Attribute(defvalue: "false", desc: "Whether renter target is turned on")]
protected bool m_bIsActive;

[Attribute(defvalue: "false", desc: "Whether it is only rendered for the owner")]
protected bool m_bOwnerOnly;

protected Widget m_wRoot;
protected RTTextureWidget m_wRTTexture;
protected InventoryItemComponent m_ItemComponent;
protected ref ScriptInvokerBool m_OnToggleActive;
protected ref ScriptInvokerBase<ScriptInvokerWidgetBool> m_OnToggleRender;

//------------------------------------------------------------------------------------------------
void ACE_RenderTargetComponent(IEntityComponentSource src, IEntity ent, IEntity parent)
{
if (!GetGame().InPlayMode())
return;

m_fRenderDistanceSq = Math.Pow(m_fRenderDistanceM, 2);

ACE_RenderTargetSystem system = ACE_RenderTargetSystem.GetInstance(GetOwner().GetWorld());
if (system && m_bIsActive)
system.Register(this);
}

//------------------------------------------------------------------------------------------------
void RequestToggleActive(bool active)
{
if (active == m_bIsActive)
return;

Rpc(RpcDo_ToggleActiveServer, active);
}

//------------------------------------------------------------------------------------------------
[RplRpc(RplChannel.Reliable, RplRcver.Server)]
protected void RpcDo_ToggleActiveServer(bool active)
{
m_bIsActive = active;
OnToggleActive();
Replication.BumpMe();
}

//------------------------------------------------------------------------------------------------
bool IsToggledOn()
{
return m_bIsActive;
}

//------------------------------------------------------------------------------------------------
void OnToggleActive()
{
ACE_RenderTargetSystem system = ACE_RenderTargetSystem.GetInstance(GetOwner().GetWorld());
if (!system)
return;

if (m_bIsActive)
system.Register(this);
else
system.Unregister(this);

if (m_OnToggleActive)
m_OnToggleActive.Invoke(m_bIsActive);
}

//------------------------------------------------------------------------------------------------
//! Whether RT is active on local client
bool IsRendered()
{
return m_wRoot;
}

//------------------------------------------------------------------------------------------------
RTTextureWidget GetRTTexture()
{
return m_wRTTexture;
}

//------------------------------------------------------------------------------------------------
float GetRenderDistanceSq()
{
return m_fRenderDistanceSq;
}

//------------------------------------------------------------------------------------------------
[Friend(ACE_RenderTargetSystem)]
protected void ToggleRender(bool active)
{
if (active)
{
if (m_wRoot)
return;

m_wRoot = GetGame().GetWorkspace().CreateWidgets(m_sLayoutName);
m_wRTTexture = RTTextureWidget.Cast(m_wRoot.FindAnyWidget("RTTexture0"));
m_wRTTexture.SetRenderTarget(GetOwner());
}

if (m_OnToggleRender)
m_OnToggleRender.Invoke(m_wRTTexture, active);

if (!active)
{
if (m_wRTTexture && !GetOwner().IsDeleted())
m_wRTTexture.RemoveRenderTarget(GetOwner());

if (m_wRoot)
m_wRoot.RemoveFromHierarchy();
}
}

//------------------------------------------------------------------------------------------------
//! Invoker for when the screen is turned on/off
ScriptInvokerBool GetOnToggleActive()
{
if (!m_OnToggleActive)
m_OnToggleActive = new ScriptInvokerBool();

return m_OnToggleActive;
}

//------------------------------------------------------------------------------------------------
//! Invoker for when the screen rendering starts/stops
ScriptInvokerBase<ScriptInvokerWidgetBool> GetOnToggleRender()
{
if (!m_OnToggleRender)
m_OnToggleRender = new ScriptInvokerBase<ScriptInvokerWidgetBool>();

return m_OnToggleRender;
}

//------------------------------------------------------------------------------------------------
//! Returns whether the local machine is allowed to render
bool CanRenderLocal()
{
if (System.IsConsoleApp())
return false;

if (!m_bOwnerOnly)
return true;

RplComponent rpl = RplComponent.Cast(GetOwner().FindComponent(RplComponent));
if (!rpl || rpl.IsOwner())
return true;

return false;
}

//------------------------------------------------------------------------------------------------
void ~ACE_RenderTargetComponent()
{
if (!GetGame().InPlayMode())
return;

ACE_RenderTargetSystem system = ACE_RenderTargetSystem.GetInstance(GetOwner().GetWorld());
if (system && m_bIsActive)
system.Unregister(this);
}
}
101 changes: 101 additions & 0 deletions addons/core/scripts/Game/ACE_Core/Systems/ACE_RenderTargetSystem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//------------------------------------------------------------------------------------------------
//! System for handling render targets on local client
class ACE_RenderTargetSystem : GameSystem
{
[Attribute(defvalue: "1", desc: "Time between updates [s]")]
protected float m_fUpdateTimeoutS;
protected float m_fUpdateTimerS = 0;

protected ref array<ACE_RenderTargetComponent> m_aComponents = {};

//------------------------------------------------------------------------------------------------
static ACE_RenderTargetSystem GetInstance(ChimeraWorld world)
{
return ACE_RenderTargetSystem.Cast(world.FindSystem(ACE_RenderTargetSystem));
}

//------------------------------------------------------------------------------------------------
override static void InitInfo(WorldSystemInfo outInfo)
{
outInfo.SetAbstract(false)
.SetUnique(true)
.SetLocation(WorldSystemLocation.Client)
.AddPoint(WorldSystemPoint.Frame);
}

//------------------------------------------------------------------------------------------------
override protected void OnInit()
{
super.OnInit();
Enable(!m_aComponents.IsEmpty());
}

//------------------------------------------------------------------------------------------------
override protected void OnUpdate(ESystemPoint point)
{
super.OnUpdate(point);
m_fUpdateTimerS += GetWorld().GetTimeSlice();

if (m_fUpdateTimerS < m_fUpdateTimeoutS)
return;

m_fUpdateTimerS = 0;

vector camPos;
if(!GetCameraPos(camPos))
return;

foreach (ACE_RenderTargetComponent component : m_aComponents)
{
OnUpdateComponent(component, camPos);
}
}

//------------------------------------------------------------------------------------------------
protected void OnUpdateComponent(ACE_RenderTargetComponent component, vector camPos)
{
bool shouldBeRendered = vector.DistanceSq(camPos, component.GetOwner().GetOrigin()) <= component.GetRenderDistanceSq();
if (shouldBeRendered != component.IsRendered())
component.ToggleRender(shouldBeRendered);
}

//------------------------------------------------------------------------------------------------
protected bool GetCameraPos(out vector pos)
{
CameraBase camera = GetGame().GetCameraManager().CurrentCamera();
if (!camera)
return false;

pos = camera.GetOrigin();
return true;
}

//------------------------------------------------------------------------------------------------
void Register(notnull ACE_RenderTargetComponent component)
{
// Only register if local machine is allowed to render
if (!component.CanRenderLocal())
return;

m_aComponents.Insert(component);

vector camPos;
if (GetCameraPos(camPos))
OnUpdateComponent(component, camPos);

if (!IsEnabled())
Enable(true);
}

//------------------------------------------------------------------------------------------------
void Unregister(ACE_RenderTargetComponent component)
{
m_aComponents.RemoveItem(component);

if (component.IsRendered())
component.ToggleRender(false);

if (m_aComponents.IsEmpty())
Enable(false);
}
}