Skip to content

Commit 0af445d

Browse files
committed
feat: execution options partiall unrealified
1 parent 81ffe9b commit 0af445d

File tree

6 files changed

+157
-1
lines changed

6 files changed

+157
-1
lines changed

Source/Ecsact/Public/EcsactAsyncRunner.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#include "EcsactAsyncRunner.h"
22
#include "Ecsact.h"
3+
#include "EcsactUnrealExecutionOptions.h"
34
#include "EcsactUnrealEventsCollector.h"
45
#include "ecsact/runtime/async.h"
56
#include "ecsact/runtime/common.h"
67

78
auto UEcsactAsyncRunner::Tick(float DeltaTime) -> void {
9+
EnqueueExecutionOptions();
10+
811
if(ecsact_async_flush_events == nullptr) {
912
UE_LOG(Ecsact, Error, TEXT("ecsact_async_flush_events is unavailable"));
1013
} else {
@@ -16,6 +19,25 @@ auto UEcsactAsyncRunner::Tick(float DeltaTime) -> void {
1619
}
1720
}
1821

22+
auto UEcsactAsyncRunner::EnqueueExecutionOptions() -> void {
23+
if(!ExecutionOptions) {
24+
return;
25+
}
26+
if(ecsact_async_enqueue_execution_options == nullptr) {
27+
UE_LOG(
28+
Ecsact,
29+
Error,
30+
TEXT("ecsact_async_enqueue_execution_options is unavailable")
31+
);
32+
return;
33+
}
34+
35+
if(ExecutionOptions->IsNotEmpty()) {
36+
ecsact_async_enqueue_execution_options(*ExecutionOptions->GetCPtr());
37+
ExecutionOptions->Clear();
38+
}
39+
}
40+
1941
auto UEcsactAsyncRunner::GetStatId() const -> TStatId {
2042
RETURN_QUICK_DECLARE_CYCLE_STAT(UEcsactAsyncRunner, STATGROUP_Tickables);
2143
}

Source/Ecsact/Public/EcsactAsyncRunner.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,11 @@ class UEcsactAsyncRunner : public UEcsactRunner {
1414
public:
1515
auto Tick(float DeltaTime) -> void override;
1616
auto GetStatId() const -> TStatId override;
17+
18+
/**
19+
* Usually execution options are enqueued during `Tick`, but if you'd prefer
20+
* to enqueue them earlier then you can call this function to immediate
21+
* enqueue the execution options.
22+
*/
23+
auto EnqueueExecutionOptions() -> void;
1724
};

Source/Ecsact/Public/EcsactRunner.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#pragma once
22

33
#include "CoreMinimal.h"
4+
#include "Tickable.h"
5+
#include "ecsact/runtime/common.h"
46
#include "EcsactRunner.generated.h"
57

68
UCLASS(Abstract)
@@ -12,6 +14,9 @@ class UEcsactRunner : public UObject, public FTickableGameObject {
1214
UPROPERTY()
1315
class UEcsactUnrealEventsCollector* EventsCollector;
1416

17+
UPROPERTY()
18+
class UEcsactUnrealExecutionOptions* ExecutionOptions;
19+
1520
public:
1621
auto Tick(float DeltaTime) -> void override;
1722
auto GetStatId() const -> TStatId override;

Source/Ecsact/Public/EcsactSyncRunner.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "EcsactSyncRunner.h"
22
#include "Ecsact.h"
3+
#include "EcsactUnrealExecutionOptions.h"
4+
#include "EcsactUnrealEventsCollector.h"
35
#include "EcsactExecution.h"
46
#include "ecsact/runtime/core.h"
57

@@ -26,7 +28,12 @@ auto UEcsactSyncRunner::Tick(float DeltaTime) -> void {
2628
evc_c = EventsCollector->GetCEVC();
2729
}
2830

29-
auto err = ecsact_execute_systems(registry_id, 1, nullptr, evc_c);
31+
ecsact_execution_options* exec_opts = nullptr;
32+
if(ExecutionOptions != nullptr && ExecutionOptions->IsNotEmpty()) {
33+
exec_opts = ExecutionOptions->GetCPtr();
34+
}
35+
36+
auto err = ecsact_execute_systems(registry_id, 1, exec_opts, evc_c);
3037
if(err != ECSACT_EXEC_SYS_OK) {
3138
UE_LOG(Ecsact, Error, TEXT("Ecsact execution failed"));
3239
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "EcsactUnrealExecutionOptions.h"
2+
3+
UEcsactUnrealExecutionOptions::UEcsactUnrealExecutionOptions() : ExecOpts({}) {
4+
}
5+
6+
auto UEcsactUnrealExecutionOptions::GetCPtr() -> ecsact_execution_options* {
7+
return &ExecOpts;
8+
}
9+
10+
auto UEcsactUnrealExecutionOptions::IsNotEmpty() const -> bool {
11+
return ExecOpts.actions_length > 0 || ExecOpts.create_entities_length > 0 ||
12+
ExecOpts.add_components_length > 0 ||
13+
ExecOpts.destroy_entities_length > 0 ||
14+
ExecOpts.update_components_length > 0 ||
15+
ExecOpts.remove_components_length > 0;
16+
}
17+
18+
auto UEcsactUnrealExecutionOptions::Clear() -> void {
19+
for(auto act : ActionList) {
20+
FMemory::Free(const_cast<void*>(act.action_data));
21+
}
22+
for(auto comp : AddComponentList) {
23+
FMemory::Free(const_cast<void*>(comp.component_data));
24+
}
25+
for(auto comp : UpdateComponentList) {
26+
FMemory::Free(const_cast<void*>(comp.component_data));
27+
}
28+
ActionList.Empty();
29+
AddComponentList.Empty();
30+
UpdateComponentList.Empty();
31+
RemoveComponentList.Empty();
32+
ExecOpts = {};
33+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
2+
#pragma once
3+
4+
#include "CoreMinimal.h"
5+
#include "ecsact/runtime/common.h"
6+
#include "EcsactUnrealExecutionOptions.generated.h"
7+
8+
UCLASS()
9+
10+
class UEcsactUnrealExecutionOptions : public UObject {
11+
GENERATED_BODY()
12+
13+
TArray<ecsact_action> ActionList;
14+
TArray<ecsact_component> AddComponentList;
15+
TArray<ecsact_component> UpdateComponentList;
16+
TArray<ecsact_component_id> RemoveComponentList;
17+
ecsact_execution_options ExecOpts;
18+
19+
public:
20+
UEcsactUnrealExecutionOptions();
21+
22+
auto Clear() -> void;
23+
auto IsNotEmpty() const -> bool;
24+
25+
/**
26+
* Get's the C `ecsact_execution_options` pointer typically passed to
27+
* `ecsact_execute_systems` or `ecsact_async_enqueue_execution_options`. The
28+
* lifetime of this pointer is the same as the owning
29+
* `UEcsactUnrealExecutionOptions`.
30+
*/
31+
auto GetCPtr() -> ecsact_execution_options*;
32+
33+
template<typename A>
34+
auto PushAction(const A& Action) -> void {
35+
auto action_data = FMemory::Malloc(sizeof(A));
36+
FMemory::Memcpy(action_data, &Action, sizeof(A));
37+
ActionList.Push(ecsact_action{
38+
.action_id = A::id,
39+
.action_data = action_data,
40+
});
41+
42+
ExecOpts.actions_length = ActionList.Num();
43+
ExecOpts.actions = ActionList.GetData();
44+
}
45+
46+
template<typename C>
47+
auto AddComponent(ecsact_entity_id Entity, const C& Component) -> void {
48+
auto component_data = FMemory::Malloc(sizeof(C));
49+
FMemory::Memcpy(component_data, &Component, sizeof(C));
50+
AddComponentList.Push(ecsact_component{
51+
.component_id = C::id,
52+
.component_data = component_data,
53+
});
54+
55+
ExecOpts.add_components_length = AddComponentList.Num();
56+
ExecOpts.add_components = AddComponentList.GetData();
57+
}
58+
59+
template<typename C>
60+
auto UpdateComponent(ecsact_entity_id Entity, const C& Component) -> void {
61+
auto component_data = FMemory::Malloc(sizeof(C));
62+
FMemory::Memcpy(component_data, &Component, sizeof(C));
63+
UpdateComponentList.Push(ecsact_component{
64+
.component_id = C::id,
65+
.component_data = component_data,
66+
});
67+
68+
ExecOpts.update_components_length = UpdateComponentList.Num();
69+
ExecOpts.update_components = UpdateComponentList.GetData();
70+
}
71+
72+
template<typename C>
73+
auto RemoveComponent(ecsact_entity_id Entity) -> void {
74+
RemoveComponentList.Push(C::id);
75+
76+
ExecOpts.remove_components_length = RemoveComponentList.Num();
77+
ExecOpts.remove_components = RemoveComponentList.GetData();
78+
}
79+
80+
inline auto DestroyEntity(ecsact_entity_id Entity) -> void {
81+
}
82+
};

0 commit comments

Comments
 (0)