diff --git a/Assets/OkapiKit/Scripts/Editor/TriggerEditor.cs b/Assets/OkapiKit/Scripts/Editor/TriggerEditor.cs index 330adb58..46830c0c 100644 --- a/Assets/OkapiKit/Scripts/Editor/TriggerEditor.cs +++ b/Assets/OkapiKit/Scripts/Editor/TriggerEditor.cs @@ -70,7 +70,7 @@ protected void StdEditor(bool useOriginalEditor = true, bool allowConditions = t } - protected void ActionPanel() + protected void ActionPanel(string title = "Actions") { serializedObject.ApplyModifiedProperties(); serializedObject.Update(); @@ -80,7 +80,7 @@ protected void ActionPanel() TryDragActionToActionDelayList(actionsRect, propActions); - EditorGUILayout.PropertyField(propActions, new GUIContent("Actions", "These actions will be performed when this trigger is executed."), true); + EditorGUILayout.PropertyField(propActions, new GUIContent(title, "These actions will be performed when this trigger is executed."), true); serializedObject.ApplyModifiedProperties(); (target as Trigger).UpdateExplanation(); diff --git a/Assets/OkapiKit/Scripts/Editor/TriggerOnInputEditor.cs b/Assets/OkapiKit/Scripts/Editor/TriggerOnInputEditor.cs index 6e6f07f5..aa74c2c6 100644 --- a/Assets/OkapiKit/Scripts/Editor/TriggerOnInputEditor.cs +++ b/Assets/OkapiKit/Scripts/Editor/TriggerOnInputEditor.cs @@ -17,6 +17,7 @@ public class TriggerOnInputEditor : TriggerEditor SerializedProperty propNegate; SerializedProperty propUseCooldown; SerializedProperty propCooldown; + SerializedProperty propElseActions; protected override void OnEnable() { @@ -31,6 +32,7 @@ protected override void OnEnable() propNegate = serializedObject.FindProperty("negate"); propUseCooldown = serializedObject.FindProperty("useCooldown"); propCooldown = serializedObject.FindProperty("cooldown"); + propElseActions = serializedObject.FindProperty("elseActions"); } protected override Texture2D GetIcon() @@ -54,17 +56,32 @@ public override void OnInspectorGUI() TriggerOnInput.InputType inputType = (TriggerOnInput.InputType)propInputType.enumValueIndex; + string actionsName = "Actions when pressed"; + string elseActionsName = "Actions when released"; + EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(propInputType, new GUIContent("Input Type", "What kind of input we're detecting?")); if (inputType == TriggerOnInput.InputType.Button) { EditorGUILayout.PropertyField(propButtonName, new GUIContent("Button Name", "Button name")); EditorGUILayout.PropertyField(propContinuous, new GUIContent("Continuous", "If active, this triggers when the button is pressed, if not this trigger only executes when the key was just pressed.")); + + if (propContinuous.boolValue) + { + actionsName = "Actions while pressed"; + elseActionsName = "Actions while released"; + } } else if (inputType == TriggerOnInput.InputType.Key) { EditorGUILayout.PropertyField(propKey, new GUIContent("Key", "Key name")); EditorGUILayout.PropertyField(propContinuous, new GUIContent("Continuous", "If active, this triggers when the button is pressed, if not this trigger only executes when the key was just pressed.")); + + if (propContinuous.boolValue) + { + actionsName = "Actions while pressed"; + elseActionsName = "Actions while released"; + } } else if (inputType == TriggerOnInput.InputType.Axis) { @@ -74,6 +91,11 @@ public override void OnInspectorGUI() if ((propContinuous.boolValue) || (inputType == TriggerOnInput.InputType.Axis)) { EditorGUILayout.PropertyField(propNegate, new GUIContent("Negate", "Do we want to trigger this when the input DOESN'T happen, instead of the other way around?")); + if (propNegate.boolValue) + { + actionsName = "Actions while not pressed"; + elseActionsName = "Actions while pressed"; + } } EditorGUILayout.PropertyField(propUseCooldown, new GUIContent("Use Cooldown", "Should we have a cooldown for this trigger?")); @@ -84,7 +106,18 @@ public override void OnInspectorGUI() EditorGUI.EndChangeCheck(); - ActionPanel(); + ActionPanel(actionsName); + + var actionsRect = GUILayoutUtility.GetLastRect(); + actionsRect = new Rect(actionsRect.xMin, actionsRect.yMax, actionsRect.width, 20.0f); + + TryDragActionToActionDelayList(actionsRect, propElseActions); + + EditorGUILayout.PropertyField(propElseActions, new GUIContent(elseActionsName, "What actions do we want while the input is not triggered"), true); + + serializedObject.ApplyModifiedProperties(); + (target as Trigger).UpdateExplanation(); + } } } diff --git a/Assets/OkapiKit/Scripts/Triggers/TriggerOnCondition.cs b/Assets/OkapiKit/Scripts/Triggers/TriggerOnCondition.cs index 5d25fec5..7ea3977e 100644 --- a/Assets/OkapiKit/Scripts/Triggers/TriggerOnCondition.cs +++ b/Assets/OkapiKit/Scripts/Triggers/TriggerOnCondition.cs @@ -77,6 +77,28 @@ protected override void CheckErrors() index++; } } + + if ((elseActions != null) && (elseActions.Length > 0)) + { + int index = 0; + foreach (var action in elseActions) + { + if (action.action == null) + { + _logs.Add(new LogEntry(LogEntry.Type.Warning, $"Else action {index} in not defined on else action list!", "Empty actions don't do anything, so either remove it or fill it in.")); + } + else + { + action.action.ForceCheckErrors(); + var actionLogs = action.action.logs; + foreach (var log in actionLogs) + { + _logs.Add(new LogEntry(log.type, $"On else action {index}: " + log.text, log.tooltip)); + } + } + index++; + } + } } private void Update() diff --git a/Assets/OkapiKit/Scripts/Triggers/TriggerOnInput.cs b/Assets/OkapiKit/Scripts/Triggers/TriggerOnInput.cs index bf763bfc..58e419c1 100644 --- a/Assets/OkapiKit/Scripts/Triggers/TriggerOnInput.cs +++ b/Assets/OkapiKit/Scripts/Triggers/TriggerOnInput.cs @@ -28,6 +28,8 @@ public enum InputType { Button = 0, Key = 1, Axis = 2 }; private bool useCooldown = false; [SerializeField] private float cooldown = 1.0f; + [SerializeField] + protected ActionTrigger[] elseActions; float cooldownTimer = 0.0f; @@ -59,6 +61,18 @@ public override string GetRawDescription(string ident, GameObject refObject) return desc; } + protected override string Internal_UpdateExplanation() + { + base.Internal_UpdateExplanation(); + + if ((elseActions != null) && (elseActions.Length > 0)) + { + _explanation += "else\n" + GetDescriptionActions(elseActions); + } + + return _explanation; + } + void Update() { if (!isTriggerEnabled) return; @@ -75,29 +89,32 @@ void Update() } bool isTrigger = false; + bool elseTrigger = false; bool c = continuous; if (inputType == InputType.Button) { isTrigger = (continuous) ? (Input.GetButton(buttonName)) : (Input.GetButtonDown(buttonName)); + elseTrigger = (continuous) ? !(Input.GetButton(buttonName)) : (Input.GetButtonUp(buttonName)); } else if (inputType == InputType.Key) { isTrigger = (continuous) ? (Input.GetKey(key)) : (Input.GetKeyDown(key)); + elseTrigger = (continuous) ? (!Input.GetKey(key)) : (Input.GetKeyUp(key)); } else if (inputType == InputType.Axis) { float a = Input.GetAxis(axis); isTrigger = (a < deadArea.x) || (a > deadArea.y); - if (isTrigger) - { - int ba = 10; - ba++; - } + elseTrigger = !isTrigger; c = true; } - if ((c) && (negate)) isTrigger = !isTrigger; + if ((c) && (negate)) + { + isTrigger = !isTrigger; + elseTrigger = !elseTrigger; + } if (isTrigger) { @@ -105,6 +122,58 @@ void Update() if (useCooldown) cooldownTimer = cooldown; } + if (elseTrigger) + { + ExecuteElseTrigger(); + } + } + + public virtual void ExecuteElseTrigger() + { + if (!enableTrigger) return; + + foreach (var action in elseActions) + { + if (action.action.isActionEnabled) + { + if (action.delay > 0) + { + StartCoroutine(ExecuteTriggerCR(action)); + } + else + { + action.action.Execute(); + } + } + } } + + protected override void CheckErrors() + { + base.CheckErrors(); + + if ((elseActions != null) && (elseActions.Length > 0)) + { + int index = 0; + foreach (var action in elseActions) + { + if (action.action == null) + { + _logs.Add(new LogEntry(LogEntry.Type.Warning, $"Else action {index} in not defined on else action list!", "Empty actions don't do anything, so either remove it or fill it in.")); + } + else + { + action.action.ForceCheckErrors(); + var actionLogs = action.action.logs; + foreach (var log in actionLogs) + { + _logs.Add(new LogEntry(log.type, $"On else action {index}: " + log.text, log.tooltip)); + } + } + index++; + } + } + } + } -} \ No newline at end of file +} diff --git a/Assets/OkapiKit/package.json b/Assets/OkapiKit/package.json index f52f01c7..e5308880 100644 --- a/Assets/OkapiKit/package.json +++ b/Assets/OkapiKit/package.json @@ -1,14 +1,14 @@ { "name": "com.videojogoslusofona.okapikit", "displayName": "OkapiKit", - "version": "1.9.0", + "version": "1.9.1", "unity": "2022.3", "description": "OkapiKit is a toolkit for creation of simple games without code.", "keywords": [ "kit" ], "category": "kit", "dependencies": {}, "author": { - "name": "Diogo de Andrade", + "name": "Diogo de Andrade - ULHT", "url": "https://github.com/VideojogosLusofona" } } diff --git a/Assets/OkapiKitSamples/Assets/Images/acid_drop.png b/Assets/OkapiKitSamples/Assets/Images/acid_drop.png index a3adbfea..1153a5bc 100644 Binary files a/Assets/OkapiKitSamples/Assets/Images/acid_drop.png and b/Assets/OkapiKitSamples/Assets/Images/acid_drop.png differ diff --git a/Assets/OkapiKitSamples/package.json b/Assets/OkapiKitSamples/package.json index 9cd9a624..eabd171d 100644 --- a/Assets/OkapiKitSamples/package.json +++ b/Assets/OkapiKitSamples/package.json @@ -1,14 +1,14 @@ { "name": "com.videojogoslusofona.okapikit.samples", "displayName": "OkapiKit Samples", - "version": "1.9.0", + "version": "1.9.1", "unity": "2022.3", "description": "OkapiKit is a toolkit for creation of simple games without code. This package is just the samples for OkapiKit, they are not required to use Okapi Kit, and requires the Okapi Kit package.", "keywords": [ "okapi", "samples" ], "category": "samples", "dependencies": {}, "relatedPackages": { - "com.videojogoslusofona.okapikit": "1.9.0" + "com.videojogoslusofona.okapikit": "1.9.1" }, "author": { "name": "Diogo de Andrade - ULHT", diff --git a/ReleaseNotes.md b/ReleaseNotes.md index cfbb7afa..160f6508 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,10 @@ # Release Notes +## V1.9.1 + +- Added else actions to OnInput +- Else actions on OnCondition weren't displaying warnings/errors + ## V1.9.0 - Added target tag and target object direction option to probe, to allow for maximum distance diff --git a/Screenshots/platformer.png b/Screenshots/platformer.png index cc645b10..289d8488 100644 Binary files a/Screenshots/platformer.png and b/Screenshots/platformer.png differ diff --git a/Todo.txt b/Todo.txt index cbe59174..fcb97e7d 100644 --- a/Todo.txt +++ b/Todo.txt @@ -1,10 +1,10 @@ Features: --------- +- Unify ValueHandler/Value with single selector that can take any of them - Movement targets should be redefinable - Replace ranges used for random number generation with a "ValueSelector", which allows a literal, a range and a ValueHandler/Variable. The range can also use ValueHandler/Variable for the limits. - Change numbers in most definitions (conditions, for example) by something that can be either a ValueHandler, a Variable, a literal, or a function, with a property drawer, etc -- Unify ValueHandler/Value with single selector that can take any of them - Add HueShift/Outline effect for sprites - Added debug system to Okapi - Enable debug system for nodes