Browse Source

Add interaction API to `_client.unreal`

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
8c927d7e4e
  1. 17
      sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc
  2. 41
      sources/ClientRealm/API/Unreal/InteractionAPI/Events/Interaction_OnRender_Signal.uc
  3. 41
      sources/ClientRealm/API/Unreal/InteractionAPI/Events/Interaction_OnRender_Slot.uc
  4. 79
      sources/ClientRealm/API/Unreal/InteractionAPI/InteractionAPI.uc
  5. 74
      sources/ClientRealm/API/Unreal/InteractionAPI/InteractionAPIBase.uc
  6. 120
      sources/ClientRealm/AcediaInteraction.uc
  7. 2
      sources/ClientRealm/ClientAcediaAdapter.uc
  8. 23
      sources/ClientRealm/ClientGlobal.uc

17
sources/ClientRealm/API/Unreal/ClientUnrealAPIBase.uc

@ -21,6 +21,23 @@
class ClientUnrealAPIBase extends UnrealAPIBase class ClientUnrealAPIBase extends UnrealAPIBase
abstract; abstract;
var protected bool initialized;
var public InteractionAPIBase interaction;
public function Initialize(class<ClientAcediaAdapter> adapterClass)
{
if (initialized) {
return;
}
initialized = true;
if (adapterClass == none) {
return;
}
interaction = InteractionAPIBase(_.memory.Allocate(
adapterClass.default.clientInteractionAPIClass));
}
/** /**
* Returns current local player's `Controller`. Useful because `level` * Returns current local player's `Controller`. Useful because `level`
* is not accessible inside objects. * is not accessible inside objects.

41
sources/ClientRealm/API/Unreal/InteractionAPI/Events/Interaction_OnRender_Signal.uc

@ -0,0 +1,41 @@
/**
* Signal class implementation for `InteractionAPI`'s `OnPreRender` and
* `OnPostRender` signals.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class Interaction_OnRender_Signal extends Signal;
public function bool Emit(Canvas canvas)
{
local Slot nextSlot;
StartIterating();
nextSlot = GetNextSlot();
while (nextSlot != none)
{
Interaction_OnRender_Slot(nextSlot).connect(canvas);
nextSlot = GetNextSlot();
}
CleanEmptySlots();
return true;
}
defaultproperties
{
relatedSlotClass = class'Interaction_OnRender_Slot'
}

41
sources/ClientRealm/API/Unreal/InteractionAPI/Events/Interaction_OnRender_Slot.uc

@ -0,0 +1,41 @@
/**
* Signal class implementation for `InteractionAPI`'s `OnPreRender` and
* `OnPostRender` signals.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class Interaction_OnRender_Slot extends Slot;
delegate connect(Canvas canvas)
{
DummyCall();
}
protected function Constructor()
{
connect = none;
}
protected function Finalizer()
{
super.Finalizer();
connect = none;
}
defaultproperties
{
}

79
sources/ClientRealm/API/Unreal/InteractionAPI/InteractionAPI.uc

@ -0,0 +1,79 @@
/**
* Default Acedia implementation for `InteractionAPIBase`.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class InteractionAPI extends InteractionAPIBase;
/* SIGNAL */
public function Interaction_OnRender_Slot OnPreRender(AcediaObject receiver)
{
local AcediaInteraction interaction;
// Simple redirect to `AcediaInteraction`
interaction = class'AcediaInteraction'.static.GetInstance();
if (interaction != none) {
return interaction.OnPreRender(receiver);
}
return none;
}
/* SIGNAL */
public function Interaction_OnRender_Slot OnPostRender(AcediaObject receiver)
{
local AcediaInteraction interaction;
// Simple redirect to `AcediaInteraction`
interaction = class'AcediaInteraction'.static.GetInstance();
if (interaction != none) {
return interaction.OnPostRender(receiver);
}
return none;
}
public function Interaction AddInteraction(BaseText interactionClass)
{
local string classAsString;
if (interactionClass == none) {
return none;
}
classAsString = interactionClass.ToString();
return AddInteraction_S(classAsString);
}
public function Interaction AddInteraction_S(string interactionClass)
{
local Interaction newInteraction;
local Player player;
local PlayerController localPlayerController;
localPlayerController = _client.unreal.GetLocalPlayer();
if (localPlayerController == none) return none;
player = localPlayerController.player;
if (player == none) return none;
if (player.interactionMaster == none) return none;
newInteraction = player.interactionMaster.AddInteraction(
"AcediaCore.AcediaInteraction",
player);
return newInteraction;
}
defaultproperties
{
}

74
sources/ClientRealm/API/Unreal/InteractionAPI/InteractionAPIBase.uc

@ -0,0 +1,74 @@
/**
* API that provides `Interaction` events and auxiliary methods.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class InteractionAPIBase extends AcediaObject;
/**
* Called before rendering, when `Interaction`s receive their `PreRender()`
* events
*
* [Signature]
* <slot>(Canvas canvas)
*
* @param Canvas `Actor` that attempts to broadcast next text message.
*/
/* SIGNAL */
public function Interaction_OnRender_Slot OnPreRender(AcediaObject receiver);
/**
* Called before rendering, when `Interaction`s receive their `PreRender()`
* events
*
* [Signature]
* <slot>(Canvas canvas)
*
* @param Canvas `Actor` that attempts to broadcast next text message.
*/
/* SIGNAL */
public function Interaction_OnRender_Slot OnPostRender(AcediaObject receiver);
/**
* Adds new interaction of class `interactionClass` to the local interaction
* master.
*
* @see `AddInteraction_S()`
*
* @param interactionClass Textual representation of interaction class
* to add.
* @return Newly added interaction. `none` if we've failed to add it to
* the interaction master.
*/
public function Interaction AddInteraction(BaseText interactionClass);
/**
* Adds new interaction of class `interactionClass` to the local interaction
* master.
*
* @see `AddInteraction()`
*
* @param interactionClass Textual representation of interaction class
* to add.
* @return Newly added interaction. `none` if we've failed to add it to
* the interaction master.
*/
public function Interaction AddInteraction_S(string interactionClass);
defaultproperties
{
}

120
sources/ClientRealm/AcediaInteraction.uc

@ -0,0 +1,120 @@
/**
* Acedia's interaction class that allows it access to drawing and user input.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class AcediaInteraction extends Interaction;
#exec OBJ LOAD FILE=KillingFloorHUD.utx
#exec OBJ LOAD FILE=KillingFloor2HUD.utx
var private Global _;
var private ClientGlobal _client;
var private AcediaInteraction myself;
var Texture shield;
var private Interaction_OnRender_Signal onPreRenderSignal;
var private Interaction_OnRender_Signal onPostRenderSignal;
/**
* Called before rendering, when `Interaction`s receive their `PreRender()`
* events
*
* [Signature]
* <slot>(Canvas canvas)
*
* @param Canvas `Actor` that attempts to broadcast next text message.
*/
/* SIGNAL */
public function Interaction_OnRender_Slot OnPreRender(AcediaObject receiver)
{
return Interaction_OnRender_Slot(onPreRenderSignal.NewSlot(receiver));
}
/**
* Called before rendering, when `Interaction`s receive their `PreRender()`
* events
*
* [Signature]
* <slot>(Canvas canvas)
*
* @param Canvas `Actor` that attempts to broadcast next text message.
*/
/* SIGNAL */
public function Interaction_OnRender_Slot OnPostRender(AcediaObject receiver)
{
return Interaction_OnRender_Slot(onPostRenderSignal.NewSlot(receiver));
}
/**
* Initializes newly created `Interaction`.
*/
public final function InitializeInteraction()
{
if (default.myself != none) {
return;
}
default.myself = self;
_ = class'Global'.static.GetInstance();
_client = class'ClientGlobal'.static.GetInstance();
onPreRenderSignal = Interaction_OnRender_Signal(
_.memory.Allocate(class'Interaction_OnRender_Signal'));
onPostRenderSignal = Interaction_OnRender_Signal(
_.memory.Allocate(class'Interaction_OnRender_Signal'));
}
event NotifyLevelChange()
{
_.environment.ShutDown();
default.myself = none;
_ = none;
_client = none;
master.RemoveInteraction(self);
}
/**
* Returns instance to the added `AcediaInteraction`'s instance.
*
* @return Instance added to interaction master.
*/
public static function AcediaInteraction GetInstance()
{
return default.myself;
}
public function PreRender(Canvas canvas)
{
if (onPreRenderSignal != none) {
onPreRenderSignal.Emit(canvas);
}
}
public function PostRender(Canvas canvas)
{
Log("dsfsdfs");
canvas.SetPos(500, 500);
canvas.DrawTile(shield, 16, 16, 0, 0, shield.MaterialUSize(), shield.MaterialVSize());
if (onPostRenderSignal != none) {
onPostRenderSignal.Emit(canvas);
}
}
defaultproperties
{
shield = Texture'KillingFloorHUD.HUD.Hud_Shield'
bVisible = true
}

2
sources/ClientRealm/ClientAcediaAdapter.uc

@ -23,8 +23,10 @@ class ClientAcediaAdapter extends AcediaAdapter
abstract; abstract;
var public const class<ClientUnrealAPIBase> clientUnrealAPIClass; var public const class<ClientUnrealAPIBase> clientUnrealAPIClass;
var public const class<InteractionAPIBase> clientInteractionAPIClass;
defaultproperties defaultproperties
{ {
clientUnrealAPIClass = class'ClientUnrealAPI' clientUnrealAPIClass = class'ClientUnrealAPI'
clientInteractionAPIClass = class'InteractionAPI'
} }

23
sources/ClientRealm/ClientGlobal.uc

@ -27,7 +27,7 @@ var protected ClientGlobal myself;
var public ClientUnrealAPIBase unreal; var public ClientUnrealAPIBase unreal;
var private LoggerAPI.Definition fatBadAdapterClass; var private LoggerAPI.Definition fatBadAdapterClass, errNoInteraction;
public final static function ClientGlobal GetInstance() public final static function ClientGlobal GetInstance()
{ {
@ -43,6 +43,8 @@ public final static function ClientGlobal GetInstance()
protected function Initialize() protected function Initialize()
{ {
local Global _; local Global _;
local PlayerController localPlayer;
local AcediaInteraction newInteraction;
local class<ClientAcediaAdapter> clientAdapterClass; local class<ClientAcediaAdapter> clientAdapterClass;
if (initialized) { if (initialized) {
@ -61,9 +63,25 @@ protected function Initialize()
if (clientAdapterClass == none) { if (clientAdapterClass == none) {
return; return;
} }
// Create APIs
_ = class'Global'.static.GetInstance(); _ = class'Global'.static.GetInstance();
unreal = ClientUnrealAPIBase( unreal = ClientUnrealAPIBase(
_.memory.Allocate(clientAdapterClass.default.clientUnrealAPIClass)); _.memory.Allocate(clientAdapterClass.default.clientUnrealAPIClass));
unreal.Initialize(clientAdapterClass);
// Create `AcediaInteraction`
localPlayer = unreal.GetLocalPlayer();
if (localPlayer != none)
{
newInteraction = AcediaInteraction(unreal
.interaction
.AddInteraction_S("AcediaCore.AcediaInteraction"));
if (newInteraction != none) {
newInteraction.InitializeInteraction();
}
else {
_.logger.Auto(errNoInteraction);
}
}
} }
public final function bool ConnectClientLevelCore() public final function bool ConnectClientLevelCore()
@ -78,5 +96,6 @@ public final function bool ConnectClientLevelCore()
defaultproperties defaultproperties
{ {
adapterClass = class'ClientAcediaAdapter' adapterClass = class'ClientAcediaAdapter'
fatBadAdapterClass = (l=LOG_Fatal,m="non-`ClientAcediaAdapter` class was specified as an adapter for `%1` level core class. This should not have happened. AcediaCore cannot properly function.") fatBadAdapterClass = (l=LOG_Fatal,m="Non-`ClientAcediaAdapter` class was specified as an adapter for `%1` level core class. This should not have happened. AcediaCore cannot properly function.")
errNoInteraction = (l=LOG_Error,m="Failed to create interaction \"AcediaCore.AcediaInteraction\". AcediaCore won't support most of its client-side functionality.")
} }
Loading…
Cancel
Save