summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-06-11 16:04:48 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-06-11 16:04:54 -0400
commit0f89d12e747b380b35143815a2c8e87c6ee752d4 (patch)
tree78617e7cb819093aa9c0ad107b5dc79891e8ff55 /src
parente478bae42cf886a12433331937887de4c4e85ce2 (diff)
pke: serialize PkeInput first-pass
Diffstat (limited to 'src')
-rw-r--r--src/player-input.cpp241
-rw-r--r--src/player-input.hpp19
-rw-r--r--src/scene-types.hpp6
-rw-r--r--src/scene.cpp16
-rw-r--r--src/scene.hpp1
-rw-r--r--src/serialization-input.cpp207
-rw-r--r--src/serialization-input.hpp13
-rw-r--r--src/serialization.cpp14
-rw-r--r--src/serialization.hpp10
9 files changed, 398 insertions, 129 deletions
diff --git a/src/player-input.cpp b/src/player-input.cpp
index 8ecc2cc..252d706 100644
--- a/src/player-input.cpp
+++ b/src/player-input.cpp
@@ -79,34 +79,35 @@ PkeInputAction *FindActionByName(const char *actionName) {
}
return nullptr;
}
-template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_ByAction(const PkeInputAction *inputAction, S *&activeEvent) {
+template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_ByAction(const PkeInputAction *inputAction, S *&activeEvent, int32_t index) {
activeEvent = nullptr;
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
- activeEvent = &registeredCursorEnterEvents[inputAction->eventIndex];
+ activeEvent = &registeredCursorEnterEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
- activeEvent = &registeredCursorPosEvents[inputAction->eventIndex];
+ activeEvent = &registeredCursorPosEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
- activeEvent = &registeredKeyEvents[inputAction->eventIndex];
+ activeEvent = &registeredKeyEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_KEY;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
- activeEvent = &registeredMouseButtonEvents[inputAction->eventIndex];
+ activeEvent = &registeredMouseButtonEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
- activeEvent = &registeredScrollEvents[inputAction->eventIndex];
+ activeEvent = &registeredScrollEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_SCROLL;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
- activeEvent = &registeredWindowFocusEvents[inputAction->eventIndex];
+ activeEvent = &registeredWindowFocusEvents[inputAction->event_indices[index]];
return PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS;
}
return InputEventHash{0};
}
+/*
template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_ByName(const char *actionName, S *&activeEvent) {
activeEvent = nullptr;
bool any = false;
@@ -167,6 +168,7 @@ template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_B
}
return InputEventHash{0};
}
+*/
template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_ByType(const PkeInputEventMask &mask, S *&activeEvent) {
uint32_t count, i;
activeEvent = nullptr;
@@ -197,7 +199,7 @@ template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_B
PkeInputSet &set = registeredInputSets[index];
for (int64_t k = 0; k < set.actionCount; ++k) {
PkeInputAction &inputAction = set.actions[k];
- for (int64_t l = 0; l < PKE_INPUT_ACTION_MASK_COUNT; ++l) {
+ for (int64_t l = 0; l < PKE_INPUT_ACTION_MASK_INDEX_COUNT; ++l) {
PkeInputEventMask &evMask = inputAction.masks[l];
if ((evMask.computedHash & mask.computedHash) == InputEventHash{0}) {
continue;
@@ -219,27 +221,27 @@ template<InputEventHash T, typename S> InputEventHash FindActivePkeInputAction_B
}
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
- activeEvent = &registeredCursorEnterEvents[inputAction.eventIndex];
+ activeEvent = &registeredCursorEnterEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
- activeEvent = &registeredCursorPosEvents[inputAction.eventIndex];
+ activeEvent = &registeredCursorPosEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
- activeEvent = &registeredKeyEvents[inputAction.eventIndex];
+ activeEvent = &registeredKeyEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_KEY;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
- activeEvent = &registeredMouseButtonEvents[inputAction.eventIndex];
+ activeEvent = &registeredMouseButtonEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
- activeEvent = &registeredScrollEvents[inputAction.eventIndex];
+ activeEvent = &registeredScrollEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_SCROLL;
}
if constexpr((T & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
- activeEvent = &registeredWindowFocusEvents[inputAction.eventIndex];
+ activeEvent = &registeredWindowFocusEvents[inputAction.event_indices[l]];
return PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS;
}
}
@@ -438,30 +440,39 @@ PkeInputEventHolder PkeInput_Query(const char *actionName) {
PkeInputEventBase *ev = nullptr;
auto *action = FindActionByName(actionName);
InputEventHash type = InputEventHash{0};
- if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER)) {
- PkeCursorEnterEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER, PkeCursorEnterEvent>(action, event);
- ev = event;
- } else if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS)) {
- PkeCursorPosEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS, PkeCursorPosEvent>(action, event);
- ev = event;
- } else if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY)) {
- PkeKeyEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_KEY, PkeKeyEvent>(action, event);
- ev = event;
- } else if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON)) {
- PkeMouseButtonEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON, PkeMouseButtonEvent>(action, event);
- ev = event;
- } else if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL)) {
- PkeScrollEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_SCROLL, PkeScrollEvent>(action, event);
- ev = event;
- } else if (bool(action->primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS)) {
- PkeWindowFocusEvent *event;
- type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS, PkeWindowFocusEvent>(action, event);
- ev = event;
+ for (int32_t i = 0; i < PKE_INPUT_ACTION_MASK_INDEX_COUNT; ++i) {
+ PkeInputEventMask event_mask = action->masks[i];
+ if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER)) {
+ PkeCursorEnterEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER, PkeCursorEnterEvent>(action, event, i);
+ ev = event;
+ break;
+ } else if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS)) {
+ PkeCursorPosEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS, PkeCursorPosEvent>(action, event, i);
+ ev = event;
+ break;
+ } else if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY)) {
+ PkeKeyEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_KEY, PkeKeyEvent>(action, event, i);
+ ev = event;
+ break;
+ } else if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON)) {
+ PkeMouseButtonEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON, PkeMouseButtonEvent>(action, event, i);
+ ev = event;
+ break;
+ } else if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL)) {
+ PkeScrollEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_SCROLL, PkeScrollEvent>(action, event, i);
+ ev = event;
+ break;
+ } else if (bool(event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS)) {
+ PkeWindowFocusEvent *event;
+ type = FindActivePkeInputAction_ByAction<PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS, PkeWindowFocusEvent>(action, event, i);
+ ev = event;
+ break;
+ }
}
return PkeInputEventHolder {
.type = type,
@@ -560,68 +571,55 @@ void PkeInput_ActivateSet(InputActionSetHandle handle) {
auto &set = registeredInputSets[index];
for (int64_t i = 0; i < set.actionCount; ++i) {
PkeInputAction &action = set.actions[i];
- // TODO doesn't support multiple masks - how do we align multiple event types?
- // EX: strafe with keyboard + joystick
- // creating multiple events doesn't make sense
- // - have to keep in sync - isPressed ?
- // - caller has to handle multiple scenarios
- // Maybe we need a unifying event, but that defeats the purpose of this refactor and wastes memory
- // Not to mention that the caller still has to know how to handle the unified response
- // Some combinations of event types cannot be combined, so the caller has to know to ignore certain values
- // Current design also has flaws
- // The caller explicitly casts to the correct event type because we know the event type.
- // If bindings were loaded dynamically, we would have to handle every scenario explicitly for every action
- // Godot has some similarities - is_action_pressed(name) could hide the type, and Godot expects the
- // programmer to know the input type in order to handle
- // If we went for a more query-based approach - PkeInput_GetPressCount(actionTitle) for example
- // there might be fewer oddities
- // Maybe you just have to restrict certain actions to certain input types
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
- action.eventIndex = registeredCursorEnterEvents.next;
- PkeCursorEnterEvent ev{};
- ev.sourceSet = handle;
- ev.isEntered = lastCursorEntered;
- pk_arr_append_t(&registeredCursorEnterEvents, ev);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
- action.eventIndex = registeredCursorPosEvents.next;
- PkeCursorPosEvent ev {};
- ev.sourceSet = handle;
- ev.xMotion = 0;
- ev.yMotion = 0;
- pk_arr_append_t(&registeredCursorPosEvents, ev);
- glfwGetCursorPos(window, &lastMousePos.x, &lastMousePos.y);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
- action.eventIndex = registeredKeyEvents.next;
- PkeKeyEvent ev{};
- ev.sourceSet = handle;
- ev.button = action.primaryHash.button;
- ev.mods = action.primaryHash.mods;
- pk_arr_append_t(&registeredKeyEvents, ev);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
- action.eventIndex = registeredMouseButtonEvents.next;
- PkeMouseButtonEvent ev{};
- ev.sourceSet = handle;
- ev.button = action.primaryHash.button;
- ev.mods = action.primaryHash.mods;
- pk_arr_append_t(&registeredMouseButtonEvents, ev);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
- action.eventIndex = registeredScrollEvents.next;
- PkeScrollEvent ev{};
- ev.sourceSet = handle;
- ev.xMotion = 0;
- ev.yMotion = 0;
- pk_arr_append_t(&registeredScrollEvents, ev);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
- action.eventIndex = registeredWindowFocusEvents.next;
- PkeWindowFocusEvent ev{};
- ev.sourceSet = handle;
- ev.isFocused = lastWindowFocus;
- pk_arr_append_t(&registeredWindowFocusEvents, ev);
+ for (int k = 0; k < PKE_INPUT_ACTION_MASK_INDEX_COUNT; ++k) {
+ PkeInputEventMask event_mask = action.masks[k];
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
+ action.event_indices[k] = registeredCursorEnterEvents.next;
+ PkeCursorEnterEvent ev{};
+ ev.sourceSet = handle;
+ ev.isEntered = lastCursorEntered;
+ pk_arr_append_t(&registeredCursorEnterEvents, ev);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
+ action.event_indices[k] = registeredCursorPosEvents.next;
+ PkeCursorPosEvent ev {};
+ ev.sourceSet = handle;
+ ev.xMotion = 0;
+ ev.yMotion = 0;
+ pk_arr_append_t(&registeredCursorPosEvents, ev);
+ glfwGetCursorPos(window, &lastMousePos.x, &lastMousePos.y);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
+ action.event_indices[k] = registeredKeyEvents.next;
+ PkeKeyEvent ev{};
+ ev.sourceSet = handle;
+ ev.button = event_mask.button;
+ ev.mods = event_mask.mods;
+ pk_arr_append_t(&registeredKeyEvents, ev);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
+ action.event_indices[k] = registeredMouseButtonEvents.next;
+ PkeMouseButtonEvent ev{};
+ ev.sourceSet = handle;
+ ev.button = event_mask.button;
+ ev.mods = event_mask.mods;
+ pk_arr_append_t(&registeredMouseButtonEvents, ev);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
+ action.event_indices[k] = registeredScrollEvents.next;
+ PkeScrollEvent ev{};
+ ev.sourceSet = handle;
+ ev.xMotion = 0;
+ ev.yMotion = 0;
+ pk_arr_append_t(&registeredScrollEvents, ev);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
+ action.event_indices[k] = registeredWindowFocusEvents.next;
+ PkeWindowFocusEvent ev{};
+ ev.sourceSet = handle;
+ ev.isFocused = lastWindowFocus;
+ pk_arr_append_t(&registeredWindowFocusEvents, ev);
+ }
}
}
}
@@ -642,25 +640,26 @@ void PkeInput_DeactivateSet(InputActionSetHandle handle) {
auto &set = registeredInputSets[handleIndex];
for (int64_t i = set.actionCount - 1; i >= 0; --i) {
PkeInputAction &action = set.actions[i];
- // TODO doesn't support multiple masks - how do we align scroll + button
- // WITHOUT having two events allocated?
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredCursorEnterEvents, action.eventIndex);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredCursorPosEvents, action.eventIndex);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredKeyEvents, action.eventIndex);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredMouseButtonEvents, action.eventIndex);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredScrollEvents, action.eventIndex);
- }
- if ((action.primaryHash.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
- pk_arr_remove_at(&registeredWindowFocusEvents, action.eventIndex);
+ for (int k = 0; k < PKE_INPUT_ACTION_MASK_INDEX_COUNT; ++k) {
+ PkeInputEventMask event_mask = action.masks[k];
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredCursorEnterEvents, action.event_indices[k]);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredCursorPosEvents, action.event_indices[k]);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_KEY) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredKeyEvents, action.event_indices[k]);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredMouseButtonEvents, action.event_indices[k]);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_SCROLL) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredScrollEvents, action.event_indices[k]);
+ }
+ if ((event_mask.computedHash & PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS) != InputEventHash{0}) {
+ pk_arr_remove_at(&registeredWindowFocusEvents, action.event_indices[k]);
+ }
}
}
pk_arr_remove_at(&activeInputSetStack, activeInputSetStack.next-1);
@@ -681,6 +680,10 @@ void PkeInput_UnregisterSet(InputActionSetHandle handle) {
pk_arr_remove_at(&registeredInputSets, index);
}
+pk_arr_t<PkeInputSet> &PkeInput_GetInputSets() {
+ return registeredInputSets;
+}
+
void PkeInput_Teardown() {
glfwSetWindowFocusCallback(window, prevWindowFocusCallback);
glfwSetScrollCallback(window, prevScrollCallback);
diff --git a/src/player-input.hpp b/src/player-input.hpp
index f67e966..abb8a40 100644
--- a/src/player-input.hpp
+++ b/src/player-input.hpp
@@ -6,9 +6,13 @@
#include <cstdint>
TypeSafeInt_H(InputActionSetHandle, uint8_t, 0xFF);
-
+TypeSafeInt_constexpr(InputActionSetFlags, uint8_t, 0xFF);
TypeSafeInt_constexpr(InputEventHash, uint16_t, 0xFFFF);
+constexpr InputActionSetFlags PKE_INPUT_ACTION_SET_FLAG_NONE = InputActionSetFlags{0x00};
+constexpr InputActionSetFlags PKE_INPUT_ACTION_SET_FLAG_DO_NOT_SERIALIZE = InputActionSetFlags{0x01};
+constexpr InputActionSetFlags PKE_INPUT_ACTION_SET_FLAG_AUTO_ENABLE = InputActionSetFlags{0x02};
+
const InputEventHash PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER = InputEventHash {0x0001};
const InputEventHash PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS = InputEventHash {0x0002};
const InputEventHash PKE_INPUT_HASH_EVENT_TYPE_KEY = InputEventHash {0x0004};
@@ -94,19 +98,19 @@ struct PkeInputEventMask {
int32_t mods = 0;
};
-constexpr int64_t PKE_INPUT_ACTION_MASK_COUNT = 1;
+#define PKE_INPUT_ACTION_MASK_INDEX_PRIMARY 0
+#define PKE_INPUT_ACTION_MASK_INDEX_SECONDARY 1
+#define PKE_INPUT_ACTION_MASK_INDEX_COUNT 2
struct PkeInputAction {
const char *name;
- union {
- PkeInputEventMask masks[PKE_INPUT_ACTION_MASK_COUNT] = {{}};
- PkeInputEventMask primaryHash;
- };
- int32_t eventIndex;
+ PkeInputEventMask masks[2] = {{},{}};
+ int32_t event_indices[2] = {-1,-1};
};
struct PkeInputSet {
const char *title;
int64_t actionCount;
PkeInputAction *actions;
+ InputActionSetFlags flags;
};
void PkeInput_Tick(double delta);
@@ -116,6 +120,7 @@ InputActionSetHandle PkeInput_RegisterSet(const PkeInputSet &set);
void PkeInput_ActivateSet(InputActionSetHandle handle);
void PkeInput_DeactivateSet(InputActionSetHandle handle);
void PkeInput_UnregisterSet(InputActionSetHandle handle);
+pk_arr_t<PkeInputSet> &PkeInput_GetInputSets();
void PkeInput_Teardown();
#endif /* PKE_PLAYER_INPUT_HPP */
diff --git a/src/scene-types.hpp b/src/scene-types.hpp
index 655c621..d010d12 100644
--- a/src/scene-types.hpp
+++ b/src/scene-types.hpp
@@ -1,9 +1,10 @@
#ifndef PKE_SCENE_TYPES_HPP
#define PKE_SCENE_TYPES_HPP
-#include "pk.h"
-#include "components.hpp"
#include "camera.hpp"
+#include "components.hpp"
+#include "pk.h"
+#include "player-input.hpp"
const uint8_t SCENE_NAME_MAX_LEN = 16;
#define pke_scene_name_printf_format "%16s"
@@ -13,6 +14,7 @@ struct pke_scene : public Entity_Base {
char name[SCENE_NAME_MAX_LEN] = {'\0'};
SceneHandle scene_handle = SceneHandle_MAX;
pk_arr_t<CameraHandle> cameras;
+ pk_arr_t<InputActionSetHandle> input_handles;
};
#endif /* PKE_SCENE_TYPES_HPP */
diff --git a/src/scene.cpp b/src/scene.cpp
index ad6b502..2c47356 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -89,12 +89,17 @@ pk_bkt_arr *pke_scene_get_scenes() {
}
void pke_scene_remove(SceneHandle handle) {
+ uint32_t i;
pke_scene *scn = &scene_mstr.bc[handle];
assert(scn != nullptr && "[pke_scene_remove] Failed to find scene by requested SceneHandle");
ECS_MarkForRemoval(scn);
- for (long i = 0; i < scn->cameras.next; ++i) {
+ for (i = 0; i < scn->cameras.next; ++i) {
PkeCamera_Destroy(scn->cameras[i]);
}
+ for (i = 0; i < scn->input_handles.next; ++i) {
+ PkeInput_DeactivateSet(scn->input_handles[i]);
+ PkeInput_UnregisterSet(scn->input_handles[i]);
+ }
if (scn->file_path.reserved > 0) {
pk_delete<char>(scn->file_path.val, scn->file_path.reserved);
}
@@ -102,6 +107,7 @@ void pke_scene_remove(SceneHandle handle) {
scn->name[0] = '\0';
scn->scene_handle = SceneHandle_MAX;
pk_arr_reset(&scn->cameras);
+ pk_arr_reset(&scn->input_handles);
pk_bkt_arr_free_handle(&scene_mstr.bc, handle);
}
@@ -112,3 +118,11 @@ void pke_scene_register_camera(SceneHandle scene_handle, CameraHandle cameraHand
assert(scene != nullptr && "Failed to find scene by requested SceneHandle");
pk_arr_append(&scene->cameras, &cameraHandle);
}
+
+void pke_scene_register_input_action_set(SceneHandle scene_handle, InputActionSetHandle handle) {
+ assert(scene_handle != SceneHandle_MAX);
+ assert(handle != InputActionSetHandle_MAX);
+ pke_scene *scene = pke_scene_get_by_handle(scene_handle);
+ assert(scene != nullptr && "Failed to find scene by requested SceneHandle");
+ pk_arr_append_t(&scene->input_handles, handle);
+}
diff --git a/src/scene.hpp b/src/scene.hpp
index 6e76987..6c80b39 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -16,5 +16,6 @@ pk_bkt_arr *pke_scene_get_scenes();
void pke_scene_remove(SceneHandle handle);
void pke_scene_register_camera(SceneHandle scene_handle, CameraHandle cameraHandle);
+void pke_scene_register_input_action_set(SceneHandle scene_handle, InputActionSetHandle handle);
#endif /* PKE_SCENE_HPP */
diff --git a/src/serialization-input.cpp b/src/serialization-input.cpp
new file mode 100644
index 0000000..e81665a
--- /dev/null
+++ b/src/serialization-input.cpp
@@ -0,0 +1,207 @@
+
+#include "serialization-input.hpp"
+
+#include "compile-time-assert.hpp"
+#include "pk.h"
+#include "scene.hpp"
+
+#include <cstring>
+
+pk_handle pke_serialize_input_action(srlztn_serialize_helper *h, PkeInputAction *action) {
+ char *s;
+ int len;
+ pke_kve kve{};
+ pke_kve_container kvec{};
+
+ kvec.srlztn_handle = h->handle_head;
+ kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_INPUT_ACTION);
+ kvec.bkt = h->bkt;
+ kvec.arr.bkt = h->bkt;
+ kvec.children.bkt = h->bkt;
+ kvec.child_handles.bkt = h->bkt;
+ h->handle_head.itemIndex++;
+
+ compt_a<40==sizeof(PkeInputAction)>();
+ {
+ kve.key = SRLZTN_INPUT_ACTION_NAME;
+ len = strlen(action->name)+1;
+ s = pk_new<char>(len, h->bkt);
+ sprintf(s, "%s", action->name);
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+ for (int i = 0; i < PKE_INPUT_ACTION_MASK_INDEX_COUNT; ++i) {
+ if (action->masks[i].computedHash == InputEventHash{0}) {
+ continue;
+ }
+ {
+ kve.key = SRLZTN_INPUT_ACTION_MASK_HASH;
+ len = snprintf(NULL, 0, "0x%.4hX", static_cast<InputEventHash_T>(action->masks[i].computedHash));
+ s = pk_new<char>(len+1, h->bkt);
+ sprintf(s, "0x%.4hX", static_cast<InputEventHash_T>(action->masks[i].computedHash));
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+ {
+ kve.key = SRLZTN_INPUT_ACTION_MASK_BUTTON;
+ len = snprintf(NULL, 0, "%i", action->masks[i].button);
+ s = pk_new<char>(len+1, h->bkt);
+ sprintf(s, "%i", action->masks[i].button);
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+ {
+ kve.key = SRLZTN_INPUT_ACTION_MASK_MODS;
+ len = snprintf(NULL, 0, "%i", action->masks[i].mods);
+ s = pk_new<char>(len+1, h->bkt);
+ sprintf(s, "%i", action->masks[i].mods);
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+ }
+
+ pk_arr_append_t(&h->kvp_containers, kvec);
+ return kvec.srlztn_handle;
+}
+
+void pke_deserialize_input_action(srlztn_deserialize_helper *h, pke_kve_container *kvec, PkeInputAction &action) {
+ (void)h;
+ uint32_t i;
+ int32_t mask_index = -1;
+ char *s;
+ pke_kve *kve = nullptr;
+ PK_STN_RES stn_res = PK_STN_RES(0);
+
+ compt_a<40==sizeof(PkeInputAction)>();
+ for (i = 0; i < kvec->arr.next; ++i) {
+ kve = &kvec->arr[i];
+ if (strncmp(kve->key, SRLZTN_INPUT_ACTION_NAME, strlen(SRLZTN_INPUT_ACTION_NAME)) == 0) {
+ // TODO specific bkt?
+ s = pk_new<char>(strlen(kve->val)+1, NULL);
+ sprintf(s, "%s", kve->key);
+ action.name = s;
+ continue;
+ }
+ if (strncmp(kve->key, SRLZTN_INPUT_ACTION_MASK_HASH, strlen(SRLZTN_INPUT_ACTION_MASK_HASH)) == 0) {
+ mask_index += 1;
+ assert(mask_index < PKE_INPUT_ACTION_MASK_INDEX_COUNT);
+ InputEventHash_T hash;
+ stn_res = pk_stn(&hash, kve->val, NULL, 16);
+ if (stn_res != PK_STN_RES_SUCCESS) {
+ fprintf(stderr, "[%s] Err '%u' parsing '%s' primary from: '%s'\n", __FILE__, stn_res, SRLZTN_INPUT_ACTION_MASK_HASH, kve->val);
+ continue;
+ }
+ action.masks[mask_index].computedHash = InputEventHash{hash};
+ continue;
+ }
+ if (strncmp(kve->key, SRLZTN_INPUT_ACTION_MASK_BUTTON, strlen(SRLZTN_INPUT_ACTION_MASK_BUTTON)) == 0) {
+ assert(mask_index >= 0);
+ assert(mask_index < PKE_INPUT_ACTION_MASK_INDEX_COUNT);
+ stn_res = pk_stn(&action.masks[mask_index].button, kve->val, NULL);
+ if (stn_res != PK_STN_RES_SUCCESS) {
+ fprintf(stderr, "[%s] Err '%u' parsing '%s' primary from: '%s'\n", __FILE__, stn_res, SRLZTN_INPUT_ACTION_MASK_BUTTON, kve->val);
+ }
+ continue;
+ }
+ if (strncmp(kve->key, SRLZTN_INPUT_ACTION_MASK_MODS, strlen(SRLZTN_INPUT_ACTION_MASK_MODS)) == 0) {
+ assert(mask_index >= 0);
+ assert(mask_index < PKE_INPUT_ACTION_MASK_INDEX_COUNT);
+ stn_res = pk_stn(&action.masks[mask_index].mods, kve->val, NULL);
+ if (stn_res != PK_STN_RES_SUCCESS) {
+ fprintf(stderr, "[%s] Err '%u' parsing '%s' primary from: '%s'\n", __FILE__, stn_res, SRLZTN_INPUT_ACTION_MASK_MODS, kve->val);
+ }
+ continue;
+ }
+ }
+}
+
+pk_handle pke_serialize_input_set(srlztn_serialize_helper *h, PkeInputSet *input_set) {
+ char *s;
+ int len;
+ pke_kve kve{};
+ pke_kve_container kvec{};
+
+ kvec.srlztn_handle = h->handle_head;
+ kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_INPUT_SET);
+ kvec.bkt = h->bkt;
+ kvec.arr.bkt = h->bkt;
+ kvec.children.bkt = h->bkt;
+ kvec.child_handles.bkt = h->bkt;
+ h->handle_head.itemIndex++;
+
+ for (int i = 0; i < input_set->actionCount; ++i) {
+ pk_handle child_handle = pke_serialize_input_action(h, &input_set->actions[i]);
+ pk_arr_append_t(&kvec.child_handles, child_handle);
+ }
+
+ compt_a<32==sizeof(PkeInputSet)>();
+ {
+ kve.key = SRLZTN_INPUT_SET_TITLE;
+ len = strlen(input_set->title)+1;
+ s = pk_new<char>(len, h->bkt);
+ sprintf(s, "%s", input_set->title);
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+ {
+ kve.key = SRLZTN_INPUT_SET_FLAGS;
+ len = snprintf(NULL, 0, "0x%.04X", static_cast<InputActionSetFlags_T>(input_set->flags));
+ s = pk_new<char>(len+1, h->bkt);
+ sprintf(s, "0x%.04X", static_cast<InputActionSetFlags_T>(input_set->flags));
+ kve.val = s;
+ kve.end = SRLZTN_KVE_END;
+ pk_arr_append_t(&kvec.arr, kve);
+ }
+
+ pk_arr_append_t(&h->kvp_containers, kvec);
+ return kvec.srlztn_handle;
+}
+
+void pke_deserialize_input_set(srlztn_deserialize_helper *h, pke_kve_container *kvec) {
+ (void)h;
+ uint32_t i, k;
+ char *s;
+ pke_kve *kve = nullptr;
+ PkeInputSet set{};
+ PK_STN_RES stn_res = PK_STN_RES(0);
+
+ // TODO specific bucket
+ set.actionCount = kvec->children.next;
+ set.actions = pk_new<PkeInputAction>(kvec->children.next, NULL);
+ for (k = 0; k < set.actionCount; ++k) {
+ pke_deserialize_input_action(h, kvec->children[k], set.actions[k]);
+ }
+
+ compt_a<40==sizeof(PkeInputAction)>();
+ for (i = 0; i < kvec->arr.next; ++i) {
+ kve = &kvec->arr[i];
+ if (strncmp(kve->key, SRLZTN_INPUT_SET_TITLE, strlen(SRLZTN_INPUT_SET_TITLE)) == 0) {
+ // TODO specific bkt?
+ s = pk_new<char>(strlen(kve->val)+1, NULL);
+ sprintf(s, "%s", kve->key);
+ set.title = s;
+ continue;
+ }
+ if (strncmp(kve->key, SRLZTN_INPUT_SET_FLAGS, strlen(SRLZTN_INPUT_SET_FLAGS)) == 0) {
+ InputActionSetFlags_T flags;
+ stn_res = pk_stn(&flags, kve->val, NULL, 16);
+ if (stn_res != PK_STN_RES_SUCCESS) {
+ fprintf(stderr, "[%s] Err '%u' parsing '%s' primary from: '%s'\n", __FILE__, stn_res, SRLZTN_INPUT_SET_FLAGS, kve->val);
+ continue;
+ }
+ set.flags = InputActionSetFlags{flags};
+ continue;
+ }
+ }
+
+ InputActionSetHandle action_set_handle = PkeInput_RegisterSet(set);
+ pke_scene_register_input_action_set(h->scene->scene_handle, action_set_handle);
+ if (PK_HAS_FLAG(set.flags, PKE_INPUT_ACTION_SET_FLAG_AUTO_ENABLE)) {
+ PkeInput_ActivateSet(action_set_handle);
+ }
+}
diff --git a/src/serialization-input.hpp b/src/serialization-input.hpp
new file mode 100644
index 0000000..6a7dde3
--- /dev/null
+++ b/src/serialization-input.hpp
@@ -0,0 +1,13 @@
+#ifndef PKE_SERIALIZATION_INPUT_HPP
+#define PKE_SERIALIZATION_INPUT_HPP
+
+#include "player-input.hpp"
+#include "serialization.hpp"
+
+pk_handle pke_serialize_input_action(srlztn_serialize_helper *h, PkeInputAction *action);
+void pke_deserialize_input_action(srlztn_deserialize_helper *h, pke_kve_container *kvec);
+
+pk_handle pke_serialize_input_set(srlztn_serialize_helper *h, PkeInputSet *input_set);
+void pke_deserialize_input_set(srlztn_deserialize_helper *h, pke_kve_container *kvec);
+
+#endif /* PKE_SERIALIZATION_INPUT_HPP */
diff --git a/src/serialization.cpp b/src/serialization.cpp
index e7e1d4c..3bd589d 100644
--- a/src/serialization.cpp
+++ b/src/serialization.cpp
@@ -2,11 +2,13 @@
#include "serialization.hpp"
#include "font.hpp"
#include "pk.h"
+#include "player-input.hpp"
#include "serialization-component.hpp"
#include "serialization-camera.hpp"
#include "camera.hpp"
#include "ecs.hpp"
#include "serialization-font.hpp"
+#include "serialization-input.hpp"
#include "serialization-static-ui.hpp"
#include "static-ui.hpp"
@@ -69,6 +71,14 @@ void pke_serialize_scene(srlztn_serialize_helper *h) {
CamIterFn cam_iter_cb{};
InstIterFn inst_iter_cb{};
+ pk_arr_t<PkeInputSet> &sets = PkeInput_GetInputSets();
+ for (uint32_t i = 0; i < sets.next; ++i) {
+ if (PK_HAS_FLAG(sets[i].flags, PKE_INPUT_ACTION_SET_FLAG_DO_NOT_SERIALIZE)) {
+ continue;
+ }
+ pke_serialize_input_set(h, &sets[i]);
+ }
+
FontTypeIndex font_type_count;
FontType *fonts = FontType_GetFonts(font_type_count);
for (FontTypeIndex_T b = 0; b < (FontTypeIndex_T)font_type_count; ++b) {
@@ -110,6 +120,10 @@ void pke_deserialize_scene(srlztn_deserialize_helper *h) {
for (i = 0; i < h->kvp_containers.next; ++i) {
kvec = &h->kvp_containers[i];
+ if (strcmp(kvec->type_code.val, SRLZTN_OBJ_INPUT_SET) == 0) {
+ pke_deserialize_input_set(h, kvec);
+ continue;
+ }
if (strcmp(kvec->type_code.val, SRLZTN_OBJ_FONT_RENDER) == 0) {
pke_deserialize_font_render(h, kvec);
continue;
diff --git a/src/serialization.hpp b/src/serialization.hpp
index e26667f..fe7d427 100644
--- a/src/serialization.hpp
+++ b/src/serialization.hpp
@@ -26,6 +26,8 @@ iccsc SRLZTN_OBJ_UI_BOX = "UIBox";
iccsc SRLZTN_OBJ_FONT_RENDER = "FontRender";
iccsc SRLZTN_OBJ_FONT_RENDER_SETTINGS = "FontRenderSettings";
iccsc SRLZTN_OBJ_UI_BOX_TYPE_DATA = "UIBoxTypeData";
+iccsc SRLZTN_OBJ_INPUT_ACTION = "InputAction";
+iccsc SRLZTN_OBJ_INPUT_SET = "InputSet";
iccsc SRLZTN_POSROT_POS = "Position:";
iccsc SRLZTN_POSROT_ROT = "Rotation:";
@@ -68,6 +70,14 @@ iccsc SRLZTN_UI_FONT_RENDER_SETTINGS_SURFACE_AREA_SIZE = "SurfaceAreaSize:";
iccsc SRLZTN_UI_FONT_RENDER_SETTINGS_SURFACE_AREA_POS = "SurfaceAreaPos:";
iccsc SRLZTN_UI_FONT_RENDER_SETTINGS_SURFACE_AREA_FLAGS = "SurfaceAreaFlags:";
+iccsc SRLZTN_INPUT_ACTION_NAME = "Name:";
+iccsc SRLZTN_INPUT_ACTION_MASK_HASH = "MaskHash:";
+iccsc SRLZTN_INPUT_ACTION_MASK_BUTTON = "MaskButton:";
+iccsc SRLZTN_INPUT_ACTION_MASK_MODS = "MaskMods:";
+
+iccsc SRLZTN_INPUT_SET_TITLE = "Title:";
+iccsc SRLZTN_INPUT_SET_FLAGS = "Flags:";
+
struct srlztn_ecs_mapping {
pk_uuid serialized_uuid = pk_uuid_zed;
Entity_Base *created_entity = nullptr;