generated from SGDA/GodotExampleProject
feat: made sure the aspect ration fit a pixel art game and added useful addons
This commit is contained in:
65
addons/guide/triggers/guide_trigger.gd
Normal file
65
addons/guide/triggers/guide_trigger.gd
Normal file
@ -0,0 +1,65 @@
|
||||
@tool
|
||||
@icon("res://addons/guide/triggers/guide_trigger.svg")
|
||||
class_name GUIDETrigger
|
||||
extends Resource
|
||||
|
||||
enum GUIDETriggerState {
|
||||
## The trigger did not fire.
|
||||
NONE,
|
||||
## The trigger's conditions are partially met
|
||||
ONGOING,
|
||||
## The trigger has fired.
|
||||
TRIGGERED
|
||||
}
|
||||
|
||||
enum GUIDETriggerType {
|
||||
# If there are more than one explicit triggers at least one must trigger
|
||||
# for the action to trigger.
|
||||
EXPLICIT = 1,
|
||||
# All implicit triggers must trigger for the action to trigger.
|
||||
IMPLICIT = 2,
|
||||
# All blocking triggers prevent the action from triggering.
|
||||
BLOCKING = 3
|
||||
}
|
||||
|
||||
|
||||
@export var actuation_threshold:float = 0.5
|
||||
var _last_value:Vector3
|
||||
|
||||
## Returns the trigger type of this trigger.
|
||||
func _get_trigger_type() -> GUIDETriggerType:
|
||||
return GUIDETriggerType.EXPLICIT
|
||||
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _is_actuated(input:Vector3, value_type:GUIDEAction.GUIDEActionValueType) -> bool:
|
||||
match value_type:
|
||||
GUIDEAction.GUIDEActionValueType.AXIS_1D, GUIDEAction.GUIDEActionValueType.BOOL:
|
||||
return _is_axis1d_actuated(input)
|
||||
GUIDEAction.GUIDEActionValueType.AXIS_2D:
|
||||
return _is_axis2d_actuated(input)
|
||||
GUIDEAction.GUIDEActionValueType.AXIS_3D:
|
||||
return _is_axis3d_actuated(input)
|
||||
|
||||
return false
|
||||
|
||||
## Checks if a 1D input is actuated.
|
||||
func _is_axis1d_actuated(input:Vector3) -> bool:
|
||||
return is_finite(input.x) and abs(input.x) > actuation_threshold
|
||||
|
||||
## Checks if a 2D input is actuated.
|
||||
func _is_axis2d_actuated(input:Vector3) -> bool:
|
||||
return is_finite(input.x) and is_finite(input.y) and Vector2(input.x, input.y).length_squared() > actuation_threshold * actuation_threshold
|
||||
|
||||
## Checks if a 3D input is actuated.
|
||||
func _is_axis3d_actuated(input:Vector3) -> bool:
|
||||
return input.is_finite() and input.length_squared() > actuation_threshold * actuation_threshold
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "GUIDETrigger"
|
||||
|
||||
func _editor_description() -> String:
|
||||
return ""
|
1
addons/guide/triggers/guide_trigger.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://x74mnwgr08a7
|
12
addons/guide/triggers/guide_trigger.svg
Normal file
12
addons/guide/triggers/guide_trigger.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1.07241,0,0,1.07396,-3.11767,-2.34767)">
|
||||
<path d="M17.827,2.164C26.061,2.164 32.747,8.85 32.747,17.084C32.747,25.319 26.061,32.004 17.827,32.004C9.592,32.004 2.907,25.319 2.907,17.084C2.907,8.85 9.592,2.164 17.827,2.164ZM17.827,4.857C11.08,4.857 5.604,10.337 5.604,17.084C5.604,23.831 11.08,29.311 17.827,29.311C24.574,29.311 30.05,23.831 30.05,17.084C30.05,10.337 24.574,4.857 17.827,4.857Z" style="fill:rgb(253,150,0);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,-2.69665,-2.69876)">
|
||||
<g transform="matrix(24,0,0,24,11.6286,27.2968)">
|
||||
<path d="M0.575,-0.717L0.575,-0.635L0.344,-0.635L0.344,-0L0.247,-0L0.247,-0.635L0.014,-0.635L0.014,-0.717L0.575,-0.717Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
38
addons/guide/triggers/guide_trigger.svg.import
Normal file
38
addons/guide/triggers/guide_trigger.svg.import
Normal file
@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ca1eiagyinhl7"
|
||||
path="res://.godot/imported/guide_trigger.svg-cd87acbd491929cf49a255f8481b0b63.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/guide/triggers/guide_trigger.svg"
|
||||
dest_files=["res://.godot/imported/guide_trigger.svg-cd87acbd491929cf49a255f8481b0b63.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=0.5
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
28
addons/guide/triggers/guide_trigger_chorded_action.gd
Normal file
28
addons/guide/triggers/guide_trigger_chorded_action.gd
Normal file
@ -0,0 +1,28 @@
|
||||
## Fires, when the given action is currently triggering. This trigger is implicit,
|
||||
## so it will prevent the action from triggering even if other triggers are successful.
|
||||
@tool
|
||||
class_name GUIDETriggerChordedAction
|
||||
extends GUIDETrigger
|
||||
|
||||
@export var action:GUIDEAction
|
||||
|
||||
|
||||
func _get_trigger_type() -> GUIDETriggerType:
|
||||
return GUIDETriggerType.IMPLICIT
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if action == null:
|
||||
push_warning("Chorded trigger without action will never trigger.")
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
if action.is_triggered():
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Chorded Action"
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires, when the given action is currently triggering. This trigger is implicit,\n" + \
|
||||
"so it will prevent the action from triggering even if other triggers are successful."
|
@ -0,0 +1 @@
|
||||
uid://brsxcrai2te83
|
117
addons/guide/triggers/guide_trigger_combo.gd
Normal file
117
addons/guide/triggers/guide_trigger_combo.gd
Normal file
@ -0,0 +1,117 @@
|
||||
@tool
|
||||
class_name GUIDETriggerCombo
|
||||
extends GUIDETrigger
|
||||
|
||||
enum ActionEventType {
|
||||
TRIGGERED = 1,
|
||||
STARTED = 2,
|
||||
ONGOING = 4,
|
||||
CANCELLED = 8,
|
||||
COMPLETED = 16
|
||||
}
|
||||
|
||||
## If set to true, the combo trigger will print information
|
||||
## about state changes to the debug log.
|
||||
@export var enable_debug_print:bool = false
|
||||
@export var steps:Array[GUIDETriggerComboStep] = []
|
||||
@export var cancellation_actions:Array[GUIDETriggerComboCancelAction] = []
|
||||
|
||||
var _current_step:int = -1
|
||||
var _remaining_time:float = 0
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if steps.is_empty():
|
||||
push_warning("Combo with no steps will never fire.")
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# initial setup
|
||||
if _current_step == -1:
|
||||
for step in steps:
|
||||
step._prepare()
|
||||
for action in cancellation_actions:
|
||||
action._prepare()
|
||||
_reset()
|
||||
|
||||
|
||||
var current_action := steps[_current_step].action
|
||||
if current_action == null:
|
||||
push_warning("Step ", _current_step , " has no action ", resource_path)
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# check if any of our cancellation actions fired
|
||||
for action in cancellation_actions:
|
||||
# if the action is the current action we don't count its firing as cancellation
|
||||
if action.action == current_action:
|
||||
continue
|
||||
|
||||
if action._has_fired:
|
||||
if enable_debug_print:
|
||||
print("Combo cancelled by action '", action.action._editor_name(), "'.")
|
||||
_reset()
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# check if any of the steps has fired out of order
|
||||
for step in steps:
|
||||
if step.action == current_action:
|
||||
continue
|
||||
|
||||
if step._has_fired:
|
||||
if enable_debug_print:
|
||||
print("Combo out of order step by action '", step.action._editor_name(), "'.")
|
||||
_reset()
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# check if we took too long (unless we're in the first step)
|
||||
if _current_step > 0:
|
||||
_remaining_time -= delta
|
||||
if _remaining_time <= 0.0:
|
||||
if enable_debug_print:
|
||||
print("Step time for step ", _current_step , " exceeded.")
|
||||
_reset()
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# if the current action was fired, if so advance to the next
|
||||
if steps[_current_step]._has_fired:
|
||||
# reset this step, so it will not count as misfired next round
|
||||
steps[_current_step]._has_fired = false
|
||||
if _current_step + 1 >= steps.size():
|
||||
# we finished the combo
|
||||
if enable_debug_print:
|
||||
print("Combo fired.")
|
||||
_reset()
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
# otherwise, pick the next step
|
||||
_current_step += 1
|
||||
if enable_debug_print:
|
||||
print("Combo advanced to step " , _current_step, ".")
|
||||
_remaining_time = steps[_current_step].time_to_actuate
|
||||
|
||||
# Reset all steps and cancellation actions to "not fired" in
|
||||
# case they were triggered by this action. Otherwise a double-tap
|
||||
# would immediately fire for both taps once the first is through
|
||||
for step in steps:
|
||||
step._has_fired = false
|
||||
for action in cancellation_actions:
|
||||
action._has_fired = false
|
||||
|
||||
# and in any case we're still processing.
|
||||
return GUIDETriggerState.ONGOING
|
||||
|
||||
|
||||
func _reset():
|
||||
if enable_debug_print:
|
||||
print("Combo reset.")
|
||||
_current_step = 0
|
||||
_remaining_time = steps[0].time_to_actuate
|
||||
for step in steps:
|
||||
step._has_fired = false
|
||||
for action in cancellation_actions:
|
||||
action._has_fired = false
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Combo"
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires, when the input exceeds the actuation threshold."
|
||||
|
1
addons/guide/triggers/guide_trigger_combo.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_combo.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://biioody2ca0e7
|
27
addons/guide/triggers/guide_trigger_combo_cancel_action.gd
Normal file
27
addons/guide/triggers/guide_trigger_combo_cancel_action.gd
Normal file
@ -0,0 +1,27 @@
|
||||
@icon("res://addons/guide/guide_internal.svg")
|
||||
class_name GUIDETriggerComboCancelAction
|
||||
extends Resource
|
||||
|
||||
@export var action:GUIDEAction
|
||||
@export_flags("Triggered:1", "Started:2", "Ongoing:4", "Cancelled:8","Completed:16")
|
||||
var completion_events:int = GUIDETriggerCombo.ActionEventType.TRIGGERED
|
||||
|
||||
var _has_fired:bool = false
|
||||
|
||||
func _prepare():
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.TRIGGERED:
|
||||
action.triggered.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.STARTED:
|
||||
action.started.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.ONGOING:
|
||||
action.ongoing.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.CANCELLED:
|
||||
action.cancelled.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.COMPLETED:
|
||||
action.completed.connect(_fired)
|
||||
_has_fired = false
|
||||
|
||||
|
||||
func _fired():
|
||||
_has_fired = true
|
||||
|
@ -0,0 +1 @@
|
||||
uid://ddgp5tashyo8o
|
29
addons/guide/triggers/guide_trigger_combo_step.gd
Normal file
29
addons/guide/triggers/guide_trigger_combo_step.gd
Normal file
@ -0,0 +1,29 @@
|
||||
@icon("res://addons/guide/guide_internal.svg")
|
||||
class_name GUIDETriggerComboStep
|
||||
extends Resource
|
||||
|
||||
@export var action:GUIDEAction
|
||||
@export_flags("Triggered:1", "Started:2", "Ongoing:4", "Cancelled:8","Completed:16")
|
||||
var completion_events:int = GUIDETriggerCombo.ActionEventType.TRIGGERED
|
||||
@export var time_to_actuate:float = 0.5
|
||||
|
||||
|
||||
var _has_fired:bool = false
|
||||
|
||||
func _prepare():
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.TRIGGERED:
|
||||
action.triggered.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.STARTED:
|
||||
action.started.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.ONGOING:
|
||||
action.ongoing.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.CANCELLED:
|
||||
action.cancelled.connect(_fired)
|
||||
if completion_events & GUIDETriggerCombo.ActionEventType.COMPLETED:
|
||||
action.completed.connect(_fired)
|
||||
_has_fired = false
|
||||
|
||||
|
||||
func _fired():
|
||||
_has_fired = true
|
||||
|
1
addons/guide/triggers/guide_trigger_combo_step.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_combo_step.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://be47edmg8hwpo
|
20
addons/guide/triggers/guide_trigger_down.gd
Normal file
20
addons/guide/triggers/guide_trigger_down.gd
Normal file
@ -0,0 +1,20 @@
|
||||
## Fires, when the input exceeds the actuation threshold. This is
|
||||
## the default trigger when no trigger is specified.
|
||||
@tool
|
||||
class_name GUIDETriggerDown
|
||||
extends GUIDETrigger
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
# if the input is actuated, then the trigger is triggered.
|
||||
if _is_actuated(input, value_type):
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
# otherwise, the trigger is not triggered.
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Down"
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires, when the input exceeds the actuation threshold. This is\n" +\
|
||||
"the default trigger when no trigger is specified."
|
1
addons/guide/triggers/guide_trigger_down.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_down.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://b4cdrn4paoj3i
|
43
addons/guide/triggers/guide_trigger_hold.gd
Normal file
43
addons/guide/triggers/guide_trigger_hold.gd
Normal file
@ -0,0 +1,43 @@
|
||||
@tool
|
||||
## A trigger that activates when the input is held down for a certain amount of time.
|
||||
class_name GUIDETriggerHold
|
||||
extends GUIDETrigger
|
||||
|
||||
## The time for how long the input must be held.
|
||||
@export var hold_treshold:float = 1.0
|
||||
## If true, the trigger will only fire once until the input is released. Otherwise the trigger will fire every frame.
|
||||
@export var is_one_shot:bool = false
|
||||
|
||||
var _accumulated_time:float = 0
|
||||
var _did_shoot:bool = false
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
# if the input is actuated, accumulate time and check if the hold threshold has been reached
|
||||
if _is_actuated(input, value_type):
|
||||
_accumulated_time += delta
|
||||
|
||||
if _accumulated_time >= hold_treshold:
|
||||
# if the trigger is one shot and we already shot, then we will not trigger again.
|
||||
if is_one_shot and _did_shoot:
|
||||
return GUIDETriggerState.NONE
|
||||
else:
|
||||
# otherwise, we will just trigger.
|
||||
_did_shoot = true
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
else:
|
||||
# if the hold threshold has not been reached, then the trigger is ongoing.
|
||||
return GUIDETriggerState.ONGOING
|
||||
else:
|
||||
# if the input is not actuated, then the trigger is not triggered and we reset the accumulated time.
|
||||
# and our one shot flag.
|
||||
_accumulated_time = 0
|
||||
_did_shoot = false
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Hold"
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires, once the input has remained actuated for hold_threshold seconds.\n" + \
|
||||
"My fire once or repeatedly."
|
1
addons/guide/triggers/guide_trigger_hold.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_hold.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cfvgpvihp74si
|
22
addons/guide/triggers/guide_trigger_pressed.gd
Normal file
22
addons/guide/triggers/guide_trigger_pressed.gd
Normal file
@ -0,0 +1,22 @@
|
||||
@tool
|
||||
## A trigger that activates when the input is pushed down. Will only emit a
|
||||
## trigger event once. Holding the input will not trigger further events.
|
||||
class_name GUIDETriggerPressed
|
||||
extends GUIDETrigger
|
||||
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if _is_actuated(input, value_type):
|
||||
if not _is_actuated(_last_value, value_type):
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Pressed"
|
||||
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires once, when the input exceeds actuation threshold. Holding the input\n" + \
|
||||
"will not fire additional triggers."
|
1
addons/guide/triggers/guide_trigger_pressed.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_pressed.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://b52rqq28tuqpg
|
86
addons/guide/triggers/guide_trigger_pulse.gd
Normal file
86
addons/guide/triggers/guide_trigger_pulse.gd
Normal file
@ -0,0 +1,86 @@
|
||||
@tool
|
||||
## A trigger that activates when the input is pushed down and then repeatedly sends trigger events at a fixed interval.
|
||||
## Note: the trigger will be either triggering or ongoing until the input is released.
|
||||
## Note: at most one pulse will be emitted per frame.
|
||||
class_name GUIDETriggerPulse
|
||||
extends GUIDETrigger
|
||||
|
||||
## If true, the trigger will trigger immediately when the input is actuated. Otherwise, the trigger will wait for the initial delay.
|
||||
@export var trigger_on_start:bool = true
|
||||
## The delay after the initial actuation before pulsing begins.
|
||||
@export var initial_delay:float = 0.3:
|
||||
set(value):
|
||||
initial_delay = max(0, value)
|
||||
|
||||
## The interval between pulses. Set to 0 to pulse every frame.
|
||||
@export var pulse_interval:float = 0.1:
|
||||
set(value):
|
||||
pulse_interval = max(0, value)
|
||||
|
||||
## Maximum number of pulses. If <= 0, the trigger will pulse indefinitely.
|
||||
@export var max_pulses:int = 0
|
||||
|
||||
var _delay_until_next_pulse:float = 0
|
||||
var _emitted_pulses:int = 0
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if _is_actuated(input, value_type):
|
||||
if not _is_actuated(_last_value, value_type):
|
||||
# we went from "not actuated" to actuated, pulsing starts
|
||||
_delay_until_next_pulse = initial_delay
|
||||
if trigger_on_start:
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
else:
|
||||
return GUIDETriggerState.ONGOING
|
||||
|
||||
# if we already are pulsing and have exceeded the maximum number of pulses, we will not pulse anymore.
|
||||
if max_pulses > 0 and _emitted_pulses >= max_pulses:
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# subtract the delta from the delay until the next pulse
|
||||
_delay_until_next_pulse -= delta
|
||||
|
||||
if _delay_until_next_pulse > 0:
|
||||
# we are still waiting for the next pulse, nothing to do.
|
||||
return GUIDETriggerState.ONGOING
|
||||
|
||||
# now delta could be larger than our pulse, in which case we loose a few pulses.
|
||||
# as we can pulse at most once per frame.
|
||||
|
||||
# in case someone sets the pulse interval to 0, we will pulse every frame.
|
||||
if is_equal_approx(pulse_interval, 0):
|
||||
_delay_until_next_pulse = 0
|
||||
if max_pulses > 0:
|
||||
_emitted_pulses += 1
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
# Now add the delay until the next pulse
|
||||
_delay_until_next_pulse += pulse_interval
|
||||
|
||||
# If the interval is really small, we can potentially have skipped some pulses
|
||||
if _delay_until_next_pulse <= 0:
|
||||
# we have skipped some pulses
|
||||
var skipped_pulses:int = int(-_delay_until_next_pulse / pulse_interval)
|
||||
_delay_until_next_pulse += skipped_pulses * pulse_interval
|
||||
if max_pulses > 0:
|
||||
_emitted_pulses += skipped_pulses
|
||||
if _emitted_pulses >= max_pulses:
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# Record a pulse and return triggered
|
||||
if max_pulses > 0:
|
||||
_emitted_pulses += 1
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
# if the input is not actuated, then the trigger is not triggered.
|
||||
_emitted_pulses = 0
|
||||
_delay_until_next_pulse = 0
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Pulse"
|
||||
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires at an interval while the input is actuated."
|
1
addons/guide/triggers/guide_trigger_pulse.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_pulse.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dna8tkcuk528v
|
21
addons/guide/triggers/guide_trigger_released.gd
Normal file
21
addons/guide/triggers/guide_trigger_released.gd
Normal file
@ -0,0 +1,21 @@
|
||||
@tool
|
||||
## A trigger that activates when the input is released down. Will only emit a
|
||||
## trigger event once.
|
||||
class_name GUIDETriggerReleased
|
||||
extends GUIDETrigger
|
||||
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if not _is_actuated(input, value_type):
|
||||
if _is_actuated(_last_value, value_type):
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Released"
|
||||
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires once, when the input goes from actuated to not actuated. The opposite of the Pressed trigger."
|
1
addons/guide/triggers/guide_trigger_released.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_released.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://biiggjw6tv4uq
|
72
addons/guide/triggers/guide_trigger_stability.gd
Normal file
72
addons/guide/triggers/guide_trigger_stability.gd
Normal file
@ -0,0 +1,72 @@
|
||||
@tool
|
||||
## Triggers depending on whether the input changes while actuated. This trigger is
|
||||
## is implicit, so it must succeed for all other triggers to succeed.
|
||||
class_name GUIDETriggerStability
|
||||
extends GUIDETrigger
|
||||
|
||||
enum TriggerWhen {
|
||||
## Input must be stable
|
||||
INPUT_IS_STABLE,
|
||||
## Input must change
|
||||
INPUT_CHANGES
|
||||
}
|
||||
|
||||
|
||||
## The maximum amount that the input can change after actuation before it is
|
||||
## considered "changed".
|
||||
@export var max_deviation:float = 1
|
||||
|
||||
## When should the trigger trigger?
|
||||
@export var trigger_when:TriggerWhen = TriggerWhen.INPUT_IS_STABLE
|
||||
|
||||
|
||||
var _initial_value:Vector3
|
||||
var _deviated:bool = false
|
||||
|
||||
|
||||
func _get_trigger_type() -> GUIDETriggerType:
|
||||
return GUIDETriggerType.IMPLICIT
|
||||
|
||||
|
||||
func _update_state(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if _is_actuated(input, value_type):
|
||||
if _deviated:
|
||||
if trigger_when == TriggerWhen.INPUT_IS_STABLE:
|
||||
return GUIDETriggerState.NONE
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
|
||||
if not _is_actuated(_last_value, value_type):
|
||||
# we went from "not actuated" to actuated, start
|
||||
_initial_value = input
|
||||
if trigger_when == TriggerWhen.INPUT_IS_STABLE:
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
else:
|
||||
return GUIDETriggerState.ONGOING
|
||||
|
||||
# calculate how far the input is from the initial value
|
||||
if _initial_value.distance_squared_to(input) > (max_deviation * max_deviation):
|
||||
_deviated = true
|
||||
if trigger_when == TriggerWhen.INPUT_IS_STABLE:
|
||||
return GUIDETriggerState.NONE
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
if trigger_when == TriggerWhen.INPUT_IS_STABLE:
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
return GUIDETriggerState.ONGOING
|
||||
|
||||
# if the input is not actuated
|
||||
_deviated = false
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
|
||||
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Stability"
|
||||
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Triggers depending on whether the input changes while actuated. This trigger\n" +\
|
||||
"is implicit, so it must succeed for all other triggers to succeed."
|
1
addons/guide/triggers/guide_trigger_stability.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_stability.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://deoksgw6vfo5v
|
48
addons/guide/triggers/guide_trigger_tap.gd
Normal file
48
addons/guide/triggers/guide_trigger_tap.gd
Normal file
@ -0,0 +1,48 @@
|
||||
@tool
|
||||
## A trigger that activates when the input is tapped and released before the time threshold is reached.
|
||||
class_name GUIDETriggerTap
|
||||
extends GUIDETrigger
|
||||
|
||||
## The time threshold for the tap to be considered a tap.
|
||||
@export var tap_threshold: float = 0.2
|
||||
|
||||
var _accumulated_time: float = 0
|
||||
|
||||
|
||||
func _update_state(input: Vector3, delta: float, value_type:GUIDEAction.GUIDEActionValueType) -> GUIDETriggerState:
|
||||
if _is_actuated(input, value_type):
|
||||
# if the input was actuated before, and the tap threshold has been exceeded, the trigger is locked down
|
||||
# until the input is released and we can exit out early
|
||||
if _is_actuated(_last_value, value_type) and _accumulated_time > tap_threshold:
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
# accumulate time
|
||||
_accumulated_time += delta
|
||||
|
||||
if _accumulated_time < tap_threshold:
|
||||
return GUIDETriggerState.ONGOING
|
||||
else:
|
||||
# we have exceeded the tap threshold, so the tap is not triggered.
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
else: # not actuated right now
|
||||
# if the input was actuated before...
|
||||
if _is_actuated(_last_value, value_type):
|
||||
# ... and the accumulated time is less than the threshold, then the tap is triggered.
|
||||
if _accumulated_time < tap_threshold:
|
||||
_accumulated_time = 0
|
||||
return GUIDETriggerState.TRIGGERED
|
||||
|
||||
# Otherwise, the tap is not triggered, but we reset the accumulated time
|
||||
# so the trigger is now again ready to be triggered.
|
||||
_accumulated_time = 0
|
||||
|
||||
# in either case, the trigger is not triggered.
|
||||
return GUIDETriggerState.NONE
|
||||
|
||||
func _editor_name() -> String:
|
||||
return "Tap"
|
||||
|
||||
|
||||
func _editor_description() -> String:
|
||||
return "Fires when the input is actuated and released within the given timeframe."
|
1
addons/guide/triggers/guide_trigger_tap.gd.uid
Normal file
1
addons/guide/triggers/guide_trigger_tap.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c76fmncyucwqc
|
Reference in New Issue
Block a user