Skip to content

Commit e6765b6

Browse files
committed
More changes to the InputAction builder API.
* Fixed handling of multiple keys bound to a single input source. * Fixed button events fighting over source status. (Pressed takes priority over others) * Fixed action runtimes to create way to many source storage objects.
1 parent 3f30f38 commit e6765b6

File tree

11 files changed

+361
-294
lines changed

11 files changed

+361
-294
lines changed

source/code/core/core/public/ice/concept/pimpl_type.hxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ namespace ice::concepts
2626

2727
// TODO: Move this somewhere else!
2828
PimplType(PimplType&& other) noexcept = delete;
29-
auto operator=(PimplType&& other) noexcept -> PimplType & = delete;
29+
auto operator=(PimplType&& other) noexcept -> PimplType& = delete;
3030
PimplType(PimplType const& other) noexcept = delete;
31-
auto operator=(PimplType const& other) noexcept -> PimplType & = delete;
31+
auto operator=(PimplType const& other) noexcept -> PimplType& = delete;
3232

3333
protected:
3434
template<typename Self>
@@ -51,4 +51,4 @@ namespace ice::concepts
5151
return *reinterpret_cast<Internal<Self>*>(self._internal);
5252
}
5353

54-
}
54+
} // namespace ice::concepts

source/code/core/memsys/private/mem_allocator.cxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ namespace ice
194194

195195
AllocatorBase<true>::~AllocatorBase() noexcept
196196
{
197+
// TODO: Introduce low-level logger just for debug and dev builds.
197198
ICE_ASSERT_CORE(allocation_count() == 0);
198199
}
199200

source/code/systems/input_action_system/private/input_action_dsl_layer_builder.cxx

Lines changed: 79 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ namespace ice
6161
}
6262

6363
ice::InputActionBuilder::Source source = _builder->define_source(node.data().name, type);
64-
if (arctic::SyntaxNode const binding = node.child<ice::syntax::LayerInputBinding>(); binding)
64+
arctic::SyntaxNode binding = node.child<ice::syntax::LayerInputBinding>();
65+
while (binding)
6566
{
6667
using ice::input::DeviceType;
6768
using ice::input::KeyboardKey;
@@ -103,6 +104,9 @@ namespace ice
103104
source.add_button(mouseinput);
104105
}
105106
}
107+
108+
// TODO: We need to fix building layers with sources having multiple inputs, before enabling this.
109+
binding = binding.sibling<ice::syntax::LayerInputBinding>();
106110
}
107111

108112
ICE_LOG(LogSeverity::Info, LogTag::Engine, "Source: {}", node.data().name);
@@ -135,17 +139,8 @@ namespace ice
135139
{
136140
if (child.type() == ice::syntax::SyntaxEntity_LayerActionCondition)
137141
{
138-
visit_cond(action, child.to<ice::syntax::LayerActionWhen>());
139-
140-
arctic::SyntaxNode<> steps = child.child();
141-
while (steps != false)
142-
{
143-
if (steps.type() == ice::syntax::SyntaxEntity_LayerActionStep)
144-
{
145-
visit_step(action, steps.to<ice::syntax::LayerActionStep>());
146-
}
147-
steps = steps.sibling();
148-
}
142+
// Returns the final node of the series. The next sibling is either a: modifier, condition_series or action
143+
child = visit_cond(action.add_condition_series(), child.to<ice::syntax::LayerActionWhen>());
149144
}
150145
else if (child.type() == ice::syntax::SyntaxEntity_LayerActionModifier)
151146
{
@@ -155,72 +150,98 @@ namespace ice
155150
}
156151
}
157152

158-
void InputActionDSLLayerBuilder::visit_cond(
159-
ice::InputActionBuilder::Action& action,
153+
auto InputActionDSLLayerBuilder::visit_cond(
154+
ice::InputActionBuilder::ConditionSeries series,
160155
arctic::SyntaxNode<ice::syntax::LayerActionWhen> node
161-
) noexcept
156+
) noexcept -> arctic::SyntaxNode<>
162157
{
163158
using enum ice::InputActionCondition;
164159

165-
ice::syntax::LayerActionWhen const& cond = node.to<ice::syntax::LayerActionWhen>().data();
166-
ICE_LOG(LogSeverity::Debug, LogTag::Tool, "- {} {}.{} {} {}", cond.type.value, cond.source_type.value, cond.source_name, cond.condition.value, cond.param.value);
167-
168-
bool const from_action = cond.source_type.type == grammar::UCT_Action
169-
|| (cond.source_type.type == arctic::TokenType::Invalid && cond.source_name.empty()); // "self"
170-
ice::InputActionCondition const condition = detail::condition_from_dsl(cond.condition, from_action);
171-
ice::InputActionConditionFlags flags = InputActionConditionFlags::None;
160+
arctic::SyntaxNode<ice::syntax::LayerActionWhen> cond_node = node;
161+
ICE_ASSERT_CORE(cond_node.data().type.type == grammar::UCT_When);
172162

173-
// No siblings or next sibling: "when" == "final" condition.
174-
if (auto sib = node.sibling<ice::syntax::LayerActionWhen>(); !sib || sib.data().type.type == grammar::UCT_When)
175-
{
176-
flags |= InputActionConditionFlags::Final;
177-
}
178-
if (node.child<syntax::LayerActionStep>()) // Only steps can introduce children.
179-
{
180-
flags |= InputActionConditionFlags::RunSteps;
181-
}
182-
if (cond.flag_series)
183-
{
184-
flags |= InputActionConditionFlags::SeriesCheck;
185-
}
186-
if (cond.type.type == grammar::UCT_WhenAnd) // Only steps can introduce children.
187-
{
188-
flags |= InputActionConditionFlags::SeriesAnd;
189-
}
190-
else // if (cond.type.type == grammar::UCT_WhenOr) // Only steps can introduce children.
163+
ICE_LOG(LogSeverity::Debug, LogTag::Tool, "New condition series");
164+
do
191165
{
192-
flags |= InputActionConditionFlags::SeriesOr;
193-
}
166+
node = cond_node; // Set the node to the current cond_node, necessary to return a valid node
167+
ice::syntax::LayerActionWhen const& cond = cond_node.data();
168+
ICE_LOG(LogSeverity::Debug, LogTag::Tool, "- {} {}.{} {} {}", cond.type.value, cond.source_type.value, cond.source_name, cond.condition.value, cond.param.value);
169+
170+
bool const from_action = cond.source_type.type == grammar::UCT_Action
171+
|| (cond.source_type.type == arctic::TokenType::Invalid && cond.source_name.empty()); // "self"
172+
ice::InputActionCondition const condition = detail::condition_from_dsl(cond.condition, from_action);
173+
174+
ice::InputActionConditionFlags flags = InputActionConditionFlags::None;
175+
if (cond_node.child<syntax::LayerActionStep>())
176+
{
177+
flags |= InputActionConditionFlags::RunSteps;
178+
}
179+
if (cond.flag_series)
180+
{
181+
flags |= InputActionConditionFlags::SeriesCheck;
182+
}
194183

195-
// TODO: SeriesCheck
196-
// TODO: non-Final
184+
if (cond.type.type == grammar::UCT_WhenAnd)
185+
{
186+
flags |= InputActionConditionFlags::SeriesAnd;
187+
}
188+
// If we are When or WhenOr, we default to 'SeriesOr'
189+
else
190+
{
191+
flags |= InputActionConditionFlags::SeriesOr;
192+
}
197193

198-
ice::f32 param = 0.0f;
199-
bool const is_param_condition = condition == Equal || condition == NotEqual
200-
|| condition == Greater || condition == GreaterOrEqual
201-
|| condition == Lower || condition == LowerOrEqual;
202-
if (is_param_condition)
194+
ice::f32 param = 0.0f;
195+
bool const is_param_condition = condition == Equal || condition == NotEqual
196+
|| condition == Greater || condition == GreaterOrEqual
197+
|| condition == Lower || condition == LowerOrEqual;
198+
if (is_param_condition)
199+
{
200+
ice::from_chars(cond.param.value, param);
201+
}
202+
203+
// Adds the new condition
204+
series.add_condition(
205+
cond.source_name, condition, flags, param, from_action
206+
);
207+
208+
// Move over all steps defined for this condition
209+
arctic::SyntaxNode<> steps = cond_node.child();
210+
while (steps != false)
211+
{
212+
if (steps.type() == ice::syntax::SyntaxEntity_LayerActionStep)
213+
{
214+
visit_step(series, steps.to<ice::syntax::LayerActionStep>());
215+
}
216+
steps = steps.sibling();
217+
}
218+
219+
cond_node = cond_node.sibling<ice::syntax::LayerActionWhen>();
220+
} while (cond_node && cond_node.data().type.type != grammar::UCT_When);
221+
222+
// TODO: Check for '.continue' flag to skip setting 'Final' flag here
223+
//if (/* DOES NOT HAVE '.continue' flag */)
203224
{
204-
ice::from_chars(cond.param.value, param);
225+
series.set_finished();
205226
}
206227

207-
action.add_condition(cond.source_name, condition, flags, param, from_action);
228+
return node;
208229
}
209230

210231
void InputActionDSLLayerBuilder::visit_step(
211-
ice::InputActionBuilder::Action& action,
232+
ice::InputActionBuilder::ConditionSeries& condition_series,
212233
arctic::SyntaxNode<ice::syntax::LayerActionStep> node
213234
) noexcept
214235
{
215236
ice::syntax::LayerActionStep const& info = node.data();
216237
ice::InputActionStep const step = detail::step_from_dsl(info.step);
217238
if (step == InputActionStep::Set || step == InputActionStep::Add || step == InputActionStep::Sub)
218239
{
219-
action.add_step(info.source, step, info.destination);
240+
condition_series.add_step(info.source, step, info.destination);
220241
}
221242
else
222243
{
223-
action.add_step(step);
244+
condition_series.add_step(step);
224245
}
225246
}
226247

@@ -275,19 +296,19 @@ namespace ice
275296
{
276297
result = KeyboardKey::Space;
277298
}
278-
else if (value == "up")
299+
else if (ice::compare(value, "up") == CompareResult::Equal)
279300
{
280301
result = KeyboardKey::Up;
281302
}
282-
else if (value == "down")
303+
else if (ice::compare(value, "down") == CompareResult::Equal)
283304
{
284305
result = KeyboardKey::Down;
285306
}
286-
else if (value == "left")
307+
else if (ice::compare(value, "left") == CompareResult::Equal)
287308
{
288309
result = KeyboardKey::Left;
289310
}
290-
else if (value == "right")
311+
else if (ice::compare(value, "right") == CompareResult::Equal)
291312
{
292313
result = KeyboardKey::Right;
293314
}
@@ -328,57 +349,6 @@ namespace ice
328349
return result;
329350
}
330351

331-
#if 0
332-
auto detail::mod_from_dsl(arctic::String value) noexcept -> ice::input::KeyboardMod
333-
{
334-
using ice::input::KeyboardMod;
335-
336-
if (strnicmp(value.data(), "mode", 4) == 0)
337-
{
338-
return KeyboardMod::Mode;
339-
}
340-
else if (strnicmp(value.data(), "numlock", 4) == 0)
341-
{
342-
return KeyboardMod::NumLock;
343-
}
344-
else if (strnicmp(value.data(), "capslock", 4) == 0)
345-
{
346-
return KeyboardMod::CapsLock;
347-
}
348-
349-
// If left == 2, if right == 1, else 0
350-
KeyboardMod result = KeyboardMod::None;
351-
ICE_ASSERT_CORE(value.size() >= 3);
352-
353-
ice::u8 const mod_side = (value[0] == 'l' ? 2 : (value[0] == 'r' ? 1 : 0));
354-
value = value.substr(ice::u32(mod_side != 0)); // We remove the prefix ('l' or 'r') from the remaining value.
355-
356-
switch (value[0])
357-
{
358-
case 's':
359-
case 'S':
360-
result = static_cast<KeyboardMod>(3 ^ mod_side);
361-
break;
362-
case 'c':
363-
case 'C':
364-
result = static_cast<KeyboardMod>((3 ^ mod_side) << 2);
365-
break;
366-
case 'a':
367-
case 'A':
368-
result = static_cast<KeyboardMod>((3 ^ mod_side) << 4);
369-
break;
370-
case 'g':
371-
case 'G':
372-
result = static_cast<KeyboardMod>((3 ^ mod_side) << 8);
373-
break;
374-
default:
375-
break;
376-
}
377-
378-
return result;
379-
}
380-
#endif
381-
382352
auto detail::mouse_from_dsl(arctic::String value) noexcept -> ice::input::MouseInput
383353
{
384354
using ice::input::MouseInput;

source/code/systems/input_action_system/private/input_action_dsl_layer_builder.hxx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ namespace ice
1717
void visit_source(arctic::SyntaxNode<ice::syntax::LayerSource> node) noexcept;
1818
void visit_layer(arctic::SyntaxNode<ice::syntax::LayerAction> node) noexcept;
1919

20-
void visit_cond(
21-
ice::InputActionBuilder::Action& action,
20+
auto visit_cond(
21+
ice::InputActionBuilder::ConditionSeries series,
2222
arctic::SyntaxNode<ice::syntax::LayerActionWhen> node
23-
) noexcept;
23+
) noexcept -> arctic::SyntaxNode<>;
2424

2525
void visit_step(
26-
ice::InputActionBuilder::Action& action,
26+
ice::InputActionBuilder::ConditionSeries& condition_series,
2727
arctic::SyntaxNode<ice::syntax::LayerActionStep> node
2828
) noexcept;
2929

source/code/systems/input_action_system/private/input_action_layer.cxx

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ namespace ice
128128
ice::ucount count_processed = 0;
129129
ice::ucount const count_events = ice::count(input_events);
130130

131+
// Reset the temporary events.
132+
for (ice::InputActionSourceInputInfo const& src : _sources)
133+
{
134+
ice::InputActionSource* const values = source_values[src.storage_offset];
135+
ice::u32 const count_values = 1 + ice::u32(src.type == InputActionSourceType::Axis2d);
136+
137+
for (ice::u32 idx = 0; idx < count_values; ++idx)
138+
{
139+
values[idx].temp_event = InputActionSourceEvent::None;
140+
}
141+
}
142+
131143
for (ice::InputActionSourceInputInfo const& src : _sources)
132144
{
133145
ice::InputActionSource* const values = source_values[src.storage_offset];
@@ -160,36 +172,48 @@ namespace ice
160172

161173
if (ev.value_type == ice::input::InputValueType::Trigger)
162174
{
163-
value = { InputActionSourceEvent::Trigger, ev.value.axis.value_f32 };
175+
value = { ev.value.axis.value_f32, InputActionSourceEvent::Trigger };
164176
}
165177
else if (ev.value_type == ice::input::InputValueType::AxisInt)
166178
{
167-
value = { InputActionSourceEvent::Axis, ice::f32(ev.value.axis.value_i32) };
179+
value = { ice::f32(ev.value.axis.value_i32), InputActionSourceEvent::Axis };
168180
}
169181
else if (ev.value_type == ice::input::InputValueType::AxisFloat)
170182
{
171183
// Check for deadzone values
172184
if (src.param < ev.value.axis.value_f32)
173185
{
174-
value = { InputActionSourceEvent::Axis, ev.value.axis.value_f32 };
186+
value = { ev.value.axis.value_f32, InputActionSourceEvent::Axis };
175187
}
176188
else
177189
{
178-
value = { InputActionSourceEvent::AxisDeadzone, ev.value.axis.value_f32 };
190+
value = { ev.value.axis.value_f32, InputActionSourceEvent::AxisDeadzone };
179191
}
180192
}
181-
else
193+
else if (value.temp_event != InputActionSourceEvent::KeyPress)
182194
{
183195
value = {
196+
ev.value.button.state.released
197+
? 0.0f : 1.0f,
184198
ev.value.button.state.released
185199
? InputActionSourceEvent::KeyRelease
186200
: InputActionSourceEvent::KeyPress,
187-
ev.value.button.state.released
188-
? 0.0f : 1.0f,
189201
};
190202
}
191203
}
192204

205+
// Select the final events.
206+
for (ice::InputActionSourceInputInfo const& src : _sources)
207+
{
208+
ice::InputActionSource* const values = source_values[src.storage_offset];
209+
ice::u32 const count_values = 1 + ice::u32(src.type == InputActionSourceType::Axis2d);
210+
211+
for (ice::u32 idx = 0; idx < count_values; ++idx)
212+
{
213+
values[idx].event = ice::exchange(values[idx].temp_event, InputActionSourceEvent::None);
214+
}
215+
}
216+
193217
// Clear the end of the events list
194218
for (ice::u32 idx = 1; idx <= count_processed; ++idx)
195219
{
@@ -308,7 +332,7 @@ namespace ice
308332
// If the series is not successful, just continue
309333
if (series_success == false || runtime->enabled == false)
310334
{
311-
// If the action finaly failes, we reset the state so we can again start counting from 0
335+
// If the action finaly fails, we reset the state so we can again start counting from 0
312336
runtime->state = 0;
313337
runtime->active = false;
314338
continue;

0 commit comments

Comments
 (0)