Browse Source

Converted tabs to spaces in all .cs files

master
Christopher 9 years ago
parent
commit
239bf8fefe
  1. 57
      Assets/Fungus/Animation/Scripts/Commands/PlayAnimState.cs
  2. 102
      Assets/Fungus/Animation/Scripts/Commands/SetAnimFloat.cs
  3. 102
      Assets/Fungus/Animation/Scripts/Commands/SetAnimInteger.cs
  4. 98
      Assets/Fungus/Animation/Scripts/Commands/SetAnimTrigger.cs
  5. 86
      Assets/Fungus/Audio/Editor/ControlAudioEditor.cs
  6. 534
      Assets/Fungus/Audio/Scripts/Commands/ControlAudio.cs
  7. 90
      Assets/Fungus/Audio/Scripts/Commands/PlayMusic.cs
  8. 102
      Assets/Fungus/Audio/Scripts/Commands/PlaySound.cs
  9. 70
      Assets/Fungus/Audio/Scripts/Commands/PlayUsfxrSound.cs
  10. 96
      Assets/Fungus/Audio/Scripts/Commands/SetAudioPitch.cs
  11. 64
      Assets/Fungus/Audio/Scripts/Commands/SetAudioVolume.cs
  12. 40
      Assets/Fungus/Audio/Scripts/Commands/StopMusic.cs
  13. 298
      Assets/Fungus/Audio/Scripts/MusicController.cs
  14. 16
      Assets/Fungus/Camera/Editor/CameraMenuItems.cs
  15. 494
      Assets/Fungus/Camera/Editor/ViewEditor.cs
  16. 1186
      Assets/Fungus/Camera/Scripts/CameraController.cs
  17. 106
      Assets/Fungus/Camera/Scripts/Commands/FadeScreen.cs
  18. 216
      Assets/Fungus/Camera/Scripts/Commands/FadeToView.cs
  19. 86
      Assets/Fungus/Camera/Scripts/Commands/Fullscreen.cs
  20. 188
      Assets/Fungus/Camera/Scripts/Commands/MoveToView.cs
  21. 96
      Assets/Fungus/Camera/Scripts/Commands/ShakeCamera.cs
  22. 112
      Assets/Fungus/Camera/Scripts/Commands/StartSwipe.cs
  23. 34
      Assets/Fungus/Camera/Scripts/Commands/StopSwipe.cs
  24. 62
      Assets/Fungus/Camera/Scripts/View.cs
  25. 64
      Assets/Fungus/Flowchart/Editor/AssetModProcessor.cs
  26. 2110
      Assets/Fungus/Flowchart/Editor/BlockEditor.cs
  27. 448
      Assets/Fungus/Flowchart/Editor/BlockInspector.cs
  28. 84
      Assets/Fungus/Flowchart/Editor/CallEditor.cs
  29. 430
      Assets/Fungus/Flowchart/Editor/CommandEditor.cs
  30. 912
      Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs
  31. 64
      Assets/Fungus/Flowchart/Editor/CustomGUI.cs
  32. 102
      Assets/Fungus/Flowchart/Editor/EditorExtensions.cs
  33. 144
      Assets/Fungus/Flowchart/Editor/EditorZoomArea.cs
  34. 92
      Assets/Fungus/Flowchart/Editor/EventHandlerEditor.cs
  35. 538
      Assets/Fungus/Flowchart/Editor/FlowchartEditor.cs
  36. 142
      Assets/Fungus/Flowchart/Editor/FlowchartMenuItems.cs
  37. 1640
      Assets/Fungus/Flowchart/Editor/FlowchartWindow.cs
  38. 354
      Assets/Fungus/Flowchart/Editor/FungusEditorResources.cs
  39. 568
      Assets/Fungus/Flowchart/Editor/GLDraw.cs
  40. 164
      Assets/Fungus/Flowchart/Editor/IfEditor.cs
  41. 120
      Assets/Fungus/Flowchart/Editor/InvokeEventEditor.cs
  42. 856
      Assets/Fungus/Flowchart/Editor/InvokeMethodEditor.cs
  43. 138
      Assets/Fungus/Flowchart/Editor/LabelEditor.cs
  44. 296
      Assets/Fungus/Flowchart/Editor/SetVariableEditor.cs
  45. 636
      Assets/Fungus/Flowchart/Editor/VariableEditor.cs
  46. 362
      Assets/Fungus/Flowchart/Editor/VariableListAdaptor.cs
  47. 578
      Assets/Fungus/Flowchart/Scripts/Block.cs
  48. 426
      Assets/Fungus/Flowchart/Scripts/Command.cs
  49. 102
      Assets/Fungus/Flowchart/Scripts/CommandCopyBuffer.cs
  50. 110
      Assets/Fungus/Flowchart/Scripts/Commands/Break.cs
  51. 236
      Assets/Fungus/Flowchart/Scripts/Commands/Call.cs
  52. 106
      Assets/Fungus/Flowchart/Scripts/Commands/CallMethod.cs
  53. 56
      Assets/Fungus/Flowchart/Scripts/Commands/Comment.cs
  54. 82
      Assets/Fungus/Flowchart/Scripts/Commands/Condition.cs
  55. 100
      Assets/Fungus/Flowchart/Scripts/Commands/DebugLog.cs
  56. 84
      Assets/Fungus/Flowchart/Scripts/Commands/DeleteSaveKey.cs
  57. 82
      Assets/Fungus/Flowchart/Scripts/Commands/Destroy.cs
  58. 100
      Assets/Fungus/Flowchart/Scripts/Commands/Else.cs
  59. 116
      Assets/Fungus/Flowchart/Scripts/Commands/ElseIf.cs
  60. 66
      Assets/Fungus/Flowchart/Scripts/Commands/End.cs
  61. 380
      Assets/Fungus/Flowchart/Scripts/Commands/If.cs
  62. 250
      Assets/Fungus/Flowchart/Scripts/Commands/InvokeEvent.cs
  63. 714
      Assets/Fungus/Flowchart/Scripts/Commands/InvokeMethod.cs
  64. 74
      Assets/Fungus/Flowchart/Scripts/Commands/Jump.cs
  65. 42
      Assets/Fungus/Flowchart/Scripts/Commands/Label.cs
  66. 84
      Assets/Fungus/Flowchart/Scripts/Commands/LoadScene.cs
  67. 156
      Assets/Fungus/Flowchart/Scripts/Commands/LoadVariable.cs
  68. 50
      Assets/Fungus/Flowchart/Scripts/Commands/OpenURL.cs
  69. 34
      Assets/Fungus/Flowchart/Scripts/Commands/Quit.cs
  70. 92
      Assets/Fungus/Flowchart/Scripts/Commands/RandomFloat.cs
  71. 92
      Assets/Fungus/Flowchart/Scripts/Commands/RandomInteger.cs
  72. 84
      Assets/Fungus/Flowchart/Scripts/Commands/ReadTextFile.cs
  73. 40
      Assets/Fungus/Flowchart/Scripts/Commands/Reset.cs
  74. 160
      Assets/Fungus/Flowchart/Scripts/Commands/SaveVariable.cs
  75. 160
      Assets/Fungus/Flowchart/Scripts/Commands/SendMessage.cs
  76. 86
      Assets/Fungus/Flowchart/Scripts/Commands/SetActive.cs
  77. 62
      Assets/Fungus/Flowchart/Scripts/Commands/SetSaveProfile.cs
  78. 390
      Assets/Fungus/Flowchart/Scripts/Commands/SetVariable.cs
  79. 180
      Assets/Fungus/Flowchart/Scripts/Commands/SpawnObject.cs
  80. 30
      Assets/Fungus/Flowchart/Scripts/Commands/Stop.cs
  81. 96
      Assets/Fungus/Flowchart/Scripts/Commands/StopFlowchart.cs
  82. 90
      Assets/Fungus/Flowchart/Scripts/Commands/Wait.cs
  83. 92
      Assets/Fungus/Flowchart/Scripts/Commands/While.cs
  84. 114
      Assets/Fungus/Flowchart/Scripts/EventHandler.cs
  85. 36
      Assets/Fungus/Flowchart/Scripts/EventHandlers/FlowchartEnabled.cs
  86. 22
      Assets/Fungus/Flowchart/Scripts/EventHandlers/GameStarted.cs
  87. 90
      Assets/Fungus/Flowchart/Scripts/EventHandlers/KeyPressed.cs
  88. 40
      Assets/Fungus/Flowchart/Scripts/EventHandlers/MessageReceived.cs
  89. 1606
      Assets/Fungus/Flowchart/Scripts/Flowchart.cs
  90. 14
      Assets/Fungus/Flowchart/Scripts/FungusState.cs
  91. 10
      Assets/Fungus/Flowchart/Scripts/Node.cs
  92. 166
      Assets/Fungus/Flowchart/Scripts/SceneLoader.cs
  93. 90
      Assets/Fungus/Flowchart/Scripts/StringFormatter.cs
  94. 140
      Assets/Fungus/Flowchart/Scripts/Variable.cs
  95. 88
      Assets/Fungus/Flowchart/Scripts/VariableTypes/AnimatorVariable.cs
  96. 88
      Assets/Fungus/Flowchart/Scripts/VariableTypes/AudioSourceVariable.cs
  97. 112
      Assets/Fungus/Flowchart/Scripts/VariableTypes/BooleanVariable.cs
  98. 88
      Assets/Fungus/Flowchart/Scripts/VariableTypes/ColorVariable.cs
  99. 134
      Assets/Fungus/Flowchart/Scripts/VariableTypes/FloatVariable.cs
  100. 88
      Assets/Fungus/Flowchart/Scripts/VariableTypes/GameObjectVariable.cs
  101. Some files were not shown because too many files have changed in this diff Show More

57
Assets/Fungus/Animation/Scripts/Commands/PlayAnimState.cs

@ -9,50 +9,49 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Animation", [CommandInfo("Animation",
"Play Anim State", "Play Anim State",
"Plays a state of an animator according to the state name")] "Plays a state of an animator according to the state name")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class PlayAnimState : Command public class PlayAnimState : Command
{ {
[Tooltip("Reference to an Animator component in a game object")] [Tooltip("Reference to an Animator component in a game object")]
public AnimatorData animator = new AnimatorData(); public AnimatorData animator = new AnimatorData();
[Tooltip("Name of the state you want to play")] [Tooltip("Name of the state you want to play")]
public StringData stateName = new StringData(); public StringData stateName = new StringData();
[Tooltip("Layer to play animation on")] [Tooltip("Layer to play animation on")]
public IntegerData layer = new IntegerData(-1); public IntegerData layer = new IntegerData(-1);
[Tooltip("Start time of animation")] [Tooltip("Start time of animation")]
public FloatData time = new FloatData(0f); public FloatData time = new FloatData(0f);
public override void OnEnter() public override void OnEnter()
{ {
if (animator.Value != null) if (animator.Value != null)
{ {
animator.Value.Play(stateName.Value, layer.Value, time.Value); animator.Value.Play(stateName.Value, layer.Value, time.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (animator.Value == null) if (animator.Value == null)
{ {
return "Error: No animator selected"; return "Error: No animator selected";
} }
return animator.Value.name + " (" + stateName.Value + ")"; return animator.Value.name + " (" + stateName.Value + ")";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(170, 204, 169, 255); return new Color32(170, 204, 169, 255);
} }
} }
} }

102
Assets/Fungus/Animation/Scripts/Commands/SetAnimFloat.cs

@ -10,68 +10,68 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Animation", [CommandInfo("Animation",
"Set Anim Float", "Set Anim Float",
"Sets a float parameter on an Animator component to control a Unity animation")] "Sets a float parameter on an Animator component to control a Unity animation")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SetAnimFloat : Command public class SetAnimFloat : Command
{ {
[Tooltip("Reference to an Animator component in a game object")] [Tooltip("Reference to an Animator component in a game object")]
public AnimatorData _animator; public AnimatorData _animator;
[Tooltip("Name of the float Animator parameter that will have its value changed")] [Tooltip("Name of the float Animator parameter that will have its value changed")]
public StringData _parameterName; public StringData _parameterName;
[Tooltip("The float value to set the parameter to")] [Tooltip("The float value to set the parameter to")]
public FloatData value; public FloatData value;
public override void OnEnter() public override void OnEnter()
{ {
if (_animator.Value != null) if (_animator.Value != null)
{ {
_animator.Value.SetFloat(_parameterName.Value, value.Value); _animator.Value.SetFloat(_parameterName.Value, value.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_animator.Value == null) if (_animator.Value == null)
{ {
return "Error: No animator selected"; return "Error: No animator selected";
} }
return _animator.Value.name + " (" + _parameterName.Value + ")"; return _animator.Value.name + " (" + _parameterName.Value + ")";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(170, 204, 169, 255); return new Color32(170, 204, 169, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD; [HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD;
[HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = ""; [HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (animatorOLD != null) if (animatorOLD != null)
{ {
_animator.Value = animatorOLD; _animator.Value = animatorOLD;
animatorOLD = null; animatorOLD = null;
} }
if (parameterNameOLD != "") if (parameterNameOLD != "")
{ {
_parameterName.Value = parameterNameOLD; _parameterName.Value = parameterNameOLD;
parameterNameOLD = ""; parameterNameOLD = "";
} }
} }
#endregion #endregion
} }
} }

102
Assets/Fungus/Animation/Scripts/Commands/SetAnimInteger.cs

@ -10,68 +10,68 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Animation", [CommandInfo("Animation",
"Set Anim Integer", "Set Anim Integer",
"Sets an integer parameter on an Animator component to control a Unity animation")] "Sets an integer parameter on an Animator component to control a Unity animation")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SetAnimInteger : Command public class SetAnimInteger : Command
{ {
[Tooltip("Reference to an Animator component in a game object")] [Tooltip("Reference to an Animator component in a game object")]
public AnimatorData _animator; public AnimatorData _animator;
[Tooltip("Name of the integer Animator parameter that will have its value changed")] [Tooltip("Name of the integer Animator parameter that will have its value changed")]
public StringData _parameterName; public StringData _parameterName;
[Tooltip("The integer value to set the parameter to")] [Tooltip("The integer value to set the parameter to")]
public IntegerData value; public IntegerData value;
public override void OnEnter() public override void OnEnter()
{ {
if (_animator.Value != null) if (_animator.Value != null)
{ {
_animator.Value.SetInteger(_parameterName.Value, value.Value); _animator.Value.SetInteger(_parameterName.Value, value.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_animator.Value == null) if (_animator.Value == null)
{ {
return "Error: No animator selected"; return "Error: No animator selected";
} }
return _animator.Value.name + " (" + _parameterName.Value + ")"; return _animator.Value.name + " (" + _parameterName.Value + ")";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(170, 204, 169, 255); return new Color32(170, 204, 169, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD; [HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD;
[HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = ""; [HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (animatorOLD != null) if (animatorOLD != null)
{ {
_animator.Value = animatorOLD; _animator.Value = animatorOLD;
animatorOLD = null; animatorOLD = null;
} }
if (parameterNameOLD != "") if (parameterNameOLD != "")
{ {
_parameterName.Value = parameterNameOLD; _parameterName.Value = parameterNameOLD;
parameterNameOLD = ""; parameterNameOLD = "";
} }
} }
#endregion #endregion
} }
} }

98
Assets/Fungus/Animation/Scripts/Commands/SetAnimTrigger.cs

@ -10,65 +10,65 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Animation", [CommandInfo("Animation",
"Set Anim Trigger", "Set Anim Trigger",
"Sets a trigger parameter on an Animator component to control a Unity animation")] "Sets a trigger parameter on an Animator component to control a Unity animation")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SetAnimTrigger : Command public class SetAnimTrigger : Command
{ {
[Tooltip("Reference to an Animator component in a game object")] [Tooltip("Reference to an Animator component in a game object")]
public AnimatorData _animator; public AnimatorData _animator;
[Tooltip("Name of the trigger Animator parameter that will have its value changed")] [Tooltip("Name of the trigger Animator parameter that will have its value changed")]
public StringData _parameterName; public StringData _parameterName;
public override void OnEnter() public override void OnEnter()
{ {
if (_animator.Value != null) if (_animator.Value != null)
{ {
_animator.Value.SetTrigger(_parameterName.Value); _animator.Value.SetTrigger(_parameterName.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_animator.Value == null) if (_animator.Value == null)
{ {
return "Error: No animator selected"; return "Error: No animator selected";
} }
return _animator.Value.name + " (" + _parameterName.Value + ")"; return _animator.Value.name + " (" + _parameterName.Value + ")";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(170, 204, 169, 255); return new Color32(170, 204, 169, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD; [HideInInspector] [FormerlySerializedAs("animator")] public Animator animatorOLD;
[HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = ""; [HideInInspector] [FormerlySerializedAs("parameterName")] public string parameterNameOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (animatorOLD != null) if (animatorOLD != null)
{ {
_animator.Value = animatorOLD; _animator.Value = animatorOLD;
animatorOLD = null; animatorOLD = null;
} }
if (parameterNameOLD != "") if (parameterNameOLD != "")
{ {
_parameterName.Value = parameterNameOLD; _parameterName.Value = parameterNameOLD;
parameterNameOLD = ""; parameterNameOLD = "";
} }
} }
#endregion #endregion
} }
} }

86
Assets/Fungus/Audio/Editor/ControlAudioEditor.cs

@ -17,52 +17,52 @@ using Rotorz.ReorderableList;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(ControlAudio))] [CustomEditor (typeof(ControlAudio))]
public class ControlAudioEditor : CommandEditor public class ControlAudioEditor : CommandEditor
{ {
protected SerializedProperty controlProp; protected SerializedProperty controlProp;
protected SerializedProperty audioSourceProp; protected SerializedProperty audioSourceProp;
protected SerializedProperty startVolumeProp; protected SerializedProperty startVolumeProp;
protected SerializedProperty endVolumeProp; protected SerializedProperty endVolumeProp;
protected SerializedProperty fadeDurationProp; protected SerializedProperty fadeDurationProp;
protected SerializedProperty waitUntilFinishedProp; protected SerializedProperty waitUntilFinishedProp;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
controlProp = serializedObject.FindProperty("control"); controlProp = serializedObject.FindProperty("control");
audioSourceProp = serializedObject.FindProperty("_audioSource"); audioSourceProp = serializedObject.FindProperty("_audioSource");
startVolumeProp = serializedObject.FindProperty("startVolume"); startVolumeProp = serializedObject.FindProperty("startVolume");
endVolumeProp = serializedObject.FindProperty("endVolume"); endVolumeProp = serializedObject.FindProperty("endVolume");
fadeDurationProp = serializedObject.FindProperty("fadeDuration"); fadeDurationProp = serializedObject.FindProperty("fadeDuration");
waitUntilFinishedProp = serializedObject.FindProperty("waitUntilFinished"); waitUntilFinishedProp = serializedObject.FindProperty("waitUntilFinished");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
serializedObject.Update(); serializedObject.Update();
ControlAudio t = target as ControlAudio; ControlAudio t = target as ControlAudio;
EditorGUILayout.PropertyField(controlProp); EditorGUILayout.PropertyField(controlProp);
EditorGUILayout.PropertyField(audioSourceProp); EditorGUILayout.PropertyField(audioSourceProp);
string fadeLabel = "Fade Out Duration"; string fadeLabel = "Fade Out Duration";
if (t.control != ControlAudio.controlType.StopLoop && t.control != ControlAudio.controlType.PauseLoop) if (t.control != ControlAudio.controlType.StopLoop && t.control != ControlAudio.controlType.PauseLoop)
{ {
fadeLabel = "Fade In Duration"; fadeLabel = "Fade In Duration";
string volumeLabel = "End Volume"; string volumeLabel = "End Volume";
if (t.control == ControlAudio.controlType.ChangeVolume) if (t.control == ControlAudio.controlType.ChangeVolume)
{ {
fadeLabel = "Fade Duration"; fadeLabel = "Fade Duration";
volumeLabel = "New Volume"; volumeLabel = "New Volume";
} }
EditorGUILayout.PropertyField(endVolumeProp,new GUIContent(volumeLabel)); EditorGUILayout.PropertyField(endVolumeProp,new GUIContent(volumeLabel));
} }
EditorGUILayout.PropertyField(fadeDurationProp,new GUIContent(fadeLabel)); EditorGUILayout.PropertyField(fadeDurationProp,new GUIContent(fadeLabel));
EditorGUILayout.PropertyField(waitUntilFinishedProp); EditorGUILayout.PropertyField(waitUntilFinishedProp);
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

534
Assets/Fungus/Audio/Scripts/Commands/ControlAudio.cs

@ -9,225 +9,225 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Control Audio", "Control Audio",
"Plays, loops, or stops an audiosource. Any AudioSources with the same tag as the target Audio Source will automatically be stoped.")] "Plays, loops, or stops an audiosource. Any AudioSources with the same tag as the target Audio Source will automatically be stoped.")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class ControlAudio : Command public class ControlAudio : Command
{ {
public enum controlType public enum controlType
{ {
PlayOnce, PlayOnce,
PlayLoop, PlayLoop,
PauseLoop, PauseLoop,
StopLoop, StopLoop,
ChangeVolume ChangeVolume
} }
[Tooltip("What to do to audio")] [Tooltip("What to do to audio")]
public controlType control; public controlType control;
[Tooltip("Audio clip to play")] [Tooltip("Audio clip to play")]
public AudioSourceData _audioSource; public AudioSourceData _audioSource;
[Range(0,1)] [Range(0,1)]
[Tooltip("Start audio at this volume")] [Tooltip("Start audio at this volume")]
public float startVolume = 1; public float startVolume = 1;
[Range(0,1)] [Range(0,1)]
[Tooltip("End audio at this volume")] [Tooltip("End audio at this volume")]
public float endVolume = 1; public float endVolume = 1;
[Tooltip("Time to fade between current volume level and target volume level.")] [Tooltip("Time to fade between current volume level and target volume level.")]
public float fadeDuration; public float fadeDuration;
[Tooltip("Wait until this command has finished before executing the next command.")] [Tooltip("Wait until this command has finished before executing the next command.")]
public bool waitUntilFinished = false; public bool waitUntilFinished = false;
public override void OnEnter() public override void OnEnter()
{ {
if (_audioSource.Value == null) if (_audioSource.Value == null)
{ {
Continue(); Continue();
return; return;
} }
if (control != controlType.ChangeVolume) if (control != controlType.ChangeVolume)
{ {
_audioSource.Value.volume = endVolume; _audioSource.Value.volume = endVolume;
}
switch(control)
{
case controlType.PlayOnce:
StopAudioWithSameTag();
PlayOnce();
break;
case controlType.PlayLoop:
StopAudioWithSameTag();
PlayLoop();
break;
case controlType.PauseLoop:
PauseLoop();
break;
case controlType.StopLoop:
StopLoop(_audioSource.Value);
break;
case controlType.ChangeVolume:
ChangeVolume();
break;
}
if (!waitUntilFinished)
{
Continue();
}
}
/**
* If there's other music playing in the scene, assign it the same tag as the new music you want to play and
* the old music will be automatically stopped.
*/
protected void StopAudioWithSameTag()
{
// Don't stop audio if there's no tag assigned
if (_audioSource.Value == null ||
_audioSource.Value.tag == "Untagged")
{
return;
}
AudioSource[] audioSources = GameObject.FindObjectsOfType<AudioSource>();
foreach (AudioSource a in audioSources)
{
if ((a.GetComponent<AudioSource>() != _audioSource.Value) && (a.tag == _audioSource.Value.tag))
{
StopLoop(a.GetComponent<AudioSource>());
}
}
}
protected void PlayOnce()
{
if (fadeDuration > 0)
{
// Fade volume in
LeanTween.value(_audioSource.Value.gameObject,
_audioSource.Value.volume,
endVolume,
fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
});
}
_audioSource.Value.PlayOneShot(_audioSource.Value.clip);
if (waitUntilFinished)
{
StartCoroutine(WaitAndContinue());
}
}
protected virtual IEnumerator WaitAndContinue()
{
// Poll the audiosource until playing has finished
// This allows for things like effects added to the audiosource.
while (_audioSource.Value.isPlaying)
{
yield return null;
}
Continue();
}
protected void PlayLoop()
{
if (fadeDuration > 0)
{
_audioSource.Value.volume = 0;
_audioSource.Value.loop = true;
_audioSource.Value.GetComponent<AudioSource>().Play();
LeanTween.value(_audioSource.Value.gameObject,0,endVolume,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
}
).setOnComplete(
()=>{
if (waitUntilFinished)
{
Continue();
}
}
);
}
else
{
_audioSource.Value.volume = 1;
_audioSource.Value.loop = true;
_audioSource.Value.GetComponent<AudioSource>().Play();
} }
}
switch(control) protected void PauseLoop()
{ {
case controlType.PlayOnce: if (fadeDuration > 0)
StopAudioWithSameTag(); {
PlayOnce(); LeanTween.value(_audioSource.Value.gameObject,_audioSource.Value.volume,0,fadeDuration
break; ).setOnUpdate(
case controlType.PlayLoop: (float updateVolume)=>{
StopAudioWithSameTag(); _audioSource.Value.volume = updateVolume;
PlayLoop(); }
break; ).setOnComplete(
case controlType.PauseLoop: ()=>{
PauseLoop();
break; _audioSource.Value.GetComponent<AudioSource>().Pause();
case controlType.StopLoop: if (waitUntilFinished)
StopLoop(_audioSource.Value); {
break; Continue();
case controlType.ChangeVolume: }
ChangeVolume(); }
break; );
} }
if (!waitUntilFinished) else
{ {
Continue(); _audioSource.Value.GetComponent<AudioSource>().Pause();
} }
} }
/** protected void StopLoop(AudioSource source)
* If there's other music playing in the scene, assign it the same tag as the new music you want to play and {
* the old music will be automatically stopped. if (fadeDuration > 0)
*/ {
protected void StopAudioWithSameTag() LeanTween.value(source.gameObject,_audioSource.Value.volume,0,fadeDuration
{ ).setOnUpdate(
// Don't stop audio if there's no tag assigned (float updateVolume)=>{
if (_audioSource.Value == null || source.volume = updateVolume;
_audioSource.Value.tag == "Untagged") }
{ ).setOnComplete(
return; ()=>{
}
source.GetComponent<AudioSource>().Stop();
AudioSource[] audioSources = GameObject.FindObjectsOfType<AudioSource>(); if (waitUntilFinished)
foreach (AudioSource a in audioSources) {
{ Continue();
if ((a.GetComponent<AudioSource>() != _audioSource.Value) && (a.tag == _audioSource.Value.tag)) }
{ }
StopLoop(a.GetComponent<AudioSource>()); );
} }
} else
} {
source.GetComponent<AudioSource>().Stop();
protected void PlayOnce() }
{ }
if (fadeDuration > 0)
{ protected void ChangeVolume()
// Fade volume in {
LeanTween.value(_audioSource.Value.gameObject, LeanTween.value(_audioSource.Value.gameObject,_audioSource.Value.volume,endVolume,fadeDuration
_audioSource.Value.volume, ).setOnUpdate(
endVolume, (float updateVolume)=>{
fadeDuration _audioSource.Value.volume = updateVolume;
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
});
}
_audioSource.Value.PlayOneShot(_audioSource.Value.clip);
if (waitUntilFinished)
{
StartCoroutine(WaitAndContinue());
}
}
protected virtual IEnumerator WaitAndContinue()
{
// Poll the audiosource until playing has finished
// This allows for things like effects added to the audiosource.
while (_audioSource.Value.isPlaying)
{
yield return null;
}
Continue();
}
protected void PlayLoop()
{
if (fadeDuration > 0)
{
_audioSource.Value.volume = 0;
_audioSource.Value.loop = true;
_audioSource.Value.GetComponent<AudioSource>().Play();
LeanTween.value(_audioSource.Value.gameObject,0,endVolume,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
}
).setOnComplete(
()=>{
if (waitUntilFinished)
{
Continue();
}
}
);
}
else
{
_audioSource.Value.volume = 1;
_audioSource.Value.loop = true;
_audioSource.Value.GetComponent<AudioSource>().Play();
}
}
protected void PauseLoop()
{
if (fadeDuration > 0)
{
LeanTween.value(_audioSource.Value.gameObject,_audioSource.Value.volume,0,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
}
).setOnComplete(
()=>{
_audioSource.Value.GetComponent<AudioSource>().Pause();
if (waitUntilFinished)
{
Continue();
}
}
);
}
else
{
_audioSource.Value.GetComponent<AudioSource>().Pause();
}
}
protected void StopLoop(AudioSource source)
{
if (fadeDuration > 0)
{
LeanTween.value(source.gameObject,_audioSource.Value.volume,0,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
source.volume = updateVolume;
}
).setOnComplete(
()=>{
source.GetComponent<AudioSource>().Stop();
if (waitUntilFinished)
{
Continue();
}
}
);
}
else
{
source.GetComponent<AudioSource>().Stop();
}
}
protected void ChangeVolume()
{
LeanTween.value(_audioSource.Value.gameObject,_audioSource.Value.volume,endVolume,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
}).setOnComplete( }).setOnComplete(
()=>{ ()=>{
if (waitUntilFinished) if (waitUntilFinished)
@ -235,58 +235,58 @@ namespace Fungus
Continue(); Continue();
} }
}); });
} }
void AudioFinished() void AudioFinished()
{ {
if (waitUntilFinished) if (waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_audioSource.Value == null) if (_audioSource.Value == null)
{ {
return "Error: No sound clip selected"; return "Error: No sound clip selected";
} }
string fadeType = ""; string fadeType = "";
if (fadeDuration > 0) if (fadeDuration > 0)
{ {
fadeType = " Fade out"; fadeType = " Fade out";
if (control != controlType.StopLoop) if (control != controlType.StopLoop)
{ {
fadeType = " Fade in volume to " + endVolume; fadeType = " Fade in volume to " + endVolume;
} }
if (control == controlType.ChangeVolume) if (control == controlType.ChangeVolume)
{ {
fadeType = " to " + endVolume; fadeType = " to " + endVolume;
} }
fadeType += " over " + fadeDuration + " seconds."; fadeType += " over " + fadeDuration + " seconds.";
} }
return control.ToString() + " \"" + _audioSource.Value.name + "\"" + fadeType; return control.ToString() + " \"" + _audioSource.Value.name + "\"" + fadeType;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("audioSource")] public AudioSource audioSourceOLD; [HideInInspector] [FormerlySerializedAs("audioSource")] public AudioSource audioSourceOLD;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (audioSourceOLD != null) if (audioSourceOLD != null)
{ {
_audioSource.Value = audioSourceOLD; _audioSource.Value = audioSourceOLD;
audioSourceOLD = null; audioSourceOLD = null;
} }
} }
#endregion #endregion
} }
} }

90
Assets/Fungus/Audio/Scripts/Commands/PlayMusic.cs

@ -8,50 +8,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Play Music", "Play Music",
"Plays looping game music. If any game music is already playing, it is stopped. Game music will continue playing across scene loads.")] "Plays looping game music. If any game music is already playing, it is stopped. Game music will continue playing across scene loads.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class PlayMusic : Command public class PlayMusic : Command
{ {
[Tooltip("Music sound clip to play")] [Tooltip("Music sound clip to play")]
public AudioClip musicClip; public AudioClip musicClip;
[Tooltip("Time to begin playing in seconds. If the audio file is compressed, the time index may be inaccurate.")] [Tooltip("Time to begin playing in seconds. If the audio file is compressed, the time index may be inaccurate.")]
public float atTime; public float atTime;
[Tooltip("The music will start playing again at end.")] [Tooltip("The music will start playing again at end.")]
public bool loop = true; public bool loop = true;
[Tooltip("Length of time to fade out previous playing music.")] [Tooltip("Length of time to fade out previous playing music.")]
public float fadeDuration = 1f; public float fadeDuration = 1f;
public override void OnEnter() public override void OnEnter()
{ {
MusicController musicController = MusicController.GetInstance(); MusicController musicController = MusicController.GetInstance();
if (musicController != null) if (musicController != null)
{ {
float startTime = Mathf.Max(0, atTime); float startTime = Mathf.Max(0, atTime);
musicController.PlayMusic(musicClip, loop, fadeDuration, startTime); musicController.PlayMusic(musicClip, loop, fadeDuration, startTime);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (musicClip == null) if (musicClip == null)
{ {
return "Error: No music clip selected"; return "Error: No music clip selected";
} }
return musicClip.name; return musicClip.name;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
} }
} }

102
Assets/Fungus/Audio/Scripts/Commands/PlaySound.cs

@ -8,65 +8,65 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Play Sound", "Play Sound",
"Plays a once-off sound effect. Multiple sound effects can be played at the same time.")] "Plays a once-off sound effect. Multiple sound effects can be played at the same time.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class PlaySound : Command public class PlaySound : Command
{ {
[Tooltip("Sound effect clip to play")] [Tooltip("Sound effect clip to play")]
public AudioClip soundClip; public AudioClip soundClip;
[Range(0,1)] [Range(0,1)]
[Tooltip("Volume level of the sound effect")] [Tooltip("Volume level of the sound effect")]
public float volume = 1; public float volume = 1;
[Tooltip("Wait until the sound has finished playing before continuing execution.")] [Tooltip("Wait until the sound has finished playing before continuing execution.")]
public bool waitUntilFinished; public bool waitUntilFinished;
public override void OnEnter() public override void OnEnter()
{ {
if (soundClip == null) if (soundClip == null)
{ {
Continue(); Continue();
return; return;
} }
MusicController musicController = MusicController.GetInstance(); MusicController musicController = MusicController.GetInstance();
if (musicController != null) if (musicController != null)
{ {
musicController.PlaySound(soundClip, volume); musicController.PlaySound(soundClip, volume);
} }
if (waitUntilFinished) if (waitUntilFinished)
{ {
Invoke("DoWait", soundClip.length); Invoke("DoWait", soundClip.length);
} }
else else
{ {
Continue(); Continue();
} }
} }
protected virtual void DoWait() protected virtual void DoWait()
{ {
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (soundClip == null) if (soundClip == null)
{ {
return "Error: No sound clip selected"; return "Error: No sound clip selected";
} }
return soundClip.name; return soundClip.name;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
} }
} }

70
Assets/Fungus/Audio/Scripts/Commands/PlayUsfxrSound.cs

@ -6,25 +6,25 @@
namespace Fungus { namespace Fungus {
using System; using System;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization; using UnityEngine.Serialization;
[CommandInfo("Audio", [CommandInfo("Audio",
"Play Usfxr Sound", "Play Usfxr Sound",
"Plays a usfxr synth sound. Use the usfxr editor [Tools > Fungus > Utilities > Generate usfxr Sound Effects] to create the SettingsString. Set a ParentTransform if using positional sound. See https://github.com/zeh/usfxr for more information about usfxr.")] "Plays a usfxr synth sound. Use the usfxr editor [Tools > Fungus > Utilities > Generate usfxr Sound Effects] to create the SettingsString. Set a ParentTransform if using positional sound. See https://github.com/zeh/usfxr for more information about usfxr.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class PlayUsfxrSound : Command public class PlayUsfxrSound : Command
{ {
protected SfxrSynth _synth = new SfxrSynth(); protected SfxrSynth _synth = new SfxrSynth();
[Tooltip("Transform to use for positional audio")] [Tooltip("Transform to use for positional audio")]
public Transform ParentTransform = null; public Transform ParentTransform = null;
[Tooltip("Settings string which describes the audio")] [Tooltip("Settings string which describes the audio")]
public StringDataMulti _SettingsString = new StringDataMulti(""); public StringDataMulti _SettingsString = new StringDataMulti("");
[Tooltip("Time to wait before executing the next command")] [Tooltip("Time to wait before executing the next command")]
public float waitDuration = 0; public float waitDuration = 0;
//Call this if the settings have changed //Call this if the settings have changed
protected void UpdateCache() { protected void UpdateCache() {
@ -42,20 +42,20 @@
public override void OnEnter() { public override void OnEnter() {
_synth.SetParentTransform(ParentTransform); _synth.SetParentTransform(ParentTransform);
_synth.Play(); _synth.Play();
if (waitDuration == 0f) if (waitDuration == 0f)
{ {
Continue(); Continue();
} }
else else
{ {
Invoke ("DoWait", waitDuration); Invoke ("DoWait", waitDuration);
} }
} }
protected void DoWait() protected void DoWait()
{ {
Continue(); Continue();
} }
public override string GetSummary() { public override string GetSummary() {
if (String.IsNullOrEmpty(_SettingsString.Value)) { if (String.IsNullOrEmpty(_SettingsString.Value)) {
@ -71,19 +71,19 @@
return new Color32(128, 200, 200, 255); return new Color32(128, 200, 200, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("SettingsString")] public String SettingsStringOLD = ""; [HideInInspector] [FormerlySerializedAs("SettingsString")] public String SettingsStringOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (SettingsStringOLD != "") if (SettingsStringOLD != "")
{ {
_SettingsString.Value = SettingsStringOLD; _SettingsString.Value = SettingsStringOLD;
SettingsStringOLD = ""; SettingsStringOLD = "";
} }
} }
#endregion #endregion
} }
} }

96
Assets/Fungus/Audio/Scripts/Commands/SetAudioPitch.cs

@ -8,53 +8,53 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Set Audio Pitch", "Set Audio Pitch",
"Sets the global pitch level for audio played with Play Music and Play Sound commands.")] "Sets the global pitch level for audio played with Play Music and Play Sound commands.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class SetAudioPitch : Command public class SetAudioPitch : Command
{ {
[Range(0,1)] [Range(0,1)]
[Tooltip("Global pitch level for audio played using the Play Music and Play Sound commands")] [Tooltip("Global pitch level for audio played using the Play Music and Play Sound commands")]
public float pitch = 1; public float pitch = 1;
[Range(0,30)] [Range(0,30)]
[Tooltip("Time to fade between current pitch level and target pitch level.")] [Tooltip("Time to fade between current pitch level and target pitch level.")]
public float fadeDuration; public float fadeDuration;
[Tooltip("Wait until the pitch change has finished before executing next command")] [Tooltip("Wait until the pitch change has finished before executing next command")]
public bool waitUntilFinished = true; public bool waitUntilFinished = true;
public override void OnEnter() public override void OnEnter()
{ {
System.Action onComplete = () => { System.Action onComplete = () => {
if (waitUntilFinished) if (waitUntilFinished)
{ {
Continue(); Continue();
} }
}; };
MusicController musicController = MusicController.GetInstance(); MusicController musicController = MusicController.GetInstance();
if (musicController != null) if (musicController != null)
{ {
musicController.SetAudioPitch(pitch, fadeDuration, onComplete); musicController.SetAudioPitch(pitch, fadeDuration, onComplete);
} }
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return "Set to " + pitch + " over " + fadeDuration + " seconds."; return "Set to " + pitch + " over " + fadeDuration + " seconds.";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
} }
} }

64
Assets/Fungus/Audio/Scripts/Commands/SetAudioVolume.cs

@ -8,51 +8,51 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Set Audio Volume", "Set Audio Volume",
"Sets the global volume level for audio played with Play Music and Play Sound commands.")] "Sets the global volume level for audio played with Play Music and Play Sound commands.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class SetAudioVolume : Command public class SetAudioVolume : Command
{ {
[Range(0,1)] [Range(0,1)]
[Tooltip("Global volume level for audio played using Play Music and Play Sound")] [Tooltip("Global volume level for audio played using Play Music and Play Sound")]
public float volume = 1f; public float volume = 1f;
[Range(0,30)] [Range(0,30)]
[Tooltip("Time to fade between current volume level and target volume level.")] [Tooltip("Time to fade between current volume level and target volume level.")]
public float fadeDuration = 1f; public float fadeDuration = 1f;
[Tooltip("Wait until the volume fade has completed before continuing.")] [Tooltip("Wait until the volume fade has completed before continuing.")]
public bool waitUntilFinished = true; public bool waitUntilFinished = true;
public override void OnEnter() public override void OnEnter()
{ {
MusicController musicController = MusicController.GetInstance(); MusicController musicController = MusicController.GetInstance();
if (musicController != null) if (musicController != null)
{ {
musicController.SetAudioVolume(volume, fadeDuration, () => { musicController.SetAudioVolume(volume, fadeDuration, () => {
if (waitUntilFinished) if (waitUntilFinished)
{ {
Continue(); Continue();
} }
}); });
} }
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return "Set to " + volume + " over " + fadeDuration + " seconds."; return "Set to " + volume + " over " + fadeDuration + " seconds.";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
} }
} }

40
Assets/Fungus/Audio/Scripts/Commands/StopMusic.cs

@ -8,27 +8,27 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Audio", [CommandInfo("Audio",
"Stop Music", "Stop Music",
"Stops the currently playing game music.")] "Stops the currently playing game music.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class StopMusic : Command public class StopMusic : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
MusicController musicController = MusicController.GetInstance(); MusicController musicController = MusicController.GetInstance();
if (musicController != null) if (musicController != null)
{ {
musicController.StopMusic(); musicController.StopMusic();
} }
Continue(); Continue();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(242, 209, 176, 255); return new Color32(242, 209, 176, 255);
} }
} }
} }

298
Assets/Fungus/Audio/Scripts/MusicController.cs

@ -8,163 +8,163 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
/** /**
* Singleton music manager component. * Singleton music manager component.
* Provides basic music and sound effect functionality. * Provides basic music and sound effect functionality.
* Music playback persists across scene loads. * Music playback persists across scene loads.
*/ */
[RequireComponent(typeof(AudioSource))] [RequireComponent(typeof(AudioSource))]
public class MusicController : MonoBehaviour public class MusicController : MonoBehaviour
{ {
static MusicController instance; static MusicController instance;
/** /**
* Returns the MusicController singleton instance. * Returns the MusicController singleton instance.
* Will create a MusicController game object if none currently exists. * Will create a MusicController game object if none currently exists.
*/ */
static public MusicController GetInstance() static public MusicController GetInstance()
{ {
if (instance == null) if (instance == null)
{ {
GameObject go = new GameObject("MusicController"); GameObject go = new GameObject("MusicController");
DontDestroyOnLoad(go); DontDestroyOnLoad(go);
instance = go.AddComponent<MusicController>(); instance = go.AddComponent<MusicController>();
} }
return instance; return instance;
} }
protected virtual void Start() protected virtual void Start()
{ {
GetComponent<AudioSource>().playOnAwake = false; GetComponent<AudioSource>().playOnAwake = false;
GetComponent<AudioSource>().loop = true; GetComponent<AudioSource>().loop = true;
} }
/** /**
* Plays game music using an audio clip. * Plays game music using an audio clip.
* One music clip may be played at a time. * One music clip may be played at a time.
* @param musicClip The music clip to play * @param musicClip The music clip to play
* @param atTime Time in the music clip to start at * @param atTime Time in the music clip to start at
*/ */
public void PlayMusic(AudioClip musicClip, bool loop, float fadeDuration, float atTime) public void PlayMusic(AudioClip musicClip, bool loop, float fadeDuration, float atTime)
{ {
AudioSource audioSource = GetComponent<AudioSource>(); AudioSource audioSource = GetComponent<AudioSource>();
if (audioSource == null || audioSource.clip == musicClip) if (audioSource == null || audioSource.clip == musicClip)
{ {
return; return;
} }
if (fadeDuration == 0f) if (fadeDuration == 0f)
{ {
audioSource.clip = musicClip; audioSource.clip = musicClip;
audioSource.loop = loop; audioSource.loop = loop;
audioSource.time = atTime; // May be inaccurate if the audio source is compressed http://docs.unity3d.com/ScriptReference/AudioSource-time.html BK audioSource.time = atTime; // May be inaccurate if the audio source is compressed http://docs.unity3d.com/ScriptReference/AudioSource-time.html BK
audioSource.Play(); audioSource.Play();
} }
else else
{ {
float startVolume = audioSource.volume; float startVolume = audioSource.volume;
LeanTween.value(gameObject, startVolume, 0f, fadeDuration) LeanTween.value(gameObject, startVolume, 0f, fadeDuration)
.setOnUpdate( (v) => { .setOnUpdate( (v) => {
// Fade out current music // Fade out current music
audioSource.volume = v; audioSource.volume = v;
}).setOnComplete( () => { }).setOnComplete( () => {
// Play new music // Play new music
audioSource.volume = startVolume; audioSource.volume = startVolume;
audioSource.clip = musicClip; audioSource.clip = musicClip;
audioSource.loop = loop; audioSource.loop = loop;
audioSource.time = atTime; // May be inaccurate if the audio source is compressed http://docs.unity3d.com/ScriptReference/AudioSource-time.html BK audioSource.time = atTime; // May be inaccurate if the audio source is compressed http://docs.unity3d.com/ScriptReference/AudioSource-time.html BK
audioSource.Play(); audioSource.Play();
}); });
} }
} }
/** /**
* Stops playing game music. * Stops playing game music.
*/ */
public virtual void StopMusic() public virtual void StopMusic()
{ {
GetComponent<AudioSource>().Stop(); GetComponent<AudioSource>().Stop();
} }
/** /**
* Fades the game music volume to required level over a period of time. * Fades the game music volume to required level over a period of time.
* @param volume The new music volume value [0..1] * @param volume The new music volume value [0..1]
* @param duration The length of time in seconds needed to complete the volume change. * @param duration The length of time in seconds needed to complete the volume change.
* @param onComplete Delegate function to call when fade completes. * @param onComplete Delegate function to call when fade completes.
*/ */
public virtual void SetAudioVolume(float volume, float duration, System.Action onComplete) public virtual void SetAudioVolume(float volume, float duration, System.Action onComplete)
{ {
AudioSource audio = GetComponent<AudioSource>(); AudioSource audio = GetComponent<AudioSource>();
if (Mathf.Approximately(duration, 0f)) if (Mathf.Approximately(duration, 0f))
{ {
audio.volume = volume; audio.volume = volume;
return; return;
} }
LeanTween.value(gameObject, LeanTween.value(gameObject,
audio.volume, audio.volume,
volume, volume,
duration).setOnUpdate( (v) => { duration).setOnUpdate( (v) => {
audio.volume = v; audio.volume = v;
}).setOnComplete( () => { }).setOnComplete( () => {
if (onComplete != null) if (onComplete != null)
{ {
onComplete(); onComplete();
} }
}); });
} }
/** /**
* Shifts the game music pitch to required value over a period of time. * Shifts the game music pitch to required value over a period of time.
* @param volume The new music pitch value * @param volume The new music pitch value
* @param duration The length of time in seconds needed to complete the pitch change. * @param duration The length of time in seconds needed to complete the pitch change.
* @param onComplete A delegate method to call when the pitch shift has completed. * @param onComplete A delegate method to call when the pitch shift has completed.
*/ */
public virtual void SetAudioPitch(float pitch, float duration, System.Action onComplete) public virtual void SetAudioPitch(float pitch, float duration, System.Action onComplete)
{ {
AudioSource audio = GetComponent<AudioSource>(); AudioSource audio = GetComponent<AudioSource>();
if (duration == 0f) if (duration == 0f)
{ {
audio.pitch = pitch; audio.pitch = pitch;
if (onComplete != null) if (onComplete != null)
{ {
onComplete(); onComplete();
} }
return; return;
} }
LeanTween.value(gameObject, LeanTween.value(gameObject,
audio.pitch, audio.pitch,
pitch, pitch,
duration).setOnUpdate( (p) => { duration).setOnUpdate( (p) => {
audio.pitch = p; audio.pitch = p;
}).setOnComplete( () => { }).setOnComplete( () => {
if (onComplete != null) if (onComplete != null)
{ {
onComplete(); onComplete();
} }
}); });
} }
/** /**
* Plays a sound effect once, at the specified volume. * Plays a sound effect once, at the specified volume.
* Multiple sound effects can be played at the same time. * Multiple sound effects can be played at the same time.
* @param soundClip The sound effect clip to play * @param soundClip The sound effect clip to play
* @param volume The volume level of the sound effect * @param volume The volume level of the sound effect
*/ */
public virtual void PlaySound(AudioClip soundClip, float volume) public virtual void PlaySound(AudioClip soundClip, float volume)
{ {
GetComponent<AudioSource>().PlayOneShot(soundClip, volume); GetComponent<AudioSource>().PlayOneShot(soundClip, volume);
} }
public virtual void PlaySoundAtTime(AudioClip soundClip, float volume, float atTime) public virtual void PlaySoundAtTime(AudioClip soundClip, float volume, float atTime)
{ {
GetComponent<AudioSource>().time = atTime; // This may not work BK GetComponent<AudioSource>().time = atTime; // This may not work BK
GetComponent<AudioSource>().PlayOneShot(soundClip, volume); GetComponent<AudioSource>().PlayOneShot(soundClip, volume);
} }
} }
} }

16
Assets/Fungus/Camera/Editor/CameraMenuItems.cs

@ -10,13 +10,13 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
public class CameraMenuItems public class CameraMenuItems
{ {
[MenuItem("Tools/Fungus/Create/View", false, 100)] [MenuItem("Tools/Fungus/Create/View", false, 100)]
static void CreateView() static void CreateView()
{ {
FlowchartMenuItems.SpawnPrefab("View"); FlowchartMenuItems.SpawnPrefab("View");
} }
} }
} }

494
Assets/Fungus/Camera/Editor/ViewEditor.cs

@ -11,257 +11,257 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CanEditMultipleObjects] [CanEditMultipleObjects]
[CustomEditor (typeof(View))] [CustomEditor (typeof(View))]
public class ViewEditor : Editor public class ViewEditor : Editor
{ {
static Color viewColor = Color.yellow; static Color viewColor = Color.yellow;
protected SerializedProperty primaryAspectRatioProp; protected SerializedProperty primaryAspectRatioProp;
protected SerializedProperty secondaryAspectRatioProp; protected SerializedProperty secondaryAspectRatioProp;
protected SerializedProperty viewSizeProp; protected SerializedProperty viewSizeProp;
// Draw Views when they're not selected // Draw Views when they're not selected
#if UNITY_5_0 #if UNITY_5_0
[DrawGizmo(GizmoType.NotSelected | GizmoType.SelectedOrChild)] [DrawGizmo(GizmoType.NotSelected | GizmoType.SelectedOrChild)]
#else #else
[DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.InSelectionHierarchy)] [DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.InSelectionHierarchy)]
#endif #endif
static void RenderCustomGizmo(Transform objectTransform, GizmoType gizmoType) static void RenderCustomGizmo(Transform objectTransform, GizmoType gizmoType)
{ {
View view = objectTransform.gameObject.GetComponent<View>(); View view = objectTransform.gameObject.GetComponent<View>();
if (view != null) if (view != null)
{ {
DrawView(view, false); DrawView(view, false);
} }
} }
protected virtual Vector2 LookupAspectRatio(int index) protected virtual Vector2 LookupAspectRatio(int index)
{ {
switch (index) switch (index)
{ {
default: default:
case 1: case 1:
return new Vector2(4, 3); return new Vector2(4, 3);
case 2: case 2:
return new Vector2(3, 2); return new Vector2(3, 2);
case 3: case 3:
return new Vector2(16, 10); return new Vector2(16, 10);
case 4: case 4:
return new Vector2(17, 10); return new Vector2(17, 10);
case 5: case 5:
return new Vector2(16, 9); return new Vector2(16, 9);
case 6: case 6:
return new Vector2(2, 1); return new Vector2(2, 1);
case 7: case 7:
return new Vector2(3, 4); return new Vector2(3, 4);
case 8: case 8:
return new Vector2(2, 3); return new Vector2(2, 3);
case 9: case 9:
return new Vector2(10, 16); return new Vector2(10, 16);
case 10: case 10:
return new Vector2(10, 17); return new Vector2(10, 17);
case 11: case 11:
return new Vector2(9, 16); return new Vector2(9, 16);
case 12: case 12:
return new Vector2(1, 2); return new Vector2(1, 2);
} }
} }
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
primaryAspectRatioProp = serializedObject.FindProperty ("primaryAspectRatio"); primaryAspectRatioProp = serializedObject.FindProperty ("primaryAspectRatio");
secondaryAspectRatioProp = serializedObject.FindProperty ("secondaryAspectRatio"); secondaryAspectRatioProp = serializedObject.FindProperty ("secondaryAspectRatio");
viewSizeProp = serializedObject.FindProperty("viewSize"); viewSizeProp = serializedObject.FindProperty("viewSize");
} }
public override void OnInspectorGUI() public override void OnInspectorGUI()
{ {
serializedObject.Update(); serializedObject.Update();
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(viewSizeProp); EditorGUILayout.PropertyField(viewSizeProp);
string[] ratios = { "<None>", "Landscape / 4:3", "Landscape / 3:2", "Landscape / 16:10", "Landscape / 17:10", "Landscape / 16:9", "Landscape / 2:1", "Portrait / 3:4", "Portrait / 2:3", "Portrait / 10:16", "Portrait / 10:17", "Portrait / 9:16", "Portrait / 1:2" }; string[] ratios = { "<None>", "Landscape / 4:3", "Landscape / 3:2", "Landscape / 16:10", "Landscape / 17:10", "Landscape / 16:9", "Landscape / 2:1", "Portrait / 3:4", "Portrait / 2:3", "Portrait / 10:16", "Portrait / 10:17", "Portrait / 9:16", "Portrait / 1:2" };
EditorGUILayout.PropertyField(primaryAspectRatioProp, new GUIContent("Primary Aspect Ratio", "Width and height values that define the primary aspect ratio (e.g. 4:3)")); EditorGUILayout.PropertyField(primaryAspectRatioProp, new GUIContent("Primary Aspect Ratio", "Width and height values that define the primary aspect ratio (e.g. 4:3)"));
int primaryIndex = EditorGUILayout.Popup("Select Aspect Ratio", 0, ratios); int primaryIndex = EditorGUILayout.Popup("Select Aspect Ratio", 0, ratios);
if (primaryIndex > 0) if (primaryIndex > 0)
{ {
primaryAspectRatioProp.vector2Value = LookupAspectRatio(primaryIndex); primaryAspectRatioProp.vector2Value = LookupAspectRatio(primaryIndex);
} }
EditorGUILayout.Separator(); EditorGUILayout.Separator();
EditorGUILayout.PropertyField(secondaryAspectRatioProp, new GUIContent("Secondary Aspect Ratio", "Width and height values that define the primary aspect ratio (e.g. 4:3)")); EditorGUILayout.PropertyField(secondaryAspectRatioProp, new GUIContent("Secondary Aspect Ratio", "Width and height values that define the primary aspect ratio (e.g. 4:3)"));
int secondaryIndex = EditorGUILayout.Popup("Select Aspect Ratio", 0, ratios); int secondaryIndex = EditorGUILayout.Popup("Select Aspect Ratio", 0, ratios);
if (secondaryIndex > 0) if (secondaryIndex > 0)
{ {
secondaryAspectRatioProp.vector2Value = LookupAspectRatio(secondaryIndex); secondaryAspectRatioProp.vector2Value = LookupAspectRatio(secondaryIndex);
} }
EditorGUILayout.Separator(); EditorGUILayout.Separator();
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
// Avoid divide by zero errors // Avoid divide by zero errors
if (primaryAspectRatioProp.vector2Value.y == 0) if (primaryAspectRatioProp.vector2Value.y == 0)
{ {
primaryAspectRatioProp.vector2Value = new Vector2(primaryAspectRatioProp.vector2Value.x, 1f); primaryAspectRatioProp.vector2Value = new Vector2(primaryAspectRatioProp.vector2Value.x, 1f);
} }
if (secondaryAspectRatioProp.vector2Value.y == 0) if (secondaryAspectRatioProp.vector2Value.y == 0)
{ {
secondaryAspectRatioProp.vector2Value = new Vector2(secondaryAspectRatioProp.vector2Value.x, 1f); secondaryAspectRatioProp.vector2Value = new Vector2(secondaryAspectRatioProp.vector2Value.x, 1f);
} }
SceneView.RepaintAll(); SceneView.RepaintAll();
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
protected virtual void OnSceneGUI () protected virtual void OnSceneGUI ()
{ {
View t = target as View; View t = target as View;
if (t.enabled) if (t.enabled)
{ {
EditViewBounds(); EditViewBounds();
} }
} }
protected virtual void EditViewBounds() protected virtual void EditViewBounds()
{ {
View view = target as View; View view = target as View;
DrawView(view, true); DrawView(view, true);
Vector3 pos = view.transform.position; Vector3 pos = view.transform.position;
float viewSize = CalculateLocalViewSize(view); float viewSize = CalculateLocalViewSize(view);
Vector3[] handles = new Vector3[2]; Vector3[] handles = new Vector3[2];
handles[0] = view.transform.TransformPoint(new Vector3(0, -viewSize, 0)); handles[0] = view.transform.TransformPoint(new Vector3(0, -viewSize, 0));
handles[1] = view.transform.TransformPoint(new Vector3(0, viewSize, 0)); handles[1] = view.transform.TransformPoint(new Vector3(0, viewSize, 0));
Handles.color = Color.white; Handles.color = Color.white;
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
Vector3 newPos = Handles.FreeMoveHandle(handles[i], Vector3 newPos = Handles.FreeMoveHandle(handles[i],
Quaternion.identity, Quaternion.identity,
HandleUtility.GetHandleSize(pos) * 0.1f, HandleUtility.GetHandleSize(pos) * 0.1f,
Vector3.zero, Vector3.zero,
Handles.CubeCap); Handles.CubeCap);
if (newPos != handles[i]) if (newPos != handles[i])
{ {
Undo.RecordObject(view, "Set View Size"); Undo.RecordObject(view, "Set View Size");
view.viewSize = (newPos - pos).magnitude; view.viewSize = (newPos - pos).magnitude;
EditorUtility.SetDirty(view); EditorUtility.SetDirty(view);
break; break;
} }
} }
} }
public static void DrawView(View view, bool drawInterior) public static void DrawView(View view, bool drawInterior)
{ {
float height = CalculateLocalViewSize(view); float height = CalculateLocalViewSize(view);
float widthA = height * (view.primaryAspectRatio.x / view.primaryAspectRatio.y); float widthA = height * (view.primaryAspectRatio.x / view.primaryAspectRatio.y);
float widthB = height * (view.secondaryAspectRatio.x / view.secondaryAspectRatio.y); float widthB = height * (view.secondaryAspectRatio.x / view.secondaryAspectRatio.y);
Color transparent = new Color(1,1,1,0f); Color transparent = new Color(1,1,1,0f);
Color fill = viewColor; Color fill = viewColor;
Color outline = viewColor; Color outline = viewColor;
bool highlight = Selection.activeGameObject == view.gameObject; bool highlight = Selection.activeGameObject == view.gameObject;
Flowchart flowchart = FlowchartWindow.GetFlowchart(); Flowchart flowchart = FlowchartWindow.GetFlowchart();
if (flowchart != null) if (flowchart != null)
{ {
foreach (Command command in flowchart.selectedCommands) foreach (Command command in flowchart.selectedCommands)
{ {
MoveToView moveToViewCommand = command as MoveToView; MoveToView moveToViewCommand = command as MoveToView;
if (moveToViewCommand != null && if (moveToViewCommand != null &&
moveToViewCommand.targetView == view) moveToViewCommand.targetView == view)
{ {
highlight = true; highlight = true;
} }
else else
{ {
FadeToView fadeToViewCommand = command as FadeToView; FadeToView fadeToViewCommand = command as FadeToView;
if (fadeToViewCommand != null && if (fadeToViewCommand != null &&
fadeToViewCommand.targetView == view) fadeToViewCommand.targetView == view)
{ {
highlight = true; highlight = true;
} }
} }
} }
} }
if (highlight) if (highlight)
{ {
fill = outline = Color.green; fill = outline = Color.green;
fill.a = 0.1f; fill.a = 0.1f;
outline.a = 1f; outline.a = 1f;
} }
else else
{ {
fill.a = 0.1f; fill.a = 0.1f;
outline.a = 0.5f; outline.a = 0.5f;
} }
if (drawInterior) if (drawInterior)
{ {
// Draw left box // Draw left box
{ {
Vector3[] verts = new Vector3[4]; Vector3[] verts = new Vector3[4];
verts[0] = view.transform.TransformPoint(new Vector3(-widthB, -height, 0)); verts[0] = view.transform.TransformPoint(new Vector3(-widthB, -height, 0));
verts[1] = view.transform.TransformPoint(new Vector3(-widthB, height, 0)); verts[1] = view.transform.TransformPoint(new Vector3(-widthB, height, 0));
verts[2] = view.transform.TransformPoint(new Vector3(-widthA, height, 0)); verts[2] = view.transform.TransformPoint(new Vector3(-widthA, height, 0));
verts[3] = view.transform.TransformPoint(new Vector3(-widthA, -height, 0)); verts[3] = view.transform.TransformPoint(new Vector3(-widthA, -height, 0));
Handles.DrawSolidRectangleWithOutline(verts, fill, transparent); Handles.DrawSolidRectangleWithOutline(verts, fill, transparent);
} }
// Draw right box // Draw right box
{ {
Vector3[] verts = new Vector3[4]; Vector3[] verts = new Vector3[4];
verts[0] = view.transform.TransformPoint(new Vector3(widthA, -height, 0)); verts[0] = view.transform.TransformPoint(new Vector3(widthA, -height, 0));
verts[1] = view.transform.TransformPoint(new Vector3(widthA, height, 0)); verts[1] = view.transform.TransformPoint(new Vector3(widthA, height, 0));
verts[2] = view.transform.TransformPoint(new Vector3(widthB, height, 0)); verts[2] = view.transform.TransformPoint(new Vector3(widthB, height, 0));
verts[3] = view.transform.TransformPoint(new Vector3(widthB, -height, 0)); verts[3] = view.transform.TransformPoint(new Vector3(widthB, -height, 0));
Handles.DrawSolidRectangleWithOutline(verts, fill, transparent); Handles.DrawSolidRectangleWithOutline(verts, fill, transparent);
} }
// Draw inner box // Draw inner box
{ {
Vector3[] verts = new Vector3[4]; Vector3[] verts = new Vector3[4];
verts[0] = view.transform.TransformPoint(new Vector3(-widthA, -height, 0)); verts[0] = view.transform.TransformPoint(new Vector3(-widthA, -height, 0));
verts[1] = view.transform.TransformPoint(new Vector3(-widthA, height, 0)); verts[1] = view.transform.TransformPoint(new Vector3(-widthA, height, 0));
verts[2] = view.transform.TransformPoint(new Vector3(widthA, height, 0)); verts[2] = view.transform.TransformPoint(new Vector3(widthA, height, 0));
verts[3] = view.transform.TransformPoint(new Vector3(widthA, -height, 0)); verts[3] = view.transform.TransformPoint(new Vector3(widthA, -height, 0));
Handles.DrawSolidRectangleWithOutline(verts, transparent, outline ); Handles.DrawSolidRectangleWithOutline(verts, transparent, outline );
} }
} }
// Draw outer box // Draw outer box
{ {
Vector3[] verts = new Vector3[4]; Vector3[] verts = new Vector3[4];
verts[0] = view.transform.TransformPoint(new Vector3(-widthB, -height, 0)); verts[0] = view.transform.TransformPoint(new Vector3(-widthB, -height, 0));
verts[1] = view.transform.TransformPoint(new Vector3(-widthB, height, 0)); verts[1] = view.transform.TransformPoint(new Vector3(-widthB, height, 0));
verts[2] = view.transform.TransformPoint(new Vector3(widthB, height, 0)); verts[2] = view.transform.TransformPoint(new Vector3(widthB, height, 0));
verts[3] = view.transform.TransformPoint(new Vector3(widthB, -height, 0)); verts[3] = view.transform.TransformPoint(new Vector3(widthB, -height, 0));
Handles.DrawSolidRectangleWithOutline(verts, transparent, outline ); Handles.DrawSolidRectangleWithOutline(verts, transparent, outline );
} }
} }
// Calculate view size in local coordinates // Calculate view size in local coordinates
// Kinda expensive, but accurate and only called in editor. // Kinda expensive, but accurate and only called in editor.
static float CalculateLocalViewSize(View view) static float CalculateLocalViewSize(View view)
{ {
return view.transform.InverseTransformPoint(view.transform.position + new Vector3(0, view.viewSize, 0)).magnitude; return view.transform.InverseTransformPoint(view.transform.position + new Vector3(0, view.viewSize, 0)).magnitude;
} }
} }
} }

1186
Assets/Fungus/Camera/Scripts/CameraController.cs

File diff suppressed because it is too large Load Diff

106
Assets/Fungus/Camera/Scripts/Commands/FadeScreen.cs

@ -9,69 +9,69 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Fade Screen", "Fade Screen",
"Draws a fullscreen texture over the scene to give a fade effect. Setting Target Alpha to 1 will obscure the screen, alpha 0 will reveal the screen. " + "Draws a fullscreen texture over the scene to give a fade effect. Setting Target Alpha to 1 will obscure the screen, alpha 0 will reveal the screen. " +
"If no Fade Texture is provided then a default flat color texture is used.")] "If no Fade Texture is provided then a default flat color texture is used.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class FadeScreen : Command public class FadeScreen : Command
{ {
[Tooltip("Time for fade effect to complete")] [Tooltip("Time for fade effect to complete")]
public float duration = 1f; public float duration = 1f;
[Tooltip("Current target alpha transparency value. The fade gradually adjusts the alpha to approach this target value.")] [Tooltip("Current target alpha transparency value. The fade gradually adjusts the alpha to approach this target value.")]
public float targetAlpha = 1f; public float targetAlpha = 1f;
[Tooltip("Wait until the fade has finished before executing next command")] [Tooltip("Wait until the fade has finished before executing next command")]
public bool waitUntilFinished = true; public bool waitUntilFinished = true;
[Tooltip("Color to render fullscreen fade texture with when screen is obscured.")] [Tooltip("Color to render fullscreen fade texture with when screen is obscured.")]
public Color fadeColor = Color.black; public Color fadeColor = Color.black;
[Tooltip("Optional texture to use when rendering the fullscreen fade effect.")] [Tooltip("Optional texture to use when rendering the fullscreen fade effect.")]
public Texture2D fadeTexture; public Texture2D fadeTexture;
public override void OnEnter() public override void OnEnter()
{ {
CameraController cameraController = CameraController.GetInstance(); CameraController cameraController = CameraController.GetInstance();
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = true; cameraController.waiting = true;
} }
if (fadeTexture) if (fadeTexture)
{ {
cameraController.screenFadeTexture = fadeTexture; cameraController.screenFadeTexture = fadeTexture;
} }
else else
{ {
cameraController.screenFadeTexture = CameraController.CreateColorTexture(fadeColor, 32, 32); cameraController.screenFadeTexture = CameraController.CreateColorTexture(fadeColor, 32, 32);
} }
cameraController.Fade(targetAlpha, duration, delegate { cameraController.Fade(targetAlpha, duration, delegate {
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = false; cameraController.waiting = false;
Continue(); Continue();
} }
}); });
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return "Fade to " + targetAlpha + " over " + duration + " seconds"; return "Fade to " + targetAlpha + " over " + duration + " seconds";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

216
Assets/Fungus/Camera/Scripts/Commands/FadeToView.cs

@ -9,113 +9,113 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Fade To View", "Fade To View",
"Fades the camera out and in again at a position specified by a View object.")] "Fades the camera out and in again at a position specified by a View object.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class FadeToView : Command public class FadeToView : Command
{ {
[Tooltip("Time for fade effect to complete")] [Tooltip("Time for fade effect to complete")]
public float duration = 1f; public float duration = 1f;
[Tooltip("Fade from fully visible to opaque at start of fade")] [Tooltip("Fade from fully visible to opaque at start of fade")]
public bool fadeOut = true; public bool fadeOut = true;
[Tooltip("View to transition to when Fade is complete")] [Tooltip("View to transition to when Fade is complete")]
public View targetView; public View targetView;
[Tooltip("Wait until the fade has finished before executing next command")] [Tooltip("Wait until the fade has finished before executing next command")]
public bool waitUntilFinished = true; public bool waitUntilFinished = true;
[Tooltip("Color to render fullscreen fade texture with when screen is obscured.")] [Tooltip("Color to render fullscreen fade texture with when screen is obscured.")]
public Color fadeColor = Color.black; public Color fadeColor = Color.black;
[Tooltip("Optional texture to use when rendering the fullscreen fade effect.")] [Tooltip("Optional texture to use when rendering the fullscreen fade effect.")]
public Texture2D fadeTexture; public Texture2D fadeTexture;
[Tooltip("Camera to use for the fade. Will use main camera if set to none.")] [Tooltip("Camera to use for the fade. Will use main camera if set to none.")]
public Camera targetCamera; public Camera targetCamera;
protected virtual void AcquireCamera() protected virtual void AcquireCamera()
{ {
if (targetCamera != null) if (targetCamera != null)
{ {
return; return;
} }
targetCamera = Camera.main; targetCamera = Camera.main;
if (targetCamera == null) if (targetCamera == null)
{ {
targetCamera = GameObject.FindObjectOfType<Camera>(); targetCamera = GameObject.FindObjectOfType<Camera>();
} }
} }
public virtual void Start() public virtual void Start()
{ {
AcquireCamera(); AcquireCamera();
} }
public override void OnEnter() public override void OnEnter()
{ {
AcquireCamera(); AcquireCamera();
if (targetCamera == null || if (targetCamera == null ||
targetView == null) targetView == null)
{ {
Continue(); Continue();
return; return;
} }
CameraController cameraController = CameraController.GetInstance(); CameraController cameraController = CameraController.GetInstance();
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = true; cameraController.waiting = true;
} }
if (fadeTexture) if (fadeTexture)
{ {
cameraController.screenFadeTexture = fadeTexture; cameraController.screenFadeTexture = fadeTexture;
} }
else else
{ {
cameraController.screenFadeTexture = CameraController.CreateColorTexture(fadeColor, 32, 32); cameraController.screenFadeTexture = CameraController.CreateColorTexture(fadeColor, 32, 32);
} }
cameraController.FadeToView(targetCamera, targetView, duration, fadeOut, delegate { cameraController.FadeToView(targetCamera, targetView, duration, fadeOut, delegate {
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = false; cameraController.waiting = false;
Continue(); Continue();
} }
}); });
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override void OnStopExecuting() public override void OnStopExecuting()
{ {
CameraController.GetInstance().StopAllCoroutines(); CameraController.GetInstance().StopAllCoroutines();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (targetView == null) if (targetView == null)
{ {
return "Error: No view selected"; return "Error: No view selected";
} }
else else
{ {
return targetView.name; return targetView.name;
} }
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

86
Assets/Fungus/Camera/Scripts/Commands/Fullscreen.cs

@ -9,48 +9,48 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Fullscreen", "Fullscreen",
"Sets the application to fullscreen, windowed or toggles the current state.")] "Sets the application to fullscreen, windowed or toggles the current state.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Fullscreen : Command public class Fullscreen : Command
{ {
public enum FullscreenMode public enum FullscreenMode
{ {
Toggle, Toggle,
Fullscreen, Fullscreen,
Windowed Windowed
} }
public FullscreenMode fullscreenMode; public FullscreenMode fullscreenMode;
public override void OnEnter() public override void OnEnter()
{ {
switch (fullscreenMode) switch (fullscreenMode)
{ {
case FullscreenMode.Toggle: case FullscreenMode.Toggle:
Screen.fullScreen = !Screen.fullScreen; Screen.fullScreen = !Screen.fullScreen;
break; break;
case FullscreenMode.Fullscreen: case FullscreenMode.Fullscreen:
Screen.fullScreen = true; Screen.fullScreen = true;
break; break;
case FullscreenMode.Windowed: case FullscreenMode.Windowed:
Screen.fullScreen = false; Screen.fullScreen = false;
break; break;
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return fullscreenMode.ToString(); return fullscreenMode.ToString();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

188
Assets/Fungus/Camera/Scripts/Commands/MoveToView.cs

@ -9,99 +9,99 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Move To View", "Move To View",
"Moves the camera to a location specified by a View object.")] "Moves the camera to a location specified by a View object.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class MoveToView : Command public class MoveToView : Command
{ {
[Tooltip("Time for move effect to complete")] [Tooltip("Time for move effect to complete")]
public float duration = 1; public float duration = 1;
[Tooltip("View to transition to when move is complete")] [Tooltip("View to transition to when move is complete")]
public Fungus.View targetView; public Fungus.View targetView;
[Tooltip("Wait until the fade has finished before executing next command")] [Tooltip("Wait until the fade has finished before executing next command")]
public bool waitUntilFinished = true; public bool waitUntilFinished = true;
[Tooltip("Camera to use for the pan. Will use main camera if set to none.")] [Tooltip("Camera to use for the pan. Will use main camera if set to none.")]
public Camera targetCamera; public Camera targetCamera;
protected virtual void AcquireCamera() protected virtual void AcquireCamera()
{ {
if (targetCamera != null) if (targetCamera != null)
{ {
return; return;
} }
targetCamera = Camera.main; targetCamera = Camera.main;
if (targetCamera == null) if (targetCamera == null)
{ {
targetCamera = GameObject.FindObjectOfType<Camera>(); targetCamera = GameObject.FindObjectOfType<Camera>();
} }
} }
public virtual void Start() public virtual void Start()
{ {
AcquireCamera(); AcquireCamera();
} }
public override void OnEnter() public override void OnEnter()
{ {
AcquireCamera(); AcquireCamera();
if (targetCamera == null || if (targetCamera == null ||
targetView == null) targetView == null)
{ {
Continue(); Continue();
return; return;
} }
CameraController cameraController = CameraController.GetInstance(); CameraController cameraController = CameraController.GetInstance();
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = true; cameraController.waiting = true;
} }
Vector3 targetPosition = targetView.transform.position; Vector3 targetPosition = targetView.transform.position;
Quaternion targetRotation = targetView.transform.rotation; Quaternion targetRotation = targetView.transform.rotation;
float targetSize = targetView.viewSize; float targetSize = targetView.viewSize;
cameraController.PanToPosition(targetCamera, targetPosition, targetRotation, targetSize, duration, delegate { cameraController.PanToPosition(targetCamera, targetPosition, targetRotation, targetSize, duration, delegate {
if (waitUntilFinished) if (waitUntilFinished)
{ {
cameraController.waiting = false; cameraController.waiting = false;
Continue(); Continue();
} }
}); });
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override void OnStopExecuting() public override void OnStopExecuting()
{ {
CameraController.GetInstance().StopAllCoroutines(); CameraController.GetInstance().StopAllCoroutines();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (targetView == null) if (targetView == null)
{ {
return "Error: No view selected"; return "Error: No view selected";
} }
else else
{ {
return targetView.name; return targetView.name;
} }
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

96
Assets/Fungus/Camera/Scripts/Commands/ShakeCamera.cs

@ -9,61 +9,61 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Shake Camera", "Shake Camera",
"Applies a camera shake effect to the main camera.")] "Applies a camera shake effect to the main camera.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class ShakeCamera : Command public class ShakeCamera : Command
{ {
[Tooltip("Time for camera shake effect to complete")] [Tooltip("Time for camera shake effect to complete")]
public float duration = 0.5f; public float duration = 0.5f;
[Tooltip("Magnitude of shake effect in x & y axes")] [Tooltip("Magnitude of shake effect in x & y axes")]
public Vector2 amount = new Vector2(1, 1); public Vector2 amount = new Vector2(1, 1);
[Tooltip("Wait until the shake effect has finished before executing next command")] [Tooltip("Wait until the shake effect has finished before executing next command")]
public bool waitUntilFinished; public bool waitUntilFinished;
public override void OnEnter() public override void OnEnter()
{ {
Vector3 v = new Vector3(); Vector3 v = new Vector3();
v = amount; v = amount;
Hashtable tweenParams = new Hashtable(); Hashtable tweenParams = new Hashtable();
tweenParams.Add("amount", v); tweenParams.Add("amount", v);
tweenParams.Add("time", duration); tweenParams.Add("time", duration);
tweenParams.Add("oncomplete", "OniTweenComplete"); tweenParams.Add("oncomplete", "OniTweenComplete");
tweenParams.Add("oncompletetarget", gameObject); tweenParams.Add("oncompletetarget", gameObject);
tweenParams.Add("oncompleteparams", this); tweenParams.Add("oncompleteparams", this);
iTween.ShakePosition(Camera.main.gameObject, tweenParams); iTween.ShakePosition(Camera.main.gameObject, tweenParams);
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
protected virtual void OniTweenComplete(object param) protected virtual void OniTweenComplete(object param)
{ {
Command command = param as Command; Command command = param as Command;
if (command != null && command.Equals(this)) if (command != null && command.Equals(this))
{ {
if (waitUntilFinished) if (waitUntilFinished)
{ {
Continue(); Continue();
} }
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return "For " + duration + " seconds."; return "For " + duration + " seconds.";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

112
Assets/Fungus/Camera/Scripts/Commands/StartSwipe.cs

@ -9,73 +9,73 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Start Swipe", "Start Swipe",
"Activates swipe panning mode where the player can pan the camera within the area between viewA & viewB.")] "Activates swipe panning mode where the player can pan the camera within the area between viewA & viewB.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class StartSwipe : Command public class StartSwipe : Command
{ {
[Tooltip("Defines one extreme of the scrollable area that the player can pan around")] [Tooltip("Defines one extreme of the scrollable area that the player can pan around")]
public View viewA; public View viewA;
[Tooltip("Defines one extreme of the scrollable area that the player can pan around")] [Tooltip("Defines one extreme of the scrollable area that the player can pan around")]
public View viewB; public View viewB;
[Tooltip("Time to move the camera to a valid starting position between the two views")] [Tooltip("Time to move the camera to a valid starting position between the two views")]
public float duration = 0.5f; public float duration = 0.5f;
[Tooltip("Multiplier factor for speed of swipe pan")] [Tooltip("Multiplier factor for speed of swipe pan")]
public float speedMultiplier = 1f; public float speedMultiplier = 1f;
[Tooltip("Camera to use for the pan. Will use main camera if set to none.")] [Tooltip("Camera to use for the pan. Will use main camera if set to none.")]
public Camera targetCamera; public Camera targetCamera;
public virtual void Start() public virtual void Start()
{ {
if (targetCamera == null) if (targetCamera == null)
{ {
targetCamera = Camera.main; targetCamera = Camera.main;
} }
if (targetCamera == null) if (targetCamera == null)
{ {
targetCamera = GameObject.FindObjectOfType<Camera>(); targetCamera = GameObject.FindObjectOfType<Camera>();
} }
} }
public override void OnEnter() public override void OnEnter()
{ {
if (targetCamera == null || if (targetCamera == null ||
viewA == null || viewA == null ||
viewB == null) viewB == null)
{ {
Continue(); Continue();
return; return;
} }
CameraController cameraController = CameraController.GetInstance(); CameraController cameraController = CameraController.GetInstance();
cameraController.StartSwipePan(targetCamera, viewA, viewB, duration, speedMultiplier, () => Continue() ); cameraController.StartSwipePan(targetCamera, viewA, viewB, duration, speedMultiplier, () => Continue() );
} }
public override string GetSummary() public override string GetSummary()
{ {
if (viewA == null) if (viewA == null)
{ {
return "Error: No view selected for View A"; return "Error: No view selected for View A";
} }
if (viewB == null) if (viewB == null)
{ {
return "Error: No view selected for View B"; return "Error: No view selected for View B";
} }
return viewA.name + " to " + viewB.name; return viewA.name + " to " + viewB.name;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

34
Assets/Fungus/Camera/Scripts/Commands/StopSwipe.cs

@ -9,25 +9,25 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Camera", [CommandInfo("Camera",
"Stop Swipe", "Stop Swipe",
"Deactivates swipe panning mode.")] "Deactivates swipe panning mode.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class StopSwipe : Command public class StopSwipe : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
CameraController cameraController = CameraController.GetInstance(); CameraController cameraController = CameraController.GetInstance();
cameraController.StopSwipePan(); cameraController.StopSwipePan();
Continue(); Continue();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(216, 228, 170, 255); return new Color32(216, 228, 170, 255);
} }
} }
} }

62
Assets/Fungus/Camera/Scripts/View.cs

@ -8,38 +8,38 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
/** /**
* Defines a camera view point. * Defines a camera view point.
* The position and rotation are specified using the game object's transform, so this class * The position and rotation are specified using the game object's transform, so this class
* only needs to specify the ortographic view size. * only needs to specify the ortographic view size.
*/ */
[ExecuteInEditMode] [ExecuteInEditMode]
public class View : MonoBehaviour public class View : MonoBehaviour
{ {
/** /**
* Orthographic size of the camera view in world units. * Orthographic size of the camera view in world units.
*/ */
[Tooltip("Orthographic size of the camera view in world units.")] [Tooltip("Orthographic size of the camera view in world units.")]
public float viewSize = 0.5f; public float viewSize = 0.5f;
/** /**
* Aspect ratio of the primary view rectangle. * Aspect ratio of the primary view rectangle.
* e.g. a 4:3 aspect ratio = 1.333 * e.g. a 4:3 aspect ratio = 1.333
*/ */
[Tooltip("Aspect ratio of the primary view rectangle. (e.g. 4:3 aspect ratio = 1.333)")] [Tooltip("Aspect ratio of the primary view rectangle. (e.g. 4:3 aspect ratio = 1.333)")]
public Vector2 primaryAspectRatio = new Vector2(4, 3); public Vector2 primaryAspectRatio = new Vector2(4, 3);
/** /**
* Aspect ratio of the secondary view rectangle. * Aspect ratio of the secondary view rectangle.
* e.g. a 2:1 aspect ratio = 2/1 = 2.0 * e.g. a 2:1 aspect ratio = 2/1 = 2.0
*/ */
[Tooltip("Aspect ratio of the secondary view rectangle. (e.g. 2:1 aspect ratio = 2.0)")] [Tooltip("Aspect ratio of the secondary view rectangle. (e.g. 2:1 aspect ratio = 2.0)")]
public Vector2 secondaryAspectRatio = new Vector2(2, 1); public Vector2 secondaryAspectRatio = new Vector2(2, 1);
protected virtual void Update() protected virtual void Update()
{ {
// Disable scaling to avoid complicating the orthographic size calculations // Disable scaling to avoid complicating the orthographic size calculations
transform.localScale = new Vector3(1,1,1); transform.localScale = new Vector3(1,1,1);
} }
} }
} }

64
Assets/Fungus/Flowchart/Editor/AssetModProcessor.cs

@ -12,41 +12,41 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
/** /**
* Prevents saving of selected blocks and commands to avoid version control conflicts * Prevents saving of selected blocks and commands to avoid version control conflicts
*/ */
public class AssetModProcessor : UnityEditor.AssetModificationProcessor public class AssetModProcessor : UnityEditor.AssetModificationProcessor
{ {
public static string[] OnWillSaveAssets(string[] paths) public static string[] OnWillSaveAssets(string[] paths)
{ {
string sceneName = ""; string sceneName = "";
foreach (string path in paths) foreach (string path in paths)
{ {
if (path.Contains(".unity")) if (path.Contains(".unity"))
{ {
sceneName = Path.GetFileNameWithoutExtension(path); sceneName = Path.GetFileNameWithoutExtension(path);
} }
} }
if (sceneName.Length == 0) if (sceneName.Length == 0)
{ {
return paths; return paths;
} }
// Reset these variables before save so that they won't cause a git conflict // Reset these variables before save so that they won't cause a git conflict
Flowchart[] flowcharts = UnityEngine.Object.FindObjectsOfType<Flowchart>(); Flowchart[] flowcharts = UnityEngine.Object.FindObjectsOfType<Flowchart>();
foreach (Flowchart f in flowcharts) foreach (Flowchart f in flowcharts)
{ {
if (!f.saveSelection) if (!f.saveSelection)
{ {
f.selectedBlock = null; f.selectedBlock = null;
f.ClearSelectedCommands(); f.ClearSelectedCommands();
} }
} }
return paths; return paths;
} }
} }
} }

2110
Assets/Fungus/Flowchart/Editor/BlockEditor.cs

File diff suppressed because it is too large Load Diff

448
Assets/Fungus/Flowchart/Editor/BlockInspector.cs

@ -12,122 +12,122 @@ using System.Linq;
namespace Fungus namespace Fungus
{ {
/** /**
* Temp hidden object which lets us use the entire inspector window to inspect * Temp hidden object which lets us use the entire inspector window to inspect
* the block command list. * the block command list.
*/ */
public class BlockInspector : ScriptableObject public class BlockInspector : ScriptableObject
{ {
[FormerlySerializedAs("sequence")] [FormerlySerializedAs("sequence")]
public Block block; public Block block;
} }
/** /**
* Custom editor for the temp hidden object. * Custom editor for the temp hidden object.
*/ */
[CustomEditor (typeof(BlockInspector), true)] [CustomEditor (typeof(BlockInspector), true)]
public class BlockInspectorEditor : Editor public class BlockInspectorEditor : Editor
{ {
protected Vector2 blockScrollPos; protected Vector2 blockScrollPos;
protected Vector2 commandScrollPos; protected Vector2 commandScrollPos;
protected bool resize = false; protected bool resize = false;
protected bool clamp = false; protected bool clamp = false;
protected float topPanelHeight = 50; protected float topPanelHeight = 50;
protected float windowHeight = 0f; protected float windowHeight = 0f;
// Cache the block and command editors so we only create and destroy them // Cache the block and command editors so we only create and destroy them
// when a different block / command is selected. // when a different block / command is selected.
protected BlockEditor activeBlockEditor; protected BlockEditor activeBlockEditor;
protected CommandEditor activeCommandEditor; protected CommandEditor activeCommandEditor;
protected Command activeCommand; // Command currently being inspected protected Command activeCommand; // Command currently being inspected
// Cached command editors to avoid creating / destroying editors more than necessary // Cached command editors to avoid creating / destroying editors more than necessary
// This list is static so persists between // This list is static so persists between
protected static List<CommandEditor> cachedCommandEditors = new List<CommandEditor>(); protected static List<CommandEditor> cachedCommandEditors = new List<CommandEditor>();
protected void OnDestroy() protected void OnDestroy()
{ {
ClearEditors(); ClearEditors();
} }
protected void OnEnable() protected void OnEnable()
{ {
ClearEditors(); ClearEditors();
} }
protected void OnDisable() protected void OnDisable()
{ {
ClearEditors(); ClearEditors();
} }
protected void ClearEditors() protected void ClearEditors()
{ {
foreach (CommandEditor commandEditor in cachedCommandEditors) foreach (CommandEditor commandEditor in cachedCommandEditors)
{ {
DestroyImmediate(commandEditor); DestroyImmediate(commandEditor);
} }
cachedCommandEditors.Clear(); cachedCommandEditors.Clear();
activeCommandEditor = null; activeCommandEditor = null;
} }
public override void OnInspectorGUI () public override void OnInspectorGUI ()
{ {
BlockInspector blockInspector = target as BlockInspector; BlockInspector blockInspector = target as BlockInspector;
Block block = blockInspector.block; Block block = blockInspector.block;
if (block == null) if (block == null)
{ {
return; return;
} }
Flowchart flowchart = block.GetFlowchart(); Flowchart flowchart = block.GetFlowchart();
if (activeBlockEditor == null || if (activeBlockEditor == null ||
block != activeBlockEditor.target) block != activeBlockEditor.target)
{ {
DestroyImmediate(activeBlockEditor); DestroyImmediate(activeBlockEditor);
activeBlockEditor = Editor.CreateEditor(block) as BlockEditor; activeBlockEditor = Editor.CreateEditor(block) as BlockEditor;
} }
activeBlockEditor.DrawBlockName(flowchart); activeBlockEditor.DrawBlockName(flowchart);
UpdateWindowHeight(); UpdateWindowHeight();
float width = EditorGUIUtility.currentViewWidth; float width = EditorGUIUtility.currentViewWidth;
float height = windowHeight; float height = windowHeight;
// Using a custom rect area to get the correct 5px indent for the scroll views // Using a custom rect area to get the correct 5px indent for the scroll views
Rect blockRect = new Rect(5, topPanelHeight, width - 5, height + 10); Rect blockRect = new Rect(5, topPanelHeight, width - 5, height + 10);
GUILayout.BeginArea(blockRect); GUILayout.BeginArea(blockRect);
blockScrollPos = GUILayout.BeginScrollView(blockScrollPos, GUILayout.Height(flowchart.blockViewHeight)); blockScrollPos = GUILayout.BeginScrollView(blockScrollPos, GUILayout.Height(flowchart.blockViewHeight));
activeBlockEditor.DrawBlockGUI(flowchart); activeBlockEditor.DrawBlockGUI(flowchart);
GUILayout.EndScrollView(); GUILayout.EndScrollView();
Command inspectCommand = null; Command inspectCommand = null;
if (flowchart.selectedCommands.Count == 1) if (flowchart.selectedCommands.Count == 1)
{ {
inspectCommand = flowchart.selectedCommands[0]; inspectCommand = flowchart.selectedCommands[0];
} }
if (Application.isPlaying && if (Application.isPlaying &&
inspectCommand != null && inspectCommand != null &&
inspectCommand.parentBlock != block) inspectCommand.parentBlock != block)
{ {
GUILayout.EndArea(); GUILayout.EndArea();
Repaint(); Repaint();
return; return;
} }
// Only change the activeCommand at the start of the GUI call sequence // Only change the activeCommand at the start of the GUI call sequence
if (Event.current.type == EventType.Layout) if (Event.current.type == EventType.Layout)
{ {
activeCommand = inspectCommand; activeCommand = inspectCommand;
} }
DrawCommandUI(flowchart, inspectCommand); DrawCommandUI(flowchart, inspectCommand);
} }
/// <summary> /// <summary>
/// In Unity 5.4, Screen.height returns the pixel height instead of the point height /// In Unity 5.4, Screen.height returns the pixel height instead of the point height
@ -147,121 +147,121 @@ namespace Fungus
} }
} }
public void DrawCommandUI(Flowchart flowchart, Command inspectCommand) public void DrawCommandUI(Flowchart flowchart, Command inspectCommand)
{ {
ResizeScrollView(flowchart); ResizeScrollView(flowchart);
GUILayout.Space(7); GUILayout.Space(7);
activeBlockEditor.DrawButtonToolbar(); activeBlockEditor.DrawButtonToolbar();
commandScrollPos = GUILayout.BeginScrollView(commandScrollPos); commandScrollPos = GUILayout.BeginScrollView(commandScrollPos);
if (inspectCommand != null) if (inspectCommand != null)
{ {
if (activeCommandEditor == null || if (activeCommandEditor == null ||
inspectCommand != activeCommandEditor.target) inspectCommand != activeCommandEditor.target)
{ {
// See if we have a cached version of the command editor already, // See if we have a cached version of the command editor already,
var editors = (from e in cachedCommandEditors where (e != null && e.target == inspectCommand) select e); var editors = (from e in cachedCommandEditors where (e != null && e.target == inspectCommand) select e);
if (editors.Count() > 0) if (editors.Count() > 0)
{ {
// Use cached editor // Use cached editor
activeCommandEditor = editors.First(); activeCommandEditor = editors.First();
} }
else else
{ {
// No cached editor, so create a new one. // No cached editor, so create a new one.
activeCommandEditor = Editor.CreateEditor(inspectCommand) as CommandEditor; activeCommandEditor = Editor.CreateEditor(inspectCommand) as CommandEditor;
cachedCommandEditors.Add(activeCommandEditor); cachedCommandEditors.Add(activeCommandEditor);
} }
} }
if (activeCommandEditor != null) if (activeCommandEditor != null)
{ {
activeCommandEditor.DrawCommandInspectorGUI(); activeCommandEditor.DrawCommandInspectorGUI();
} }
} }
GUILayout.EndScrollView(); GUILayout.EndScrollView();
GUILayout.EndArea(); GUILayout.EndArea();
// Draw the resize bar after everything else has finished drawing // Draw the resize bar after everything else has finished drawing
// This is mainly to avoid incorrect indenting. // This is mainly to avoid incorrect indenting.
Rect resizeRect = new Rect(0, topPanelHeight + flowchart.blockViewHeight + 1, Screen.width, 4f); Rect resizeRect = new Rect(0, topPanelHeight + flowchart.blockViewHeight + 1, Screen.width, 4f);
GUI.color = new Color(0.64f, 0.64f, 0.64f); GUI.color = new Color(0.64f, 0.64f, 0.64f);
GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture); GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture);
resizeRect.height = 1; resizeRect.height = 1;
GUI.color = new Color32(132, 132, 132, 255); GUI.color = new Color32(132, 132, 132, 255);
GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture); GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture);
resizeRect.y += 3; resizeRect.y += 3;
GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture); GUI.DrawTexture(resizeRect, EditorGUIUtility.whiteTexture);
GUI.color = Color.white; GUI.color = Color.white;
Repaint(); Repaint();
} }
private void ResizeScrollView(Flowchart flowchart) private void ResizeScrollView(Flowchart flowchart)
{ {
Rect cursorChangeRect = new Rect(0, flowchart.blockViewHeight + 1, Screen.width, 4f); Rect cursorChangeRect = new Rect(0, flowchart.blockViewHeight + 1, Screen.width, 4f);
EditorGUIUtility.AddCursorRect(cursorChangeRect, MouseCursor.ResizeVertical); EditorGUIUtility.AddCursorRect(cursorChangeRect, MouseCursor.ResizeVertical);
if (Event.current.type == EventType.mouseDown && cursorChangeRect.Contains(Event.current.mousePosition)) if (Event.current.type == EventType.mouseDown && cursorChangeRect.Contains(Event.current.mousePosition))
{ {
resize = true; resize = true;
} }
if (resize) if (resize)
{ {
Undo.RecordObject(flowchart, "Resize view"); Undo.RecordObject(flowchart, "Resize view");
flowchart.blockViewHeight = Event.current.mousePosition.y; flowchart.blockViewHeight = Event.current.mousePosition.y;
} }
ClampBlockViewHeight(flowchart); ClampBlockViewHeight(flowchart);
// Stop resizing if mouse is outside inspector window. // Stop resizing if mouse is outside inspector window.
// This isn't standard Unity UI behavior but it is robust and safe. // This isn't standard Unity UI behavior but it is robust and safe.
if (resize && Event.current.type == EventType.mouseDrag) if (resize && Event.current.type == EventType.mouseDrag)
{ {
Rect windowRect = new Rect(0, 0, Screen.width, Screen.height); Rect windowRect = new Rect(0, 0, Screen.width, Screen.height);
if (!windowRect.Contains(Event.current.mousePosition)) if (!windowRect.Contains(Event.current.mousePosition))
{ {
resize = false; resize = false;
} }
} }
if (Event.current.type == EventType.MouseUp) if (Event.current.type == EventType.MouseUp)
{ {
resize = false; resize = false;
} }
} }
protected virtual void ClampBlockViewHeight(Flowchart flowchart) protected virtual void ClampBlockViewHeight(Flowchart flowchart)
{ {
// Screen.height seems to temporarily reset to 480 for a single frame whenever a command like // Screen.height seems to temporarily reset to 480 for a single frame whenever a command like
// Copy, Paste, etc. happens. Only clamp the block view height when one of these operations is not occuring. // Copy, Paste, etc. happens. Only clamp the block view height when one of these operations is not occuring.
if (Event.current.commandName != "") if (Event.current.commandName != "")
{ {
clamp = false; clamp = false;
} }
if (clamp) if (clamp)
{ {
// Make sure block view is always clamped to visible area // Make sure block view is always clamped to visible area
float height = flowchart.blockViewHeight; float height = flowchart.blockViewHeight;
height = Mathf.Max(200, height); height = Mathf.Max(200, height);
height = Mathf.Min(Screen.height - 200,height); height = Mathf.Min(Screen.height - 200,height);
flowchart.blockViewHeight = height; flowchart.blockViewHeight = height;
} }
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
clamp = true; clamp = true;
} }
} }
} }
} }

84
Assets/Fungus/Flowchart/Editor/CallEditor.cs

@ -10,57 +10,57 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(Call))] [CustomEditor (typeof(Call))]
public class CallEditor : CommandEditor public class CallEditor : CommandEditor
{ {
protected SerializedProperty targetFlowchartProp; protected SerializedProperty targetFlowchartProp;
protected SerializedProperty targetBlockProp; protected SerializedProperty targetBlockProp;
protected SerializedProperty startIndexProp; protected SerializedProperty startIndexProp;
protected SerializedProperty callModeProp; protected SerializedProperty callModeProp;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
targetFlowchartProp = serializedObject.FindProperty("targetFlowchart"); targetFlowchartProp = serializedObject.FindProperty("targetFlowchart");
targetBlockProp = serializedObject.FindProperty("targetBlock"); targetBlockProp = serializedObject.FindProperty("targetBlock");
startIndexProp = serializedObject.FindProperty("startIndex"); startIndexProp = serializedObject.FindProperty("startIndex");
callModeProp = serializedObject.FindProperty("callMode"); callModeProp = serializedObject.FindProperty("callMode");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
serializedObject.Update(); serializedObject.Update();
Call t = target as Call; Call t = target as Call;
Flowchart flowchart = null; Flowchart flowchart = null;
if (targetFlowchartProp.objectReferenceValue == null) if (targetFlowchartProp.objectReferenceValue == null)
{ {
flowchart = t.GetFlowchart(); flowchart = t.GetFlowchart();
} }
else else
{ {
flowchart = targetFlowchartProp.objectReferenceValue as Flowchart; flowchart = targetFlowchartProp.objectReferenceValue as Flowchart;
} }
EditorGUILayout.PropertyField(targetFlowchartProp); EditorGUILayout.PropertyField(targetFlowchartProp);
if (flowchart != null) if (flowchart != null)
{ {
BlockEditor.BlockField(targetBlockProp, BlockEditor.BlockField(targetBlockProp,
new GUIContent("Target Block", "Block to call"), new GUIContent("Target Block", "Block to call"),
new GUIContent("<None>"), new GUIContent("<None>"),
flowchart); flowchart);
EditorGUILayout.PropertyField(startIndexProp); EditorGUILayout.PropertyField(startIndexProp);
} }
EditorGUILayout.PropertyField(callModeProp); EditorGUILayout.PropertyField(callModeProp);
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

430
Assets/Fungus/Flowchart/Editor/CommandEditor.cs

@ -13,219 +13,219 @@ using Rotorz.ReorderableList;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(Command), true)] [CustomEditor (typeof(Command), true)]
public class CommandEditor : Editor public class CommandEditor : Editor
{ {
public static Command selectedCommand; public static Command selectedCommand;
public static CommandInfoAttribute GetCommandInfo(System.Type commandType) public static CommandInfoAttribute GetCommandInfo(System.Type commandType)
{ {
object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false); object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false);
foreach (object obj in attributes) foreach (object obj in attributes)
{ {
CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute; CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute;
if (commandInfoAttr != null) if (commandInfoAttr != null)
{ {
return commandInfoAttr; return commandInfoAttr;
} }
} }
return null; return null;
} }
public virtual void DrawCommandInspectorGUI() public virtual void DrawCommandInspectorGUI()
{ {
Command t = target as Command; Command t = target as Command;
if (t == null) if (t == null)
{ {
return; return;
} }
Flowchart flowchart = t.GetFlowchart(); Flowchart flowchart = t.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(t.GetType()); CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (commandInfoAttr == null) if (commandInfoAttr == null)
{ {
return; return;
} }
GUILayout.BeginVertical(GUI.skin.box); GUILayout.BeginVertical(GUI.skin.box);
if (t.enabled) if (t.enabled)
{ {
if (flowchart.colorCommands) if (flowchart.colorCommands)
{ {
GUI.backgroundColor = t.GetButtonColor(); GUI.backgroundColor = t.GetButtonColor();
} }
else else
{ {
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
} }
} }
else else
{ {
GUI.backgroundColor = Color.grey; GUI.backgroundColor = Color.grey;
} }
GUILayout.BeginHorizontal(GUI.skin.button); GUILayout.BeginHorizontal(GUI.skin.button);
string commandName = commandInfoAttr.CommandName; string commandName = commandInfoAttr.CommandName;
GUILayout.Label(commandName, GUILayout.MinWidth(80), GUILayout.ExpandWidth(true)); GUILayout.Label(commandName, GUILayout.MinWidth(80), GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label(new GUIContent("(" + t.itemId + ")")); GUILayout.Label(new GUIContent("(" + t.itemId + ")"));
GUILayout.Space(10); GUILayout.Space(10);
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
bool enabled = t.enabled; bool enabled = t.enabled;
enabled = GUILayout.Toggle(enabled, new GUIContent()); enabled = GUILayout.Toggle(enabled, new GUIContent());
if (t.enabled != enabled) if (t.enabled != enabled)
{ {
Undo.RecordObject(t, "Set Enabled"); Undo.RecordObject(t, "Set Enabled");
t.enabled = enabled; t.enabled = enabled;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
EditorGUILayout.Separator(); EditorGUILayout.Separator();
DrawCommandGUI(); DrawCommandGUI();
EditorGUILayout.Separator(); EditorGUILayout.Separator();
if (t.errorMessage.Length > 0) if (t.errorMessage.Length > 0)
{ {
GUIStyle style = new GUIStyle(GUI.skin.label); GUIStyle style = new GUIStyle(GUI.skin.label);
style.normal.textColor = new Color(1,0,0); style.normal.textColor = new Color(1,0,0);
EditorGUILayout.LabelField(new GUIContent("Error: " + t.errorMessage), style); EditorGUILayout.LabelField(new GUIContent("Error: " + t.errorMessage), style);
} }
GUILayout.EndVertical(); GUILayout.EndVertical();
// Display help text // Display help text
CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(t.GetType()); CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (infoAttr != null) if (infoAttr != null)
{ {
EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info, true); EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info, true);
} }
} }
public virtual void DrawCommandGUI() public virtual void DrawCommandGUI()
{ {
Command t = target as Command; Command t = target as Command;
// Code below was copied from here // Code below was copied from here
// http://answers.unity3d.com/questions/550829/how-to-add-a-script-field-in-custom-inspector.html // http://answers.unity3d.com/questions/550829/how-to-add-a-script-field-in-custom-inspector.html
// Users should not be able to change the MonoScript for the command using the usual Script field. // Users should not be able to change the MonoScript for the command using the usual Script field.
// Doing so could cause block.commandList to contain null entries. // Doing so could cause block.commandList to contain null entries.
// To avoid this we manually display all properties, except for m_Script. // To avoid this we manually display all properties, except for m_Script.
serializedObject.Update(); serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator(); SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true; bool enterChildren = true;
while (iterator.NextVisible(enterChildren)) while (iterator.NextVisible(enterChildren))
{ {
enterChildren = false; enterChildren = false;
if (iterator.name == "m_Script") if (iterator.name == "m_Script")
{ {
continue; continue;
} }
if (!t.IsPropertyVisible(iterator.name)) if (!t.IsPropertyVisible(iterator.name))
{ {
continue; continue;
} }
if (iterator.isArray && if (iterator.isArray &&
t.IsReorderableArray(iterator.name)) t.IsReorderableArray(iterator.name))
{ {
ReorderableListGUI.Title(new GUIContent(iterator.displayName, iterator.tooltip)); ReorderableListGUI.Title(new GUIContent(iterator.displayName, iterator.tooltip));
ReorderableListGUI.ListField(iterator); ReorderableListGUI.ListField(iterator);
} }
else else
{ {
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]); EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
} }
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
static public void ObjectField<T>(SerializedProperty property, GUIContent label, GUIContent nullLabel, List<T> objectList) where T : Object static public void ObjectField<T>(SerializedProperty property, GUIContent label, GUIContent nullLabel, List<T> objectList) where T : Object
{ {
if (property == null) if (property == null)
{ {
return; return;
} }
List<GUIContent> objectNames = new List<GUIContent>(); List<GUIContent> objectNames = new List<GUIContent>();
T selectedObject = property.objectReferenceValue as T; T selectedObject = property.objectReferenceValue as T;
int selectedIndex = 0; int selectedIndex = 0;
objectNames.Add(nullLabel); objectNames.Add(nullLabel);
for (int i = 0; i < objectList.Count; ++i) for (int i = 0; i < objectList.Count; ++i)
{ {
if (objectList[i] == null) continue; if (objectList[i] == null) continue;
objectNames.Add(new GUIContent(objectList[i].name)); objectNames.Add(new GUIContent(objectList[i].name));
if (selectedObject == objectList[i]) if (selectedObject == objectList[i])
{ {
selectedIndex = i + 1; selectedIndex = i + 1;
} }
} }
T result; T result;
selectedIndex = EditorGUILayout.Popup(label, selectedIndex, objectNames.ToArray()); selectedIndex = EditorGUILayout.Popup(label, selectedIndex, objectNames.ToArray());
if (selectedIndex == 0) if (selectedIndex == 0)
{ {
result = null; // Null option result = null; // Null option
} }
else else
{ {
result = objectList[selectedIndex - 1]; result = objectList[selectedIndex - 1];
} }
property.objectReferenceValue = result; property.objectReferenceValue = result;
} }
/** /**
* When modifying custom editor code you can occasionally end up with orphaned editor instances. * When modifying custom editor code you can occasionally end up with orphaned editor instances.
* When this happens, you'll get a null exception error every time the scene serializes / deserialized. * When this happens, you'll get a null exception error every time the scene serializes / deserialized.
* Once this situation occurs, the only way to fix it is to restart the Unity editor. * Once this situation occurs, the only way to fix it is to restart the Unity editor.
* *
* As a workaround, this function detects if this command editor is an orphan and deletes it. * As a workaround, this function detects if this command editor is an orphan and deletes it.
* To use it, just call this function at the top of the OnEnable() method in your custom editor. * To use it, just call this function at the top of the OnEnable() method in your custom editor.
*/ */
protected virtual bool NullTargetCheck() protected virtual bool NullTargetCheck()
{ {
try try
{ {
// The serializedObject accessor create a new SerializedObject if needed. // The serializedObject accessor create a new SerializedObject if needed.
// However, this will fail with a null exception if the target object no longer exists. // However, this will fail with a null exception if the target object no longer exists.
#pragma warning disable 0219 #pragma warning disable 0219
SerializedObject so = serializedObject; SerializedObject so = serializedObject;
} }
catch (System.NullReferenceException) catch (System.NullReferenceException)
{ {
DestroyImmediate(this); DestroyImmediate(this);
return true; return true;
} }
return false; return false;
} }
} }
} }

912
Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs

@ -16,460 +16,460 @@ using Rotorz.ReorderableList;
namespace Fungus namespace Fungus
{ {
public class CommandListAdaptor : IReorderableListAdaptor { public class CommandListAdaptor : IReorderableListAdaptor {
protected SerializedProperty _arrayProperty; protected SerializedProperty _arrayProperty;
public float fixedItemHeight; public float fixedItemHeight;
public Rect nodeRect = new Rect(); public Rect nodeRect = new Rect();
public SerializedProperty this[int index] { public SerializedProperty this[int index] {
get { return _arrayProperty.GetArrayElementAtIndex(index); } get { return _arrayProperty.GetArrayElementAtIndex(index); }
} }
public SerializedProperty arrayProperty { public SerializedProperty arrayProperty {
get { return _arrayProperty; } get { return _arrayProperty; }
} }
public CommandListAdaptor(SerializedProperty arrayProperty, float fixedItemHeight) { public CommandListAdaptor(SerializedProperty arrayProperty, float fixedItemHeight) {
if (arrayProperty == null) if (arrayProperty == null)
throw new ArgumentNullException("Array property was null."); throw new ArgumentNullException("Array property was null.");
if (!arrayProperty.isArray) if (!arrayProperty.isArray)
throw new InvalidOperationException("Specified serialized propery is not an array."); throw new InvalidOperationException("Specified serialized propery is not an array.");
this._arrayProperty = arrayProperty; this._arrayProperty = arrayProperty;
this.fixedItemHeight = fixedItemHeight; this.fixedItemHeight = fixedItemHeight;
} }
public CommandListAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) { public CommandListAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) {
} }
public int Count { public int Count {
get { return _arrayProperty.arraySize; } get { return _arrayProperty.arraySize; }
} }
public virtual bool CanDrag(int index) { public virtual bool CanDrag(int index) {
return true; return true;
} }
public virtual bool CanRemove(int index) { public virtual bool CanRemove(int index) {
return true; return true;
} }
public void Add() { public void Add() {
Command newCommand = AddNewCommand(); Command newCommand = AddNewCommand();
if (newCommand == null) if (newCommand == null)
{ {
return; return;
} }
int newIndex = _arrayProperty.arraySize; int newIndex = _arrayProperty.arraySize;
++_arrayProperty.arraySize; ++_arrayProperty.arraySize;
_arrayProperty.GetArrayElementAtIndex(newIndex).objectReferenceValue = newCommand; _arrayProperty.GetArrayElementAtIndex(newIndex).objectReferenceValue = newCommand;
} }
public void Insert(int index) { public void Insert(int index) {
Command newCommand = AddNewCommand(); Command newCommand = AddNewCommand();
if (newCommand == null) if (newCommand == null)
{ {
return; return;
} }
_arrayProperty.InsertArrayElementAtIndex(index); _arrayProperty.InsertArrayElementAtIndex(index);
_arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = newCommand; _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = newCommand;
} }
Command AddNewCommand() Command AddNewCommand()
{ {
Flowchart flowchart = FlowchartWindow.GetFlowchart(); Flowchart flowchart = FlowchartWindow.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return null; return null;
} }
Block block = flowchart.selectedBlock; Block block = flowchart.selectedBlock;
if (block == null) if (block == null)
{ {
return null; return null;
} }
Command newCommand = Undo.AddComponent<Comment>(block.gameObject) as Command; Command newCommand = Undo.AddComponent<Comment>(block.gameObject) as Command;
newCommand.itemId = flowchart.NextItemId(); newCommand.itemId = flowchart.NextItemId();
flowchart.ClearSelectedCommands(); flowchart.ClearSelectedCommands();
flowchart.AddSelectedCommand(newCommand); flowchart.AddSelectedCommand(newCommand);
return newCommand; return newCommand;
} }
public void Duplicate(int index) { public void Duplicate(int index) {
Command command = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Command; Command command = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Command;
// Add the command as a new component // Add the command as a new component
Block parentBlock = command.GetComponent<Block>(); Block parentBlock = command.GetComponent<Block>();
System.Type type = command.GetType(); System.Type type = command.GetType();
Command newCommand = Undo.AddComponent(parentBlock.gameObject, type) as Command; Command newCommand = Undo.AddComponent(parentBlock.gameObject, type) as Command;
newCommand.itemId = newCommand.GetFlowchart().NextItemId(); newCommand.itemId = newCommand.GetFlowchart().NextItemId();
System.Reflection.FieldInfo[] fields = type.GetFields(); System.Reflection.FieldInfo[] fields = type.GetFields();
foreach (System.Reflection.FieldInfo field in fields) foreach (System.Reflection.FieldInfo field in fields)
{ {
field.SetValue(newCommand, field.GetValue(command)); field.SetValue(newCommand, field.GetValue(command));
} }
_arrayProperty.InsertArrayElementAtIndex(index); _arrayProperty.InsertArrayElementAtIndex(index);
_arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = newCommand; _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = newCommand;
} }
public void Remove(int index) { public void Remove(int index) {
// Remove the Fungus Command component // Remove the Fungus Command component
Command command = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Command; Command command = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Command;
if (command != null) if (command != null)
{ {
Undo.DestroyObjectImmediate(command); Undo.DestroyObjectImmediate(command);
} }
_arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = null; _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = null;
_arrayProperty.DeleteArrayElementAtIndex(index); _arrayProperty.DeleteArrayElementAtIndex(index);
} }
public void Move(int sourceIndex, int destIndex) { public void Move(int sourceIndex, int destIndex) {
if (destIndex > sourceIndex) if (destIndex > sourceIndex)
--destIndex; --destIndex;
_arrayProperty.MoveArrayElement(sourceIndex, destIndex); _arrayProperty.MoveArrayElement(sourceIndex, destIndex);
} }
public void Clear() { public void Clear() {
while (Count > 0) while (Count > 0)
{ {
Remove(0); Remove(0);
} }
} }
public void BeginGUI() public void BeginGUI()
{} {}
public void EndGUI() public void EndGUI()
{} {}
public void DrawItemBackground(Rect position, int index) { public void DrawItemBackground(Rect position, int index) {
} }
public void DrawItem(Rect position, int index) public void DrawItem(Rect position, int index)
{ {
Command command = this[index].objectReferenceValue as Command; Command command = this[index].objectReferenceValue as Command;
if (command == null) if (command == null)
{ {
return; return;
} }
CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(command.GetType()); CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(command.GetType());
if (commandInfoAttr == null) if (commandInfoAttr == null)
{ {
return; return;
} }
Flowchart flowchart = command.GetFlowchart(); Flowchart flowchart = command.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
bool isComment = command.GetType() == typeof(Comment); bool isComment = command.GetType() == typeof(Comment);
bool isLabel = (command.GetType() == typeof(Label)); bool isLabel = (command.GetType() == typeof(Label));
bool error = false; bool error = false;
string summary = command.GetSummary(); string summary = command.GetSummary();
if (summary == null) if (summary == null)
{ {
summary = ""; summary = "";
} }
else else
{ {
summary = summary.Replace("\n", "").Replace("\r", ""); summary = summary.Replace("\n", "").Replace("\r", "");
} }
if (summary.StartsWith("Error:")) if (summary.StartsWith("Error:"))
{ {
error = true; error = true;
} }
if (isComment || isLabel) if (isComment || isLabel)
{ {
summary = "<b> " + summary + "</b>"; summary = "<b> " + summary + "</b>";
} }
else else
{ {
summary = "<i>" + summary + "</i>"; summary = "<i>" + summary + "</i>";
} }
bool commandIsSelected = false; bool commandIsSelected = false;
foreach (Command selectedCommand in flowchart.selectedCommands) foreach (Command selectedCommand in flowchart.selectedCommands)
{ {
if (selectedCommand == command) if (selectedCommand == command)
{ {
commandIsSelected = true; commandIsSelected = true;
break; break;
} }
} }
string commandName = commandInfoAttr.CommandName; string commandName = commandInfoAttr.CommandName;
GUIStyle commandLabelStyle = new GUIStyle(GUI.skin.box); GUIStyle commandLabelStyle = new GUIStyle(GUI.skin.box);
commandLabelStyle.normal.background = FungusEditorResources.texCommandBackground; commandLabelStyle.normal.background = FungusEditorResources.texCommandBackground;
int borderSize = 5; int borderSize = 5;
commandLabelStyle.border.top = borderSize; commandLabelStyle.border.top = borderSize;
commandLabelStyle.border.bottom = borderSize; commandLabelStyle.border.bottom = borderSize;
commandLabelStyle.border.left = borderSize; commandLabelStyle.border.left = borderSize;
commandLabelStyle.border.right = borderSize; commandLabelStyle.border.right = borderSize;
commandLabelStyle.alignment = TextAnchor.MiddleLeft; commandLabelStyle.alignment = TextAnchor.MiddleLeft;
commandLabelStyle.richText = true; commandLabelStyle.richText = true;
commandLabelStyle.fontSize = 11; commandLabelStyle.fontSize = 11;
commandLabelStyle.padding.top -= 1; commandLabelStyle.padding.top -= 1;
float indentSize = 20; float indentSize = 20;
for (int i = 0; i < command.indentLevel; ++i) for (int i = 0; i < command.indentLevel; ++i)
{ {
Rect indentRect = position; Rect indentRect = position;
indentRect.x += i * indentSize - 21; indentRect.x += i * indentSize - 21;
indentRect.width = indentSize + 1; indentRect.width = indentSize + 1;
indentRect.y -= 2; indentRect.y -= 2;
indentRect.height += 5; indentRect.height += 5;
GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1f); GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 1f);
GUI.Box(indentRect, "", commandLabelStyle); GUI.Box(indentRect, "", commandLabelStyle);
} }
float commandNameWidth = Mathf.Max(commandLabelStyle.CalcSize(new GUIContent(commandName)).x, 90f); float commandNameWidth = Mathf.Max(commandLabelStyle.CalcSize(new GUIContent(commandName)).x, 90f);
float indentWidth = command.indentLevel * indentSize; float indentWidth = command.indentLevel * indentSize;
Rect commandLabelRect = position; Rect commandLabelRect = position;
commandLabelRect.x += indentWidth - 21; commandLabelRect.x += indentWidth - 21;
commandLabelRect.y -= 2; commandLabelRect.y -= 2;
commandLabelRect.width -= (indentSize * command.indentLevel - 22); commandLabelRect.width -= (indentSize * command.indentLevel - 22);
commandLabelRect.height += 5; commandLabelRect.height += 5;
// There's a weird incompatibility between the Reorderable list control used for the command list and // There's a weird incompatibility between the Reorderable list control used for the command list and
// the UnityEvent list control used in some commands. In play mode, if you click on the reordering grabber // the UnityEvent list control used in some commands. In play mode, if you click on the reordering grabber
// for a command in the list it causes the UnityEvent list to spew null exception errors. // for a command in the list it causes the UnityEvent list to spew null exception errors.
// The workaround for now is to hide the reordering grabber from mouse clicks by extending the command // The workaround for now is to hide the reordering grabber from mouse clicks by extending the command
// selection rectangle to cover it. We are planning to totally replace the command list display system. // selection rectangle to cover it. We are planning to totally replace the command list display system.
Rect clickRect = position; Rect clickRect = position;
clickRect.x -= 20; clickRect.x -= 20;
clickRect.width += 20; clickRect.width += 20;
// Select command via left click // Select command via left click
if (Event.current.type == EventType.MouseDown && if (Event.current.type == EventType.MouseDown &&
Event.current.button == 0 && Event.current.button == 0 &&
clickRect.Contains(Event.current.mousePosition)) clickRect.Contains(Event.current.mousePosition))
{ {
if (flowchart.selectedCommands.Contains(command) && Event.current.button == 0) if (flowchart.selectedCommands.Contains(command) && Event.current.button == 0)
{ {
// Left click on already selected command // Left click on already selected command
// Command key and shift key is not pressed // Command key and shift key is not pressed
if (!EditorGUI.actionKey && !Event.current.shift) if (!EditorGUI.actionKey && !Event.current.shift)
{ {
BlockEditor.actionList.Add ( delegate { BlockEditor.actionList.Add ( delegate {
flowchart.selectedCommands.Remove(command); flowchart.selectedCommands.Remove(command);
flowchart.ClearSelectedCommands(); flowchart.ClearSelectedCommands();
}); });
} }
// Command key pressed // Command key pressed
if (EditorGUI.actionKey) if (EditorGUI.actionKey)
{ {
BlockEditor.actionList.Add ( delegate { BlockEditor.actionList.Add ( delegate {
flowchart.selectedCommands.Remove(command); flowchart.selectedCommands.Remove(command);
}); });
Event.current.Use(); Event.current.Use();
} }
} }
else else
{ {
bool shift = Event.current.shift; bool shift = Event.current.shift;
// Left click and no command key // Left click and no command key
if (!shift && !EditorGUI.actionKey && Event.current.button == 0) if (!shift && !EditorGUI.actionKey && Event.current.button == 0)
{ {
BlockEditor.actionList.Add ( delegate { BlockEditor.actionList.Add ( delegate {
flowchart.ClearSelectedCommands(); flowchart.ClearSelectedCommands();
}); });
Event.current.Use(); Event.current.Use();
} }
BlockEditor.actionList.Add ( delegate { BlockEditor.actionList.Add ( delegate {
flowchart.AddSelectedCommand(command); flowchart.AddSelectedCommand(command);
}); });
// Find first and last selected commands // Find first and last selected commands
int firstSelectedIndex = -1; int firstSelectedIndex = -1;
int lastSelectedIndex = -1; int lastSelectedIndex = -1;
if (flowchart.selectedCommands.Count > 0) if (flowchart.selectedCommands.Count > 0)
{ {
if ( flowchart.selectedBlock != null) if ( flowchart.selectedBlock != null)
{ {
for (int i = 0; i < flowchart.selectedBlock.commandList.Count; i++) for (int i = 0; i < flowchart.selectedBlock.commandList.Count; i++)
{ {
Command commandInBlock = flowchart.selectedBlock.commandList[i]; Command commandInBlock = flowchart.selectedBlock.commandList[i];
foreach (Command selectedCommand in flowchart.selectedCommands) foreach (Command selectedCommand in flowchart.selectedCommands)
{ {
if (commandInBlock == selectedCommand) if (commandInBlock == selectedCommand)
{ {
firstSelectedIndex = i; firstSelectedIndex = i;
break; break;
} }
} }
} }
for (int i = flowchart.selectedBlock.commandList.Count - 1; i >=0; i--) for (int i = flowchart.selectedBlock.commandList.Count - 1; i >=0; i--)
{ {
Command commandInBlock = flowchart.selectedBlock.commandList[i]; Command commandInBlock = flowchart.selectedBlock.commandList[i];
foreach (Command selectedCommand in flowchart.selectedCommands) foreach (Command selectedCommand in flowchart.selectedCommands)
{ {
if (commandInBlock == selectedCommand) if (commandInBlock == selectedCommand)
{ {
lastSelectedIndex = i; lastSelectedIndex = i;
break; break;
} }
} }
} }
} }
} }
if (shift) if (shift)
{ {
int currentIndex = command.commandIndex; int currentIndex = command.commandIndex;
if (firstSelectedIndex == -1 || if (firstSelectedIndex == -1 ||
lastSelectedIndex == -1) lastSelectedIndex == -1)
{ {
// No selected command found - select entire list // No selected command found - select entire list
firstSelectedIndex = 0; firstSelectedIndex = 0;
lastSelectedIndex = currentIndex; lastSelectedIndex = currentIndex;
} }
else else
{ {
if (currentIndex < firstSelectedIndex) if (currentIndex < firstSelectedIndex)
{ {
firstSelectedIndex = currentIndex; firstSelectedIndex = currentIndex;
} }
if (currentIndex > lastSelectedIndex) if (currentIndex > lastSelectedIndex)
{ {
lastSelectedIndex = currentIndex; lastSelectedIndex = currentIndex;
} }
} }
for (int i = Math.Min(firstSelectedIndex, lastSelectedIndex); i < Math.Max(firstSelectedIndex, lastSelectedIndex); ++i) for (int i = Math.Min(firstSelectedIndex, lastSelectedIndex); i < Math.Max(firstSelectedIndex, lastSelectedIndex); ++i)
{ {
Command selectedCommand = flowchart.selectedBlock.commandList[i]; Command selectedCommand = flowchart.selectedBlock.commandList[i];
BlockEditor.actionList.Add ( delegate { BlockEditor.actionList.Add ( delegate {
flowchart.AddSelectedCommand(selectedCommand); flowchart.AddSelectedCommand(selectedCommand);
}); });
} }
} }
Event.current.Use(); Event.current.Use();
} }
GUIUtility.keyboardControl = 0; // Fix for textarea not refeshing (change focus) GUIUtility.keyboardControl = 0; // Fix for textarea not refeshing (change focus)
} }
Color commandLabelColor = Color.white; Color commandLabelColor = Color.white;
if (flowchart.colorCommands) if (flowchart.colorCommands)
{ {
commandLabelColor = command.GetButtonColor(); commandLabelColor = command.GetButtonColor();
} }
if (commandIsSelected) if (commandIsSelected)
{ {
commandLabelColor = Color.green; commandLabelColor = Color.green;
} }
else if (!command.enabled) else if (!command.enabled)
{ {
commandLabelColor = Color.grey; commandLabelColor = Color.grey;
} }
else if (error) else if (error)
{ {
// TODO: Show warning icon // TODO: Show warning icon
} }
GUI.backgroundColor = commandLabelColor; GUI.backgroundColor = commandLabelColor;
if (isComment) if (isComment)
{ {
GUI.Label(commandLabelRect, "", commandLabelStyle); GUI.Label(commandLabelRect, "", commandLabelStyle);
} }
else else
{ {
string commandNameLabel; string commandNameLabel;
if (flowchart.showLineNumbers) if (flowchart.showLineNumbers)
{ {
commandNameLabel = command.commandIndex.ToString() + ": " + commandName; commandNameLabel = command.commandIndex.ToString() + ": " + commandName;
} }
else else
{ {
commandNameLabel = commandName; commandNameLabel = commandName;
} }
GUI.Label(commandLabelRect, commandNameLabel, commandLabelStyle); GUI.Label(commandLabelRect, commandNameLabel, commandLabelStyle);
} }
if (command.executingIconTimer > Time.realtimeSinceStartup) if (command.executingIconTimer > Time.realtimeSinceStartup)
{ {
Rect iconRect = new Rect(commandLabelRect); Rect iconRect = new Rect(commandLabelRect);
iconRect.x += iconRect.width - commandLabelRect.width - 20; iconRect.x += iconRect.width - commandLabelRect.width - 20;
iconRect.width = 20; iconRect.width = 20;
iconRect.height = 20; iconRect.height = 20;
Color storeColor = GUI.color; Color storeColor = GUI.color;
float alpha = (command.executingIconTimer - Time.realtimeSinceStartup) / Block.executingIconFadeTime; float alpha = (command.executingIconTimer - Time.realtimeSinceStartup) / Block.executingIconFadeTime;
alpha = Mathf.Clamp01(alpha); alpha = Mathf.Clamp01(alpha);
GUI.color = new Color(1f, 1f, 1f, alpha); GUI.color = new Color(1f, 1f, 1f, alpha);
GUI.Label(iconRect, FungusEditorResources.texPlaySmall, new GUIStyle()); GUI.Label(iconRect, FungusEditorResources.texPlaySmall, new GUIStyle());
GUI.color = storeColor; GUI.color = storeColor;
} }
Rect summaryRect = new Rect(commandLabelRect); Rect summaryRect = new Rect(commandLabelRect);
if (isComment) if (isComment)
{ {
summaryRect.x += 5; summaryRect.x += 5;
} }
else else
{ {
summaryRect.x += commandNameWidth + 5; summaryRect.x += commandNameWidth + 5;
summaryRect.width -= commandNameWidth + 5; summaryRect.width -= commandNameWidth + 5;
} }
GUIStyle summaryStyle = new GUIStyle(); GUIStyle summaryStyle = new GUIStyle();
summaryStyle.fontSize = 10; summaryStyle.fontSize = 10;
summaryStyle.padding.top += 5; summaryStyle.padding.top += 5;
summaryStyle.richText = true; summaryStyle.richText = true;
summaryStyle.wordWrap = false; summaryStyle.wordWrap = false;
summaryStyle.clipping = TextClipping.Clip; summaryStyle.clipping = TextClipping.Clip;
commandLabelStyle.alignment = TextAnchor.MiddleLeft; commandLabelStyle.alignment = TextAnchor.MiddleLeft;
GUI.Label(summaryRect, summary, summaryStyle); GUI.Label(summaryRect, summary, summaryStyle);
if (error) if (error)
{ {
GUISkin editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector); GUISkin editorSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector);
Rect errorRect = new Rect(summaryRect); Rect errorRect = new Rect(summaryRect);
errorRect.x += errorRect.width - 20; errorRect.x += errorRect.width - 20;
errorRect.y += 2; errorRect.y += 2;
errorRect.width = 20; errorRect.width = 20;
GUI.Label(errorRect, editorSkin.GetStyle("CN EntryError").normal.background); GUI.Label(errorRect, editorSkin.GetStyle("CN EntryError").normal.background);
summaryRect.width -= 20; summaryRect.width -= 20;
} }
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
} }
public virtual float GetItemHeight(int index) { public virtual float GetItemHeight(int index) {
return fixedItemHeight != 0f return fixedItemHeight != 0f
? fixedItemHeight ? fixedItemHeight
: EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false) : EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false)
; ;
} }
} }
} }

64
Assets/Fungus/Flowchart/Editor/CustomGUI.cs

@ -12,39 +12,39 @@ using System.Reflection;
namespace Fungus namespace Fungus
{ {
/** /**
* Utility functions for drawing custom UI in the editor * Utility functions for drawing custom UI in the editor
*/ */
public static class CustomGUI public static class CustomGUI
{ {
public static Texture2D CreateBlackTexture() public static Texture2D CreateBlackTexture()
{ {
Texture2D blackTex = new Texture2D(1,2); Texture2D blackTex = new Texture2D(1,2);
blackTex.SetPixel(0, 0, Color.gray); blackTex.SetPixel(0, 0, Color.gray);
blackTex.SetPixel(1, 0, Color.black); blackTex.SetPixel(1, 0, Color.black);
blackTex.Apply(); blackTex.Apply();
blackTex.hideFlags = HideFlags.DontSave; blackTex.hideFlags = HideFlags.DontSave;
return blackTex; return blackTex;
} }
public static Texture2D CreateColorTexture(Color color) public static Texture2D CreateColorTexture(Color color)
{ {
Texture2D colorTex = new Texture2D(1,1); Texture2D colorTex = new Texture2D(1,1);
colorTex.SetPixel(0, 0, color); colorTex.SetPixel(0, 0, color);
colorTex.Apply(); colorTex.Apply();
colorTex.hideFlags = HideFlags.DontSave; colorTex.hideFlags = HideFlags.DontSave;
return colorTex; return colorTex;
} }
public static void DrawLineSeparator(Texture2D blackTex, float width) public static void DrawLineSeparator(Texture2D blackTex, float width)
{ {
GUIStyle separatorStyle = new GUIStyle(GUI.skin.box); GUIStyle separatorStyle = new GUIStyle(GUI.skin.box);
separatorStyle.fixedWidth = width; separatorStyle.fixedWidth = width;
separatorStyle.fixedHeight = 2; separatorStyle.fixedHeight = 2;
separatorStyle.margin.top = 10; separatorStyle.margin.top = 10;
separatorStyle.margin.bottom = 10; separatorStyle.margin.bottom = 10;
GUILayout.Box(blackTex,separatorStyle); GUILayout.Box(blackTex,separatorStyle);
} }
} }
} }

102
Assets/Fungus/Flowchart/Editor/EditorExtensions.cs

@ -11,62 +11,62 @@ using System.Linq;
namespace Fungus namespace Fungus
{ {
public static class EditorExtensions public static class EditorExtensions
{ {
/// <summary> /// <summary>
/// FindDerivedTypesFromAssembly allows a user to query all of types derived from a /// FindDerivedTypesFromAssembly allows a user to query all of types derived from a
/// particular Type at runtime. /// particular Type at runtime.
/// Example usage: /// Example usage:
/// foreach (System.Type st in EditorUtility.FindDerivedTypesFromAssembly(System.Reflection.Assembly.GetAssembly(typeof(BaseTimelineEvent)), typeof(BaseTimelineEvent), true)) /// foreach (System.Type st in EditorUtility.FindDerivedTypesFromAssembly(System.Reflection.Assembly.GetAssembly(typeof(BaseTimelineEvent)), typeof(BaseTimelineEvent), true))
/// </summary> /// </summary>
/// <param name="assembly">The assembly to search in</param> /// <param name="assembly">The assembly to search in</param>
/// <param name="baseType">The base Type from which all returned Types derive</param> /// <param name="baseType">The base Type from which all returned Types derive</param>
/// <param name="classOnly">If true, only class Types will be returned</param> /// <param name="classOnly">If true, only class Types will be returned</param>
/// <returns></returns> /// <returns></returns>
public static System.Type[] FindDerivedTypesFromAssembly(this System.Reflection.Assembly assembly, System.Type baseType, bool classOnly = true) public static System.Type[] FindDerivedTypesFromAssembly(this System.Reflection.Assembly assembly, System.Type baseType, bool classOnly = true)
{ {
if (assembly == null) if (assembly == null)
Debug.LogError("Assembly must be defined"); Debug.LogError("Assembly must be defined");
if (baseType == null) if (baseType == null)
Debug.LogError("Base type must be defined"); Debug.LogError("Base type must be defined");
// Iterate through all available types in the assembly // Iterate through all available types in the assembly
var types = assembly.GetTypes().Where(type => var types = assembly.GetTypes().Where(type =>
{ {
if (classOnly && !type.IsClass) if (classOnly && !type.IsClass)
return false; return false;
if (baseType.IsInterface) if (baseType.IsInterface)
{ {
var it = type.GetInterface(baseType.FullName); var it = type.GetInterface(baseType.FullName);
if (it != null) if (it != null)
return true; return true;
} }
else if (type.IsSubclassOf(baseType)) else if (type.IsSubclassOf(baseType))
{ {
return true; return true;
} }
return false; return false;
} }
); );
return types.ToArray(); return types.ToArray();
} }
/// <summary> /// <summary>
/// A convenient method for calling the above. /// A convenient method for calling the above.
/// Example usage: /// Example usage:
/// List<System.Type> subTypes = EditorUtility.FindDerivedTypes(typeof(BaseTimelineEvent)).ToList(); /// List<System.Type> subTypes = EditorUtility.FindDerivedTypes(typeof(BaseTimelineEvent)).ToList();
/// </summary> /// </summary>
/// <param name="baseType"></param> /// <param name="baseType"></param>
/// <param name="classOnly"></param> /// <param name="classOnly"></param>
/// <returns></returns> /// <returns></returns>
public static System.Type[] FindDerivedTypes(System.Type baseType, bool classOnly = true) public static System.Type[] FindDerivedTypes(System.Type baseType, bool classOnly = true)
{ {
return FindDerivedTypesFromAssembly(System.Reflection.Assembly.GetAssembly(baseType), baseType, classOnly); return FindDerivedTypesFromAssembly(System.Reflection.Assembly.GetAssembly(baseType), baseType, classOnly);
} }
} }
} }

144
Assets/Fungus/Flowchart/Editor/EditorZoomArea.cs

@ -10,82 +10,82 @@ using UnityEngine;
namespace Fungus namespace Fungus
{ {
// Helper Rect extension methods // Helper Rect extension methods
public static class RectExtensions public static class RectExtensions
{ {
public static Vector2 TopLeft(this Rect rect) public static Vector2 TopLeft(this Rect rect)
{ {
return new Vector2(rect.xMin, rect.yMin); return new Vector2(rect.xMin, rect.yMin);
} }
public static Rect ScaleSizeBy(this Rect rect, float scale) public static Rect ScaleSizeBy(this Rect rect, float scale)
{ {
return rect.ScaleSizeBy(scale, rect.center); return rect.ScaleSizeBy(scale, rect.center);
} }
public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint) public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint)
{ {
Rect result = rect; Rect result = rect;
result.x -= pivotPoint.x; result.x -= pivotPoint.x;
result.y -= pivotPoint.y; result.y -= pivotPoint.y;
result.xMin *= scale; result.xMin *= scale;
result.xMax *= scale; result.xMax *= scale;
result.yMin *= scale; result.yMin *= scale;
result.yMax *= scale; result.yMax *= scale;
result.x += pivotPoint.x; result.x += pivotPoint.x;
result.y += pivotPoint.y; result.y += pivotPoint.y;
return result; return result;
} }
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale) public static Rect ScaleSizeBy(this Rect rect, Vector2 scale)
{ {
return rect.ScaleSizeBy(scale, rect.center); return rect.ScaleSizeBy(scale, rect.center);
} }
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint) public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint)
{ {
Rect result = rect; Rect result = rect;
result.x -= pivotPoint.x; result.x -= pivotPoint.x;
result.y -= pivotPoint.y; result.y -= pivotPoint.y;
result.xMin *= scale.x; result.xMin *= scale.x;
result.xMax *= scale.x; result.xMax *= scale.x;
result.yMin *= scale.y; result.yMin *= scale.y;
result.yMax *= scale.y; result.yMax *= scale.y;
result.x += pivotPoint.x; result.x += pivotPoint.x;
result.y += pivotPoint.y; result.y += pivotPoint.y;
return result; return result;
} }
} }
public class EditorZoomArea public class EditorZoomArea
{ {
private const float kEditorWindowTabHeight = 21.0f; private const float kEditorWindowTabHeight = 21.0f;
private static Matrix4x4 _prevGuiMatrix; private static Matrix4x4 _prevGuiMatrix;
public static Rect Begin(float zoomScale, Rect screenCoordsArea) public static Rect Begin(float zoomScale, Rect screenCoordsArea)
{ {
GUI.EndGroup(); // End the group Unity begins automatically for an EditorWindow to clip out the window tab. This allows us to draw outside of the size of the EditorWindow. GUI.EndGroup(); // End the group Unity begins automatically for an EditorWindow to clip out the window tab. This allows us to draw outside of the size of the EditorWindow.
Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft()); Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft());
clippedArea.y += kEditorWindowTabHeight; clippedArea.y += kEditorWindowTabHeight;
GUI.BeginGroup(clippedArea); GUI.BeginGroup(clippedArea);
_prevGuiMatrix = GUI.matrix; _prevGuiMatrix = GUI.matrix;
Matrix4x4 translation = Matrix4x4.TRS(clippedArea.TopLeft(), Quaternion.identity, Vector3.one); Matrix4x4 translation = Matrix4x4.TRS(clippedArea.TopLeft(), Quaternion.identity, Vector3.one);
Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f)); Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f));
GUI.matrix = translation * scale * translation.inverse * GUI.matrix; GUI.matrix = translation * scale * translation.inverse * GUI.matrix;
return clippedArea; return clippedArea;
} }
public static void End() public static void End()
{ {
GUI.matrix = _prevGuiMatrix; GUI.matrix = _prevGuiMatrix;
GUI.EndGroup(); GUI.EndGroup();
GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height)); GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height));
} }
} }
} }

92
Assets/Fungus/Flowchart/Editor/EventHandlerEditor.cs

@ -12,57 +12,57 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(EventHandler), true)] [CustomEditor (typeof(EventHandler), true)]
public class EventHandlerEditor : Editor public class EventHandlerEditor : Editor
{ {
/** /**
* Returns the class attribute info for an event handler class. * Returns the class attribute info for an event handler class.
*/ */
public static EventHandlerInfoAttribute GetEventHandlerInfo(System.Type eventHandlerType) public static EventHandlerInfoAttribute GetEventHandlerInfo(System.Type eventHandlerType)
{ {
object[] attributes = eventHandlerType.GetCustomAttributes(typeof(EventHandlerInfoAttribute), false); object[] attributes = eventHandlerType.GetCustomAttributes(typeof(EventHandlerInfoAttribute), false);
foreach (object obj in attributes) foreach (object obj in attributes)
{ {
EventHandlerInfoAttribute eventHandlerInfoAttr = obj as EventHandlerInfoAttribute; EventHandlerInfoAttribute eventHandlerInfoAttr = obj as EventHandlerInfoAttribute;
if (eventHandlerInfoAttr != null) if (eventHandlerInfoAttr != null)
{ {
return eventHandlerInfoAttr; return eventHandlerInfoAttr;
} }
} }
return null; return null;
} }
public virtual void DrawInspectorGUI() public virtual void DrawInspectorGUI()
{ {
// Users should not be able to change the MonoScript for the command using the usual Script field. // Users should not be able to change the MonoScript for the command using the usual Script field.
// Doing so could cause block.commandList to contain null entries. // Doing so could cause block.commandList to contain null entries.
// To avoid this we manually display all properties, except for m_Script. // To avoid this we manually display all properties, except for m_Script.
serializedObject.Update(); serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator(); SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true; bool enterChildren = true;
while (iterator.NextVisible(enterChildren)) while (iterator.NextVisible(enterChildren))
{ {
enterChildren = false; enterChildren = false;
if (iterator.name == "m_Script") if (iterator.name == "m_Script")
{ {
continue; continue;
} }
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]); EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
} }
EventHandler t = target as EventHandler; EventHandler t = target as EventHandler;
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType()); EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType());
if (info != null && if (info != null &&
info.HelpText.Length > 0) info.HelpText.Length > 0)
{ {
EditorGUILayout.HelpBox(info.HelpText, MessageType.Info); EditorGUILayout.HelpBox(info.HelpText, MessageType.Info);
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

538
Assets/Fungus/Flowchart/Editor/FlowchartEditor.cs

@ -14,288 +14,288 @@ using System.IO;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(Flowchart))] [CustomEditor (typeof(Flowchart))]
public class FlowchartEditor : Editor public class FlowchartEditor : Editor
{ {
protected class AddVariableInfo protected class AddVariableInfo
{ {
public Flowchart flowchart; public Flowchart flowchart;
public System.Type variableType; public System.Type variableType;
} }
protected SerializedProperty descriptionProp; protected SerializedProperty descriptionProp;
protected SerializedProperty colorCommandsProp; protected SerializedProperty colorCommandsProp;
protected SerializedProperty hideComponentsProp; protected SerializedProperty hideComponentsProp;
protected SerializedProperty stepPauseProp; protected SerializedProperty stepPauseProp;
protected SerializedProperty saveSelectionProp; protected SerializedProperty saveSelectionProp;
protected SerializedProperty localizationIdProp; protected SerializedProperty localizationIdProp;
protected SerializedProperty variablesProp; protected SerializedProperty variablesProp;
protected SerializedProperty showLineNumbersProp; protected SerializedProperty showLineNumbersProp;
protected SerializedProperty hideCommandsProp; protected SerializedProperty hideCommandsProp;
protected SerializedProperty luaEnvironmentProp; protected SerializedProperty luaEnvironmentProp;
protected SerializedProperty luaBindingNameProp; protected SerializedProperty luaBindingNameProp;
protected Texture2D addTexture; protected Texture2D addTexture;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
descriptionProp = serializedObject.FindProperty("description"); descriptionProp = serializedObject.FindProperty("description");
colorCommandsProp = serializedObject.FindProperty("colorCommands"); colorCommandsProp = serializedObject.FindProperty("colorCommands");
hideComponentsProp = serializedObject.FindProperty("hideComponents"); hideComponentsProp = serializedObject.FindProperty("hideComponents");
stepPauseProp = serializedObject.FindProperty("stepPause"); stepPauseProp = serializedObject.FindProperty("stepPause");
saveSelectionProp = serializedObject.FindProperty("saveSelection"); saveSelectionProp = serializedObject.FindProperty("saveSelection");
localizationIdProp = serializedObject.FindProperty("localizationId"); localizationIdProp = serializedObject.FindProperty("localizationId");
variablesProp = serializedObject.FindProperty("variables"); variablesProp = serializedObject.FindProperty("variables");
showLineNumbersProp = serializedObject.FindProperty("showLineNumbers"); showLineNumbersProp = serializedObject.FindProperty("showLineNumbers");
hideCommandsProp = serializedObject.FindProperty("hideCommands"); hideCommandsProp = serializedObject.FindProperty("hideCommands");
luaEnvironmentProp = serializedObject.FindProperty("luaEnvironment"); luaEnvironmentProp = serializedObject.FindProperty("luaEnvironment");
luaBindingNameProp = serializedObject.FindProperty("luaBindingName"); luaBindingNameProp = serializedObject.FindProperty("luaBindingName");
addTexture = Resources.Load("Icons/add_small") as Texture2D; addTexture = Resources.Load("Icons/add_small") as Texture2D;
} }
public override void OnInspectorGUI() public override void OnInspectorGUI()
{ {
serializedObject.Update(); serializedObject.Update();
Flowchart flowchart = target as Flowchart; Flowchart flowchart = target as Flowchart;
flowchart.UpdateHideFlags(); flowchart.UpdateHideFlags();
EditorGUILayout.PropertyField(descriptionProp); EditorGUILayout.PropertyField(descriptionProp);
EditorGUILayout.PropertyField(colorCommandsProp); EditorGUILayout.PropertyField(colorCommandsProp);
EditorGUILayout.PropertyField(hideComponentsProp); EditorGUILayout.PropertyField(hideComponentsProp);
EditorGUILayout.PropertyField(stepPauseProp); EditorGUILayout.PropertyField(stepPauseProp);
EditorGUILayout.PropertyField(saveSelectionProp); EditorGUILayout.PropertyField(saveSelectionProp);
EditorGUILayout.PropertyField(localizationIdProp); EditorGUILayout.PropertyField(localizationIdProp);
EditorGUILayout.PropertyField(showLineNumbersProp); EditorGUILayout.PropertyField(showLineNumbersProp);
EditorGUILayout.PropertyField(luaEnvironmentProp); EditorGUILayout.PropertyField(luaEnvironmentProp);
EditorGUILayout.PropertyField(luaBindingNameProp); EditorGUILayout.PropertyField(luaBindingNameProp);
// Show list of commands to hide in Add Command menu // Show list of commands to hide in Add Command menu
ReorderableListGUI.Title(new GUIContent(hideCommandsProp.displayName, hideCommandsProp.tooltip)); ReorderableListGUI.Title(new GUIContent(hideCommandsProp.displayName, hideCommandsProp.tooltip));
ReorderableListGUI.ListField(hideCommandsProp); ReorderableListGUI.ListField(hideCommandsProp);
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent("Open Flowchart Window", "Opens the Flowchart Window"))) if (GUILayout.Button(new GUIContent("Open Flowchart Window", "Opens the Flowchart Window")))
{ {
EditorWindow.GetWindow(typeof(FlowchartWindow), false, "Flowchart"); EditorWindow.GetWindow(typeof(FlowchartWindow), false, "Flowchart");
} }
GUILayout.Space(10); GUILayout.Space(10);
if (GUILayout.Button(new GUIContent("Center View", "Centers the window view at the center of all blocks in the Flowchart"))) if (GUILayout.Button(new GUIContent("Center View", "Centers the window view at the center of all blocks in the Flowchart")))
{ {
// Reset the zoom so we don't have adjust the center position depending on zoom // Reset the zoom so we don't have adjust the center position depending on zoom
flowchart.scrollPos = flowchart.centerPosition; flowchart.scrollPos = flowchart.centerPosition;
flowchart.zoom = FlowchartWindow.maxZoomValue; flowchart.zoom = FlowchartWindow.maxZoomValue;
} }
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
public virtual void DrawVariablesGUI() public virtual void DrawVariablesGUI()
{ {
serializedObject.Update(); serializedObject.Update();
Flowchart t = target as Flowchart; Flowchart t = target as Flowchart;
if (t.variables.Count == 0) if (t.variables.Count == 0)
{ {
t.variablesExpanded = true; t.variablesExpanded = true;
} }
if (!t.variablesExpanded) if (!t.variablesExpanded)
{ {
if (GUILayout.Button ("Variables (" + t.variables.Count + ")", GUILayout.Height(24))) if (GUILayout.Button ("Variables (" + t.variables.Count + ")", GUILayout.Height(24)))
{ {
t.variablesExpanded = true; t.variablesExpanded = true;
} }
// Draw disclosure triangle // Draw disclosure triangle
Rect lastRect = GUILayoutUtility.GetLastRect(); Rect lastRect = GUILayoutUtility.GetLastRect();
lastRect.x += 5; lastRect.x += 5;
lastRect.y += 5; lastRect.y += 5;
EditorGUI.Foldout(lastRect, false, ""); EditorGUI.Foldout(lastRect, false, "");
} }
else else
{ {
Rect listRect = new Rect(); Rect listRect = new Rect();
if (t.variables.Count > 0) if (t.variables.Count > 0)
{ {
// Remove any null variables from the list // Remove any null variables from the list
// Can sometimes happen when upgrading to a new version of Fungus (if .meta GUID changes for a variable class) // Can sometimes happen when upgrading to a new version of Fungus (if .meta GUID changes for a variable class)
for (int i = t.variables.Count - 1; i >= 0; i--) for (int i = t.variables.Count - 1; i >= 0; i--)
{ {
if (t.variables[i] == null) if (t.variables[i] == null)
{ {
t.variables.RemoveAt(i); t.variables.RemoveAt(i);
} }
} }
ReorderableListGUI.Title("Variables"); ReorderableListGUI.Title("Variables");
VariableListAdaptor adaptor = new VariableListAdaptor(variablesProp, 0); VariableListAdaptor adaptor = new VariableListAdaptor(variablesProp, 0);
ReorderableListFlags flags = ReorderableListFlags.DisableContextMenu | ReorderableListFlags.HideAddButton; ReorderableListFlags flags = ReorderableListFlags.DisableContextMenu | ReorderableListFlags.HideAddButton;
ReorderableListControl.DrawControlFromState(adaptor, null, flags); ReorderableListControl.DrawControlFromState(adaptor, null, flags);
listRect = GUILayoutUtility.GetLastRect(); listRect = GUILayoutUtility.GetLastRect();
} }
else else
{ {
GUILayoutUtility.GetRect(300, 24); GUILayoutUtility.GetRect(300, 24);
listRect = GUILayoutUtility.GetLastRect(); listRect = GUILayoutUtility.GetLastRect();
listRect.y += 20; listRect.y += 20;
} }
float plusWidth = 32; float plusWidth = 32;
float plusHeight = 24; float plusHeight = 24;
Rect buttonRect = listRect; Rect buttonRect = listRect;
float buttonHeight = 24; float buttonHeight = 24;
buttonRect.x = 4; buttonRect.x = 4;
buttonRect.y -= buttonHeight - 1; buttonRect.y -= buttonHeight - 1;
buttonRect.height = buttonHeight; buttonRect.height = buttonHeight;
if (!Application.isPlaying) if (!Application.isPlaying)
{ {
buttonRect.width -= 30; buttonRect.width -= 30;
} }
if (GUI.Button (buttonRect, "Variables")) if (GUI.Button (buttonRect, "Variables"))
{ {
t.variablesExpanded = false; t.variablesExpanded = false;
} }
// Draw disclosure triangle // Draw disclosure triangle
Rect lastRect = buttonRect; Rect lastRect = buttonRect;
lastRect.x += 5; lastRect.x += 5;
lastRect.y += 5; lastRect.y += 5;
EditorGUI.Foldout(lastRect, true, ""); EditorGUI.Foldout(lastRect, true, "");
Rect plusRect = listRect; Rect plusRect = listRect;
plusRect.x += plusRect.width - plusWidth; plusRect.x += plusRect.width - plusWidth;
plusRect.y -= plusHeight - 1; plusRect.y -= plusHeight - 1;
plusRect.width = plusWidth; plusRect.width = plusWidth;
plusRect.height = plusHeight; plusRect.height = plusHeight;
if (!Application.isPlaying && if (!Application.isPlaying &&
GUI.Button(plusRect, addTexture)) GUI.Button(plusRect, addTexture))
{ {
GenericMenu menu = new GenericMenu (); GenericMenu menu = new GenericMenu ();
List<System.Type> types = FindAllDerivedTypes<Variable>(); List<System.Type> types = FindAllDerivedTypes<Variable>();
// Add variable types without a category // Add variable types without a category
foreach (System.Type type in types) foreach (System.Type type in types)
{ {
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type); VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type);
if (variableInfo == null || if (variableInfo == null ||
variableInfo.Category != "") variableInfo.Category != "")
{ {
continue; continue;
} }
AddVariableInfo addVariableInfo = new AddVariableInfo(); AddVariableInfo addVariableInfo = new AddVariableInfo();
addVariableInfo.flowchart = t; addVariableInfo.flowchart = t;
addVariableInfo.variableType = type; addVariableInfo.variableType = type;
GUIContent typeName = new GUIContent(variableInfo.VariableType); GUIContent typeName = new GUIContent(variableInfo.VariableType);
menu.AddItem(typeName, false, AddVariable, addVariableInfo); menu.AddItem(typeName, false, AddVariable, addVariableInfo);
} }
// Add types with a category // Add types with a category
foreach (System.Type type in types) foreach (System.Type type in types)
{ {
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type); VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(type);
if (variableInfo == null || if (variableInfo == null ||
variableInfo.Category == "") variableInfo.Category == "")
{ {
continue; continue;
} }
AddVariableInfo info = new AddVariableInfo(); AddVariableInfo info = new AddVariableInfo();
info.flowchart = t; info.flowchart = t;
info.variableType = type; info.variableType = type;
GUIContent typeName = new GUIContent(variableInfo.Category + "/" + variableInfo.VariableType); GUIContent typeName = new GUIContent(variableInfo.Category + "/" + variableInfo.VariableType);
menu.AddItem(typeName, false, AddVariable, info); menu.AddItem(typeName, false, AddVariable, info);
} }
menu.ShowAsContext (); menu.ShowAsContext ();
} }
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
protected virtual void AddVariable(object obj) protected virtual void AddVariable(object obj)
{ {
AddVariableInfo addVariableInfo = obj as AddVariableInfo; AddVariableInfo addVariableInfo = obj as AddVariableInfo;
if (addVariableInfo == null) if (addVariableInfo == null)
{ {
return; return;
} }
Flowchart flowchart = addVariableInfo.flowchart; Flowchart flowchart = addVariableInfo.flowchart;
System.Type variableType = addVariableInfo.variableType; System.Type variableType = addVariableInfo.variableType;
Undo.RecordObject(flowchart, "Add Variable"); Undo.RecordObject(flowchart, "Add Variable");
Variable newVariable = flowchart.gameObject.AddComponent(variableType) as Variable; Variable newVariable = flowchart.gameObject.AddComponent(variableType) as Variable;
newVariable.key = flowchart.GetUniqueVariableKey(""); newVariable.key = flowchart.GetUniqueVariableKey("");
flowchart.variables.Add(newVariable); flowchart.variables.Add(newVariable);
// Because this is an async call, we need to force prefab instances to record changes // Because this is an async call, we need to force prefab instances to record changes
PrefabUtility.RecordPrefabInstancePropertyModifications(flowchart); PrefabUtility.RecordPrefabInstancePropertyModifications(flowchart);
} }
public static List<System.Type> FindAllDerivedTypes<T>() public static List<System.Type> FindAllDerivedTypes<T>()
{ {
return FindAllDerivedTypes<T>(Assembly.GetAssembly(typeof(T))); return FindAllDerivedTypes<T>(Assembly.GetAssembly(typeof(T)));
} }
public static List<System.Type> FindAllDerivedTypes<T>(Assembly assembly) public static List<System.Type> FindAllDerivedTypes<T>(Assembly assembly)
{ {
var derivedType = typeof(T); var derivedType = typeof(T);
return assembly return assembly
.GetTypes() .GetTypes()
.Where(t => .Where(t =>
t != derivedType && t != derivedType &&
derivedType.IsAssignableFrom(t) derivedType.IsAssignableFrom(t)
).ToList(); ).ToList();
} }
/** /**
* When modifying custom editor code you can occasionally end up with orphaned editor instances. * When modifying custom editor code you can occasionally end up with orphaned editor instances.
* When this happens, you'll get a null exception error every time the scene serializes / deserialized. * When this happens, you'll get a null exception error every time the scene serializes / deserialized.
* Once this situation occurs, the only way to fix it is to restart the Unity editor. * Once this situation occurs, the only way to fix it is to restart the Unity editor.
* As a workaround, this function detects if this editor is an orphan and deletes it. * As a workaround, this function detects if this editor is an orphan and deletes it.
*/ */
protected virtual bool NullTargetCheck() protected virtual bool NullTargetCheck()
{ {
try try
{ {
// The serializedObject accessor creates a new SerializedObject if needed. // The serializedObject accessor creates a new SerializedObject if needed.
// However, this will fail with a null exception if the target object no longer exists. // However, this will fail with a null exception if the target object no longer exists.
#pragma warning disable 0219 #pragma warning disable 0219
SerializedObject so = serializedObject; SerializedObject so = serializedObject;
} }
catch (System.NullReferenceException) catch (System.NullReferenceException)
{ {
DestroyImmediate(this); DestroyImmediate(this);
return true; return true;
} }
return false; return false;
} }
} }
} }

142
Assets/Fungus/Flowchart/Editor/FlowchartMenuItems.cs

@ -11,76 +11,76 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
public class FlowchartMenuItems public class FlowchartMenuItems
{ {
[MenuItem("Tools/Fungus/Create/Flowchart", false, 0)] [MenuItem("Tools/Fungus/Create/Flowchart", false, 0)]
static void CreateFlowchart() static void CreateFlowchart()
{ {
GameObject go = SpawnPrefab("Flowchart"); GameObject go = SpawnPrefab("Flowchart");
go.transform.position = Vector3.zero; go.transform.position = Vector3.zero;
// This is the latest version of Flowchart, so no need to update. // This is the latest version of Flowchart, so no need to update.
Flowchart flowchart = go.GetComponent<Flowchart>(); Flowchart flowchart = go.GetComponent<Flowchart>();
if (flowchart != null) if (flowchart != null)
{ {
flowchart.version = Flowchart.CURRENT_VERSION; flowchart.version = Flowchart.CURRENT_VERSION;
} }
// Only the first created Flowchart in the scene should have a default GameStarted block // Only the first created Flowchart in the scene should have a default GameStarted block
if (GameObject.FindObjectsOfType<Flowchart>().Length > 1) if (GameObject.FindObjectsOfType<Flowchart>().Length > 1)
{ {
Block block = go.GetComponent<Block>(); Block block = go.GetComponent<Block>();
block.eventHandler = null; block.eventHandler = null;
GameObject.DestroyImmediate(block.eventHandler); GameObject.DestroyImmediate(block.eventHandler);
} }
} }
[MenuItem("Tools/Fungus/Create/Fungus Logo", false, 1000)] [MenuItem("Tools/Fungus/Create/Fungus Logo", false, 1000)]
static void CreateFungusLogo() static void CreateFungusLogo()
{ {
SpawnPrefab("FungusLogo"); SpawnPrefab("FungusLogo");
} }
[MenuItem("Tools/Fungus/Utilities/Export Fungus Package")] [MenuItem("Tools/Fungus/Utilities/Export Fungus Package")]
static void ExportFungusPackage() static void ExportFungusPackage()
{ {
string path = EditorUtility.SaveFilePanel("Export Fungus Package", "", "Fungus", "unitypackage"); string path = EditorUtility.SaveFilePanel("Export Fungus Package", "", "Fungus", "unitypackage");
if(path.Length == 0) if(path.Length == 0)
{ {
return; return;
} }
string[] folders = new string[] {"Assets/Fungus", "Assets/FungusExamples" }; string[] folders = new string[] {"Assets/Fungus", "Assets/FungusExamples" };
AssetDatabase.ExportPackage(folders, path, ExportPackageOptions.Recurse); AssetDatabase.ExportPackage(folders, path, ExportPackageOptions.Recurse);
} }
public static GameObject SpawnPrefab(string prefabName) public static GameObject SpawnPrefab(string prefabName)
{ {
GameObject prefab = Resources.Load<GameObject>(prefabName); GameObject prefab = Resources.Load<GameObject>(prefabName);
if (prefab == null) if (prefab == null)
{ {
return null; return null;
} }
GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject; GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
PrefabUtility.DisconnectPrefabInstance(go); PrefabUtility.DisconnectPrefabInstance(go);
SceneView view = SceneView.lastActiveSceneView; SceneView view = SceneView.lastActiveSceneView;
if (view != null) if (view != null)
{ {
Camera sceneCam = view.camera; Camera sceneCam = view.camera;
Vector3 pos = sceneCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 10f)); Vector3 pos = sceneCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 10f));
pos.z = 0f; pos.z = 0f;
go.transform.position = pos; go.transform.position = pos;
} }
Selection.activeGameObject = go; Selection.activeGameObject = go;
Undo.RegisterCreatedObjectUndo(go, "Create Object"); Undo.RegisterCreatedObjectUndo(go, "Create Object");
return go; return go;
} }
} }
} }

1640
Assets/Fungus/Flowchart/Editor/FlowchartWindow.cs

File diff suppressed because it is too large Load Diff

354
Assets/Fungus/Flowchart/Editor/FungusEditorResources.cs

File diff suppressed because one or more lines are too long

568
Assets/Fungus/Flowchart/Editor/GLDraw.cs

@ -10,289 +10,289 @@ using System;
namespace Fungus namespace Fungus
{ {
public class GLDraw public class GLDraw
{ {
/* /*
* Clipping code: http://forum.unity3d.com/threads/17066-How-to-draw-a-GUI-2D-quot-line-quot?p=230386#post230386 * Clipping code: http://forum.unity3d.com/threads/17066-How-to-draw-a-GUI-2D-quot-line-quot?p=230386#post230386
* Thick line drawing code: http://unifycommunity.com/wiki/index.php?title=VectorLine * Thick line drawing code: http://unifycommunity.com/wiki/index.php?title=VectorLine
*/ */
protected static bool clippingEnabled; protected static bool clippingEnabled;
protected static Rect clippingBounds; protected static Rect clippingBounds;
public static Material lineMaterial = null; public static Material lineMaterial = null;
/* @ Credit: "http://cs-people.bu.edu/jalon/cs480/Oct11Lab/clip.c" */ /* @ Credit: "http://cs-people.bu.edu/jalon/cs480/Oct11Lab/clip.c" */
protected static bool clip_test(float p, float q, ref float u1, ref float u2) protected static bool clip_test(float p, float q, ref float u1, ref float u2)
{ {
float r; float r;
bool retval = true; bool retval = true;
if (p < 0.0) if (p < 0.0)
{ {
r = q / p; r = q / p;
if (r > u2) if (r > u2)
retval = false; retval = false;
else if (r > u1) else if (r > u1)
u1 = r; u1 = r;
} }
else if (p > 0.0) else if (p > 0.0)
{ {
r = q / p; r = q / p;
if (r < u1) if (r < u1)
retval = false; retval = false;
else if (r < u2) else if (r < u2)
u2 = r; u2 = r;
} }
else if (q < 0.0) else if (q < 0.0)
retval = false; retval = false;
return retval; return retval;
} }
public static bool segment_rect_intersection(Rect bounds, ref Vector2 p1, ref Vector2 p2) public static bool segment_rect_intersection(Rect bounds, ref Vector2 p1, ref Vector2 p2)
{ {
float u1 = 0.0f, u2 = 1.0f, dx = p2.x - p1.x, dy; float u1 = 0.0f, u2 = 1.0f, dx = p2.x - p1.x, dy;
if (clip_test(-dx, p1.x - bounds.xMin, ref u1, ref u2)) if (clip_test(-dx, p1.x - bounds.xMin, ref u1, ref u2))
{ {
if (clip_test(dx, bounds.xMax - p1.x, ref u1, ref u2)) if (clip_test(dx, bounds.xMax - p1.x, ref u1, ref u2))
{ {
dy = p2.y - p1.y; dy = p2.y - p1.y;
if (clip_test(-dy, p1.y - bounds.yMin, ref u1, ref u2)) if (clip_test(-dy, p1.y - bounds.yMin, ref u1, ref u2))
{ {
if (clip_test(dy, bounds.yMax - p1.y, ref u1, ref u2)) if (clip_test(dy, bounds.yMax - p1.y, ref u1, ref u2))
{ {
if (u2 < 1.0) if (u2 < 1.0)
{ {
p2.x = p1.x + u2 * dx; p2.x = p1.x + u2 * dx;
p2.y = p1.y + u2 * dy; p2.y = p1.y + u2 * dy;
} }
if (u1 > 0.0) if (u1 > 0.0)
{ {
p1.x += u1 * dx; p1.x += u1 * dx;
p1.y += u1 * dy; p1.y += u1 * dy;
} }
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
public static void BeginGroup(Rect position) public static void BeginGroup(Rect position)
{ {
clippingEnabled = true; clippingEnabled = true;
clippingBounds = new Rect(0, 0, position.width, position.height); clippingBounds = new Rect(0, 0, position.width, position.height);
GUI.BeginGroup(position); GUI.BeginGroup(position);
} }
public static void EndGroup() public static void EndGroup()
{ {
GUI.EndGroup(); GUI.EndGroup();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height); clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false; clippingEnabled = false;
} }
public static Vector2 BeginScrollView(Rect position, Vector2 scrollPos, Rect viewRect, Rect clipRect) public static Vector2 BeginScrollView(Rect position, Vector2 scrollPos, Rect viewRect, Rect clipRect)
{ {
clippingEnabled = true; clippingEnabled = true;
clippingBounds = clipRect; clippingBounds = clipRect;
return GUI.BeginScrollView(position, scrollPos, viewRect, GUIStyle.none, GUIStyle.none); return GUI.BeginScrollView(position, scrollPos, viewRect, GUIStyle.none, GUIStyle.none);
} }
public static void EndScrollView() public static void EndScrollView()
{ {
GUI.EndScrollView(); GUI.EndScrollView();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height); clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false; clippingEnabled = false;
} }
public static void CreateMaterial() public static void CreateMaterial()
{ {
if (lineMaterial != null) if (lineMaterial != null)
return; return;
lineMaterial = Resources.Load("GLLineDraw", typeof(Material)) as Material; lineMaterial = Resources.Load("GLLineDraw", typeof(Material)) as Material;
} }
public static void DrawLine(Vector2 start, Vector2 end, Color color, float width) public static void DrawLine(Vector2 start, Vector2 end, Color color, float width)
{ {
if (Event.current == null) if (Event.current == null)
return; return;
if (Event.current.type != EventType.repaint) if (Event.current.type != EventType.repaint)
return; return;
if (clippingEnabled) if (clippingEnabled)
if (!segment_rect_intersection(clippingBounds, ref start, ref end)) if (!segment_rect_intersection(clippingBounds, ref start, ref end))
return; return;
CreateMaterial(); CreateMaterial();
lineMaterial.SetPass(0); lineMaterial.SetPass(0);
Vector3 startPt; Vector3 startPt;
Vector3 endPt; Vector3 endPt;
if (width == 1) if (width == 1)
{ {
GL.Begin(GL.LINES); GL.Begin(GL.LINES);
GL.Color(color); GL.Color(color);
startPt = new Vector3(start.x, start.y, 0); startPt = new Vector3(start.x, start.y, 0);
endPt = new Vector3(end.x, end.y, 0); endPt = new Vector3(end.x, end.y, 0);
GL.Vertex(startPt); GL.Vertex(startPt);
GL.Vertex(endPt); GL.Vertex(endPt);
} }
else else
{ {
GL.Begin(GL.QUADS); GL.Begin(GL.QUADS);
GL.Color(color); GL.Color(color);
startPt = new Vector3(end.y, start.x, 0); startPt = new Vector3(end.y, start.x, 0);
endPt = new Vector3(start.y, end.x, 0); endPt = new Vector3(start.y, end.x, 0);
Vector3 perpendicular = (startPt - endPt).normalized * width; Vector3 perpendicular = (startPt - endPt).normalized * width;
Vector3 v1 = new Vector3(start.x, start.y, 0); Vector3 v1 = new Vector3(start.x, start.y, 0);
Vector3 v2 = new Vector3(end.x, end.y, 0); Vector3 v2 = new Vector3(end.x, end.y, 0);
GL.Vertex(v1 - perpendicular); GL.Vertex(v1 - perpendicular);
GL.Vertex(v1 + perpendicular); GL.Vertex(v1 + perpendicular);
GL.Vertex(v2 + perpendicular); GL.Vertex(v2 + perpendicular);
GL.Vertex(v2 - perpendicular); GL.Vertex(v2 - perpendicular);
} }
GL.End(); GL.End();
} }
public static void DrawRect(Rect rect, Color color) public static void DrawRect(Rect rect, Color color)
{ {
if (Event.current == null) if (Event.current == null)
return; return;
if (Event.current.type != EventType.repaint) if (Event.current.type != EventType.repaint)
return; return;
CreateMaterial(); CreateMaterial();
// set the current material // set the current material
lineMaterial.SetPass( 0 ); lineMaterial.SetPass( 0 );
GL.Begin( GL.QUADS ); GL.Begin( GL.QUADS );
GL.Color( color ); GL.Color( color );
GL.Vertex3( rect.xMin, rect.yMin, 0 ); GL.Vertex3( rect.xMin, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMin, 0 ); GL.Vertex3( rect.xMax, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMax, 0 ); GL.Vertex3( rect.xMax, rect.yMax, 0 );
GL.Vertex3( rect.xMin, rect.yMax, 0 ); GL.Vertex3( rect.xMin, rect.yMax, 0 );
GL.End(); GL.End();
} }
public static void DrawBox(Rect box, Color color, float width) public static void DrawBox(Rect box, Color color, float width)
{ {
Vector2 p1 = new Vector2(box.xMin, box.yMin); Vector2 p1 = new Vector2(box.xMin, box.yMin);
Vector2 p2 = new Vector2(box.xMax, box.yMin); Vector2 p2 = new Vector2(box.xMax, box.yMin);
Vector2 p3 = new Vector2(box.xMax, box.yMax); Vector2 p3 = new Vector2(box.xMax, box.yMax);
Vector2 p4 = new Vector2(box.xMin, box.yMax); Vector2 p4 = new Vector2(box.xMin, box.yMax);
DrawLine(p1, p2, color, width); DrawLine(p1, p2, color, width);
DrawLine(p2, p3, color, width); DrawLine(p2, p3, color, width);
DrawLine(p3, p4, color, width); DrawLine(p3, p4, color, width);
DrawLine(p4, p1, color, width); DrawLine(p4, p1, color, width);
} }
public static void DrawBox(Vector2 topLeftCorner, Vector2 bottomRightCorner, Color color, float width) public static void DrawBox(Vector2 topLeftCorner, Vector2 bottomRightCorner, Color color, float width)
{ {
Rect box = new Rect(topLeftCorner.x, topLeftCorner.y, bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - topLeftCorner.y); Rect box = new Rect(topLeftCorner.x, topLeftCorner.y, bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - topLeftCorner.y);
DrawBox(box, color, width); DrawBox(box, color, width);
} }
public static void DrawRoundedBox(Rect box, float radius, Color color, float width) public static void DrawRoundedBox(Rect box, float radius, Color color, float width)
{ {
Vector2 p1, p2, p3, p4, p5, p6, p7, p8; Vector2 p1, p2, p3, p4, p5, p6, p7, p8;
p1 = new Vector2(box.xMin + radius, box.yMin); p1 = new Vector2(box.xMin + radius, box.yMin);
p2 = new Vector2(box.xMax - radius, box.yMin); p2 = new Vector2(box.xMax - radius, box.yMin);
p3 = new Vector2(box.xMax, box.yMin + radius); p3 = new Vector2(box.xMax, box.yMin + radius);
p4 = new Vector2(box.xMax, box.yMax - radius); p4 = new Vector2(box.xMax, box.yMax - radius);
p5 = new Vector2(box.xMax - radius, box.yMax); p5 = new Vector2(box.xMax - radius, box.yMax);
p6 = new Vector2(box.xMin + radius, box.yMax); p6 = new Vector2(box.xMin + radius, box.yMax);
p7 = new Vector2(box.xMin, box.yMax - radius); p7 = new Vector2(box.xMin, box.yMax - radius);
p8 = new Vector2(box.xMin, box.yMin + radius); p8 = new Vector2(box.xMin, box.yMin + radius);
DrawLine(p1, p2, color, width); DrawLine(p1, p2, color, width);
DrawLine(p3, p4, color, width); DrawLine(p3, p4, color, width);
DrawLine(p5, p6, color, width); DrawLine(p5, p6, color, width);
DrawLine(p7, p8, color, width); DrawLine(p7, p8, color, width);
Vector2 t1, t2; Vector2 t1, t2;
float halfRadius = radius / 2; float halfRadius = radius / 2;
t1 = new Vector2(p8.x, p8.y + halfRadius); t1 = new Vector2(p8.x, p8.y + halfRadius);
t2 = new Vector2(p1.x - halfRadius, p1.y); t2 = new Vector2(p1.x - halfRadius, p1.y);
DrawBezier(p8, t1, p1, t2, color, width); DrawBezier(p8, t1, p1, t2, color, width);
t1 = new Vector2(p2.x + halfRadius, p2.y); t1 = new Vector2(p2.x + halfRadius, p2.y);
t2 = new Vector2(p3.x, p3.y - halfRadius); t2 = new Vector2(p3.x, p3.y - halfRadius);
DrawBezier(p2, t1, p3, t2, color, width); DrawBezier(p2, t1, p3, t2, color, width);
t1 = new Vector2(p4.x, p4.y + halfRadius); t1 = new Vector2(p4.x, p4.y + halfRadius);
t2 = new Vector2(p5.x + halfRadius, p5.y); t2 = new Vector2(p5.x + halfRadius, p5.y);
DrawBezier(p4, t1, p5, t2, color, width); DrawBezier(p4, t1, p5, t2, color, width);
t1 = new Vector2(p6.x - halfRadius, p6.y); t1 = new Vector2(p6.x - halfRadius, p6.y);
t2 = new Vector2(p7.x, p7.y + halfRadius); t2 = new Vector2(p7.x, p7.y + halfRadius);
DrawBezier(p6, t1, p7, t2, color, width); DrawBezier(p6, t1, p7, t2, color, width);
} }
public static void DrawConnectingCurve(Vector2 start, Vector2 end, Color color, float width) public static void DrawConnectingCurve(Vector2 start, Vector2 end, Color color, float width)
{ {
Vector2 distance = start - end; Vector2 distance = start - end;
Vector2 tangentA = start; Vector2 tangentA = start;
tangentA.x -= distance.x * 0.5f; tangentA.x -= distance.x * 0.5f;
Vector2 tangentB = end; Vector2 tangentB = end;
tangentB.x += distance.x * 0.5f; tangentB.x += distance.x * 0.5f;
int segments = Mathf.FloorToInt((distance.magnitude / 20) * 3); int segments = Mathf.FloorToInt((distance.magnitude / 20) * 3);
DrawBezier(start, tangentA, end, tangentB, color, width, segments); DrawBezier(start, tangentA, end, tangentB, color, width, segments);
Vector2 pA = CubeBezier(start, tangentA, end, tangentB, 0.6f); Vector2 pA = CubeBezier(start, tangentA, end, tangentB, 0.6f);
Vector2 pB = CubeBezier(start, tangentA, end, tangentB, 0.7f); Vector2 pB = CubeBezier(start, tangentA, end, tangentB, 0.7f);
float arrowHeadSize = 5; float arrowHeadSize = 5;
Vector2 arrowPosA = pB; Vector2 arrowPosA = pB;
Vector2 arrowPosB = arrowPosA; Vector2 arrowPosB = arrowPosA;
Vector2 arrowPosC = arrowPosA; Vector2 arrowPosC = arrowPosA;
Vector2 dir = (pB - pA).normalized; Vector2 dir = (pB - pA).normalized;
arrowPosB.x += dir.y * arrowHeadSize; arrowPosB.x += dir.y * arrowHeadSize;
arrowPosB.y -= dir.x * arrowHeadSize; arrowPosB.y -= dir.x * arrowHeadSize;
arrowPosB -= dir * arrowHeadSize; arrowPosB -= dir * arrowHeadSize;
arrowPosC.x -= dir.y * arrowHeadSize; arrowPosC.x -= dir.y * arrowHeadSize;
arrowPosC.y += dir.x * arrowHeadSize; arrowPosC.y += dir.x * arrowHeadSize;
arrowPosC -= dir * arrowHeadSize; arrowPosC -= dir * arrowHeadSize;
DrawLine(arrowPosA, arrowPosB, color, 1.025f); DrawLine(arrowPosA, arrowPosB, color, 1.025f);
DrawLine(arrowPosA, arrowPosC, color, 1.025f); DrawLine(arrowPosA, arrowPosC, color, 1.025f);
} }
public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width) public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width)
{ {
int segments = Mathf.FloorToInt((start - end).magnitude / 20) * 3; // Three segments per distance of 20 int segments = Mathf.FloorToInt((start - end).magnitude / 20) * 3; // Three segments per distance of 20
DrawBezier(start, startTangent, end, endTangent, color, width, segments); DrawBezier(start, startTangent, end, endTangent, color, width, segments);
} }
public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, int segments) public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, int segments)
{ {
Vector2 startVector = CubeBezier(start, startTangent, end, endTangent, 0); Vector2 startVector = CubeBezier(start, startTangent, end, endTangent, 0);
for (int i = 1; i <= segments; i++) for (int i = 1; i <= segments; i++)
{ {
Vector2 endVector = CubeBezier(start, startTangent, end, endTangent, i / (float)segments); Vector2 endVector = CubeBezier(start, startTangent, end, endTangent, i / (float)segments);
DrawLine(startVector, endVector, color, width); DrawLine(startVector, endVector, color, width);
startVector = endVector; startVector = endVector;
} }
} }
private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t) private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t)
{ {
float rt = 1 - t; float rt = 1 - t;
float rtt = rt * t; float rtt = rt * t;
return rt * rt * rt * s + 3 * rt * rtt * st + 3 * rtt * t * et + t * t * t * e; return rt * rt * rt * s + 3 * rt * rtt * st + 3 * rtt * t * et + t * t * t * e;
} }
} }
} }

164
Assets/Fungus/Flowchart/Editor/IfEditor.cs

@ -12,87 +12,87 @@ using System.Reflection;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(If), true)] [CustomEditor (typeof(If), true)]
public class IfEditor : CommandEditor public class IfEditor : CommandEditor
{ {
protected SerializedProperty variableProp; protected SerializedProperty variableProp;
protected SerializedProperty compareOperatorProp; protected SerializedProperty compareOperatorProp;
protected SerializedProperty booleanDataProp; protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp; protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp; protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp; protected SerializedProperty stringDataProp;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
variableProp = serializedObject.FindProperty("variable"); variableProp = serializedObject.FindProperty("variable");
compareOperatorProp = serializedObject.FindProperty("compareOperator"); compareOperatorProp = serializedObject.FindProperty("compareOperator");
booleanDataProp = serializedObject.FindProperty("booleanData"); booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData"); integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData"); floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData"); stringDataProp = serializedObject.FindProperty("stringData");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
serializedObject.Update(); serializedObject.Update();
If t = target as If; If t = target as If;
Flowchart flowchart = t.GetFlowchart(); Flowchart flowchart = t.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
EditorGUILayout.PropertyField(variableProp); EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null) if (variableProp.objectReferenceValue == null)
{ {
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
return; return;
} }
Variable selectedVariable = variableProp.objectReferenceValue as Variable; Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType(); System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorList = new List<GUIContent>(); List<GUIContent> operatorList = new List<GUIContent>();
operatorList.Add(new GUIContent("==")); operatorList.Add(new GUIContent("=="));
operatorList.Add(new GUIContent("!=")); operatorList.Add(new GUIContent("!="));
if (variableType == typeof(IntegerVariable) || if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable)) variableType == typeof(FloatVariable))
{ {
operatorList.Add(new GUIContent("<")); operatorList.Add(new GUIContent("<"));
operatorList.Add(new GUIContent(">")); operatorList.Add(new GUIContent(">"));
operatorList.Add(new GUIContent("<=")); operatorList.Add(new GUIContent("<="));
operatorList.Add(new GUIContent(">=")); operatorList.Add(new GUIContent(">="));
} }
compareOperatorProp.enumValueIndex = EditorGUILayout.Popup(new GUIContent("Compare", "The comparison operator to use when comparing values"), compareOperatorProp.enumValueIndex = EditorGUILayout.Popup(new GUIContent("Compare", "The comparison operator to use when comparing values"),
compareOperatorProp.enumValueIndex, compareOperatorProp.enumValueIndex,
operatorList.ToArray()); operatorList.ToArray());
if (variableType == typeof(BooleanVariable)) if (variableType == typeof(BooleanVariable))
{ {
EditorGUILayout.PropertyField(booleanDataProp); EditorGUILayout.PropertyField(booleanDataProp);
} }
else if (variableType == typeof(IntegerVariable)) else if (variableType == typeof(IntegerVariable))
{ {
EditorGUILayout.PropertyField(integerDataProp); EditorGUILayout.PropertyField(integerDataProp);
} }
else if (variableType == typeof(FloatVariable)) else if (variableType == typeof(FloatVariable))
{ {
EditorGUILayout.PropertyField(floatDataProp); EditorGUILayout.PropertyField(floatDataProp);
} }
else if (variableType == typeof(StringVariable)) else if (variableType == typeof(StringVariable))
{ {
EditorGUILayout.PropertyField(stringDataProp); EditorGUILayout.PropertyField(stringDataProp);
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

120
Assets/Fungus/Flowchart/Editor/InvokeEventEditor.cs

@ -10,70 +10,70 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(InvokeEvent))] [CustomEditor (typeof(InvokeEvent))]
public class InvokeEventEditor : CommandEditor public class InvokeEventEditor : CommandEditor
{ {
protected SerializedProperty delayProp; protected SerializedProperty delayProp;
protected SerializedProperty invokeTypeProp; protected SerializedProperty invokeTypeProp;
protected SerializedProperty staticEventProp; protected SerializedProperty staticEventProp;
protected SerializedProperty booleanParameterProp; protected SerializedProperty booleanParameterProp;
protected SerializedProperty booleanEventProp; protected SerializedProperty booleanEventProp;
protected SerializedProperty integerParameterProp; protected SerializedProperty integerParameterProp;
protected SerializedProperty integerEventProp; protected SerializedProperty integerEventProp;
protected SerializedProperty floatParameterProp; protected SerializedProperty floatParameterProp;
protected SerializedProperty floatEventProp; protected SerializedProperty floatEventProp;
protected SerializedProperty stringParameterProp; protected SerializedProperty stringParameterProp;
protected SerializedProperty stringEventProp; protected SerializedProperty stringEventProp;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
delayProp = serializedObject.FindProperty("delay"); delayProp = serializedObject.FindProperty("delay");
invokeTypeProp = serializedObject.FindProperty("invokeType"); invokeTypeProp = serializedObject.FindProperty("invokeType");
staticEventProp = serializedObject.FindProperty("staticEvent"); staticEventProp = serializedObject.FindProperty("staticEvent");
booleanParameterProp = serializedObject.FindProperty("booleanParameter"); booleanParameterProp = serializedObject.FindProperty("booleanParameter");
booleanEventProp = serializedObject.FindProperty("booleanEvent"); booleanEventProp = serializedObject.FindProperty("booleanEvent");
integerParameterProp = serializedObject.FindProperty("integerParameter"); integerParameterProp = serializedObject.FindProperty("integerParameter");
integerEventProp = serializedObject.FindProperty("integerEvent"); integerEventProp = serializedObject.FindProperty("integerEvent");
floatParameterProp = serializedObject.FindProperty("floatParameter"); floatParameterProp = serializedObject.FindProperty("floatParameter");
floatEventProp = serializedObject.FindProperty("floatEvent"); floatEventProp = serializedObject.FindProperty("floatEvent");
stringParameterProp = serializedObject.FindProperty("stringParameter"); stringParameterProp = serializedObject.FindProperty("stringParameter");
stringEventProp = serializedObject.FindProperty("stringEvent"); stringEventProp = serializedObject.FindProperty("stringEvent");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
serializedObject.Update(); serializedObject.Update();
EditorGUILayout.PropertyField(delayProp); EditorGUILayout.PropertyField(delayProp);
EditorGUILayout.PropertyField(invokeTypeProp); EditorGUILayout.PropertyField(invokeTypeProp);
switch ((InvokeEvent.InvokeType)invokeTypeProp.enumValueIndex) switch ((InvokeEvent.InvokeType)invokeTypeProp.enumValueIndex)
{ {
case InvokeEvent.InvokeType.Static: case InvokeEvent.InvokeType.Static:
EditorGUILayout.PropertyField(staticEventProp); EditorGUILayout.PropertyField(staticEventProp);
break; break;
case InvokeEvent.InvokeType.DynamicBoolean: case InvokeEvent.InvokeType.DynamicBoolean:
EditorGUILayout.PropertyField(booleanEventProp); EditorGUILayout.PropertyField(booleanEventProp);
EditorGUILayout.PropertyField(booleanParameterProp); EditorGUILayout.PropertyField(booleanParameterProp);
break; break;
case InvokeEvent.InvokeType.DynamicInteger: case InvokeEvent.InvokeType.DynamicInteger:
EditorGUILayout.PropertyField(integerEventProp); EditorGUILayout.PropertyField(integerEventProp);
EditorGUILayout.PropertyField(integerParameterProp); EditorGUILayout.PropertyField(integerParameterProp);
break; break;
case InvokeEvent.InvokeType.DynamicFloat: case InvokeEvent.InvokeType.DynamicFloat:
EditorGUILayout.PropertyField(floatEventProp); EditorGUILayout.PropertyField(floatEventProp);
EditorGUILayout.PropertyField(floatParameterProp); EditorGUILayout.PropertyField(floatParameterProp);
break; break;
case InvokeEvent.InvokeType.DynamicString: case InvokeEvent.InvokeType.DynamicString:
EditorGUILayout.PropertyField(stringEventProp); EditorGUILayout.PropertyField(stringEventProp);
EditorGUILayout.PropertyField(stringParameterProp); EditorGUILayout.PropertyField(stringParameterProp);
break; break;
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

856
Assets/Fungus/Flowchart/Editor/InvokeMethodEditor.cs

@ -15,433 +15,433 @@ using System.Text;
namespace Fungus namespace Fungus
{ {
[CustomEditor(typeof(InvokeMethod))] [CustomEditor(typeof(InvokeMethod))]
public class InvokeMethodEditor : CommandEditor public class InvokeMethodEditor : CommandEditor
{ {
InvokeMethod targetMethod; InvokeMethod targetMethod;
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
base.DrawCommandGUI(); base.DrawCommandGUI();
targetMethod = target as InvokeMethod; targetMethod = target as InvokeMethod;
if (targetMethod == null || targetMethod.targetObject == null) if (targetMethod == null || targetMethod.targetObject == null)
return; return;
SerializedObject objSerializedTarget = new SerializedObject(targetMethod); SerializedObject objSerializedTarget = new SerializedObject(targetMethod);
string component = ShowComponents(objSerializedTarget, targetMethod.targetObject); string component = ShowComponents(objSerializedTarget, targetMethod.targetObject);
// show component methods if selected // show component methods if selected
if (!string.IsNullOrEmpty(component)) if (!string.IsNullOrEmpty(component))
{ {
var method = ShowMethods(objSerializedTarget, targetMethod.targetObject, component); var method = ShowMethods(objSerializedTarget, targetMethod.targetObject, component);
// show method parameters if selected // show method parameters if selected
if (method != null) if (method != null)
{ {
objSerializedTarget.ApplyModifiedProperties(); objSerializedTarget.ApplyModifiedProperties();
ShowParameters(objSerializedTarget, targetMethod.targetObject, method); ShowParameters(objSerializedTarget, targetMethod.targetObject, method);
ShowReturnValue(objSerializedTarget, method); ShowReturnValue(objSerializedTarget, method);
} }
} }
} }
private string ShowComponents(SerializedObject objTarget, GameObject gameObject) private string ShowComponents(SerializedObject objTarget, GameObject gameObject)
{ {
var targetComponentAssemblyName = objTarget.FindProperty("targetComponentAssemblyName"); var targetComponentAssemblyName = objTarget.FindProperty("targetComponentAssemblyName");
var targetComponentFullname = objTarget.FindProperty("targetComponentFullname"); var targetComponentFullname = objTarget.FindProperty("targetComponentFullname");
var targetComponentText = objTarget.FindProperty("targetComponentText"); var targetComponentText = objTarget.FindProperty("targetComponentText");
var objComponents = gameObject.GetComponents<Component>(); var objComponents = gameObject.GetComponents<Component>();
var objTypesAssemblynames = (from objComp in objComponents select objComp.GetType().AssemblyQualifiedName).ToList(); var objTypesAssemblynames = (from objComp in objComponents select objComp.GetType().AssemblyQualifiedName).ToList();
var objTypesName = (from objComp in objComponents select objComp.GetType().Name).ToList(); var objTypesName = (from objComp in objComponents select objComp.GetType().Name).ToList();
int index = objTypesAssemblynames.IndexOf(targetComponentAssemblyName.stringValue); int index = objTypesAssemblynames.IndexOf(targetComponentAssemblyName.stringValue);
index = EditorGUILayout.Popup("Target Component", index, objTypesName.ToArray()); index = EditorGUILayout.Popup("Target Component", index, objTypesName.ToArray());
if (index != -1) if (index != -1)
{ {
targetComponentAssemblyName.stringValue = objTypesAssemblynames[index]; targetComponentAssemblyName.stringValue = objTypesAssemblynames[index];
targetComponentFullname.stringValue = objComponents.GetType().FullName; targetComponentFullname.stringValue = objComponents.GetType().FullName;
targetComponentText.stringValue = objTypesName[index]; targetComponentText.stringValue = objTypesName[index];
} }
else else
{ {
targetComponentAssemblyName.stringValue = null; targetComponentAssemblyName.stringValue = null;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
return targetComponentAssemblyName.stringValue; return targetComponentAssemblyName.stringValue;
} }
private MethodInfo ShowMethods(SerializedObject objTarget, GameObject gameObject, string component) private MethodInfo ShowMethods(SerializedObject objTarget, GameObject gameObject, string component)
{ {
MethodInfo result = null; MethodInfo result = null;
var targetMethodProp = objTarget.FindProperty("targetMethod"); var targetMethodProp = objTarget.FindProperty("targetMethod");
var targetMethodTextProp = objTarget.FindProperty("targetMethodText"); var targetMethodTextProp = objTarget.FindProperty("targetMethodText");
var methodParametersProp = objTarget.FindProperty("methodParameters"); var methodParametersProp = objTarget.FindProperty("methodParameters");
var showInheritedProp = objTarget.FindProperty("showInherited"); var showInheritedProp = objTarget.FindProperty("showInherited");
var saveReturnValueProp = objTarget.FindProperty("saveReturnValue"); var saveReturnValueProp = objTarget.FindProperty("saveReturnValue");
var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey"); var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey");
var objComponent = gameObject.GetComponent(ReflectionHelper.GetType(component)); var objComponent = gameObject.GetComponent(ReflectionHelper.GetType(component));
var bindingFlags = BindingFlags.Default | BindingFlags.Public | BindingFlags.Instance; var bindingFlags = BindingFlags.Default | BindingFlags.Public | BindingFlags.Instance;
if (!showInheritedProp.boolValue) if (!showInheritedProp.boolValue)
{ {
bindingFlags |= BindingFlags.DeclaredOnly; bindingFlags |= BindingFlags.DeclaredOnly;
} }
if (objComponent != null) if (objComponent != null)
{ {
var objMethods = objComponent.GetType().GetMethods(bindingFlags); var objMethods = objComponent.GetType().GetMethods(bindingFlags);
var methods = (from objMethod in objMethods where !objMethod.IsSpecialName select objMethod).ToList(); // filter out the getter/setter methods var methods = (from objMethod in objMethods where !objMethod.IsSpecialName select objMethod).ToList(); // filter out the getter/setter methods
var methodText = (from objMethod in methods select objMethod.Name + FormatParameters(objMethod.GetParameters()) + ": " + objMethod.ReturnType.Name).ToList(); var methodText = (from objMethod in methods select objMethod.Name + FormatParameters(objMethod.GetParameters()) + ": " + objMethod.ReturnType.Name).ToList();
int index = methodText.IndexOf(targetMethodTextProp.stringValue); int index = methodText.IndexOf(targetMethodTextProp.stringValue);
index = EditorGUILayout.Popup("Target Method", index, methodText.ToArray()); index = EditorGUILayout.Popup("Target Method", index, methodText.ToArray());
EditorGUILayout.PropertyField(showInheritedProp); EditorGUILayout.PropertyField(showInheritedProp);
if (index != -1) if (index != -1)
{ {
if (targetMethodTextProp.stringValue != methodText[index]) if (targetMethodTextProp.stringValue != methodText[index])
{ {
// reset // reset
methodParametersProp.ClearArray(); methodParametersProp.ClearArray();
methodParametersProp.arraySize = methods[index].GetParameters().Length; methodParametersProp.arraySize = methods[index].GetParameters().Length;
saveReturnValueProp.boolValue = false; saveReturnValueProp.boolValue = false;
returnValueKeyProp.stringValue = null; returnValueKeyProp.stringValue = null;
} }
targetMethodTextProp.stringValue = methodText[index]; targetMethodTextProp.stringValue = methodText[index];
targetMethodProp.stringValue = methods[index].Name; targetMethodProp.stringValue = methods[index].Name;
result = methods[index]; result = methods[index];
} }
else else
{ {
targetMethodTextProp.stringValue = null; targetMethodTextProp.stringValue = null;
targetMethodProp.stringValue = null; targetMethodProp.stringValue = null;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
return result; return result;
} }
private void ShowParameters(SerializedObject objTarget, GameObject gameObject, MethodInfo method) private void ShowParameters(SerializedObject objTarget, GameObject gameObject, MethodInfo method)
{ {
var methodParametersProp = objTarget.FindProperty("methodParameters"); var methodParametersProp = objTarget.FindProperty("methodParameters");
var objParams = method.GetParameters(); var objParams = method.GetParameters();
if (objParams.Length > 0) if (objParams.Length > 0)
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel); EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginVertical(EditorStyles.helpBox);
for (int i = 0; i < objParams.Length; i++) for (int i = 0; i < objParams.Length; i++)
{ {
var objParam = objParams[i]; var objParam = objParams[i];
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
string labelFormat = string.Format("{0}: {1}", objParam.ParameterType.Name, objParam.Name); string labelFormat = string.Format("{0}: {1}", objParam.ParameterType.Name, objParam.Name);
var objItemProp = methodParametersProp.GetArrayElementAtIndex(i); var objItemProp = methodParametersProp.GetArrayElementAtIndex(i);
var serObjValueProp = objItemProp.FindPropertyRelative("objValue"); var serObjValueProp = objItemProp.FindPropertyRelative("objValue");
var serVariableKeyProp = objItemProp.FindPropertyRelative("variableKey"); var serVariableKeyProp = objItemProp.FindPropertyRelative("variableKey");
var serValueTypeAssemblynameProp = serObjValueProp.FindPropertyRelative("typeAssemblyname"); var serValueTypeAssemblynameProp = serObjValueProp.FindPropertyRelative("typeAssemblyname");
var serValueTypeFullnameProp = serObjValueProp.FindPropertyRelative("typeFullname"); var serValueTypeFullnameProp = serObjValueProp.FindPropertyRelative("typeFullname");
serValueTypeAssemblynameProp.stringValue = objParam.ParameterType.AssemblyQualifiedName; serValueTypeAssemblynameProp.stringValue = objParam.ParameterType.AssemblyQualifiedName;
serValueTypeFullnameProp.stringValue = objParam.ParameterType.FullName; serValueTypeFullnameProp.stringValue = objParam.ParameterType.FullName;
bool isDrawn = true; bool isDrawn = true;
if (string.IsNullOrEmpty(serVariableKeyProp.stringValue)) if (string.IsNullOrEmpty(serVariableKeyProp.stringValue))
{ {
isDrawn = DrawTypedPropertyInput(labelFormat, serObjValueProp, objParam.ParameterType); isDrawn = DrawTypedPropertyInput(labelFormat, serObjValueProp, objParam.ParameterType);
} }
if (isDrawn) if (isDrawn)
{ {
var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, objParam.ParameterType); var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, objParam.ParameterType);
var values = new string[] { "<Value>" }; var values = new string[] { "<Value>" };
var displayValue = values.Concat(vars).ToList(); var displayValue = values.Concat(vars).ToList();
int index = displayValue.IndexOf(serVariableKeyProp.stringValue); int index = displayValue.IndexOf(serVariableKeyProp.stringValue);
if (index == -1) if (index == -1)
{ {
index = 0; index = 0;
} }
if (string.IsNullOrEmpty(serVariableKeyProp.stringValue)) if (string.IsNullOrEmpty(serVariableKeyProp.stringValue))
{ {
index = EditorGUILayout.Popup(index, displayValue.ToArray(), GUILayout.MaxWidth(80)); index = EditorGUILayout.Popup(index, displayValue.ToArray(), GUILayout.MaxWidth(80));
} }
else else
{ {
index = EditorGUILayout.Popup(labelFormat, index, displayValue.ToArray()); index = EditorGUILayout.Popup(labelFormat, index, displayValue.ToArray());
} }
if (index > 0) if (index > 0)
{ {
serVariableKeyProp.stringValue = displayValue[index]; serVariableKeyProp.stringValue = displayValue[index];
} }
else else
{ {
serVariableKeyProp.stringValue = null; serVariableKeyProp.stringValue = null;
} }
} }
else else
{ {
var style = EditorStyles.label; var style = EditorStyles.label;
var prevColor = style.normal.textColor; var prevColor = style.normal.textColor;
style.normal.textColor = Color.red; style.normal.textColor = Color.red;
EditorGUILayout.LabelField(new GUIContent(objParam.ParameterType.Name + " cannot be drawn, don´t use this method in the flowchart."), style); EditorGUILayout.LabelField(new GUIContent(objParam.ParameterType.Name + " cannot be drawn, don´t use this method in the flowchart."), style);
style.normal.textColor = prevColor; style.normal.textColor = prevColor;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
} }
private void ShowReturnValue(SerializedObject objTarget, MethodInfo method) private void ShowReturnValue(SerializedObject objTarget, MethodInfo method)
{ {
var saveReturnValueProp = objTarget.FindProperty("saveReturnValue"); var saveReturnValueProp = objTarget.FindProperty("saveReturnValue");
var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey"); var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey");
var returnValueTypeProp = objTarget.FindProperty("returnValueType"); var returnValueTypeProp = objTarget.FindProperty("returnValueType");
var callModeProp = objTarget.FindProperty("callMode"); var callModeProp = objTarget.FindProperty("callMode");
returnValueTypeProp.stringValue = method.ReturnType.FullName; returnValueTypeProp.stringValue = method.ReturnType.FullName;
if (method.ReturnType == typeof(IEnumerator)) if (method.ReturnType == typeof(IEnumerator))
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.PropertyField(callModeProp); EditorGUILayout.PropertyField(callModeProp);
} }
else if (method.ReturnType != typeof(void)) else if (method.ReturnType != typeof(void))
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.LabelField("Return Value", EditorStyles.boldLabel); EditorGUILayout.LabelField("Return Value", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginVertical(EditorStyles.helpBox);
saveReturnValueProp.boolValue = EditorGUILayout.Toggle("Save return value", saveReturnValueProp.boolValue); saveReturnValueProp.boolValue = EditorGUILayout.Toggle("Save return value", saveReturnValueProp.boolValue);
if (saveReturnValueProp.boolValue) if (saveReturnValueProp.boolValue)
{ {
var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, method.ReturnType).ToList(); var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, method.ReturnType).ToList();
int index = vars.IndexOf(returnValueKeyProp.stringValue); int index = vars.IndexOf(returnValueKeyProp.stringValue);
index = EditorGUILayout.Popup(method.ReturnType.Name, index, vars.ToArray()); index = EditorGUILayout.Popup(method.ReturnType.Name, index, vars.ToArray());
if (index != -1) if (index != -1)
{ {
returnValueKeyProp.stringValue = vars[index]; returnValueKeyProp.stringValue = vars[index];
} }
} }
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
} }
else else
{ {
saveReturnValueProp.boolValue = false; saveReturnValueProp.boolValue = false;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
private bool DrawTypedPropertyInput(string label, SerializedProperty objProperty, Type type) private bool DrawTypedPropertyInput(string label, SerializedProperty objProperty, Type type)
{ {
SerializedProperty objectValue = null; SerializedProperty objectValue = null;
if (type == typeof(int)) if (type == typeof(int))
{ {
objectValue = objProperty.FindPropertyRelative("intValue"); objectValue = objProperty.FindPropertyRelative("intValue");
objectValue.intValue = EditorGUILayout.IntField(new GUIContent(label), objectValue.intValue); objectValue.intValue = EditorGUILayout.IntField(new GUIContent(label), objectValue.intValue);
return true; return true;
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
objectValue = objProperty.FindPropertyRelative("boolValue"); objectValue = objProperty.FindPropertyRelative("boolValue");
objectValue.boolValue = EditorGUILayout.Toggle(new GUIContent(label), objectValue.boolValue); objectValue.boolValue = EditorGUILayout.Toggle(new GUIContent(label), objectValue.boolValue);
return true; return true;
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
objectValue = objProperty.FindPropertyRelative("floatValue"); objectValue = objProperty.FindPropertyRelative("floatValue");
objectValue.floatValue = EditorGUILayout.FloatField(new GUIContent(label), objectValue.floatValue); objectValue.floatValue = EditorGUILayout.FloatField(new GUIContent(label), objectValue.floatValue);
return true; return true;
} }
else if (type == typeof(string)) else if (type == typeof(string))
{ {
objectValue = objProperty.FindPropertyRelative("stringValue"); objectValue = objProperty.FindPropertyRelative("stringValue");
objectValue.stringValue = EditorGUILayout.TextField(new GUIContent(label), objectValue.stringValue); objectValue.stringValue = EditorGUILayout.TextField(new GUIContent(label), objectValue.stringValue);
return true; return true;
} }
else if (type == typeof(Color)) else if (type == typeof(Color))
{ {
objectValue = objProperty.FindPropertyRelative("colorValue"); objectValue = objProperty.FindPropertyRelative("colorValue");
objectValue.colorValue = EditorGUILayout.ColorField(new GUIContent(label), objectValue.colorValue); objectValue.colorValue = EditorGUILayout.ColorField(new GUIContent(label), objectValue.colorValue);
return true; return true;
} }
else if (type == typeof(UnityEngine.GameObject)) else if (type == typeof(UnityEngine.GameObject))
{ {
objectValue = objProperty.FindPropertyRelative("gameObjectValue"); objectValue = objProperty.FindPropertyRelative("gameObjectValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.GameObject), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.GameObject), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Material)) else if (type == typeof(UnityEngine.Material))
{ {
objectValue = objProperty.FindPropertyRelative("materialValue"); objectValue = objProperty.FindPropertyRelative("materialValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Material), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Material), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Sprite)) else if (type == typeof(UnityEngine.Sprite))
{ {
objectValue = objProperty.FindPropertyRelative("spriteValue"); objectValue = objProperty.FindPropertyRelative("spriteValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Sprite), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Sprite), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Texture)) else if (type == typeof(UnityEngine.Texture))
{ {
objectValue = objProperty.FindPropertyRelative("textureValue"); objectValue = objProperty.FindPropertyRelative("textureValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Texture), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Texture), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Vector2)) else if (type == typeof(UnityEngine.Vector2))
{ {
objectValue = objProperty.FindPropertyRelative("vector2Value"); objectValue = objProperty.FindPropertyRelative("vector2Value");
objectValue.vector2Value = EditorGUILayout.Vector2Field(new GUIContent(label), objectValue.vector2Value); objectValue.vector2Value = EditorGUILayout.Vector2Field(new GUIContent(label), objectValue.vector2Value);
return true; return true;
} }
else if (type == typeof(UnityEngine.Vector3)) else if (type == typeof(UnityEngine.Vector3))
{ {
objectValue = objProperty.FindPropertyRelative("vector3Value"); objectValue = objProperty.FindPropertyRelative("vector3Value");
objectValue.vector3Value = EditorGUILayout.Vector3Field(new GUIContent(label), objectValue.vector3Value); objectValue.vector3Value = EditorGUILayout.Vector3Field(new GUIContent(label), objectValue.vector3Value);
return true; return true;
} }
else if (type.IsSubclassOf(typeof(UnityEngine.Object))) else if (type.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
objectValue = objProperty.FindPropertyRelative("objectValue"); objectValue = objProperty.FindPropertyRelative("objectValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, type, true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, type, true);
return true; return true;
} }
else if (type.IsEnum) else if (type.IsEnum)
{ {
var enumNames = Enum.GetNames(type); var enumNames = Enum.GetNames(type);
objectValue = objProperty.FindPropertyRelative("intValue"); objectValue = objProperty.FindPropertyRelative("intValue");
objectValue.intValue = EditorGUILayout.Popup(label, objectValue.intValue, enumNames); objectValue.intValue = EditorGUILayout.Popup(label, objectValue.intValue, enumNames);
return true; return true;
} }
return false; return false;
} }
private string[] GetFungusVariablesByType(List<Variable> variables, Type type) private string[] GetFungusVariablesByType(List<Variable> variables, Type type)
{ {
string[] result = new string[0]; string[] result = new string[0];
if (type == typeof(int)) if (type == typeof(int))
{ {
result = (from v in variables where v.GetType() == typeof(IntegerVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(IntegerVariable) select v.key).ToArray();
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
result = (from v in variables where v.GetType() == typeof(BooleanVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(BooleanVariable) select v.key).ToArray();
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
result = (from v in variables where v.GetType() == typeof(FloatVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(FloatVariable) select v.key).ToArray();
} }
else if (type == typeof(string)) else if (type == typeof(string))
{ {
result = (from v in variables where v.GetType() == typeof(StringVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(StringVariable) select v.key).ToArray();
} }
else if (type == typeof(Color)) else if (type == typeof(Color))
{ {
result = (from v in variables where v.GetType() == typeof(ColorVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(ColorVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.GameObject)) else if (type == typeof(UnityEngine.GameObject))
{ {
result = (from v in variables where v.GetType() == typeof(GameObjectVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(GameObjectVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Material)) else if (type == typeof(UnityEngine.Material))
{ {
result = (from v in variables where v.GetType() == typeof(MaterialVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(MaterialVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Sprite)) else if (type == typeof(UnityEngine.Sprite))
{ {
result = (from v in variables where v.GetType() == typeof(SpriteVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(SpriteVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Texture)) else if (type == typeof(UnityEngine.Texture))
{ {
result = (from v in variables where v.GetType() == typeof(TextureVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(TextureVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Vector2)) else if (type == typeof(UnityEngine.Vector2))
{ {
result = (from v in variables where v.GetType() == typeof(Vector2Variable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(Vector2Variable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Vector3)) else if (type == typeof(UnityEngine.Vector3))
{ {
result = (from v in variables where v.GetType() == typeof(Vector3Variable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(Vector3Variable) select v.key).ToArray();
} }
else if (type.IsSubclassOf(typeof(UnityEngine.Object))) else if (type.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
result = (from v in variables where v.GetType() == typeof(ObjectVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(ObjectVariable) select v.key).ToArray();
} }
return result; return result;
} }
private string FormatParameters(ParameterInfo[] paramInfo) private string FormatParameters(ParameterInfo[] paramInfo)
{ {
string result = " ("; string result = " (";
for (int i = 0; i < paramInfo.Length; i++) for (int i = 0; i < paramInfo.Length; i++)
{ {
var pi = paramInfo[i]; var pi = paramInfo[i];
result += pi.ParameterType.Name; // " arg" + (i + 1); result += pi.ParameterType.Name; // " arg" + (i + 1);
if (i < paramInfo.Length - 1) if (i < paramInfo.Length - 1)
{ {
result += ", "; result += ", ";
} }
} }
return result + ")"; return result + ")";
} }
private object GetDefaultValue(Type t) private object GetDefaultValue(Type t)
{ {
if (t.IsValueType) if (t.IsValueType)
return Activator.CreateInstance(t); return Activator.CreateInstance(t);
return null; return null;
} }
} }
} }

138
Assets/Fungus/Flowchart/Editor/LabelEditor.cs

@ -13,74 +13,74 @@ using System.Linq;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(Label))] [CustomEditor (typeof(Label))]
public class LabelEditor : CommandEditor public class LabelEditor : CommandEditor
{ {
protected SerializedProperty keyProp; protected SerializedProperty keyProp;
static public void LabelField(SerializedProperty property, static public void LabelField(SerializedProperty property,
GUIContent labelText, GUIContent labelText,
Block block) Block block)
{ {
List<string> labelKeys = new List<string>(); List<string> labelKeys = new List<string>();
List<Label> labelObjects = new List<Label>(); List<Label> labelObjects = new List<Label>();
labelKeys.Add("<None>"); labelKeys.Add("<None>");
labelObjects.Add(null); labelObjects.Add(null);
Label selectedLabel = property.objectReferenceValue as Label; Label selectedLabel = property.objectReferenceValue as Label;
int index = 0; int index = 0;
int selectedIndex = 0; int selectedIndex = 0;
foreach (Command command in block.commandList) foreach (Command command in block.commandList)
{ {
Label label = command as Label; Label label = command as Label;
if (label == null) if (label == null)
{ {
continue; continue;
} }
labelKeys.Add(label.key); labelKeys.Add(label.key);
labelObjects.Add(label); labelObjects.Add(label);
index++; index++;
if (label == selectedLabel) if (label == selectedLabel)
{ {
selectedIndex = index; selectedIndex = index;
} }
} }
selectedIndex = EditorGUILayout.Popup(labelText.text, selectedIndex, labelKeys.ToArray()); selectedIndex = EditorGUILayout.Popup(labelText.text, selectedIndex, labelKeys.ToArray());
property.objectReferenceValue = labelObjects[selectedIndex]; property.objectReferenceValue = labelObjects[selectedIndex];
} }
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
keyProp = serializedObject.FindProperty("key"); keyProp = serializedObject.FindProperty("key");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
Label t = target as Label; Label t = target as Label;
Flowchart flowchart = t.GetFlowchart(); Flowchart flowchart = t.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
serializedObject.Update(); serializedObject.Update();
EditorGUILayout.PropertyField(keyProp); EditorGUILayout.PropertyField(keyProp);
keyProp.stringValue = flowchart.GetUniqueLabelKey(keyProp.stringValue, t); keyProp.stringValue = flowchart.GetUniqueLabelKey(keyProp.stringValue, t);
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

296
Assets/Fungus/Flowchart/Editor/SetVariableEditor.cs

@ -11,153 +11,153 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(SetVariable))] [CustomEditor (typeof(SetVariable))]
public class SetVariableEditor : CommandEditor public class SetVariableEditor : CommandEditor
{ {
protected SerializedProperty variableProp; protected SerializedProperty variableProp;
protected SerializedProperty setOperatorProp; protected SerializedProperty setOperatorProp;
protected SerializedProperty booleanDataProp; protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp; protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp; protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp; protected SerializedProperty stringDataProp;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (NullTargetCheck()) // Check for an orphaned editor instance if (NullTargetCheck()) // Check for an orphaned editor instance
return; return;
variableProp = serializedObject.FindProperty("variable"); variableProp = serializedObject.FindProperty("variable");
setOperatorProp = serializedObject.FindProperty("setOperator"); setOperatorProp = serializedObject.FindProperty("setOperator");
booleanDataProp = serializedObject.FindProperty("booleanData"); booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData"); integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData"); floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData"); stringDataProp = serializedObject.FindProperty("stringData");
} }
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
serializedObject.Update(); serializedObject.Update();
SetVariable t = target as SetVariable; SetVariable t = target as SetVariable;
Flowchart flowchart = t.GetFlowchart(); Flowchart flowchart = t.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
EditorGUILayout.PropertyField(variableProp); EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null) if (variableProp.objectReferenceValue == null)
{ {
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
return; return;
} }
Variable selectedVariable = variableProp.objectReferenceValue as Variable; Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType(); System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorsList = new List<GUIContent>(); List<GUIContent> operatorsList = new List<GUIContent>();
operatorsList.Add(new GUIContent("=")); operatorsList.Add(new GUIContent("="));
if (variableType == typeof(BooleanVariable)) if (variableType == typeof(BooleanVariable))
{ {
operatorsList.Add(new GUIContent("=!")); operatorsList.Add(new GUIContent("=!"));
} }
else if (variableType == typeof(IntegerVariable) || else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable)) variableType == typeof(FloatVariable))
{ {
operatorsList.Add(new GUIContent("+=")); operatorsList.Add(new GUIContent("+="));
operatorsList.Add(new GUIContent("-=")); operatorsList.Add(new GUIContent("-="));
operatorsList.Add(new GUIContent("*=")); operatorsList.Add(new GUIContent("*="));
operatorsList.Add(new GUIContent("/=")); operatorsList.Add(new GUIContent("/="));
} }
int selectedIndex = 0; int selectedIndex = 0;
switch (t.setOperator) switch (t.setOperator)
{ {
default: default:
case SetVariable.SetOperator.Assign: case SetVariable.SetOperator.Assign:
selectedIndex = 0; selectedIndex = 0;
break; break;
case SetVariable.SetOperator.Negate: case SetVariable.SetOperator.Negate:
selectedIndex = 1; selectedIndex = 1;
break; break;
case SetVariable.SetOperator.Add: case SetVariable.SetOperator.Add:
selectedIndex = 1; selectedIndex = 1;
break; break;
case SetVariable.SetOperator.Subtract: case SetVariable.SetOperator.Subtract:
selectedIndex = 2; selectedIndex = 2;
break; break;
case SetVariable.SetOperator.Multiply: case SetVariable.SetOperator.Multiply:
selectedIndex = 3; selectedIndex = 3;
break; break;
case SetVariable.SetOperator.Divide: case SetVariable.SetOperator.Divide:
selectedIndex = 4; selectedIndex = 4;
break; break;
} }
selectedIndex = EditorGUILayout.Popup(new GUIContent("Operation", "Arithmetic operator to use"), selectedIndex, operatorsList.ToArray()); selectedIndex = EditorGUILayout.Popup(new GUIContent("Operation", "Arithmetic operator to use"), selectedIndex, operatorsList.ToArray());
SetVariable.SetOperator setOperator = SetVariable.SetOperator.Assign; SetVariable.SetOperator setOperator = SetVariable.SetOperator.Assign;
if (variableType == typeof(BooleanVariable) || if (variableType == typeof(BooleanVariable) ||
variableType == typeof(StringVariable)) variableType == typeof(StringVariable))
{ {
switch (selectedIndex) switch (selectedIndex)
{ {
default: default:
case 0: case 0:
setOperator = SetVariable.SetOperator.Assign; setOperator = SetVariable.SetOperator.Assign;
break; break;
case 1: case 1:
setOperator = SetVariable.SetOperator.Negate; setOperator = SetVariable.SetOperator.Negate;
break; break;
} }
} }
else if (variableType == typeof(IntegerVariable) || else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable)) variableType == typeof(FloatVariable))
{ {
switch (selectedIndex) switch (selectedIndex)
{ {
default: default:
case 0: case 0:
setOperator = SetVariable.SetOperator.Assign; setOperator = SetVariable.SetOperator.Assign;
break; break;
case 1: case 1:
setOperator = SetVariable.SetOperator.Add; setOperator = SetVariable.SetOperator.Add;
break; break;
case 2: case 2:
setOperator = SetVariable.SetOperator.Subtract; setOperator = SetVariable.SetOperator.Subtract;
break; break;
case 3: case 3:
setOperator = SetVariable.SetOperator.Multiply; setOperator = SetVariable.SetOperator.Multiply;
break; break;
case 4: case 4:
setOperator = SetVariable.SetOperator.Divide; setOperator = SetVariable.SetOperator.Divide;
break; break;
} }
} }
setOperatorProp.enumValueIndex = (int)setOperator; setOperatorProp.enumValueIndex = (int)setOperator;
if (variableType == typeof(BooleanVariable)) if (variableType == typeof(BooleanVariable))
{ {
EditorGUILayout.PropertyField(booleanDataProp, new GUIContent("Boolean")); EditorGUILayout.PropertyField(booleanDataProp, new GUIContent("Boolean"));
} }
else if (variableType == typeof(IntegerVariable)) else if (variableType == typeof(IntegerVariable))
{ {
EditorGUILayout.PropertyField(integerDataProp, new GUIContent("Integer")); EditorGUILayout.PropertyField(integerDataProp, new GUIContent("Integer"));
} }
else if (variableType == typeof(FloatVariable)) else if (variableType == typeof(FloatVariable))
{ {
EditorGUILayout.PropertyField(floatDataProp, new GUIContent("Float")); EditorGUILayout.PropertyField(floatDataProp, new GUIContent("Float"));
} }
else if (variableType == typeof(StringVariable)) else if (variableType == typeof(StringVariable))
{ {
EditorGUILayout.PropertyField(stringDataProp, new GUIContent("String")); EditorGUILayout.PropertyField(stringDataProp, new GUIContent("String"));
} }
serializedObject.ApplyModifiedProperties(); serializedObject.ApplyModifiedProperties();
} }
} }
} }

636
Assets/Fungus/Flowchart/Editor/VariableEditor.cs

@ -13,294 +13,294 @@ using System.Linq;
namespace Fungus namespace Fungus
{ {
[CustomEditor (typeof(Variable), true)] [CustomEditor (typeof(Variable), true)]
public class VariableEditor : CommandEditor public class VariableEditor : CommandEditor
{ {
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
Variable t = target as Variable; Variable t = target as Variable;
t.hideFlags = HideFlags.HideInInspector; t.hideFlags = HideFlags.HideInInspector;
} }
public static VariableInfoAttribute GetVariableInfo(System.Type variableType) public static VariableInfoAttribute GetVariableInfo(System.Type variableType)
{ {
object[] attributes = variableType.GetCustomAttributes(typeof(VariableInfoAttribute), false); object[] attributes = variableType.GetCustomAttributes(typeof(VariableInfoAttribute), false);
foreach (object obj in attributes) foreach (object obj in attributes)
{ {
VariableInfoAttribute variableInfoAttr = obj as VariableInfoAttribute; VariableInfoAttribute variableInfoAttr = obj as VariableInfoAttribute;
if (variableInfoAttr != null) if (variableInfoAttr != null)
{ {
return variableInfoAttr; return variableInfoAttr;
} }
} }
return null; return null;
} }
static public void VariableField(SerializedProperty property, static public void VariableField(SerializedProperty property,
GUIContent label, GUIContent label,
Flowchart flowchart, Flowchart flowchart,
string defaultText, string defaultText,
Func<Variable, bool> filter, Func<Variable, bool> filter,
Func<string, int, string[], int> drawer = null) Func<string, int, string[], int> drawer = null)
{ {
List<string> variableKeys = new List<string>(); List<string> variableKeys = new List<string>();
List<Variable> variableObjects = new List<Variable>(); List<Variable> variableObjects = new List<Variable>();
variableKeys.Add(defaultText); variableKeys.Add(defaultText);
variableObjects.Add(null); variableObjects.Add(null);
List<Variable> variables = flowchart.variables; List<Variable> variables = flowchart.variables;
int index = 0; int index = 0;
int selectedIndex = 0; int selectedIndex = 0;
Variable selectedVariable = property.objectReferenceValue as Variable; Variable selectedVariable = property.objectReferenceValue as Variable;
// When there are multiple Flowcharts in a scene with variables, switching // When there are multiple Flowcharts in a scene with variables, switching
// between the Flowcharts can cause the wrong variable property // between the Flowcharts can cause the wrong variable property
// to be inspected for a single frame. This has the effect of causing private // to be inspected for a single frame. This has the effect of causing private
// variable references to be set to null when inspected. When this condition // variable references to be set to null when inspected. When this condition
// occurs we just skip displaying the property for this frame. // occurs we just skip displaying the property for this frame.
if (selectedVariable != null && if (selectedVariable != null &&
selectedVariable.gameObject != flowchart.gameObject && selectedVariable.gameObject != flowchart.gameObject &&
selectedVariable.scope == VariableScope.Private) selectedVariable.scope == VariableScope.Private)
{ {
property.objectReferenceValue = null; property.objectReferenceValue = null;
return; return;
} }
foreach (Variable v in variables) foreach (Variable v in variables)
{ {
if (filter != null) if (filter != null)
{ {
if (!filter(v)) if (!filter(v))
{ {
continue; continue;
} }
} }
variableKeys.Add(v.key); variableKeys.Add(v.key);
variableObjects.Add(v); variableObjects.Add(v);
index++; index++;
if (v == selectedVariable) if (v == selectedVariable)
{ {
selectedIndex = index; selectedIndex = index;
} }
} }
Flowchart[] fsList = GameObject.FindObjectsOfType<Flowchart>(); Flowchart[] fsList = GameObject.FindObjectsOfType<Flowchart>();
foreach (Flowchart fs in fsList) foreach (Flowchart fs in fsList)
{ {
if (fs == flowchart) if (fs == flowchart)
{ {
continue; continue;
} }
List<Variable> publicVars = fs.GetPublicVariables(); List<Variable> publicVars = fs.GetPublicVariables();
foreach (Variable v in publicVars) foreach (Variable v in publicVars)
{ {
if (filter != null) if (filter != null)
{ {
if (!filter(v)) if (!filter(v))
{ {
continue; continue;
} }
} }
variableKeys.Add(fs.name + " / " + v.key); variableKeys.Add(fs.name + " / " + v.key);
variableObjects.Add(v); variableObjects.Add(v);
index++; index++;
if (v == selectedVariable) if (v == selectedVariable)
{ {
selectedIndex = index; selectedIndex = index;
} }
} }
} }
if (drawer == null) if (drawer == null)
{ {
selectedIndex = EditorGUILayout.Popup(label.text, selectedIndex, variableKeys.ToArray()); selectedIndex = EditorGUILayout.Popup(label.text, selectedIndex, variableKeys.ToArray());
} }
else else
{ {
selectedIndex = drawer(label.text, selectedIndex, variableKeys.ToArray()); selectedIndex = drawer(label.text, selectedIndex, variableKeys.ToArray());
} }
property.objectReferenceValue = variableObjects[selectedIndex]; property.objectReferenceValue = variableObjects[selectedIndex];
} }
} }
[CustomPropertyDrawer(typeof(VariablePropertyAttribute))] [CustomPropertyDrawer(typeof(VariablePropertyAttribute))]
public class VariableDrawer : PropertyDrawer public class VariableDrawer : PropertyDrawer
{ {
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{ {
VariablePropertyAttribute variableProperty = attribute as VariablePropertyAttribute; VariablePropertyAttribute variableProperty = attribute as VariablePropertyAttribute;
if (variableProperty == null) if (variableProperty == null)
{ {
return; return;
} }
EditorGUI.BeginProperty(position, label, property); EditorGUI.BeginProperty(position, label, property);
// Filter the variables by the types listed in the VariableProperty attribute // Filter the variables by the types listed in the VariableProperty attribute
Func<Variable, bool> compare = v => Func<Variable, bool> compare = v =>
{ {
if (v == null) if (v == null)
{ {
return false; return false;
} }
if (variableProperty.VariableTypes.Length == 0) if (variableProperty.VariableTypes.Length == 0)
{ {
return true; return true;
} }
return variableProperty.VariableTypes.Contains<System.Type>(v.GetType()); return variableProperty.VariableTypes.Contains<System.Type>(v.GetType());
}; };
VariableEditor.VariableField(property, VariableEditor.VariableField(property,
label, label,
FlowchartWindow.GetFlowchart(), FlowchartWindow.GetFlowchart(),
variableProperty.defaultText, variableProperty.defaultText,
compare, compare,
(s,t,u) => (EditorGUI.Popup(position, s, t, u))); (s,t,u) => (EditorGUI.Popup(position, s, t, u)));
EditorGUI.EndProperty(); EditorGUI.EndProperty();
} }
} }
public class VariableDataDrawer<T> : PropertyDrawer where T : Variable public class VariableDataDrawer<T> : PropertyDrawer where T : Variable
{ {
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{ {
EditorGUI.BeginProperty(position, label, property); EditorGUI.BeginProperty(position, label, property);
// The variable reference and data properties must follow the naming convention 'typeRef', 'typeVal' // The variable reference and data properties must follow the naming convention 'typeRef', 'typeVal'
VariableInfoAttribute typeInfo = VariableEditor.GetVariableInfo(typeof(T)); VariableInfoAttribute typeInfo = VariableEditor.GetVariableInfo(typeof(T));
if (typeInfo == null) if (typeInfo == null)
{ {
return; return;
} }
string propNameBase = typeInfo.VariableType; string propNameBase = typeInfo.VariableType;
propNameBase = Char.ToLowerInvariant(propNameBase[0]) + propNameBase.Substring(1); propNameBase = Char.ToLowerInvariant(propNameBase[0]) + propNameBase.Substring(1);
SerializedProperty referenceProp = property.FindPropertyRelative(propNameBase + "Ref"); SerializedProperty referenceProp = property.FindPropertyRelative(propNameBase + "Ref");
SerializedProperty valueProp = property.FindPropertyRelative(propNameBase + "Val"); SerializedProperty valueProp = property.FindPropertyRelative(propNameBase + "Val");
if (referenceProp == null || valueProp == null) if (referenceProp == null || valueProp == null)
{ {
return; return;
} }
Command command = property.serializedObject.targetObject as Command; Command command = property.serializedObject.targetObject as Command;
if (command == null) if (command == null)
{ {
return; return;
} }
Flowchart flowchart = command.GetFlowchart() as Flowchart; Flowchart flowchart = command.GetFlowchart() as Flowchart;
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
if (EditorGUI.GetPropertyHeight(valueProp, label) > EditorGUIUtility.singleLineHeight) if (EditorGUI.GetPropertyHeight(valueProp, label) > EditorGUIUtility.singleLineHeight)
{ {
DrawMultiLineProperty(position, label, referenceProp, valueProp, flowchart); DrawMultiLineProperty(position, label, referenceProp, valueProp, flowchart);
} }
else else
{ {
DrawSingleLineProperty(position, label, referenceProp, valueProp, flowchart); DrawSingleLineProperty(position, label, referenceProp, valueProp, flowchart);
} }
EditorGUI.EndProperty(); EditorGUI.EndProperty();
} }
protected virtual void DrawSingleLineProperty(Rect rect, GUIContent label, SerializedProperty referenceProp, SerializedProperty valueProp, Flowchart flowchart) protected virtual void DrawSingleLineProperty(Rect rect, GUIContent label, SerializedProperty referenceProp, SerializedProperty valueProp, Flowchart flowchart)
{ {
const int popupWidth = 17; const int popupWidth = 17;
Rect controlRect = EditorGUI.PrefixLabel(rect, label); Rect controlRect = EditorGUI.PrefixLabel(rect, label);
Rect valueRect = controlRect; Rect valueRect = controlRect;
valueRect.width = controlRect.width - popupWidth - 5; valueRect.width = controlRect.width - popupWidth - 5;
Rect popupRect = controlRect; Rect popupRect = controlRect;
if (referenceProp.objectReferenceValue == null) if (referenceProp.objectReferenceValue == null)
{ {
EditorGUI.PropertyField(valueRect, valueProp, new GUIContent("")); EditorGUI.PropertyField(valueRect, valueProp, new GUIContent(""));
popupRect.x += valueRect.width + 5; popupRect.x += valueRect.width + 5;
popupRect.width = popupWidth; popupRect.width = popupWidth;
} }
EditorGUI.PropertyField(popupRect, referenceProp, new GUIContent("")); EditorGUI.PropertyField(popupRect, referenceProp, new GUIContent(""));
} }
protected virtual void DrawMultiLineProperty(Rect rect, GUIContent label, SerializedProperty referenceProp, SerializedProperty valueProp, Flowchart flowchart) protected virtual void DrawMultiLineProperty(Rect rect, GUIContent label, SerializedProperty referenceProp, SerializedProperty valueProp, Flowchart flowchart)
{ {
const int popupWidth = 100; const int popupWidth = 100;
Rect controlRect = rect; Rect controlRect = rect;
Rect valueRect = controlRect; Rect valueRect = controlRect;
valueRect.width = controlRect.width - 5; valueRect.width = controlRect.width - 5;
Rect popupRect = controlRect; Rect popupRect = controlRect;
if (referenceProp.objectReferenceValue == null) if (referenceProp.objectReferenceValue == null)
{ {
EditorGUI.PropertyField(valueRect, valueProp, label); EditorGUI.PropertyField(valueRect, valueProp, label);
popupRect.x = rect.width - popupWidth + 5; popupRect.x = rect.width - popupWidth + 5;
popupRect.width = popupWidth; popupRect.width = popupWidth;
} }
else else
{ {
popupRect = EditorGUI.PrefixLabel(rect, label); popupRect = EditorGUI.PrefixLabel(rect, label);
} }
EditorGUI.PropertyField(popupRect, referenceProp, new GUIContent("")); EditorGUI.PropertyField(popupRect, referenceProp, new GUIContent(""));
} }
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{ {
VariableInfoAttribute typeInfo = VariableEditor.GetVariableInfo(typeof(T)); VariableInfoAttribute typeInfo = VariableEditor.GetVariableInfo(typeof(T));
if (typeInfo == null) if (typeInfo == null)
{ {
return EditorGUIUtility.singleLineHeight; return EditorGUIUtility.singleLineHeight;
} }
string propNameBase = typeInfo.VariableType; string propNameBase = typeInfo.VariableType;
propNameBase = Char.ToLowerInvariant(propNameBase[0]) + propNameBase.Substring(1); propNameBase = Char.ToLowerInvariant(propNameBase[0]) + propNameBase.Substring(1);
SerializedProperty referenceProp = property.FindPropertyRelative(propNameBase + "Ref"); SerializedProperty referenceProp = property.FindPropertyRelative(propNameBase + "Ref");
if (referenceProp.objectReferenceValue != null) if (referenceProp.objectReferenceValue != null)
{ {
return EditorGUIUtility.singleLineHeight; return EditorGUIUtility.singleLineHeight;
} }
SerializedProperty valueProp = property.FindPropertyRelative(propNameBase + "Val"); SerializedProperty valueProp = property.FindPropertyRelative(propNameBase + "Val");
return EditorGUI.GetPropertyHeight(valueProp, label); return EditorGUI.GetPropertyHeight(valueProp, label);
} }
} }
[CustomPropertyDrawer (typeof(BooleanData))] [CustomPropertyDrawer (typeof(BooleanData))]
public class BooleanDataDrawer : VariableDataDrawer<BooleanVariable> public class BooleanDataDrawer : VariableDataDrawer<BooleanVariable>
{} {}
[CustomPropertyDrawer (typeof(IntegerData))] [CustomPropertyDrawer (typeof(IntegerData))]
public class IntegerDataDrawer : VariableDataDrawer<IntegerVariable> public class IntegerDataDrawer : VariableDataDrawer<IntegerVariable>
{} {}
[CustomPropertyDrawer (typeof(FloatData))] [CustomPropertyDrawer (typeof(FloatData))]
public class FloatDataDrawer : VariableDataDrawer<FloatVariable> public class FloatDataDrawer : VariableDataDrawer<FloatVariable>
{} {}
[CustomPropertyDrawer (typeof(StringData))] [CustomPropertyDrawer (typeof(StringData))]
public class StringDataDrawer : VariableDataDrawer<StringVariable> public class StringDataDrawer : VariableDataDrawer<StringVariable>
@ -310,47 +310,47 @@ namespace Fungus
public class StringDataMultiDrawer : VariableDataDrawer<StringVariable> public class StringDataMultiDrawer : VariableDataDrawer<StringVariable>
{} {}
[CustomPropertyDrawer (typeof(ColorData))] [CustomPropertyDrawer (typeof(ColorData))]
public class ColorDataDrawer : VariableDataDrawer<ColorVariable> public class ColorDataDrawer : VariableDataDrawer<ColorVariable>
{} {}
[CustomPropertyDrawer (typeof(Vector2Data))] [CustomPropertyDrawer (typeof(Vector2Data))]
public class Vector2DataDrawer : VariableDataDrawer<Vector2Variable> public class Vector2DataDrawer : VariableDataDrawer<Vector2Variable>
{} {}
[CustomPropertyDrawer (typeof(Vector3Data))] [CustomPropertyDrawer (typeof(Vector3Data))]
public class Vector3DataDrawer : VariableDataDrawer<Vector3Variable> public class Vector3DataDrawer : VariableDataDrawer<Vector3Variable>
{} {}
[CustomPropertyDrawer (typeof(MaterialData))] [CustomPropertyDrawer (typeof(MaterialData))]
public class MaterialDataDrawer : VariableDataDrawer<MaterialVariable> public class MaterialDataDrawer : VariableDataDrawer<MaterialVariable>
{} {}
[CustomPropertyDrawer (typeof(TextureData))] [CustomPropertyDrawer (typeof(TextureData))]
public class TextureDataDrawer : VariableDataDrawer<TextureVariable> public class TextureDataDrawer : VariableDataDrawer<TextureVariable>
{} {}
[CustomPropertyDrawer (typeof(SpriteData))] [CustomPropertyDrawer (typeof(SpriteData))]
public class SpriteDataDrawer : VariableDataDrawer<SpriteVariable> public class SpriteDataDrawer : VariableDataDrawer<SpriteVariable>
{} {}
[CustomPropertyDrawer (typeof(GameObjectData))] [CustomPropertyDrawer (typeof(GameObjectData))]
public class GameObjectDataDrawer : VariableDataDrawer<GameObjectVariable> public class GameObjectDataDrawer : VariableDataDrawer<GameObjectVariable>
{} {}
[CustomPropertyDrawer (typeof(ObjectData))] [CustomPropertyDrawer (typeof(ObjectData))]
public class ObjectDataDrawer : VariableDataDrawer<ObjectVariable> public class ObjectDataDrawer : VariableDataDrawer<ObjectVariable>
{} {}
[CustomPropertyDrawer (typeof(AnimatorData))] [CustomPropertyDrawer (typeof(AnimatorData))]
public class AnimatorDataDrawer : VariableDataDrawer<AnimatorVariable> public class AnimatorDataDrawer : VariableDataDrawer<AnimatorVariable>
{} {}
[CustomPropertyDrawer (typeof(TransformData))] [CustomPropertyDrawer (typeof(TransformData))]
public class TransformDataDrawer : VariableDataDrawer<TransformVariable> public class TransformDataDrawer : VariableDataDrawer<TransformVariable>
{} {}
[CustomPropertyDrawer (typeof(AudioSourceData))] [CustomPropertyDrawer (typeof(AudioSourceData))]
public class AudioSourceDrawer : VariableDataDrawer<AudioSourceVariable> public class AudioSourceDrawer : VariableDataDrawer<AudioSourceVariable>
{} {}
} }

362
Assets/Fungus/Flowchart/Editor/VariableListAdaptor.cs

@ -14,188 +14,188 @@ using Rotorz.ReorderableList;
namespace Fungus namespace Fungus
{ {
public class VariableListAdaptor : IReorderableListAdaptor { public class VariableListAdaptor : IReorderableListAdaptor {
protected SerializedProperty _arrayProperty; protected SerializedProperty _arrayProperty;
public float fixedItemHeight; public float fixedItemHeight;
public SerializedProperty this[int index] { public SerializedProperty this[int index] {
get { return _arrayProperty.GetArrayElementAtIndex(index); } get { return _arrayProperty.GetArrayElementAtIndex(index); }
} }
public SerializedProperty arrayProperty { public SerializedProperty arrayProperty {
get { return _arrayProperty; } get { return _arrayProperty; }
} }
public VariableListAdaptor(SerializedProperty arrayProperty, float fixedItemHeight) { public VariableListAdaptor(SerializedProperty arrayProperty, float fixedItemHeight) {
if (arrayProperty == null) if (arrayProperty == null)
throw new ArgumentNullException("Array property was null."); throw new ArgumentNullException("Array property was null.");
if (!arrayProperty.isArray) if (!arrayProperty.isArray)
throw new InvalidOperationException("Specified serialized propery is not an array."); throw new InvalidOperationException("Specified serialized propery is not an array.");
this._arrayProperty = arrayProperty; this._arrayProperty = arrayProperty;
this.fixedItemHeight = fixedItemHeight; this.fixedItemHeight = fixedItemHeight;
} }
public VariableListAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) { public VariableListAdaptor(SerializedProperty arrayProperty) : this(arrayProperty, 0f) {
} }
public int Count { public int Count {
get { return _arrayProperty.arraySize; } get { return _arrayProperty.arraySize; }
} }
public virtual bool CanDrag(int index) { public virtual bool CanDrag(int index) {
return true; return true;
} }
public virtual bool CanRemove(int index) { public virtual bool CanRemove(int index) {
return true; return true;
} }
public void Add() { public void Add() {
int newIndex = _arrayProperty.arraySize; int newIndex = _arrayProperty.arraySize;
++_arrayProperty.arraySize; ++_arrayProperty.arraySize;
_arrayProperty.GetArrayElementAtIndex(newIndex).ResetValue(); _arrayProperty.GetArrayElementAtIndex(newIndex).ResetValue();
} }
public void Insert(int index) { public void Insert(int index) {
_arrayProperty.InsertArrayElementAtIndex(index); _arrayProperty.InsertArrayElementAtIndex(index);
_arrayProperty.GetArrayElementAtIndex(index).ResetValue(); _arrayProperty.GetArrayElementAtIndex(index).ResetValue();
} }
public void Duplicate(int index) { public void Duplicate(int index) {
_arrayProperty.InsertArrayElementAtIndex(index); _arrayProperty.InsertArrayElementAtIndex(index);
} }
public void Remove(int index) { public void Remove(int index) {
// Remove the Fungus Variable component // Remove the Fungus Variable component
Variable variable = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Variable; Variable variable = _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue as Variable;
Undo.DestroyObjectImmediate(variable); Undo.DestroyObjectImmediate(variable);
_arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = null; _arrayProperty.GetArrayElementAtIndex(index).objectReferenceValue = null;
_arrayProperty.DeleteArrayElementAtIndex(index); _arrayProperty.DeleteArrayElementAtIndex(index);
} }
public void Move(int sourceIndex, int destIndex) { public void Move(int sourceIndex, int destIndex) {
if (destIndex > sourceIndex) if (destIndex > sourceIndex)
--destIndex; --destIndex;
_arrayProperty.MoveArrayElement(sourceIndex, destIndex); _arrayProperty.MoveArrayElement(sourceIndex, destIndex);
} }
public void Clear() { public void Clear() {
_arrayProperty.ClearArray(); _arrayProperty.ClearArray();
} }
public void BeginGUI() public void BeginGUI()
{} {}
public void EndGUI() public void EndGUI()
{} {}
public virtual void DrawItemBackground(Rect position, int index) { public virtual void DrawItemBackground(Rect position, int index) {
} }
public void DrawItem(Rect position, int index) public void DrawItem(Rect position, int index)
{ {
Variable variable = this[index].objectReferenceValue as Variable; Variable variable = this[index].objectReferenceValue as Variable;
if (variable == null) if (variable == null)
{ {
return; return;
} }
float[] widths = { 80, 100, 140, 60 }; float[] widths = { 80, 100, 140, 60 };
Rect[] rects = new Rect[4]; Rect[] rects = new Rect[4];
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
rects[i] = position; rects[i] = position;
rects[i].width = widths[i] - 5; rects[i].width = widths[i] - 5;
for (int j = 0; j < i; ++j) for (int j = 0; j < i; ++j)
{ {
rects[i].x += widths[j]; rects[i].x += widths[j];
} }
} }
VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(variable.GetType()); VariableInfoAttribute variableInfo = VariableEditor.GetVariableInfo(variable.GetType());
if (variableInfo == null) if (variableInfo == null)
{ {
return; return;
} }
Flowchart flowchart = FlowchartWindow.GetFlowchart(); Flowchart flowchart = FlowchartWindow.GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return; return;
} }
// Highlight if an active or selected command is referencing this variable // Highlight if an active or selected command is referencing this variable
bool highlight = false; bool highlight = false;
if (flowchart.selectedBlock != null) if (flowchart.selectedBlock != null)
{ {
if (Application.isPlaying && flowchart.selectedBlock.IsExecuting()) if (Application.isPlaying && flowchart.selectedBlock.IsExecuting())
{ {
highlight = flowchart.selectedBlock.activeCommand.HasReference(variable); highlight = flowchart.selectedBlock.activeCommand.HasReference(variable);
} }
else if (!Application.isPlaying && flowchart.selectedCommands.Count > 0) else if (!Application.isPlaying && flowchart.selectedCommands.Count > 0)
{ {
foreach (Command selectedCommand in flowchart.selectedCommands) foreach (Command selectedCommand in flowchart.selectedCommands)
{ {
if (selectedCommand == null) if (selectedCommand == null)
{ {
continue; continue;
} }
if (selectedCommand.HasReference(variable)) if (selectedCommand.HasReference(variable))
{ {
highlight = true; highlight = true;
break; break;
} }
} }
} }
} }
if (highlight) if (highlight)
{ {
GUI.backgroundColor = Color.green; GUI.backgroundColor = Color.green;
GUI.Box(position, ""); GUI.Box(position, "");
} }
string key = variable.key; string key = variable.key;
VariableScope scope = variable.scope; VariableScope scope = variable.scope;
// To access properties in a monobehavior, you have to new a SerializedObject // To access properties in a monobehavior, you have to new a SerializedObject
// http://answers.unity3d.com/questions/629803/findrelativeproperty-never-worked-for-me-how-does.html // http://answers.unity3d.com/questions/629803/findrelativeproperty-never-worked-for-me-how-does.html
SerializedObject variableObject = new SerializedObject(this[index].objectReferenceValue); SerializedObject variableObject = new SerializedObject(this[index].objectReferenceValue);
variableObject.Update(); variableObject.Update();
GUI.Label(rects[0], variableInfo.VariableType); GUI.Label(rects[0], variableInfo.VariableType);
key = EditorGUI.TextField(rects[1], variable.key); key = EditorGUI.TextField(rects[1], variable.key);
SerializedProperty keyProp = variableObject.FindProperty("key"); SerializedProperty keyProp = variableObject.FindProperty("key");
keyProp.stringValue = flowchart.GetUniqueVariableKey(key, variable); keyProp.stringValue = flowchart.GetUniqueVariableKey(key, variable);
SerializedProperty defaultProp = variableObject.FindProperty("value"); SerializedProperty defaultProp = variableObject.FindProperty("value");
EditorGUI.PropertyField(rects[2], defaultProp, new GUIContent("")); EditorGUI.PropertyField(rects[2], defaultProp, new GUIContent(""));
SerializedProperty scopeProp = variableObject.FindProperty("scope"); SerializedProperty scopeProp = variableObject.FindProperty("scope");
scope = (VariableScope)EditorGUI.EnumPopup(rects[3], variable.scope); scope = (VariableScope)EditorGUI.EnumPopup(rects[3], variable.scope);
scopeProp.enumValueIndex = (int)scope; scopeProp.enumValueIndex = (int)scope;
variableObject.ApplyModifiedProperties(); variableObject.ApplyModifiedProperties();
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
} }
public virtual float GetItemHeight(int index) { public virtual float GetItemHeight(int index) {
return fixedItemHeight != 0f return fixedItemHeight != 0f
? fixedItemHeight ? fixedItemHeight
: EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false) : EditorGUI.GetPropertyHeight(this[index], GUIContent.none, false)
; ;
} }
} }
} }

578
Assets/Fungus/Flowchart/Scripts/Block.cs

@ -11,149 +11,149 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[ExecuteInEditMode] [ExecuteInEditMode]
[RequireComponent(typeof(Flowchart))] [RequireComponent(typeof(Flowchart))]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Block : Node public class Block : Node
{ {
public enum ExecutionState public enum ExecutionState
{ {
Idle, Idle,
Executing, Executing,
} }
[NonSerialized] [NonSerialized]
public ExecutionState executionState; public ExecutionState executionState;
[HideInInspector] [HideInInspector]
public int itemId = -1; // Invalid flowchart item id public int itemId = -1; // Invalid flowchart item id
[FormerlySerializedAs("sequenceName")] [FormerlySerializedAs("sequenceName")]
[Tooltip("The name of the block node as displayed in the Flowchart window")] [Tooltip("The name of the block node as displayed in the Flowchart window")]
public string blockName = "New Block"; public string blockName = "New Block";
[TextArea(2, 5)] [TextArea(2, 5)]
[Tooltip("Description text to display under the block node")] [Tooltip("Description text to display under the block node")]
public string description = ""; public string description = "";
[Tooltip("An optional Event Handler which can execute the block when an event occurs")] [Tooltip("An optional Event Handler which can execute the block when an event occurs")]
public EventHandler eventHandler; public EventHandler eventHandler;
[HideInInspector] [HideInInspector]
[System.NonSerialized] [System.NonSerialized]
public Command activeCommand; public Command activeCommand;
// Index of last command executed before the current one // Index of last command executed before the current one
// -1 indicates no previous command // -1 indicates no previous command
[HideInInspector] [HideInInspector]
[System.NonSerialized] [System.NonSerialized]
public int previousActiveCommandIndex = -1; public int previousActiveCommandIndex = -1;
[HideInInspector] [HideInInspector]
[System.NonSerialized] [System.NonSerialized]
public float executingIconTimer; public float executingIconTimer;
[HideInInspector] [HideInInspector]
public List<Command> commandList = new List<Command>(); public List<Command> commandList = new List<Command>();
protected int executionCount; protected int executionCount;
/** /**
* Duration of fade for executing icon displayed beside blocks & commands. * Duration of fade for executing icon displayed beside blocks & commands.
*/ */
public const float executingIconFadeTime = 0.5f; public const float executingIconFadeTime = 0.5f;
/** /**
* Controls the next command to execute in the block execution coroutine. * Controls the next command to execute in the block execution coroutine.
*/ */
[NonSerialized] [NonSerialized]
public int jumpToCommandIndex = -1; public int jumpToCommandIndex = -1;
protected bool executionInfoSet = false; protected bool executionInfoSet = false;
protected virtual void Awake() protected virtual void Awake()
{ {
SetExecutionInfo(); SetExecutionInfo();
} }
protected virtual void SetExecutionInfo() protected virtual void SetExecutionInfo()
{ {
// Give each child command a reference back to its parent block // Give each child command a reference back to its parent block
// and tell each command its index in the list. // and tell each command its index in the list.
int index = 0; int index = 0;
foreach (Command command in commandList) foreach (Command command in commandList)
{ {
if (command == null) if (command == null)
{ {
continue; continue;
} }
command.parentBlock = this; command.parentBlock = this;
command.commandIndex = index++; command.commandIndex = index++;
} }
// Ensure all commands are at their correct indent level // Ensure all commands are at their correct indent level
// This should have already happened in the editor, but may be necessary // This should have already happened in the editor, but may be necessary
// if commands are added to the Block at runtime. // if commands are added to the Block at runtime.
UpdateIndentLevels(); UpdateIndentLevels();
executionInfoSet = true; executionInfoSet = true;
} }
#if UNITY_EDITOR #if UNITY_EDITOR
// The user can modify the command list order while playing in the editor, // The user can modify the command list order while playing in the editor,
// so we keep the command indices updated every frame. There's no need to // so we keep the command indices updated every frame. There's no need to
// do this in player builds so we compile this bit out for those builds. // do this in player builds so we compile this bit out for those builds.
void Update() void Update()
{ {
int index = 0; int index = 0;
foreach (Command command in commandList) foreach (Command command in commandList)
{ {
if (command == null) // Null entry will be deleted automatically later if (command == null) // Null entry will be deleted automatically later
{ {
continue; continue;
} }
command.commandIndex = index++; command.commandIndex = index++;
} }
} }
#endif #endif
public virtual Flowchart GetFlowchart() public virtual Flowchart GetFlowchart()
{ {
return GetComponent<Flowchart>(); return GetComponent<Flowchart>();
} }
public virtual bool HasError() public virtual bool HasError()
{ {
foreach (Command command in commandList) foreach (Command command in commandList)
{ {
if (command.errorMessage.Length > 0) if (command.errorMessage.Length > 0)
{ {
return true; return true;
} }
} }
return false; return false;
} }
public virtual bool IsExecuting() public virtual bool IsExecuting()
{ {
return (executionState == ExecutionState.Executing); return (executionState == ExecutionState.Executing);
} }
public virtual int GetExecutionCount() public virtual int GetExecutionCount()
{ {
return executionCount; return executionCount;
} }
/// <summary> /// <summary>
/// Start a coroutine which executes all commands in the Block. Only one running instance of each Block is permitted. /// Start a coroutine which executes all commands in the Block. Only one running instance of each Block is permitted.
/// </summary> /// </summary>
public virtual void StartExecution() public virtual void StartExecution()
{ {
StartCoroutine(Execute()); StartCoroutine(Execute());
} }
/// <summary> /// <summary>
/// A coroutine method that executes all commands in the Block. Only one running instance of each Block is permitted. /// A coroutine method that executes all commands in the Block. Only one running instance of each Block is permitted.
@ -161,7 +161,7 @@ namespace Fungus
/// <param name="commandIndex">Index of command to start execution at</param> /// <param name="commandIndex">Index of command to start execution at</param>
/// <param name="onComplete">Delegate function to call when execution completes</param> /// <param name="onComplete">Delegate function to call when execution completes</param>
public virtual IEnumerator Execute(int commandIndex = 0, Action onComplete = null) public virtual IEnumerator Execute(int commandIndex = 0, Action onComplete = null)
{ {
if (executionState != ExecutionState.Idle) if (executionState != ExecutionState.Idle)
{ {
yield break; yield break;
@ -174,162 +174,162 @@ namespace Fungus
executionCount++; executionCount++;
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
executionState = ExecutionState.Executing; executionState = ExecutionState.Executing;
#if UNITY_EDITOR #if UNITY_EDITOR
// Select the executing block & the first command // Select the executing block & the first command
flowchart.selectedBlock = this; flowchart.selectedBlock = this;
if (commandList.Count > 0) if (commandList.Count > 0)
{ {
flowchart.ClearSelectedCommands(); flowchart.ClearSelectedCommands();
flowchart.AddSelectedCommand(commandList[0]); flowchart.AddSelectedCommand(commandList[0]);
} }
#endif #endif
jumpToCommandIndex = commandIndex; jumpToCommandIndex = commandIndex;
int i = 0; int i = 0;
while (true) while (true)
{ {
// Executing commands specify the next command to skip to by setting jumpToCommandIndex using Command.Continue() // Executing commands specify the next command to skip to by setting jumpToCommandIndex using Command.Continue()
if (jumpToCommandIndex > -1) if (jumpToCommandIndex > -1)
{ {
i = jumpToCommandIndex; i = jumpToCommandIndex;
jumpToCommandIndex = -1; jumpToCommandIndex = -1;
} }
// Skip disabled commands, comments and labels // Skip disabled commands, comments and labels
while (i < commandList.Count && while (i < commandList.Count &&
(!commandList[i].enabled || (!commandList[i].enabled ||
commandList[i].GetType() == typeof(Comment) || commandList[i].GetType() == typeof(Comment) ||
commandList[i].GetType() == typeof(Label))) commandList[i].GetType() == typeof(Label)))
{ {
i = commandList[i].commandIndex + 1; i = commandList[i].commandIndex + 1;
} }
if (i >= commandList.Count) if (i >= commandList.Count)
{ {
break; break;
} }
// The previous active command is needed for if / else / else if commands // The previous active command is needed for if / else / else if commands
if (activeCommand == null) if (activeCommand == null)
{ {
previousActiveCommandIndex = -1; previousActiveCommandIndex = -1;
} }
else else
{ {
previousActiveCommandIndex = activeCommand.commandIndex; previousActiveCommandIndex = activeCommand.commandIndex;
} }
Command command = commandList[i]; Command command = commandList[i];
activeCommand = command; activeCommand = command;
if (flowchart.gameObject.activeInHierarchy) if (flowchart.gameObject.activeInHierarchy)
{ {
// Auto select a command in some situations // Auto select a command in some situations
if ((flowchart.selectedCommands.Count == 0 && i == 0) || if ((flowchart.selectedCommands.Count == 0 && i == 0) ||
(flowchart.selectedCommands.Count == 1 && flowchart.selectedCommands[0].commandIndex == previousActiveCommandIndex)) (flowchart.selectedCommands.Count == 1 && flowchart.selectedCommands[0].commandIndex == previousActiveCommandIndex))
{ {
flowchart.ClearSelectedCommands(); flowchart.ClearSelectedCommands();
flowchart.AddSelectedCommand(commandList[i]); flowchart.AddSelectedCommand(commandList[i]);
} }
} }
command.isExecuting = true; command.isExecuting = true;
// This icon timer is managed by the FlowchartWindow class, but we also need to // This icon timer is managed by the FlowchartWindow class, but we also need to
// set it here in case a command starts and finishes execution before the next window update. // set it here in case a command starts and finishes execution before the next window update.
command.executingIconTimer = Time.realtimeSinceStartup + executingIconFadeTime; command.executingIconTimer = Time.realtimeSinceStartup + executingIconFadeTime;
command.Execute(); command.Execute();
// Wait until the executing command sets another command to jump to via Command.Continue() // Wait until the executing command sets another command to jump to via Command.Continue()
while (jumpToCommandIndex == -1) while (jumpToCommandIndex == -1)
{ {
yield return null; yield return null;
} }
#if UNITY_EDITOR #if UNITY_EDITOR
if (flowchart.stepPause > 0f) if (flowchart.stepPause > 0f)
{ {
yield return new WaitForSeconds(flowchart.stepPause); yield return new WaitForSeconds(flowchart.stepPause);
} }
#endif #endif
command.isExecuting = false; command.isExecuting = false;
} }
executionState = ExecutionState.Idle; executionState = ExecutionState.Idle;
activeCommand = null; activeCommand = null;
if (onComplete != null) if (onComplete != null)
{ {
onComplete(); onComplete();
} }
} }
public virtual void Stop() public virtual void Stop()
{ {
// Tell the executing command to stop immediately // Tell the executing command to stop immediately
if (activeCommand != null) if (activeCommand != null)
{ {
activeCommand.isExecuting = false; activeCommand.isExecuting = false;
activeCommand.OnStopExecuting(); activeCommand.OnStopExecuting();
} }
// This will cause the execution loop to break on the next iteration // This will cause the execution loop to break on the next iteration
jumpToCommandIndex = int.MaxValue; jumpToCommandIndex = int.MaxValue;
} }
public virtual List<Block> GetConnectedBlocks() public virtual List<Block> GetConnectedBlocks()
{ {
List<Block> connectedBlocks = new List<Block>(); List<Block> connectedBlocks = new List<Block>();
foreach (Command command in commandList) foreach (Command command in commandList)
{ {
if (command != null) if (command != null)
{ {
command.GetConnectedBlocks(ref connectedBlocks); command.GetConnectedBlocks(ref connectedBlocks);
} }
} }
return connectedBlocks; return connectedBlocks;
} }
public virtual System.Type GetPreviousActiveCommandType() public virtual System.Type GetPreviousActiveCommandType()
{ {
if (previousActiveCommandIndex >= 0 && if (previousActiveCommandIndex >= 0 &&
previousActiveCommandIndex < commandList.Count) previousActiveCommandIndex < commandList.Count)
{ {
return commandList[previousActiveCommandIndex].GetType(); return commandList[previousActiveCommandIndex].GetType();
} }
return null; return null;
} }
public virtual void UpdateIndentLevels() public virtual void UpdateIndentLevels()
{ {
int indentLevel = 0; int indentLevel = 0;
foreach(Command command in commandList) foreach(Command command in commandList)
{ {
if (command == null) if (command == null)
{ {
continue; continue;
} }
if (command.CloseBlock()) if (command.CloseBlock())
{ {
indentLevel--; indentLevel--;
} }
// Negative indent level is not permitted // Negative indent level is not permitted
indentLevel = Math.Max(indentLevel, 0); indentLevel = Math.Max(indentLevel, 0);
command.indentLevel = indentLevel; command.indentLevel = indentLevel;
if (command.OpenBlock()) if (command.OpenBlock())
{ {
indentLevel++; indentLevel++;
} }
} }
} }
} }
} }

426
Assets/Fungus/Flowchart/Scripts/Command.cs

@ -12,218 +12,218 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
public class CommandInfoAttribute : Attribute public class CommandInfoAttribute : Attribute
{ {
/** /**
* Metadata atribute for the Command class. * Metadata atribute for the Command class.
* @param category The category to place this command in. * @param category The category to place this command in.
* @param commandName The display name of the command. * @param commandName The display name of the command.
* @param helpText Help information to display in the inspector. * @param helpText Help information to display in the inspector.
* @param priority If two command classes have the same name, the one with highest priority is listed. Negative priority removess the command from the list. * @param priority If two command classes have the same name, the one with highest priority is listed. Negative priority removess the command from the list.
*/ */
public CommandInfoAttribute(string category, string commandName, string helpText, int priority = 0) public CommandInfoAttribute(string category, string commandName, string helpText, int priority = 0)
{ {
this.Category = category; this.Category = category;
this.CommandName = commandName; this.CommandName = commandName;
this.HelpText = helpText; this.HelpText = helpText;
this.Priority = priority; this.Priority = priority;
} }
public string Category { get; set; } public string Category { get; set; }
public string CommandName { get; set; } public string CommandName { get; set; }
public string HelpText { get; set; } public string HelpText { get; set; }
public int Priority { get; set; } public int Priority { get; set; }
} }
public class Command : MonoBehaviour public class Command : MonoBehaviour
{ {
[FormerlySerializedAs("commandId")] [FormerlySerializedAs("commandId")]
[HideInInspector] [HideInInspector]
public int itemId = -1; // Invalid flowchart item id public int itemId = -1; // Invalid flowchart item id
[HideInInspector] [HideInInspector]
public string errorMessage = ""; public string errorMessage = "";
[HideInInspector] [HideInInspector]
public int indentLevel; public int indentLevel;
[NonSerialized] [NonSerialized]
public int commandIndex; public int commandIndex;
/** /**
* Set to true by the parent block while the command is executing. * Set to true by the parent block while the command is executing.
*/ */
[NonSerialized] [NonSerialized]
public bool isExecuting; public bool isExecuting;
/** /**
* Timer used to control appearance of executing icon in inspector. * Timer used to control appearance of executing icon in inspector.
*/ */
[NonSerialized] [NonSerialized]
public float executingIconTimer; public float executingIconTimer;
/** /**
* Reference to the Block object that this command belongs to. * Reference to the Block object that this command belongs to.
* This reference is only populated at runtime and in the editor when the * This reference is only populated at runtime and in the editor when the
* block is selected. * block is selected.
*/ */
[NonSerialized] [NonSerialized]
public Block parentBlock; public Block parentBlock;
public virtual Flowchart GetFlowchart() public virtual Flowchart GetFlowchart()
{ {
Flowchart flowchart = GetComponent<Flowchart>(); Flowchart flowchart = GetComponent<Flowchart>();
if (flowchart == null && if (flowchart == null &&
transform.parent != null) transform.parent != null)
{ {
flowchart = transform.parent.GetComponent<Flowchart>(); flowchart = transform.parent.GetComponent<Flowchart>();
} }
return flowchart; return flowchart;
} }
public virtual void Execute() public virtual void Execute()
{ {
OnEnter(); OnEnter();
} }
public virtual void Continue() public virtual void Continue()
{ {
// This is a noop if the Block has already been stopped // This is a noop if the Block has already been stopped
if (isExecuting) if (isExecuting)
{ {
Continue(commandIndex + 1); Continue(commandIndex + 1);
} }
} }
public virtual void Continue(int nextCommandIndex) public virtual void Continue(int nextCommandIndex)
{ {
OnExit(); OnExit();
if (parentBlock != null) if (parentBlock != null)
{ {
parentBlock.jumpToCommandIndex = nextCommandIndex; parentBlock.jumpToCommandIndex = nextCommandIndex;
} }
} }
public virtual void StopParentBlock() public virtual void StopParentBlock()
{ {
OnExit(); OnExit();
if (parentBlock != null) if (parentBlock != null)
{ {
parentBlock.Stop(); parentBlock.Stop();
} }
} }
/** /**
* Called when the parent block has been requested to stop executing, and * Called when the parent block has been requested to stop executing, and
* this command is the currently executing command. * this command is the currently executing command.
* Use this callback to terminate any asynchronous operations and * Use this callback to terminate any asynchronous operations and
* cleanup state so that the command is ready to execute again later on. * cleanup state so that the command is ready to execute again later on.
*/ */
public virtual void OnStopExecuting() public virtual void OnStopExecuting()
{} {}
/** /**
* Called when the new command is added to a block in the editor. * Called when the new command is added to a block in the editor.
*/ */
public virtual void OnCommandAdded(Block parentBlock) public virtual void OnCommandAdded(Block parentBlock)
{} {}
/** /**
* Called when the command is deleted from a block in the editor. * Called when the command is deleted from a block in the editor.
*/ */
public virtual void OnCommandRemoved(Block parentBlock) public virtual void OnCommandRemoved(Block parentBlock)
{} {}
public virtual void OnEnter() public virtual void OnEnter()
{} {}
public virtual void OnExit() public virtual void OnExit()
{} {}
public virtual void OnReset() public virtual void OnReset()
{} {}
public virtual void GetConnectedBlocks(ref List<Block> connectedBlocks) public virtual void GetConnectedBlocks(ref List<Block> connectedBlocks)
{} {}
public virtual bool HasReference(Variable variable) public virtual bool HasReference(Variable variable)
{ {
return false; return false;
} }
public virtual string GetSummary() public virtual string GetSummary()
{ {
return ""; return "";
} }
public virtual string GetHelpText() public virtual string GetHelpText()
{ {
return ""; return "";
} }
/** /**
* This command starts a block of commands. * This command starts a block of commands.
*/ */
public virtual bool OpenBlock() public virtual bool OpenBlock()
{ {
return false; return false;
} }
/** /**
* This command ends a block of commands. * This command ends a block of commands.
*/ */
public virtual bool CloseBlock() public virtual bool CloseBlock()
{ {
return false; return false;
} }
/** /**
* Return the color for the command background in inspector. * Return the color for the command background in inspector.
*/ */
public virtual Color GetButtonColor() public virtual Color GetButtonColor()
{ {
return Color.white; return Color.white;
} }
/** /**
* Returns true if the specified property should be displayed in the inspector. * Returns true if the specified property should be displayed in the inspector.
* This is useful for hiding certain properties based on the value of another property. * This is useful for hiding certain properties based on the value of another property.
*/ */
public virtual bool IsPropertyVisible(string propertyName) public virtual bool IsPropertyVisible(string propertyName)
{ {
return true; return true;
} }
/** /**
* Returns true if the specified property should be displayed as a reorderable list in the inspector. * Returns true if the specified property should be displayed as a reorderable list in the inspector.
* This only applies for array properties and has no effect for non-array properties. * This only applies for array properties and has no effect for non-array properties.
*/ */
public virtual bool IsReorderableArray(string propertyName) public virtual bool IsReorderableArray(string propertyName)
{ {
return false; return false;
} }
/** /**
* Returns the localization id for the Flowchart that contains this command. * Returns the localization id for the Flowchart that contains this command.
*/ */
public virtual string GetFlowchartLocalizationId() public virtual string GetFlowchartLocalizationId()
{ {
// If no localization id has been set then use the Flowchart name // If no localization id has been set then use the Flowchart name
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
if (flowchart == null) if (flowchart == null)
{ {
return ""; return "";
} }
string localizationId = GetFlowchart().localizationId; string localizationId = GetFlowchart().localizationId;
if (localizationId.Length == 0) if (localizationId.Length == 0)
{ {
localizationId = flowchart.name; localizationId = flowchart.name;
} }
return localizationId; return localizationId;
} }
} }
} }

102
Assets/Fungus/Flowchart/Scripts/CommandCopyBuffer.cs

@ -9,63 +9,63 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[AddComponentMenu("")] [AddComponentMenu("")]
public class CommandCopyBuffer : Block public class CommandCopyBuffer : Block
{ {
protected static CommandCopyBuffer instance; protected static CommandCopyBuffer instance;
/** /**
* Returns the CommandCopyBuffer singleton instance. * Returns the CommandCopyBuffer singleton instance.
* Will create a CommandCopyBuffer game object if none currently exists. * Will create a CommandCopyBuffer game object if none currently exists.
*/ */
static public CommandCopyBuffer GetInstance() static public CommandCopyBuffer GetInstance()
{ {
if (instance == null) if (instance == null)
{ {
// Static variables are not serialized (e.g. when playing in the editor) // Static variables are not serialized (e.g. when playing in the editor)
// We need to reaquire the static reference to the game object in this case // We need to reaquire the static reference to the game object in this case
GameObject go = GameObject.Find("_CommandCopyBuffer"); GameObject go = GameObject.Find("_CommandCopyBuffer");
if (go == null) if (go == null)
{ {
go = new GameObject("_CommandCopyBuffer"); go = new GameObject("_CommandCopyBuffer");
go.hideFlags = HideFlags.HideAndDontSave; go.hideFlags = HideFlags.HideAndDontSave;
} }
instance = go.GetComponent<CommandCopyBuffer>(); instance = go.GetComponent<CommandCopyBuffer>();
if (instance == null) if (instance == null)
{ {
instance = go.AddComponent<CommandCopyBuffer>(); instance = go.AddComponent<CommandCopyBuffer>();
} }
} }
return instance; return instance;
} }
protected virtual void Start() protected virtual void Start()
{ {
if (Application.isPlaying) if (Application.isPlaying)
{ {
Destroy(this.gameObject); Destroy(this.gameObject);
} }
} }
public virtual bool HasCommands() public virtual bool HasCommands()
{ {
return GetCommands().Length > 0; return GetCommands().Length > 0;
} }
public virtual Command[] GetCommands() public virtual Command[] GetCommands()
{ {
return GetComponents<Command>(); return GetComponents<Command>();
} }
public virtual void Clear() public virtual void Clear()
{ {
foreach (Command command in GetCommands()) foreach (Command command in GetCommands())
{ {
DestroyImmediate(command); DestroyImmediate(command);
} }
} }
} }
} }

110
Assets/Fungus/Flowchart/Scripts/Commands/Break.cs

@ -10,65 +10,65 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Break", "Break",
"Force a loop to terminate immediately.")] "Force a loop to terminate immediately.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Break : Command public class Break : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
// Find index of previous while command // Find index of previous while command
int whileIndex = -1; int whileIndex = -1;
int whileIndentLevel = -1; int whileIndentLevel = -1;
for (int i = commandIndex - 1; i >=0; --i) for (int i = commandIndex - 1; i >=0; --i)
{ {
While whileCommand = parentBlock.commandList[i] as While; While whileCommand = parentBlock.commandList[i] as While;
if (whileCommand != null) if (whileCommand != null)
{ {
whileIndex = i; whileIndex = i;
whileIndentLevel = whileCommand.indentLevel; whileIndentLevel = whileCommand.indentLevel;
break; break;
} }
} }
if (whileIndex == -1) if (whileIndex == -1)
{ {
// No enclosing While command found, just continue // No enclosing While command found, just continue
Continue(); Continue();
return; return;
} }
// Find matching End statement at same indent level as While // Find matching End statement at same indent level as While
for (int i = whileIndex + 1; i < parentBlock.commandList.Count; ++i) for (int i = whileIndex + 1; i < parentBlock.commandList.Count; ++i)
{ {
End endCommand = parentBlock.commandList[i] as End; End endCommand = parentBlock.commandList[i] as End;
if (endCommand != null && if (endCommand != null &&
endCommand.indentLevel == whileIndentLevel) endCommand.indentLevel == whileIndentLevel)
{ {
// Sanity check that break command is actually between the While and End commands // Sanity check that break command is actually between the While and End commands
if (commandIndex > whileIndex && commandIndex < endCommand.commandIndex) if (commandIndex > whileIndex && commandIndex < endCommand.commandIndex)
{ {
// Continue at next command after End // Continue at next command after End
Continue (endCommand.commandIndex + 1); Continue (endCommand.commandIndex + 1);
return; return;
} }
else else
{ {
break; break;
} }
} }
} }
// No matching End command found so just continue // No matching End command found so just continue
Continue(); Continue();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

236
Assets/Fungus/Flowchart/Scripts/Commands/Call.cs

@ -12,127 +12,127 @@ using System;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Call", "Call",
"Execute another block in the same Flowchart as the command, or in a different Flowchart.")] "Execute another block in the same Flowchart as the command, or in a different Flowchart.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Call : Command public class Call : Command
{ {
[Tooltip("Flowchart which contains the block to execute. If none is specified then the current Flowchart is used.")] [Tooltip("Flowchart which contains the block to execute. If none is specified then the current Flowchart is used.")]
public Flowchart targetFlowchart; public Flowchart targetFlowchart;
[FormerlySerializedAs("targetSequence")] [FormerlySerializedAs("targetSequence")]
[Tooltip("Block to start executing")] [Tooltip("Block to start executing")]
public Block targetBlock; public Block targetBlock;
[Tooltip("Command index to start executing")] [Tooltip("Command index to start executing")]
[FormerlySerializedAs("commandIndex")] [FormerlySerializedAs("commandIndex")]
public int startIndex; public int startIndex;
public enum CallMode public enum CallMode
{ {
Stop, // Stop executing the current block after calling Stop, // Stop executing the current block after calling
Continue, // Continue executing the current block after calling Continue, // Continue executing the current block after calling
WaitUntilFinished // Wait until the called block finishes executing, then continue executing current block WaitUntilFinished // Wait until the called block finishes executing, then continue executing current block
} }
[Tooltip("Select if the calling block should stop or continue executing commands, or wait until the called block finishes.")] [Tooltip("Select if the calling block should stop or continue executing commands, or wait until the called block finishes.")]
public CallMode callMode; public CallMode callMode;
public override void OnEnter() public override void OnEnter()
{ {
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
if (targetBlock != null) if (targetBlock != null)
{ {
// Check if calling your own parent block // Check if calling your own parent block
if (targetBlock == parentBlock) if (targetBlock == parentBlock)
{ {
// Just ignore the callmode in this case, and jump to first command in list // Just ignore the callmode in this case, and jump to first command in list
Continue(0); Continue(0);
return; return;
} }
// Callback action for Wait Until Finished mode // Callback action for Wait Until Finished mode
Action onComplete = null; Action onComplete = null;
if (callMode == CallMode.WaitUntilFinished) if (callMode == CallMode.WaitUntilFinished)
{ {
onComplete = delegate { onComplete = delegate {
flowchart.selectedBlock = parentBlock; flowchart.selectedBlock = parentBlock;
Continue(); Continue();
}; };
} }
if (targetFlowchart == null || if (targetFlowchart == null ||
targetFlowchart == GetFlowchart()) targetFlowchart == GetFlowchart())
{ {
// If the executing block is currently selected then follow the execution // If the executing block is currently selected then follow the execution
// onto the next block in the inspector. // onto the next block in the inspector.
if (flowchart.selectedBlock == parentBlock) if (flowchart.selectedBlock == parentBlock)
{ {
flowchart.selectedBlock = targetBlock; flowchart.selectedBlock = targetBlock;
} }
StartCoroutine(targetBlock.Execute(startIndex, onComplete)); StartCoroutine(targetBlock.Execute(startIndex, onComplete));
} }
else else
{ {
// Execute block in another Flowchart // Execute block in another Flowchart
targetFlowchart.ExecuteBlock(targetBlock, startIndex, onComplete); targetFlowchart.ExecuteBlock(targetBlock, startIndex, onComplete);
} }
} }
if (callMode == CallMode.Stop) if (callMode == CallMode.Stop)
{ {
StopParentBlock(); StopParentBlock();
} }
else if (callMode == CallMode.Continue) else if (callMode == CallMode.Continue)
{ {
Continue(); Continue();
} }
} }
public override void GetConnectedBlocks(ref List<Block> connectedBlocks) public override void GetConnectedBlocks(ref List<Block> connectedBlocks)
{ {
if (targetBlock != null) if (targetBlock != null)
{ {
connectedBlocks.Add(targetBlock); connectedBlocks.Add(targetBlock);
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
string summary = ""; string summary = "";
if (targetBlock == null) if (targetBlock == null)
{ {
summary = "<None>"; summary = "<None>";
} }
else else
{ {
summary = targetBlock.blockName; summary = targetBlock.blockName;
} }
switch (callMode) switch (callMode)
{ {
case CallMode.Stop: case CallMode.Stop:
summary += " : Stop"; summary += " : Stop";
break; break;
case CallMode.Continue: case CallMode.Continue:
summary += " : Continue"; summary += " : Continue";
break; break;
case CallMode.WaitUntilFinished: case CallMode.WaitUntilFinished:
summary += " : Wait"; summary += " : Wait";
break; break;
} }
return summary; return summary;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

106
Assets/Fungus/Flowchart/Scripts/Commands/CallMethod.cs

@ -8,69 +8,69 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
// This command is called "Call Method" because a) it's more descriptive than Send Message and we're already have // This command is called "Call Method" because a) it's more descriptive than Send Message and we're already have
// a Send Message command for sending messages to trigger block execution. // a Send Message command for sending messages to trigger block execution.
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Call Method", "Call Method",
"Calls a named method on a GameObject using the GameObject.SendMessage() system.")] "Calls a named method on a GameObject using the GameObject.SendMessage() system.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class CallMethod : Command public class CallMethod : Command
{ {
[Tooltip("Target monobehavior which contains the method we want to call")] [Tooltip("Target monobehavior which contains the method we want to call")]
public GameObject targetObject; public GameObject targetObject;
[Tooltip("Name of the method to call")] [Tooltip("Name of the method to call")]
public string methodName = ""; public string methodName = "";
[Tooltip("Delay (in seconds) before the method will be called")] [Tooltip("Delay (in seconds) before the method will be called")]
public float delay; public float delay;
public override void OnEnter() public override void OnEnter()
{ {
if (targetObject == null || if (targetObject == null ||
methodName.Length == 0) methodName.Length == 0)
{ {
Continue(); Continue();
return; return;
} }
if (delay == 0f) if (delay == 0f)
{ {
CallTheMethod(); CallTheMethod();
} }
else else
{ {
Invoke("CallTheMethod", delay); Invoke("CallTheMethod", delay);
} }
Continue(); Continue();
} }
protected virtual void CallTheMethod() protected virtual void CallTheMethod()
{ {
targetObject.SendMessage(methodName, SendMessageOptions.DontRequireReceiver); targetObject.SendMessage(methodName, SendMessageOptions.DontRequireReceiver);
} }
public override string GetSummary() public override string GetSummary()
{ {
if (targetObject == null) if (targetObject == null)
{ {
return "Error: No target GameObject specified"; return "Error: No target GameObject specified";
} }
if (methodName.Length == 0) if (methodName.Length == 0)
{ {
return "Error: No named method specified"; return "Error: No named method specified";
} }
return targetObject.name + " : " + methodName; return targetObject.name + " : " + methodName;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

56
Assets/Fungus/Flowchart/Scripts/Commands/Comment.cs

@ -9,37 +9,37 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("", [CommandInfo("",
"Comment", "Comment",
"Use comments to record design notes and reminders about your game.")] "Use comments to record design notes and reminders about your game.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Comment : Command public class Comment : Command
{ {
[Tooltip("Name of Commenter")] [Tooltip("Name of Commenter")]
public string commenterName = ""; public string commenterName = "";
[Tooltip("Text to display for this comment")] [Tooltip("Text to display for this comment")]
[TextArea(2,4)] [TextArea(2,4)]
public string commentText = ""; public string commentText = "";
public override void OnEnter() public override void OnEnter()
{ {
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (commenterName != "") if (commenterName != "")
{ {
return commenterName + ": " + commentText; return commenterName + ": " + commentText;
} }
return commentText; return commentText;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(220, 220, 220, 255); return new Color32(220, 220, 220, 255);
} }
} }
} }

82
Assets/Fungus/Flowchart/Scripts/Commands/Condition.cs

@ -9,49 +9,49 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
public enum CompareOperator public enum CompareOperator
{ {
Equals, // == Equals, // ==
NotEquals, // != NotEquals, // !=
LessThan, // < LessThan, // <
GreaterThan, // > GreaterThan, // >
LessThanOrEquals, // <= LessThanOrEquals, // <=
GreaterThanOrEquals // >= GreaterThanOrEquals // >=
} }
[AddComponentMenu("")] [AddComponentMenu("")]
public abstract class Condition : Command public abstract class Condition : Command
{ {
[Tooltip("The type of comparison to be performed")] [Tooltip("The type of comparison to be performed")]
public CompareOperator compareOperator; public CompareOperator compareOperator;
public static string GetOperatorDescription(CompareOperator compareOperator) public static string GetOperatorDescription(CompareOperator compareOperator)
{ {
string summary = ""; string summary = "";
switch (compareOperator) switch (compareOperator)
{ {
case CompareOperator.Equals: case CompareOperator.Equals:
summary += "=="; summary += "==";
break; break;
case CompareOperator.NotEquals: case CompareOperator.NotEquals:
summary += "!="; summary += "!=";
break; break;
case CompareOperator.LessThan: case CompareOperator.LessThan:
summary += "<"; summary += "<";
break; break;
case CompareOperator.GreaterThan: case CompareOperator.GreaterThan:
summary += ">"; summary += ">";
break; break;
case CompareOperator.LessThanOrEquals: case CompareOperator.LessThanOrEquals:
summary += "<="; summary += "<=";
break; break;
case CompareOperator.GreaterThanOrEquals: case CompareOperator.GreaterThanOrEquals:
summary += ">="; summary += ">=";
break; break;
} }
return summary; return summary;
} }
} }
} }

100
Assets/Fungus/Flowchart/Scripts/Commands/DebugLog.cs

@ -8,55 +8,55 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Debug Log", "Debug Log",
"Writes a log message to the debug console.")] "Writes a log message to the debug console.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class DebugLog : Command public class DebugLog : Command
{ {
public enum DebugLogType public enum DebugLogType
{ {
Info, Info,
Warning, Warning,
Error Error
} }
[Tooltip("Display type of debug log info")] [Tooltip("Display type of debug log info")]
public DebugLogType logType; public DebugLogType logType;
[Tooltip("Text to write to the debug log. Supports variable substitution, e.g. {$Myvar}")] [Tooltip("Text to write to the debug log. Supports variable substitution, e.g. {$Myvar}")]
public StringDataMulti logMessage; public StringDataMulti logMessage;
public override void OnEnter () public override void OnEnter ()
{ {
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
string message = flowchart.SubstituteVariables(logMessage.Value); string message = flowchart.SubstituteVariables(logMessage.Value);
switch (logType) switch (logType)
{ {
case DebugLogType.Info: case DebugLogType.Info:
Debug.Log(message); Debug.Log(message);
break; break;
case DebugLogType.Warning: case DebugLogType.Warning:
Debug.LogWarning(message); Debug.LogWarning(message);
break; break;
case DebugLogType.Error: case DebugLogType.Error:
Debug.LogError(message); Debug.LogError(message);
break; break;
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return logMessage.GetDescription(); return logMessage.GetDescription();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

84
Assets/Fungus/Flowchart/Scripts/Commands/DeleteSaveKey.cs

@ -9,47 +9,47 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Delete Save Key", "Delete Save Key",
"Deletes a saved value from permanent storage.")] "Deletes a saved value from permanent storage.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class DeleteSaveKey : Command public class DeleteSaveKey : Command
{ {
[Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")] [Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")]
public string key = ""; public string key = "";
public override void OnEnter() public override void OnEnter()
{ {
if (key == "") if (key == "")
{ {
Continue(); Continue();
return; return;
} }
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
// Prepend the current save profile (if any) // Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key); string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
PlayerPrefs.DeleteKey(prefsKey); PlayerPrefs.DeleteKey(prefsKey);
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (key.Length == 0) if (key.Length == 0)
{ {
return "Error: No stored value key selected"; return "Error: No stored value key selected";
} }
return key; return key;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

82
Assets/Fungus/Flowchart/Scripts/Commands/Destroy.cs

@ -10,55 +10,55 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Destroy", "Destroy",
"Destroys a specified game object in the scene.")] "Destroys a specified game object in the scene.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class Destroy : Command public class Destroy : Command
{ {
[Tooltip("Reference to game object to destroy")] [Tooltip("Reference to game object to destroy")]
public GameObjectData _targetGameObject; public GameObjectData _targetGameObject;
public override void OnEnter() public override void OnEnter()
{ {
if (_targetGameObject.Value != null) if (_targetGameObject.Value != null)
{ {
Destroy(_targetGameObject.Value); Destroy(_targetGameObject.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_targetGameObject.Value == null) if (_targetGameObject.Value == null)
{ {
return "Error: No game object selected"; return "Error: No game object selected";
} }
return _targetGameObject.Value.name; return _targetGameObject.Value.name;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("targetGameObject")] public GameObject targetGameObjectOLD; [HideInInspector] [FormerlySerializedAs("targetGameObject")] public GameObject targetGameObjectOLD;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (targetGameObjectOLD != null) if (targetGameObjectOLD != null)
{ {
_targetGameObject.Value = targetGameObjectOLD; _targetGameObject.Value = targetGameObjectOLD;
targetGameObjectOLD = null; targetGameObjectOLD = null;
} }
} }
#endregion #endregion
} }
} }

100
Assets/Fungus/Flowchart/Scripts/Commands/Else.cs

@ -9,62 +9,62 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Else", "Else",
"Marks the start of a command block to be executed when the preceding If statement is False.")] "Marks the start of a command block to be executed when the preceding If statement is False.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Else : Command public class Else : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
if (parentBlock == null) if (parentBlock == null)
{ {
return; return;
} }
// Stop if this is the last command in the list // Stop if this is the last command in the list
if (commandIndex >= parentBlock.commandList.Count - 1) if (commandIndex >= parentBlock.commandList.Count - 1)
{ {
StopParentBlock(); StopParentBlock();
return; return;
} }
// Find the next End command at the same indent level as this Else command // Find the next End command at the same indent level as this Else command
int indent = indentLevel; int indent = indentLevel;
for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i) for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i)
{ {
Command command = parentBlock.commandList[i]; Command command = parentBlock.commandList[i];
if (command.indentLevel == indent) if (command.indentLevel == indent)
{ {
System.Type type = command.GetType(); System.Type type = command.GetType();
if (type == typeof(End)) if (type == typeof(End))
{ {
// Execute command immediately after the EndIf command // Execute command immediately after the EndIf command
Continue(command.commandIndex + 1); Continue(command.commandIndex + 1);
return; return;
} }
} }
} }
// No End command found // No End command found
StopParentBlock(); StopParentBlock();
} }
public override bool OpenBlock() public override bool OpenBlock()
{ {
return true; return true;
} }
public override bool CloseBlock() public override bool CloseBlock()
{ {
return true; return true;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

116
Assets/Fungus/Flowchart/Scripts/Commands/ElseIf.cs

@ -11,72 +11,72 @@ using System;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Else If", "Else If",
"Marks the start of a command block to be executed when the preceding If statement is False and the test expression is true.")] "Marks the start of a command block to be executed when the preceding If statement is False and the test expression is true.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class ElseIf : If public class ElseIf : If
{ {
public override void OnEnter() public override void OnEnter()
{ {
System.Type previousCommandType = parentBlock.GetPreviousActiveCommandType(); System.Type previousCommandType = parentBlock.GetPreviousActiveCommandType();
if (previousCommandType == typeof(If) || if (previousCommandType == typeof(If) ||
previousCommandType == typeof(ElseIf) ) previousCommandType == typeof(ElseIf) )
{ {
// Else If behaves the same as an If command // Else If behaves the same as an If command
EvaluateAndContinue(); EvaluateAndContinue();
} }
else else
{ {
// Else If behaves mostly like an Else command, // Else If behaves mostly like an Else command,
// but will also jump to a following Else command. // but will also jump to a following Else command.
// Stop if this is the last command in the list // Stop if this is the last command in the list
if (commandIndex >= parentBlock.commandList.Count - 1) if (commandIndex >= parentBlock.commandList.Count - 1)
{ {
StopParentBlock(); StopParentBlock();
return; return;
} }
// Find the next End command at the same indent level as this Else If command // Find the next End command at the same indent level as this Else If command
int indent = indentLevel; int indent = indentLevel;
for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i) for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i)
{ {
Command command = parentBlock.commandList[i]; Command command = parentBlock.commandList[i];
if (command.indentLevel == indent) if (command.indentLevel == indent)
{ {
System.Type type = command.GetType(); System.Type type = command.GetType();
if (type == typeof(End)) if (type == typeof(End))
{ {
// Execute command immediately after the Else or End command // Execute command immediately after the Else or End command
Continue(command.commandIndex + 1); Continue(command.commandIndex + 1);
return; return;
} }
} }
} }
// No End command found // No End command found
StopParentBlock(); StopParentBlock();
} }
} }
public override bool OpenBlock() public override bool OpenBlock()
{ {
return true; return true;
} }
public override bool CloseBlock() public override bool CloseBlock()
{ {
return true; return true;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

66
Assets/Fungus/Flowchart/Scripts/Commands/End.cs

@ -10,42 +10,42 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"End", "End",
"Marks the end of a conditional block.")] "Marks the end of a conditional block.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class End : Command public class End : Command
{ {
[NonSerialized] [NonSerialized]
public bool loop = false; public bool loop = false;
public override void OnEnter() public override void OnEnter()
{ {
if (loop) if (loop)
{ {
for (int i = commandIndex - 1; i >= 0; --i) for (int i = commandIndex - 1; i >= 0; --i)
{ {
System.Type commandType = parentBlock.commandList[i].GetType(); System.Type commandType = parentBlock.commandList[i].GetType();
if (commandType == typeof(While)) if (commandType == typeof(While))
{ {
Continue(i); Continue(i);
return; return;
} }
} }
} }
Continue(); Continue();
} }
public override bool CloseBlock() public override bool CloseBlock()
{ {
return true; return true;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

380
Assets/Fungus/Flowchart/Scripts/Commands/If.cs

@ -10,195 +10,195 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"If", "If",
"If the test expression is true, execute the following command block.")] "If the test expression is true, execute the following command block.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class If : Condition public class If : Condition
{ {
[Tooltip("Variable to use in expression")] [Tooltip("Variable to use in expression")]
[VariableProperty(typeof(BooleanVariable), [VariableProperty(typeof(BooleanVariable),
typeof(IntegerVariable), typeof(IntegerVariable),
typeof(FloatVariable), typeof(FloatVariable),
typeof(StringVariable))] typeof(StringVariable))]
public Variable variable; public Variable variable;
[Tooltip("Boolean value to compare against")] [Tooltip("Boolean value to compare against")]
public BooleanData booleanData; public BooleanData booleanData;
[Tooltip("Integer value to compare against")] [Tooltip("Integer value to compare against")]
public IntegerData integerData; public IntegerData integerData;
[Tooltip("Float value to compare against")] [Tooltip("Float value to compare against")]
public FloatData floatData; public FloatData floatData;
[Tooltip("String value to compare against")] [Tooltip("String value to compare against")]
public StringDataMulti stringData; public StringDataMulti stringData;
public override void OnEnter() public override void OnEnter()
{ {
if (parentBlock == null) if (parentBlock == null)
{ {
return; return;
} }
if (variable == null) if (variable == null)
{ {
Continue(); Continue();
return; return;
} }
EvaluateAndContinue(); EvaluateAndContinue();
} }
public bool EvaluateCondition() public bool EvaluateCondition()
{ {
BooleanVariable booleanVariable = variable as BooleanVariable; BooleanVariable booleanVariable = variable as BooleanVariable;
IntegerVariable integerVariable = variable as IntegerVariable; IntegerVariable integerVariable = variable as IntegerVariable;
FloatVariable floatVariable = variable as FloatVariable; FloatVariable floatVariable = variable as FloatVariable;
StringVariable stringVariable = variable as StringVariable; StringVariable stringVariable = variable as StringVariable;
bool condition = false; bool condition = false;
if (booleanVariable != null) if (booleanVariable != null)
{ {
condition = booleanVariable.Evaluate(compareOperator, booleanData.Value); condition = booleanVariable.Evaluate(compareOperator, booleanData.Value);
} }
else if (integerVariable != null) else if (integerVariable != null)
{ {
condition = integerVariable.Evaluate(compareOperator, integerData.Value); condition = integerVariable.Evaluate(compareOperator, integerData.Value);
} }
else if (floatVariable != null) else if (floatVariable != null)
{ {
condition = floatVariable.Evaluate(compareOperator, floatData.Value); condition = floatVariable.Evaluate(compareOperator, floatData.Value);
} }
else if (stringVariable != null) else if (stringVariable != null)
{ {
condition = stringVariable.Evaluate(compareOperator, stringData.Value); condition = stringVariable.Evaluate(compareOperator, stringData.Value);
} }
return condition; return condition;
} }
protected void EvaluateAndContinue() protected void EvaluateAndContinue()
{ {
if (EvaluateCondition()) if (EvaluateCondition())
{ {
OnTrue(); OnTrue();
} }
else else
{ {
OnFalse(); OnFalse();
} }
} }
protected virtual void OnTrue() protected virtual void OnTrue()
{ {
Continue(); Continue();
} }
protected virtual void OnFalse() protected virtual void OnFalse()
{ {
// Last command in block // Last command in block
if (commandIndex >= parentBlock.commandList.Count) if (commandIndex >= parentBlock.commandList.Count)
{ {
StopParentBlock(); StopParentBlock();
return; return;
} }
// Find the next Else, ElseIf or End command at the same indent level as this If command // Find the next Else, ElseIf or End command at the same indent level as this If command
for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i) for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i)
{ {
Command nextCommand = parentBlock.commandList[i]; Command nextCommand = parentBlock.commandList[i];
if (nextCommand == null) if (nextCommand == null)
{ {
continue; continue;
} }
// Find next command at same indent level as this If command // Find next command at same indent level as this If command
// Skip disabled commands, comments & labels // Skip disabled commands, comments & labels
if (!nextCommand.enabled || if (!nextCommand.enabled ||
nextCommand.GetType() == typeof(Comment) || nextCommand.GetType() == typeof(Comment) ||
nextCommand.GetType() == typeof(Label) || nextCommand.GetType() == typeof(Label) ||
nextCommand.indentLevel != indentLevel) nextCommand.indentLevel != indentLevel)
{ {
continue; continue;
} }
System.Type type = nextCommand.GetType(); System.Type type = nextCommand.GetType();
if (type == typeof(Else) || if (type == typeof(Else) ||
type == typeof(End)) type == typeof(End))
{ {
if (i >= parentBlock.commandList.Count - 1) if (i >= parentBlock.commandList.Count - 1)
{ {
// Last command in Block, so stop // Last command in Block, so stop
StopParentBlock(); StopParentBlock();
} }
else else
{ {
// Execute command immediately after the Else or End command // Execute command immediately after the Else or End command
Continue(nextCommand.commandIndex + 1); Continue(nextCommand.commandIndex + 1);
return; return;
} }
} }
else if (type == typeof(ElseIf)) else if (type == typeof(ElseIf))
{ {
// Execute the Else If command // Execute the Else If command
Continue(i); Continue(i);
return; return;
} }
} }
// No matching End command found, so just stop the block // No matching End command found, so just stop the block
StopParentBlock(); StopParentBlock();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (variable == null) if (variable == null)
{ {
return "Error: No variable selected"; return "Error: No variable selected";
} }
string summary = variable.key + " "; string summary = variable.key + " ";
summary += Condition.GetOperatorDescription(compareOperator) + " "; summary += Condition.GetOperatorDescription(compareOperator) + " ";
if (variable.GetType() == typeof(BooleanVariable)) if (variable.GetType() == typeof(BooleanVariable))
{ {
summary += booleanData.GetDescription(); summary += booleanData.GetDescription();
} }
else if (variable.GetType() == typeof(IntegerVariable)) else if (variable.GetType() == typeof(IntegerVariable))
{ {
summary += integerData.GetDescription(); summary += integerData.GetDescription();
} }
else if (variable.GetType() == typeof(FloatVariable)) else if (variable.GetType() == typeof(FloatVariable))
{ {
summary += floatData.GetDescription(); summary += floatData.GetDescription();
} }
else if (variable.GetType() == typeof(StringVariable)) else if (variable.GetType() == typeof(StringVariable))
{ {
summary += stringData.GetDescription(); summary += stringData.GetDescription();
} }
return summary; return summary;
} }
public override bool HasReference(Variable variable) public override bool HasReference(Variable variable)
{ {
return (variable == this.variable); return (variable == this.variable);
} }
public override bool OpenBlock() public override bool OpenBlock()
{ {
return true; return true;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

250
Assets/Fungus/Flowchart/Scripts/Commands/InvokeEvent.cs

@ -10,130 +10,130 @@ using UnityEngine.Events;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Invoke Event", "Invoke Event",
"Calls a list of component methods via the Unity Event System (as used in the Unity UI). " + "Calls a list of component methods via the Unity Event System (as used in the Unity UI). " +
"This command is more efficient than the Invoke Method command but can only pass a single parameter and doesn't support return values.")] "This command is more efficient than the Invoke Method command but can only pass a single parameter and doesn't support return values.")]
[AddComponentMenu("")] [AddComponentMenu("")]
// This command uses the UnityEvent system to call methods in script. // This command uses the UnityEvent system to call methods in script.
// http://docs.unity3d.com/Manual/UnityEvents.html // http://docs.unity3d.com/Manual/UnityEvents.html
public class InvokeEvent : Command public class InvokeEvent : Command
{ {
[Serializable] public class BooleanEvent : UnityEvent<bool> {} [Serializable] public class BooleanEvent : UnityEvent<bool> {}
[Serializable] public class IntegerEvent : UnityEvent<int> {} [Serializable] public class IntegerEvent : UnityEvent<int> {}
[Serializable] public class FloatEvent : UnityEvent<float> {} [Serializable] public class FloatEvent : UnityEvent<float> {}
[Serializable] public class StringEvent : UnityEvent<string> {} [Serializable] public class StringEvent : UnityEvent<string> {}
public enum InvokeType public enum InvokeType
{ {
Static, // Call a method with an optional constant value parameter Static, // Call a method with an optional constant value parameter
DynamicBoolean, // Call a method with an optional boolean constant / variable parameter DynamicBoolean, // Call a method with an optional boolean constant / variable parameter
DynamicInteger, // Call a method with an optional integer constant / variable parameter DynamicInteger, // Call a method with an optional integer constant / variable parameter
DynamicFloat, // Call a method with an optional float constant / variable parameter DynamicFloat, // Call a method with an optional float constant / variable parameter
DynamicString // Call a method with an optional string constant / variable parameter DynamicString // Call a method with an optional string constant / variable parameter
} }
[Tooltip("Delay (in seconds) before the methods will be called")] [Tooltip("Delay (in seconds) before the methods will be called")]
public float delay; public float delay;
public InvokeType invokeType; public InvokeType invokeType;
[Tooltip("List of methods to call. Supports methods with no parameters or exactly one string, int, float or object parameter.")] [Tooltip("List of methods to call. Supports methods with no parameters or exactly one string, int, float or object parameter.")]
public UnityEvent staticEvent = new UnityEvent(); public UnityEvent staticEvent = new UnityEvent();
[Tooltip("Boolean parameter to pass to the invoked methods.")] [Tooltip("Boolean parameter to pass to the invoked methods.")]
public BooleanData booleanParameter; public BooleanData booleanParameter;
[Tooltip("List of methods to call. Supports methods with one boolean parameter.")] [Tooltip("List of methods to call. Supports methods with one boolean parameter.")]
public BooleanEvent booleanEvent = new BooleanEvent(); public BooleanEvent booleanEvent = new BooleanEvent();
[Tooltip("Integer parameter to pass to the invoked methods.")] [Tooltip("Integer parameter to pass to the invoked methods.")]
public IntegerData integerParameter; public IntegerData integerParameter;
[Tooltip("List of methods to call. Supports methods with one integer parameter.")] [Tooltip("List of methods to call. Supports methods with one integer parameter.")]
public IntegerEvent integerEvent = new IntegerEvent(); public IntegerEvent integerEvent = new IntegerEvent();
[Tooltip("Float parameter to pass to the invoked methods.")] [Tooltip("Float parameter to pass to the invoked methods.")]
public FloatData floatParameter; public FloatData floatParameter;
[Tooltip("List of methods to call. Supports methods with one float parameter.")] [Tooltip("List of methods to call. Supports methods with one float parameter.")]
public FloatEvent floatEvent = new FloatEvent(); public FloatEvent floatEvent = new FloatEvent();
[Tooltip("String parameter to pass to the invoked methods.")] [Tooltip("String parameter to pass to the invoked methods.")]
public StringDataMulti stringParameter; public StringDataMulti stringParameter;
[Tooltip("List of methods to call. Supports methods with one string parameter.")] [Tooltip("List of methods to call. Supports methods with one string parameter.")]
public StringEvent stringEvent = new StringEvent(); public StringEvent stringEvent = new StringEvent();
public override void OnEnter() public override void OnEnter()
{ {
if (delay == 0f) if (delay == 0f)
{ {
DoInvoke(); DoInvoke();
} }
else else
{ {
Invoke("DoInvoke", delay); Invoke("DoInvoke", delay);
} }
Continue(); Continue();
} }
protected virtual void DoInvoke() protected virtual void DoInvoke()
{ {
switch (invokeType) switch (invokeType)
{ {
default: default:
case InvokeType.Static: case InvokeType.Static:
staticEvent.Invoke(); staticEvent.Invoke();
break; break;
case InvokeType.DynamicBoolean: case InvokeType.DynamicBoolean:
booleanEvent.Invoke(booleanParameter); booleanEvent.Invoke(booleanParameter);
break; break;
case InvokeType.DynamicInteger: case InvokeType.DynamicInteger:
integerEvent.Invoke(integerParameter); integerEvent.Invoke(integerParameter);
break; break;
case InvokeType.DynamicFloat: case InvokeType.DynamicFloat:
floatEvent.Invoke(floatParameter); floatEvent.Invoke(floatParameter);
break; break;
case InvokeType.DynamicString: case InvokeType.DynamicString:
stringEvent.Invoke(stringParameter); stringEvent.Invoke(stringParameter);
break; break;
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
string summary = invokeType.ToString() + " "; string summary = invokeType.ToString() + " ";
switch (invokeType) switch (invokeType)
{ {
default: default:
case InvokeType.Static: case InvokeType.Static:
summary += staticEvent.GetPersistentEventCount(); summary += staticEvent.GetPersistentEventCount();
break; break;
case InvokeType.DynamicBoolean: case InvokeType.DynamicBoolean:
summary += booleanEvent.GetPersistentEventCount(); summary += booleanEvent.GetPersistentEventCount();
break; break;
case InvokeType.DynamicInteger: case InvokeType.DynamicInteger:
summary += integerEvent.GetPersistentEventCount(); summary += integerEvent.GetPersistentEventCount();
break; break;
case InvokeType.DynamicFloat: case InvokeType.DynamicFloat:
summary += floatEvent.GetPersistentEventCount(); summary += floatEvent.GetPersistentEventCount();
break; break;
case InvokeType.DynamicString: case InvokeType.DynamicString:
summary += stringEvent.GetPersistentEventCount(); summary += stringEvent.GetPersistentEventCount();
break; break;
} }
return summary + " methods"; return summary + " methods";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

714
Assets/Fungus/Flowchart/Scripts/Commands/InvokeMethod.cs

@ -15,187 +15,187 @@ using MarkerMetro.Unity.WinLegacy.Reflection;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Invoke Method", "Invoke Method",
"Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")] "Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")]
public class InvokeMethod : Command public class InvokeMethod : Command
{ {
[Tooltip("GameObject containing the component method to be invoked")] [Tooltip("GameObject containing the component method to be invoked")]
public GameObject targetObject; public GameObject targetObject;
[HideInInspector] [HideInInspector]
[Tooltip("Name of assembly containing the target component")] [Tooltip("Name of assembly containing the target component")]
public string targetComponentAssemblyName; public string targetComponentAssemblyName;
[HideInInspector] [HideInInspector]
[Tooltip("Full name of the target component")] [Tooltip("Full name of the target component")]
public string targetComponentFullname; public string targetComponentFullname;
[HideInInspector] [HideInInspector]
[Tooltip("Display name of the target component")] [Tooltip("Display name of the target component")]
public string targetComponentText; public string targetComponentText;
[HideInInspector] [HideInInspector]
[Tooltip("Name of target method to invoke on the target component")] [Tooltip("Name of target method to invoke on the target component")]
public string targetMethod; public string targetMethod;
[HideInInspector] [HideInInspector]
[Tooltip("Display name of target method to invoke on the target component")] [Tooltip("Display name of target method to invoke on the target component")]
public string targetMethodText; public string targetMethodText;
[HideInInspector] [HideInInspector]
[Tooltip("List of parameters to pass to the invoked method")] [Tooltip("List of parameters to pass to the invoked method")]
public InvokeMethodParameter[] methodParameters; public InvokeMethodParameter[] methodParameters;
[HideInInspector] [HideInInspector]
[Tooltip("If true, store the return value in a flowchart variable of the same type.")] [Tooltip("If true, store the return value in a flowchart variable of the same type.")]
public bool saveReturnValue; public bool saveReturnValue;
[HideInInspector] [HideInInspector]
[Tooltip("Name of Fungus variable to store the return value in")] [Tooltip("Name of Fungus variable to store the return value in")]
public string returnValueVariableKey; public string returnValueVariableKey;
[HideInInspector] [HideInInspector]
[Tooltip("The type of the return value")] [Tooltip("The type of the return value")]
public string returnValueType; public string returnValueType;
[HideInInspector] [HideInInspector]
[Tooltip("If true, list all inherited methods for the component")] [Tooltip("If true, list all inherited methods for the component")]
public bool showInherited; public bool showInherited;
[HideInInspector] [HideInInspector]
[Tooltip("The coroutine call behavior for methods that return IEnumerator")] [Tooltip("The coroutine call behavior for methods that return IEnumerator")]
public Fungus.Call.CallMode callMode; public Fungus.Call.CallMode callMode;
protected Type componentType; protected Type componentType;
protected Component objComponent; protected Component objComponent;
protected Type[] parameterTypes = null; protected Type[] parameterTypes = null;
protected MethodInfo objMethod; protected MethodInfo objMethod;
protected virtual void Awake() protected virtual void Awake()
{ {
if (componentType == null) if (componentType == null)
{ {
componentType = ReflectionHelper.GetType(targetComponentAssemblyName); componentType = ReflectionHelper.GetType(targetComponentAssemblyName);
} }
if (objComponent == null) if (objComponent == null)
{ {
objComponent = targetObject.GetComponent(componentType); objComponent = targetObject.GetComponent(componentType);
} }
if (parameterTypes == null) if (parameterTypes == null)
{ {
parameterTypes = GetParameterTypes(); parameterTypes = GetParameterTypes();
} }
if (objMethod == null) if (objMethod == null)
{ {
objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes); objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes);
} }
} }
public override void OnEnter() public override void OnEnter()
{ {
try try
{ {
if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod)) if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod))
{ {
Continue(); Continue();
return; return;
} }
if (returnValueType != "System.Collections.IEnumerator") if (returnValueType != "System.Collections.IEnumerator")
{ {
var objReturnValue = objMethod.Invoke(objComponent, GetParameterValues()); var objReturnValue = objMethod.Invoke(objComponent, GetParameterValues());
if (saveReturnValue) if (saveReturnValue)
{ {
SetVariable(returnValueVariableKey, objReturnValue, returnValueType); SetVariable(returnValueVariableKey, objReturnValue, returnValueType);
} }
Continue(); Continue();
} }
else else
{ {
StartCoroutine(ExecuteCoroutine()); StartCoroutine(ExecuteCoroutine());
if (callMode == Call.CallMode.Continue) if (callMode == Call.CallMode.Continue)
{ {
Continue(); Continue();
} }
else if(callMode == Call.CallMode.Stop) else if(callMode == Call.CallMode.Stop)
{ {
StopParentBlock(); StopParentBlock();
} }
} }
} }
catch (System.Exception ex) catch (System.Exception ex)
{ {
Debug.LogError("Error: " + ex.Message); Debug.LogError("Error: " + ex.Message);
} }
} }
protected virtual IEnumerator ExecuteCoroutine() protected virtual IEnumerator ExecuteCoroutine()
{ {
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues())); yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
if (callMode == Call.CallMode.WaitUntilFinished) if (callMode == Call.CallMode.WaitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
public override string GetSummary() public override string GetSummary()
{ {
if (targetObject == null) if (targetObject == null)
{ {
return "Error: targetObject is not assigned"; return "Error: targetObject is not assigned";
} }
return targetObject.name + "." + targetComponentText + "." + targetMethodText; return targetObject.name + "." + targetComponentText + "." + targetMethodText;
} }
protected System.Type[] GetParameterTypes() protected System.Type[] GetParameterTypes()
{ {
System.Type[] types = new System.Type[methodParameters.Length]; System.Type[] types = new System.Type[methodParameters.Length];
for (int i = 0; i < methodParameters.Length; i++) for (int i = 0; i < methodParameters.Length; i++)
{ {
var item = methodParameters[i]; var item = methodParameters[i];
var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname); var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname);
types[i] = objType; types[i] = objType;
} }
return types; return types;
} }
protected object[] GetParameterValues() protected object[] GetParameterValues()
{ {
object[] values = new object[methodParameters.Length]; object[] values = new object[methodParameters.Length];
var flowChart = GetFlowchart(); var flowChart = GetFlowchart();
for (int i = 0; i < methodParameters.Length; i++) for (int i = 0; i < methodParameters.Length; i++)
{ {
var item = methodParameters[i]; var item = methodParameters[i];
if (string.IsNullOrEmpty(item.variableKey)) if (string.IsNullOrEmpty(item.variableKey))
{ {
values[i] = item.objValue.GetValue(); values[i] = item.objValue.GetValue();
} }
else else
{ {
object objValue = null; object objValue = null;
switch (item.objValue.typeFullname) switch (item.objValue.typeFullname)
{ {
case "System.Int32": case "System.Int32":
var intvalue = flowChart.GetVariable<IntegerVariable>(item.variableKey); var intvalue = flowChart.GetVariable<IntegerVariable>(item.variableKey);
if (intvalue != null) if (intvalue != null)
objValue = intvalue.value; objValue = intvalue.value;
@ -205,7 +205,7 @@ namespace Fungus
if (boolean != null) if (boolean != null)
objValue = boolean.value; objValue = boolean.value;
break; break;
case "System.Single": case "System.Single":
var floatvalue = flowChart.GetVariable<FloatVariable>(item.variableKey); var floatvalue = flowChart.GetVariable<FloatVariable>(item.variableKey);
if (floatvalue != null) if (floatvalue != null)
objValue = floatvalue.value; objValue = floatvalue.value;
@ -216,187 +216,187 @@ namespace Fungus
objValue = stringvalue.value; objValue = stringvalue.value;
break; break;
case "UnityEngine.Color": case "UnityEngine.Color":
var color = flowChart.GetVariable<ColorVariable>(item.variableKey); var color = flowChart.GetVariable<ColorVariable>(item.variableKey);
if (color != null) if (color != null)
objValue = color.value; objValue = color.value;
break; break;
case "UnityEngine.GameObject": case "UnityEngine.GameObject":
var gameObject = flowChart.GetVariable<GameObjectVariable>(item.variableKey); var gameObject = flowChart.GetVariable<GameObjectVariable>(item.variableKey);
if (gameObject != null) if (gameObject != null)
objValue = gameObject.value; objValue = gameObject.value;
break; break;
case "UnityEngine.Material": case "UnityEngine.Material":
var material = flowChart.GetVariable<MaterialVariable>(item.variableKey); var material = flowChart.GetVariable<MaterialVariable>(item.variableKey);
if (material != null) if (material != null)
objValue = material.value; objValue = material.value;
break; break;
case "UnityEngine.Sprite": case "UnityEngine.Sprite":
var sprite = flowChart.GetVariable<SpriteVariable>(item.variableKey); var sprite = flowChart.GetVariable<SpriteVariable>(item.variableKey);
if (sprite != null) if (sprite != null)
objValue = sprite.value; objValue = sprite.value;
break; break;
case "UnityEngine.Texture": case "UnityEngine.Texture":
var texture = flowChart.GetVariable<TextureVariable>(item.variableKey); var texture = flowChart.GetVariable<TextureVariable>(item.variableKey);
if (texture != null) if (texture != null)
objValue = texture.value; objValue = texture.value;
break; break;
case "UnityEngine.Vector2": case "UnityEngine.Vector2":
var vector2 = flowChart.GetVariable<Vector2Variable>(item.variableKey); var vector2 = flowChart.GetVariable<Vector2Variable>(item.variableKey);
if (vector2 != null) if (vector2 != null)
objValue = vector2.value; objValue = vector2.value;
break; break;
case "UnityEngine.Vector3": case "UnityEngine.Vector3":
var vector3 = flowChart.GetVariable<Vector3Variable>(item.variableKey); var vector3 = flowChart.GetVariable<Vector3Variable>(item.variableKey);
if (vector3 != null) if (vector3 != null)
objValue = vector3.value; objValue = vector3.value;
break; break;
default: default:
var obj = flowChart.GetVariable<ObjectVariable>(item.variableKey); var obj = flowChart.GetVariable<ObjectVariable>(item.variableKey);
if (obj != null) if (obj != null)
objValue = obj.value; objValue = obj.value;
break; break;
} }
values[i] = objValue; values[i] = objValue;
} }
} }
return values; return values;
} }
protected void SetVariable(string key, object value, string returnType) protected void SetVariable(string key, object value, string returnType)
{ {
var flowChart = GetFlowchart(); var flowChart = GetFlowchart();
switch (returnType) switch (returnType)
{ {
case "System.Int32": case "System.Int32":
flowChart.GetVariable<IntegerVariable>(key).value = (int)value; flowChart.GetVariable<IntegerVariable>(key).value = (int)value;
break; break;
case "System.Boolean": case "System.Boolean":
flowChart.GetVariable<BooleanVariable>(key).value = (bool)value; flowChart.GetVariable<BooleanVariable>(key).value = (bool)value;
break; break;
case "System.Single": case "System.Single":
flowChart.GetVariable<FloatVariable>(key).value = (float)value; flowChart.GetVariable<FloatVariable>(key).value = (float)value;
break; break;
case "System.String": case "System.String":
flowChart.GetVariable<StringVariable>(key).value = (string)value; flowChart.GetVariable<StringVariable>(key).value = (string)value;
break; break;
case "UnityEngine.Color": case "UnityEngine.Color":
flowChart.GetVariable<ColorVariable>(key).value = (UnityEngine.Color)value; flowChart.GetVariable<ColorVariable>(key).value = (UnityEngine.Color)value;
break; break;
case "UnityEngine.GameObject": case "UnityEngine.GameObject":
flowChart.GetVariable<GameObjectVariable>(key).value = (UnityEngine.GameObject)value; flowChart.GetVariable<GameObjectVariable>(key).value = (UnityEngine.GameObject)value;
break; break;
case "UnityEngine.Material": case "UnityEngine.Material":
flowChart.GetVariable<MaterialVariable>(key).value = (UnityEngine.Material)value; flowChart.GetVariable<MaterialVariable>(key).value = (UnityEngine.Material)value;
break; break;
case "UnityEngine.Sprite": case "UnityEngine.Sprite":
flowChart.GetVariable<SpriteVariable>(key).value = (UnityEngine.Sprite)value; flowChart.GetVariable<SpriteVariable>(key).value = (UnityEngine.Sprite)value;
break; break;
case "UnityEngine.Texture": case "UnityEngine.Texture":
flowChart.GetVariable<TextureVariable>(key).value = (UnityEngine.Texture)value; flowChart.GetVariable<TextureVariable>(key).value = (UnityEngine.Texture)value;
break; break;
case "UnityEngine.Vector2": case "UnityEngine.Vector2":
flowChart.GetVariable<Vector2Variable>(key).value = (UnityEngine.Vector2)value; flowChart.GetVariable<Vector2Variable>(key).value = (UnityEngine.Vector2)value;
break; break;
case "UnityEngine.Vector3": case "UnityEngine.Vector3":
flowChart.GetVariable<Vector3Variable>(key).value = (UnityEngine.Vector3)value; flowChart.GetVariable<Vector3Variable>(key).value = (UnityEngine.Vector3)value;
break; break;
default: default:
flowChart.GetVariable<ObjectVariable>(key).value = (UnityEngine.Object)value; flowChart.GetVariable<ObjectVariable>(key).value = (UnityEngine.Object)value;
break; break;
} }
} }
} }
[System.Serializable] [System.Serializable]
public class InvokeMethodParameter public class InvokeMethodParameter
{ {
[SerializeField] [SerializeField]
public ObjectValue objValue; public ObjectValue objValue;
[SerializeField] [SerializeField]
public string variableKey; public string variableKey;
} }
[System.Serializable] [System.Serializable]
public class ObjectValue public class ObjectValue
{ {
public string typeAssemblyname; public string typeAssemblyname;
public string typeFullname; public string typeFullname;
public int intValue; public int intValue;
public bool boolValue; public bool boolValue;
public float floatValue; public float floatValue;
public string stringValue; public string stringValue;
public Color colorValue; public Color colorValue;
public GameObject gameObjectValue; public GameObject gameObjectValue;
public Material materialValue; public Material materialValue;
public UnityEngine.Object objectValue; public UnityEngine.Object objectValue;
public Sprite spriteValue; public Sprite spriteValue;
public Texture textureValue; public Texture textureValue;
public Vector2 vector2Value; public Vector2 vector2Value;
public Vector3 vector3Value; public Vector3 vector3Value;
public object GetValue() public object GetValue()
{ {
switch (typeFullname) switch (typeFullname)
{ {
case "System.Int32": case "System.Int32":
return intValue; return intValue;
case "System.Boolean": case "System.Boolean":
return boolValue; return boolValue;
case "System.Single": case "System.Single":
return floatValue; return floatValue;
case "System.String": case "System.String":
return stringValue; return stringValue;
case "UnityEngine.Color": case "UnityEngine.Color":
return colorValue; return colorValue;
case "UnityEngine.GameObject": case "UnityEngine.GameObject":
return gameObjectValue; return gameObjectValue;
case "UnityEngine.Material": case "UnityEngine.Material":
return materialValue; return materialValue;
case "UnityEngine.Sprite": case "UnityEngine.Sprite":
return spriteValue; return spriteValue;
case "UnityEngine.Texture": case "UnityEngine.Texture":
return textureValue; return textureValue;
case "UnityEngine.Vector2": case "UnityEngine.Vector2":
return vector2Value; return vector2Value;
case "UnityEngine.Vector3": case "UnityEngine.Vector3":
return vector3Value; return vector3Value;
default: default:
var objType = ReflectionHelper.GetType(typeAssemblyname); var objType = ReflectionHelper.GetType(typeAssemblyname);
if (objType.IsSubclassOf(typeof(UnityEngine.Object))) if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
return objectValue; return objectValue;
} }
else if (objType.IsEnum()) else if (objType.IsEnum())
return System.Enum.ToObject(objType, intValue); return System.Enum.ToObject(objType, intValue);
break; break;
} }
return null; return null;
} }
} }
public static class ReflectionHelper public static class ReflectionHelper
{ {
static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>(); static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>();
public static System.Type GetType(string typeName) public static System.Type GetType(string typeName)
{ {
if (types.ContainsKey(typeName)) if (types.ContainsKey(typeName))
return types[typeName]; return types[typeName];
types[typeName] = System.Type.GetType(typeName); types[typeName] = System.Type.GetType(typeName);
return types[typeName]; return types[typeName];
} }
} }
} }

74
Assets/Fungus/Flowchart/Scripts/Commands/Jump.cs

@ -8,54 +8,54 @@ using UnityEngine.Serialization;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Jump", "Jump",
"Move execution to a specific Label command in the same block")] "Move execution to a specific Label command in the same block")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class Jump : Command public class Jump : Command
{ {
[Tooltip("Name of a label in this block to jump to")] [Tooltip("Name of a label in this block to jump to")]
public StringData _targetLabel = new StringData(""); public StringData _targetLabel = new StringData("");
public override void OnEnter() public override void OnEnter()
{ {
if (_targetLabel.Value == "") if (_targetLabel.Value == "")
{ {
Continue(); Continue();
return; return;
} }
foreach (Command command in parentBlock.commandList) foreach (Command command in parentBlock.commandList)
{ {
Label label = command as Label; Label label = command as Label;
if (label != null && if (label != null &&
label.key == _targetLabel.Value) label.key == _targetLabel.Value)
{ {
Continue(label.commandIndex + 1); Continue(label.commandIndex + 1);
return; return;
} }
} }
// Label not found // Label not found
Debug.LogWarning("Label not found: " + _targetLabel.Value); Debug.LogWarning("Label not found: " + _targetLabel.Value);
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_targetLabel.Value == "") if (_targetLabel.Value == "")
{ {
return "Error: No label selected"; return "Error: No label selected";
} }
return _targetLabel.Value; return _targetLabel.Value;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
#region Backwards compatibility #region Backwards compatibility
@ -71,6 +71,6 @@ namespace Fungus
} }
#endregion #endregion
} }
} }

42
Assets/Fungus/Flowchart/Scripts/Commands/Label.cs

@ -9,29 +9,29 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Label", "Label",
"Marks a position in the command list for execution to jump to.")] "Marks a position in the command list for execution to jump to.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Label : Command public class Label : Command
{ {
[Tooltip("Display name for the label")] [Tooltip("Display name for the label")]
public string key = ""; public string key = "";
public override void OnEnter() public override void OnEnter()
{ {
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return key; return key;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(200, 200, 253, 255); return new Color32(200, 200, 253, 255);
} }
} }
} }

84
Assets/Fungus/Flowchart/Scripts/Commands/LoadScene.cs

@ -10,56 +10,56 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Load Scene", "Load Scene",
"Loads a new Unity scene and displays an optional loading image. This is useful " + "Loads a new Unity scene and displays an optional loading image. This is useful " +
"for splitting a large game across multiple scene files to reduce peak memory " + "for splitting a large game across multiple scene files to reduce peak memory " +
"usage. Previously loaded assets will be released before loading the scene to free up memory." + "usage. Previously loaded assets will be released before loading the scene to free up memory." +
"The scene to be loaded must be added to the scene list in Build Settings.")] "The scene to be loaded must be added to the scene list in Build Settings.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class LoadScene : Command public class LoadScene : Command
{ {
[Tooltip("Name of the scene to load. The scene must also be added to the build settings.")] [Tooltip("Name of the scene to load. The scene must also be added to the build settings.")]
public StringData _sceneName = new StringData(""); public StringData _sceneName = new StringData("");
[Tooltip("Image to display while loading the scene")] [Tooltip("Image to display while loading the scene")]
public Texture2D loadingImage; public Texture2D loadingImage;
public override void OnEnter() public override void OnEnter()
{ {
SceneLoader.LoadScene(_sceneName.Value, loadingImage); SceneLoader.LoadScene(_sceneName.Value, loadingImage);
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_sceneName.Value.Length == 0) if (_sceneName.Value.Length == 0)
{ {
return "Error: No scene name selected"; return "Error: No scene name selected";
} }
return _sceneName; return _sceneName;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("sceneName")] public string sceneNameOLD = ""; [HideInInspector] [FormerlySerializedAs("sceneName")] public string sceneNameOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (sceneNameOLD != "") if (sceneNameOLD != "")
{ {
_sceneName.Value = sceneNameOLD; _sceneName.Value = sceneNameOLD;
sceneNameOLD = ""; sceneNameOLD = "";
} }
} }
#endregion #endregion
} }
} }

156
Assets/Fungus/Flowchart/Scripts/Commands/LoadVariable.cs

@ -9,94 +9,94 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Load Variable", "Load Variable",
"Loads a saved value and stores it in a Boolean, Integer, Float or String variable. If the key is not found then the variable is not modified.")] "Loads a saved value and stores it in a Boolean, Integer, Float or String variable. If the key is not found then the variable is not modified.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class LoadVariable : Command public class LoadVariable : Command
{ {
[Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}\"")] [Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}\"")]
public string key = ""; public string key = "";
[Tooltip("Variable to store the value in.")] [Tooltip("Variable to store the value in.")]
[VariableProperty(typeof(BooleanVariable), [VariableProperty(typeof(BooleanVariable),
typeof(IntegerVariable), typeof(IntegerVariable),
typeof(FloatVariable), typeof(FloatVariable),
typeof(StringVariable))] typeof(StringVariable))]
public Variable variable; public Variable variable;
public override void OnEnter() public override void OnEnter()
{ {
if (key == "" || if (key == "" ||
variable == null) variable == null)
{ {
Continue(); Continue();
return; return;
} }
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
// Prepend the current save profile (if any) // Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key); string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
System.Type variableType = variable.GetType(); System.Type variableType = variable.GetType();
if (variableType == typeof(BooleanVariable)) if (variableType == typeof(BooleanVariable))
{ {
BooleanVariable booleanVariable = variable as BooleanVariable; BooleanVariable booleanVariable = variable as BooleanVariable;
if (booleanVariable != null) if (booleanVariable != null)
{ {
// PlayerPrefs does not have bool accessors, so just use int // PlayerPrefs does not have bool accessors, so just use int
booleanVariable.value = (PlayerPrefs.GetInt(prefsKey) == 1); booleanVariable.value = (PlayerPrefs.GetInt(prefsKey) == 1);
} }
} }
else if (variableType == typeof(IntegerVariable)) else if (variableType == typeof(IntegerVariable))
{ {
IntegerVariable integerVariable = variable as IntegerVariable; IntegerVariable integerVariable = variable as IntegerVariable;
if (integerVariable != null) if (integerVariable != null)
{ {
integerVariable.value = PlayerPrefs.GetInt(prefsKey); integerVariable.value = PlayerPrefs.GetInt(prefsKey);
} }
} }
else if (variableType == typeof(FloatVariable)) else if (variableType == typeof(FloatVariable))
{ {
FloatVariable floatVariable = variable as FloatVariable; FloatVariable floatVariable = variable as FloatVariable;
if (floatVariable != null) if (floatVariable != null)
{ {
floatVariable.value = PlayerPrefs.GetFloat(prefsKey); floatVariable.value = PlayerPrefs.GetFloat(prefsKey);
} }
} }
else if (variableType == typeof(StringVariable)) else if (variableType == typeof(StringVariable))
{ {
StringVariable stringVariable = variable as StringVariable; StringVariable stringVariable = variable as StringVariable;
if (stringVariable != null) if (stringVariable != null)
{ {
stringVariable.value = PlayerPrefs.GetString(prefsKey); stringVariable.value = PlayerPrefs.GetString(prefsKey);
} }
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (key.Length == 0) if (key.Length == 0)
{ {
return "Error: No stored value key selected"; return "Error: No stored value key selected";
} }
if (variable == null) if (variable == null)
{ {
return "Error: No variable selected"; return "Error: No variable selected";
} }
return "'" + key + "' into " + variable.key; return "'" + key + "' into " + variable.key;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

50
Assets/Fungus/Flowchart/Scripts/Commands/OpenURL.cs

@ -10,30 +10,30 @@ using Fungus;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Open URL", "Open URL",
"Opens the specified URL in the browser.")] "Opens the specified URL in the browser.")]
public class LinkToWebsite : Command public class LinkToWebsite : Command
{ {
[Tooltip("URL to open in the browser")] [Tooltip("URL to open in the browser")]
public StringData url = new StringData(); public StringData url = new StringData();
public override void OnEnter() public override void OnEnter()
{ {
Application.OpenURL(url.Value); Application.OpenURL(url.Value);
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return url.Value; return url.Value;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

34
Assets/Fungus/Flowchart/Scripts/Commands/Quit.cs

@ -9,24 +9,24 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Quit", "Quit",
"Quits the application. Does not work in Editor or Webplayer builds. Shouldn't generally be used on iOS.")] "Quits the application. Does not work in Editor or Webplayer builds. Shouldn't generally be used on iOS.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Quit : Command public class Quit : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
Application.Quit(); Application.Quit();
// On platforms that don't support Quit we just continue onto the next command // On platforms that don't support Quit we just continue onto the next command
Continue(); Continue();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

92
Assets/Fungus/Flowchart/Scripts/Commands/RandomFloat.cs

@ -8,51 +8,51 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Random Float", "Random Float",
"Sets an float variable to a random value in the defined range.")] "Sets an float variable to a random value in the defined range.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class RandomFloat : Command public class RandomFloat : Command
{ {
[Tooltip("The variable whos value will be set")] [Tooltip("The variable whos value will be set")]
[VariableProperty(typeof(FloatVariable))] [VariableProperty(typeof(FloatVariable))]
public FloatVariable variable; public FloatVariable variable;
[Tooltip("Minimum value for random range")] [Tooltip("Minimum value for random range")]
public FloatData minValue; public FloatData minValue;
[Tooltip("Maximum value for random range")] [Tooltip("Maximum value for random range")]
public FloatData maxValue; public FloatData maxValue;
public override void OnEnter() public override void OnEnter()
{ {
if (variable != null) if (variable != null)
{ {
variable.value = Random.Range(minValue.Value, maxValue.Value); variable.value = Random.Range(minValue.Value, maxValue.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (variable == null) if (variable == null)
{ {
return "Error: Variable not selected"; return "Error: Variable not selected";
} }
return variable.key; return variable.key;
} }
public override bool HasReference(Variable variable) public override bool HasReference(Variable variable)
{ {
return (variable == this.variable); return (variable == this.variable);
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

92
Assets/Fungus/Flowchart/Scripts/Commands/RandomInteger.cs

@ -8,51 +8,51 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Random Integer", "Random Integer",
"Sets an integer variable to a random value in the defined range.")] "Sets an integer variable to a random value in the defined range.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class RandomInteger : Command public class RandomInteger : Command
{ {
[Tooltip("The variable whos value will be set")] [Tooltip("The variable whos value will be set")]
[VariableProperty(typeof(IntegerVariable))] [VariableProperty(typeof(IntegerVariable))]
public IntegerVariable variable; public IntegerVariable variable;
[Tooltip("Minimum value for random range")] [Tooltip("Minimum value for random range")]
public IntegerData minValue; public IntegerData minValue;
[Tooltip("Maximum value for random range")] [Tooltip("Maximum value for random range")]
public IntegerData maxValue; public IntegerData maxValue;
public override void OnEnter() public override void OnEnter()
{ {
if (variable != null) if (variable != null)
{ {
variable.value = Random.Range(minValue.Value, maxValue.Value); variable.value = Random.Range(minValue.Value, maxValue.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (variable == null) if (variable == null)
{ {
return "Error: Variable not selected"; return "Error: Variable not selected";
} }
return variable.key; return variable.key;
} }
public override bool HasReference(Variable variable) public override bool HasReference(Variable variable)
{ {
return (variable == this.variable); return (variable == this.variable);
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

84
Assets/Fungus/Flowchart/Scripts/Commands/ReadTextFile.cs

@ -10,56 +10,56 @@ using Fungus;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Read Text File", "Read Text File",
"Reads in a text file and stores the contents in a string variable")] "Reads in a text file and stores the contents in a string variable")]
public class ReadTextFile : Command public class ReadTextFile : Command
{ {
[Tooltip("Text file to read into the string variable")] [Tooltip("Text file to read into the string variable")]
public TextAsset textFile; public TextAsset textFile;
[Tooltip("String variable to store the tex file contents in")] [Tooltip("String variable to store the tex file contents in")]
[VariableProperty(typeof(StringVariable))] [VariableProperty(typeof(StringVariable))]
public StringVariable stringVariable; public StringVariable stringVariable;
public override void OnEnter() public override void OnEnter()
{ {
if (textFile == null || if (textFile == null ||
stringVariable == null) stringVariable == null)
{ {
Continue(); Continue();
return; return;
} }
stringVariable.value = textFile.text; stringVariable.value = textFile.text;
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (stringVariable == null) if (stringVariable == null)
{ {
return "Error: Variable not selected"; return "Error: Variable not selected";
} }
if (textFile == null) if (textFile == null)
{ {
return "Error: Text file not selected"; return "Error: Text file not selected";
} }
return stringVariable.key; return stringVariable.key;
} }
public override bool HasReference(Variable variable) public override bool HasReference(Variable variable)
{ {
return (variable == stringVariable); return (variable == stringVariable);
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

40
Assets/Fungus/Flowchart/Scripts/Commands/Reset.cs

@ -9,28 +9,28 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Reset", "Reset",
"Resets the state of all commands and variables in the Flowchart.")] "Resets the state of all commands and variables in the Flowchart.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Reset : Command public class Reset : Command
{ {
[Tooltip("Reset state of all commands in the script")] [Tooltip("Reset state of all commands in the script")]
public bool resetCommands = true; public bool resetCommands = true;
[Tooltip("Reset variables back to their default values")] [Tooltip("Reset variables back to their default values")]
public bool resetVariables = true; public bool resetVariables = true;
public override void OnEnter() public override void OnEnter()
{ {
GetFlowchart().Reset(resetCommands, resetVariables); GetFlowchart().Reset(resetCommands, resetVariables);
Continue(); Continue();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

160
Assets/Fungus/Flowchart/Scripts/Commands/SaveVariable.cs

@ -9,96 +9,96 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Save Variable", "Save Variable",
"Save an Boolean, Integer, Float or String variable to persistent storage using a string key. " + "Save an Boolean, Integer, Float or String variable to persistent storage using a string key. " +
"The value can be loaded again later using the Load Variable command. You can also " + "The value can be loaded again later using the Load Variable command. You can also " +
"use the Set Save Profile command to manage separate save profiles for multiple players.")] "use the Set Save Profile command to manage separate save profiles for multiple players.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class SaveVariable : Command public class SaveVariable : Command
{ {
[Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")] [Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")]
public string key = ""; public string key = "";
[Tooltip("Variable to read the value from. Only Boolean, Integer, Float and String are supported.")] [Tooltip("Variable to read the value from. Only Boolean, Integer, Float and String are supported.")]
[VariableProperty(typeof(BooleanVariable), [VariableProperty(typeof(BooleanVariable),
typeof(IntegerVariable), typeof(IntegerVariable),
typeof(FloatVariable), typeof(FloatVariable),
typeof(StringVariable))] typeof(StringVariable))]
public Variable variable; public Variable variable;
public override void OnEnter() public override void OnEnter()
{ {
if (key == "" || if (key == "" ||
variable == null) variable == null)
{ {
Continue(); Continue();
return; return;
} }
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
// Prepend the current save profile (if any) // Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key); string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
System.Type variableType = variable.GetType(); System.Type variableType = variable.GetType();
if (variableType == typeof(BooleanVariable)) if (variableType == typeof(BooleanVariable))
{ {
BooleanVariable booleanVariable = variable as BooleanVariable; BooleanVariable booleanVariable = variable as BooleanVariable;
if (booleanVariable != null) if (booleanVariable != null)
{ {
// PlayerPrefs does not have bool accessors, so just use int // PlayerPrefs does not have bool accessors, so just use int
PlayerPrefs.SetInt(prefsKey, booleanVariable.value ? 1 : 0); PlayerPrefs.SetInt(prefsKey, booleanVariable.value ? 1 : 0);
} }
} }
else if (variableType == typeof(IntegerVariable)) else if (variableType == typeof(IntegerVariable))
{ {
IntegerVariable integerVariable = variable as IntegerVariable; IntegerVariable integerVariable = variable as IntegerVariable;
if (integerVariable != null) if (integerVariable != null)
{ {
PlayerPrefs.SetInt(prefsKey, integerVariable.value); PlayerPrefs.SetInt(prefsKey, integerVariable.value);
} }
} }
else if (variableType == typeof(FloatVariable)) else if (variableType == typeof(FloatVariable))
{ {
FloatVariable floatVariable = variable as FloatVariable; FloatVariable floatVariable = variable as FloatVariable;
if (floatVariable != null) if (floatVariable != null)
{ {
PlayerPrefs.SetFloat(prefsKey, floatVariable.value); PlayerPrefs.SetFloat(prefsKey, floatVariable.value);
} }
} }
else if (variableType == typeof(StringVariable)) else if (variableType == typeof(StringVariable))
{ {
StringVariable stringVariable = variable as StringVariable; StringVariable stringVariable = variable as StringVariable;
if (stringVariable != null) if (stringVariable != null)
{ {
PlayerPrefs.SetString(prefsKey, stringVariable.value); PlayerPrefs.SetString(prefsKey, stringVariable.value);
} }
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (key.Length == 0) if (key.Length == 0)
{ {
return "Error: No stored value key selected"; return "Error: No stored value key selected";
} }
if (variable == null) if (variable == null)
{ {
return "Error: No variable selected"; return "Error: No variable selected";
} }
return variable.key + " into '" + key + "'"; return variable.key + " into '" + key + "'";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

160
Assets/Fungus/Flowchart/Scripts/Commands/SendMessage.cs

@ -9,85 +9,85 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Send Message", "Send Message",
"Sends a message to either the owner Flowchart or all Flowcharts in the scene. Blocks can listen for this message using a Message Received event handler.")] "Sends a message to either the owner Flowchart or all Flowcharts in the scene. Blocks can listen for this message using a Message Received event handler.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SendMessage : Command public class SendMessage : Command
{ {
public enum MessageTarget public enum MessageTarget
{ {
SameFlowchart, SameFlowchart,
AllFlowcharts AllFlowcharts
} }
[Tooltip("Target flowchart(s) to send the message to")] [Tooltip("Target flowchart(s) to send the message to")]
public MessageTarget messageTarget; public MessageTarget messageTarget;
[Tooltip("Name of the message to send")] [Tooltip("Name of the message to send")]
public StringData _message = new StringData(""); public StringData _message = new StringData("");
public override void OnEnter() public override void OnEnter()
{ {
if (_message.Value.Length == 0) if (_message.Value.Length == 0)
{ {
Continue(); Continue();
return; return;
} }
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
MessageReceived[] receivers = null; MessageReceived[] receivers = null;
if (messageTarget == MessageTarget.SameFlowchart) if (messageTarget == MessageTarget.SameFlowchart)
{ {
receivers = flowchart.GetComponents<MessageReceived>(); receivers = flowchart.GetComponents<MessageReceived>();
} }
else else
{ {
receivers = GameObject.FindObjectsOfType<MessageReceived>(); receivers = GameObject.FindObjectsOfType<MessageReceived>();
} }
if (receivers != null) if (receivers != null)
{ {
foreach (MessageReceived receiver in receivers) foreach (MessageReceived receiver in receivers)
{ {
receiver.OnSendFungusMessage(_message.Value); receiver.OnSendFungusMessage(_message.Value);
} }
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_message.Value.Length == 0) if (_message.Value.Length == 0)
{ {
return "Error: No message specified"; return "Error: No message specified";
} }
return _message.Value; return _message.Value;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("message")] public string messageOLD = ""; [HideInInspector] [FormerlySerializedAs("message")] public string messageOLD = "";
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (messageOLD != "") if (messageOLD != "")
{ {
_message.Value = messageOLD; _message.Value = messageOLD;
messageOLD = ""; messageOLD = "";
} }
} }
#endregion #endregion
} }
} }

86
Assets/Fungus/Flowchart/Scripts/Commands/SetActive.cs

@ -10,58 +10,58 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Set Active", "Set Active",
"Sets a game object in the scene to be active / inactive.")] "Sets a game object in the scene to be active / inactive.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SetActive : Command public class SetActive : Command
{ {
[Tooltip("Reference to game object to enable / disable")] [Tooltip("Reference to game object to enable / disable")]
public GameObjectData _targetGameObject; public GameObjectData _targetGameObject;
[Tooltip("Set to true to enable the game object")] [Tooltip("Set to true to enable the game object")]
public BooleanData activeState; public BooleanData activeState;
public override void OnEnter() public override void OnEnter()
{ {
if (_targetGameObject.Value != null) if (_targetGameObject.Value != null)
{ {
_targetGameObject.Value.SetActive(activeState.Value); _targetGameObject.Value.SetActive(activeState.Value);
} }
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_targetGameObject.Value == null) if (_targetGameObject.Value == null)
{ {
return "Error: No game object selected"; return "Error: No game object selected";
} }
return _targetGameObject.Value.name + " = " + activeState.GetDescription(); return _targetGameObject.Value.name + " = " + activeState.GetDescription();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("targetGameObject")] public GameObject targetGameObjectOLD; [HideInInspector] [FormerlySerializedAs("targetGameObject")] public GameObject targetGameObjectOLD;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (targetGameObjectOLD != null) if (targetGameObjectOLD != null)
{ {
_targetGameObject.Value = targetGameObjectOLD; _targetGameObject.Value = targetGameObjectOLD;
targetGameObjectOLD = null; targetGameObjectOLD = null;
} }
} }
#endregion #endregion
} }
} }

62
Assets/Fungus/Flowchart/Scripts/Commands/SetSaveProfile.cs

@ -9,36 +9,36 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Set Save Profile", "Set Save Profile",
"Sets the active profile that the Save Variable and Load Variable commands will use. This is useful to crete multiple player save games. Once set, the profile applies across all Flowcharts and will also persist across scene loads.")] "Sets the active profile that the Save Variable and Load Variable commands will use. This is useful to crete multiple player save games. Once set, the profile applies across all Flowcharts and will also persist across scene loads.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class SetSaveProfile : Command public class SetSaveProfile : Command
{ {
/** /**
* Shared save profile name used by SaveVariable and LoadVariable. * Shared save profile name used by SaveVariable and LoadVariable.
*/ */
public static string saveProfile = ""; public static string saveProfile = "";
[Tooltip("Name of save profile to make active.")] [Tooltip("Name of save profile to make active.")]
public string saveProfileName = ""; public string saveProfileName = "";
public override void OnEnter() public override void OnEnter()
{ {
saveProfile = saveProfileName; saveProfile = saveProfileName;
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return saveProfileName; return saveProfileName;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

390
Assets/Fungus/Flowchart/Scripts/Commands/SetVariable.cs

@ -8,200 +8,200 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Variable", [CommandInfo("Variable",
"Set Variable", "Set Variable",
"Sets a Boolean, Integer, Float or String variable to a new value using a simple arithmetic operation. The value can be a constant or reference another variable of the same type.")] "Sets a Boolean, Integer, Float or String variable to a new value using a simple arithmetic operation. The value can be a constant or reference another variable of the same type.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class SetVariable : Command public class SetVariable : Command
{ {
public enum SetOperator public enum SetOperator
{ {
Assign, // = Assign, // =
Negate, // =! Negate, // =!
Add, // += Add, // +=
Subtract, // -= Subtract, // -=
Multiply, // *= Multiply, // *=
Divide // /= Divide // /=
} }
[Tooltip("The variable whos value will be set")] [Tooltip("The variable whos value will be set")]
[VariableProperty(typeof(BooleanVariable), [VariableProperty(typeof(BooleanVariable),
typeof(IntegerVariable), typeof(IntegerVariable),
typeof(FloatVariable), typeof(FloatVariable),
typeof(StringVariable))] typeof(StringVariable))]
public Variable variable; public Variable variable;
[Tooltip("The type of math operation to be performed")] [Tooltip("The type of math operation to be performed")]
public SetOperator setOperator; public SetOperator setOperator;
[Tooltip("Boolean value to set with")] [Tooltip("Boolean value to set with")]
public BooleanData booleanData; public BooleanData booleanData;
[Tooltip("Integer value to set with")] [Tooltip("Integer value to set with")]
public IntegerData integerData; public IntegerData integerData;
[Tooltip("Float value to set with")] [Tooltip("Float value to set with")]
public FloatData floatData; public FloatData floatData;
[Tooltip("String value to set with")] [Tooltip("String value to set with")]
public StringDataMulti stringData; public StringDataMulti stringData;
public override void OnEnter() public override void OnEnter()
{ {
DoSetOperation(); DoSetOperation();
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (variable == null) if (variable == null)
{ {
return "Error: Variable not selected"; return "Error: Variable not selected";
} }
string description = variable.key; string description = variable.key;
switch (setOperator) switch (setOperator)
{ {
default: default:
case SetOperator.Assign: case SetOperator.Assign:
description += " = "; description += " = ";
break; break;
case SetOperator.Negate: case SetOperator.Negate:
description += " =! "; description += " =! ";
break; break;
case SetOperator.Add: case SetOperator.Add:
description += " += "; description += " += ";
break; break;
case SetOperator.Subtract: case SetOperator.Subtract:
description += " -= "; description += " -= ";
break; break;
case SetOperator.Multiply: case SetOperator.Multiply:
description += " *= "; description += " *= ";
break; break;
case SetOperator.Divide: case SetOperator.Divide:
description += " /= "; description += " /= ";
break; break;
} }
if (variable.GetType() == typeof(BooleanVariable)) if (variable.GetType() == typeof(BooleanVariable))
{ {
description += booleanData.GetDescription(); description += booleanData.GetDescription();
} }
else if (variable.GetType() == typeof(IntegerVariable)) else if (variable.GetType() == typeof(IntegerVariable))
{ {
description += integerData.GetDescription(); description += integerData.GetDescription();
} }
else if (variable.GetType() == typeof(FloatVariable)) else if (variable.GetType() == typeof(FloatVariable))
{ {
description += floatData.GetDescription(); description += floatData.GetDescription();
} }
else if (variable.GetType() == typeof(StringVariable)) else if (variable.GetType() == typeof(StringVariable))
{ {
description += stringData.GetDescription(); description += stringData.GetDescription();
} }
return description; return description;
} }
public override bool HasReference(Variable variable) public override bool HasReference(Variable variable)
{ {
return (variable == this.variable); return (variable == this.variable);
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
protected virtual void DoSetOperation() protected virtual void DoSetOperation()
{ {
if (variable == null) if (variable == null)
{ {
return; return;
} }
if (variable.GetType() == typeof(BooleanVariable)) if (variable.GetType() == typeof(BooleanVariable))
{ {
BooleanVariable lhs = (variable as BooleanVariable); BooleanVariable lhs = (variable as BooleanVariable);
bool rhs = booleanData.Value; bool rhs = booleanData.Value;
switch (setOperator) switch (setOperator)
{ {
default: default:
case SetOperator.Assign: case SetOperator.Assign:
lhs.value = rhs; lhs.value = rhs;
break; break;
case SetOperator.Negate: case SetOperator.Negate:
lhs.value = !rhs; lhs.value = !rhs;
break; break;
} }
} }
else if (variable.GetType() == typeof(IntegerVariable)) else if (variable.GetType() == typeof(IntegerVariable))
{ {
IntegerVariable lhs = (variable as IntegerVariable); IntegerVariable lhs = (variable as IntegerVariable);
int rhs = integerData.Value; int rhs = integerData.Value;
switch (setOperator) switch (setOperator)
{ {
default: default:
case SetOperator.Assign: case SetOperator.Assign:
lhs.value = rhs; lhs.value = rhs;
break; break;
case SetOperator.Add: case SetOperator.Add:
lhs.value += rhs; lhs.value += rhs;
break; break;
case SetOperator.Subtract: case SetOperator.Subtract:
lhs.value -= rhs; lhs.value -= rhs;
break; break;
case SetOperator.Multiply: case SetOperator.Multiply:
lhs.value *= rhs; lhs.value *= rhs;
break; break;
case SetOperator.Divide: case SetOperator.Divide:
lhs.value /= rhs; lhs.value /= rhs;
break; break;
} }
} }
else if (variable.GetType() == typeof(FloatVariable)) else if (variable.GetType() == typeof(FloatVariable))
{ {
FloatVariable lhs = (variable as FloatVariable); FloatVariable lhs = (variable as FloatVariable);
float rhs = floatData.Value; float rhs = floatData.Value;
switch (setOperator) switch (setOperator)
{ {
default: default:
case SetOperator.Assign: case SetOperator.Assign:
lhs.value = rhs; lhs.value = rhs;
break; break;
case SetOperator.Add: case SetOperator.Add:
lhs.value += rhs; lhs.value += rhs;
break; break;
case SetOperator.Subtract: case SetOperator.Subtract:
lhs.value -= rhs; lhs.value -= rhs;
break; break;
case SetOperator.Multiply: case SetOperator.Multiply:
lhs.value *= rhs; lhs.value *= rhs;
break; break;
case SetOperator.Divide: case SetOperator.Divide:
lhs.value /= rhs; lhs.value /= rhs;
break; break;
} }
} }
else if (variable.GetType() == typeof(StringVariable)) else if (variable.GetType() == typeof(StringVariable))
{ {
StringVariable lhs = (variable as StringVariable); StringVariable lhs = (variable as StringVariable);
string rhs = stringData.Value; string rhs = stringData.Value;
switch (setOperator) switch (setOperator)
{ {
default: default:
case SetOperator.Assign: case SetOperator.Assign:
lhs.value = rhs; lhs.value = rhs;
break; break;
} }
} }
} }
} }
} }

180
Assets/Fungus/Flowchart/Scripts/Commands/SpawnObject.cs

@ -9,95 +9,95 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
// This command is called "Call Method" because a) it's more descriptive than Send Message and we're already have // This command is called "Call Method" because a) it's more descriptive than Send Message and we're already have
// a Send Message command for sending messages to trigger block execution. // a Send Message command for sending messages to trigger block execution.
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Spawn Object", "Spawn Object",
"Spawns a new object based on a reference to a scene or prefab game object.")] "Spawns a new object based on a reference to a scene or prefab game object.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class SpawnObject : Command public class SpawnObject : Command
{ {
[Tooltip("Game object to copy when spawning. Can be a scene object or a prefab.")] [Tooltip("Game object to copy when spawning. Can be a scene object or a prefab.")]
public GameObjectData _sourceObject; public GameObjectData _sourceObject;
[Tooltip("Transform to use for position of newly spawned object.")] [Tooltip("Transform to use for position of newly spawned object.")]
public TransformData _parentTransform; public TransformData _parentTransform;
[Tooltip("Local position of newly spawned object.")] [Tooltip("Local position of newly spawned object.")]
public Vector3Data _spawnPosition; public Vector3Data _spawnPosition;
[Tooltip("Local rotation of newly spawned object.")] [Tooltip("Local rotation of newly spawned object.")]
public Vector3Data _spawnRotation; public Vector3Data _spawnRotation;
public override void OnEnter() public override void OnEnter()
{ {
if (_sourceObject.Value == null) if (_sourceObject.Value == null)
{ {
Continue(); Continue();
return; return;
} }
GameObject newObject = GameObject.Instantiate(_sourceObject.Value); GameObject newObject = GameObject.Instantiate(_sourceObject.Value);
if (_parentTransform.Value != null) if (_parentTransform.Value != null)
{ {
newObject.transform.parent = _parentTransform.Value; newObject.transform.parent = _parentTransform.Value;
} }
newObject.transform.localPosition = _spawnPosition.Value; newObject.transform.localPosition = _spawnPosition.Value;
newObject.transform.localRotation = Quaternion.Euler(_spawnRotation.Value); newObject.transform.localRotation = Quaternion.Euler(_spawnRotation.Value);
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
if (_sourceObject.Value == null) if (_sourceObject.Value == null)
{ {
return "Error: No source GameObject specified"; return "Error: No source GameObject specified";
} }
return _sourceObject.Value.name; return _sourceObject.Value.name;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("sourceObject")] public GameObject sourceObjectOLD; [HideInInspector] [FormerlySerializedAs("sourceObject")] public GameObject sourceObjectOLD;
[HideInInspector] [FormerlySerializedAs("parentTransform")] public Transform parentTransformOLD; [HideInInspector] [FormerlySerializedAs("parentTransform")] public Transform parentTransformOLD;
[HideInInspector] [FormerlySerializedAs("spawnPosition")] public Vector3 spawnPositionOLD; [HideInInspector] [FormerlySerializedAs("spawnPosition")] public Vector3 spawnPositionOLD;
[HideInInspector] [FormerlySerializedAs("spawnRotation")] public Vector3 spawnRotationOLD; [HideInInspector] [FormerlySerializedAs("spawnRotation")] public Vector3 spawnRotationOLD;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (sourceObjectOLD != null) if (sourceObjectOLD != null)
{ {
_sourceObject.Value = sourceObjectOLD; _sourceObject.Value = sourceObjectOLD;
sourceObjectOLD = null; sourceObjectOLD = null;
} }
if (parentTransformOLD != null) if (parentTransformOLD != null)
{ {
_parentTransform.Value = parentTransformOLD; _parentTransform.Value = parentTransformOLD;
parentTransformOLD = null; parentTransformOLD = null;
} }
if (spawnPositionOLD != default(Vector3)) if (spawnPositionOLD != default(Vector3))
{ {
_spawnPosition.Value = spawnPositionOLD; _spawnPosition.Value = spawnPositionOLD;
spawnPositionOLD = default(Vector3); spawnPositionOLD = default(Vector3);
} }
if (spawnRotationOLD != default(Vector3)) if (spawnRotationOLD != default(Vector3))
{ {
_spawnRotation.Value = spawnRotationOLD; _spawnRotation.Value = spawnRotationOLD;
spawnRotationOLD = default(Vector3); spawnRotationOLD = default(Vector3);
} }
} }
#endregion #endregion
} }
} }

30
Assets/Fungus/Flowchart/Scripts/Commands/Stop.cs

@ -9,21 +9,21 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Stop", "Stop",
"Stop executing the Block that contains this command.")] "Stop executing the Block that contains this command.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class Stop : Command public class Stop : Command
{ {
public override void OnEnter() public override void OnEnter()
{ {
StopParentBlock(); StopParentBlock();
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

96
Assets/Fungus/Flowchart/Scripts/Commands/StopFlowchart.cs

@ -9,53 +9,53 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Stop Flowchart", "Stop Flowchart",
"Stops execution of all Blocks in a Flowchart")] "Stops execution of all Blocks in a Flowchart")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class StopFlowchart : Command public class StopFlowchart : Command
{ {
[Tooltip("Stop all executing Blocks in the Flowchart that contains this command")] [Tooltip("Stop all executing Blocks in the Flowchart that contains this command")]
public bool stopParentFlowchart; public bool stopParentFlowchart;
[Tooltip("Stop all executing Blocks in a list of target Flowcharts")] [Tooltip("Stop all executing Blocks in a list of target Flowcharts")]
public List<Flowchart> targetFlowcharts = new List<Flowchart>(); public List<Flowchart> targetFlowcharts = new List<Flowchart>();
public override void OnEnter() public override void OnEnter()
{ {
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
if (stopParentFlowchart) if (stopParentFlowchart)
{ {
flowchart.StopAllBlocks(); flowchart.StopAllBlocks();
} }
foreach (Flowchart f in targetFlowcharts) foreach (Flowchart f in targetFlowcharts)
{ {
if (f == flowchart) if (f == flowchart)
{ {
// Flowchart has already been stopped // Flowchart has already been stopped
continue; continue;
} }
f.StopAllBlocks(); f.StopAllBlocks();
} }
} }
public override bool IsReorderableArray(string propertyName) public override bool IsReorderableArray(string propertyName)
{ {
if (propertyName == "targetFlowcharts") if (propertyName == "targetFlowcharts")
{ {
return true; return true;
} }
return false; return false;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
} }
} }

90
Assets/Fungus/Flowchart/Scripts/Commands/Wait.cs

@ -10,50 +10,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"Wait", "Wait",
"Waits for period of time before executing the next command in the block.")] "Waits for period of time before executing the next command in the block.")]
[AddComponentMenu("")] [AddComponentMenu("")]
[ExecuteInEditMode] [ExecuteInEditMode]
public class Wait : Command public class Wait : Command
{ {
[Tooltip("Duration to wait for")] [Tooltip("Duration to wait for")]
public FloatData _duration = new FloatData(1); public FloatData _duration = new FloatData(1);
public override void OnEnter() public override void OnEnter()
{ {
Invoke ("OnWaitComplete", _duration.Value); Invoke ("OnWaitComplete", _duration.Value);
} }
void OnWaitComplete() void OnWaitComplete()
{ {
Continue(); Continue();
} }
public override string GetSummary() public override string GetSummary()
{ {
return _duration.Value.ToString() + " seconds"; return _duration.Value.ToString() + " seconds";
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
#region Backwards compatibility #region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("duration")] public float durationOLD; [HideInInspector] [FormerlySerializedAs("duration")] public float durationOLD;
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
if (durationOLD != default(float)) if (durationOLD != default(float))
{ {
_duration.Value = durationOLD; _duration.Value = durationOLD;
durationOLD = default(float); durationOLD = default(float);
} }
} }
#endregion #endregion
} }
} }

92
Assets/Fungus/Flowchart/Scripts/Commands/While.cs

@ -10,56 +10,56 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[CommandInfo("Flow", [CommandInfo("Flow",
"While", "While",
"Continuously loop through a block of commands while the condition is true. Use the Break command to force the loop to terminate immediately.")] "Continuously loop through a block of commands while the condition is true. Use the Break command to force the loop to terminate immediately.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class While : If public class While : If
{ {
public override void OnEnter() public override void OnEnter()
{ {
bool execute = true; bool execute = true;
if (variable != null) if (variable != null)
{ {
execute = EvaluateCondition(); execute = EvaluateCondition();
} }
// Find next End statement at same indent level // Find next End statement at same indent level
End endCommand = null; End endCommand = null;
for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i) for (int i = commandIndex + 1; i < parentBlock.commandList.Count; ++i)
{ {
End command = parentBlock.commandList[i] as End; End command = parentBlock.commandList[i] as End;
if (command != null && if (command != null &&
command.indentLevel == indentLevel) command.indentLevel == indentLevel)
{ {
endCommand = command; endCommand = command;
break; break;
} }
} }
if (execute) if (execute)
{ {
// Tell the following end command to loop back // Tell the following end command to loop back
endCommand.loop = true; endCommand.loop = true;
Continue(); Continue();
} }
else else
{ {
// Continue at next command after End // Continue at next command after End
Continue (endCommand.commandIndex + 1); Continue (endCommand.commandIndex + 1);
} }
} }
public override bool OpenBlock() public override bool OpenBlock()
{ {
return true; return true;
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(253, 253, 150, 255); return new Color32(253, 253, 150, 255);
} }
} }
} }

114
Assets/Fungus/Flowchart/Scripts/EventHandler.cs

@ -12,69 +12,69 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
public class EventHandlerInfoAttribute : Attribute public class EventHandlerInfoAttribute : Attribute
{ {
public EventHandlerInfoAttribute(string category, string eventHandlerName, string helpText) public EventHandlerInfoAttribute(string category, string eventHandlerName, string helpText)
{ {
this.Category = category; this.Category = category;
this.EventHandlerName = eventHandlerName; this.EventHandlerName = eventHandlerName;
this.HelpText = helpText; this.HelpText = helpText;
} }
public string Category { get; set; } public string Category { get; set; }
public string EventHandlerName { get; set; } public string EventHandlerName { get; set; }
public string HelpText { get; set; } public string HelpText { get; set; }
} }
/** /**
* A Block may have an associated Event Handler which starts executing commands when * A Block may have an associated Event Handler which starts executing commands when
* a specific event occurs. * a specific event occurs.
* To create a custom Event Handler, simply subclass EventHandler and call the ExecuteBlock() method * To create a custom Event Handler, simply subclass EventHandler and call the ExecuteBlock() method
* when the event occurs. * when the event occurs.
* Add an EventHandlerInfo attibute and your new EventHandler class will automatically appear in the * Add an EventHandlerInfo attibute and your new EventHandler class will automatically appear in the
* 'Execute On Event' dropdown menu when a block is selected. * 'Execute On Event' dropdown menu when a block is selected.
*/ */
[RequireComponent(typeof(Block))] [RequireComponent(typeof(Block))]
[RequireComponent(typeof(Flowchart))] [RequireComponent(typeof(Flowchart))]
[AddComponentMenu("")] [AddComponentMenu("")]
public class EventHandler : MonoBehaviour public class EventHandler : MonoBehaviour
{ {
[HideInInspector] [HideInInspector]
[FormerlySerializedAs("parentSequence")] [FormerlySerializedAs("parentSequence")]
public Block parentBlock; public Block parentBlock;
/** /**
* The Event Handler should call this method when the event is detected. * The Event Handler should call this method when the event is detected.
*/ */
public virtual bool ExecuteBlock() public virtual bool ExecuteBlock()
{ {
if (parentBlock == null) if (parentBlock == null)
{ {
return false; return false;
} }
if (parentBlock.eventHandler != this) if (parentBlock.eventHandler != this)
{ {
return false; return false;
} }
Flowchart flowchart = parentBlock.GetFlowchart(); Flowchart flowchart = parentBlock.GetFlowchart();
// Auto-follow the executing block if none is currently selected // Auto-follow the executing block if none is currently selected
if (flowchart.selectedBlock == null) if (flowchart.selectedBlock == null)
{ {
flowchart.selectedBlock = parentBlock; flowchart.selectedBlock = parentBlock;
} }
return flowchart.ExecuteBlock(parentBlock); return flowchart.ExecuteBlock(parentBlock);
} }
/** /**
* Returns a custom summary for the event handler. * Returns a custom summary for the event handler.
*/ */
public virtual string GetSummary() public virtual string GetSummary()
{ {
return ""; return "";
} }
} }
} }

36
Assets/Fungus/Flowchart/Scripts/EventHandlers/FlowchartEnabled.cs

@ -10,23 +10,23 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[EventHandlerInfo("", [EventHandlerInfo("",
"Flowchart Enabled", "Flowchart Enabled",
"The block will execute when the Flowchart game object is enabled.")] "The block will execute when the Flowchart game object is enabled.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class FlowchartEnabled : EventHandler public class FlowchartEnabled : EventHandler
{ {
protected virtual void OnEnable() protected virtual void OnEnable()
{ {
// Blocks use coroutines to schedule command execution, but Unity's coroutines are // Blocks use coroutines to schedule command execution, but Unity's coroutines are
// sometimes unreliable when enabling / disabling objects. // sometimes unreliable when enabling / disabling objects.
// To workaround this we execute the block on the next frame. // To workaround this we execute the block on the next frame.
Invoke("DoEvent", 0); Invoke("DoEvent", 0);
} }
protected virtual void DoEvent() protected virtual void DoEvent()
{ {
ExecuteBlock(); ExecuteBlock();
} }
} }
} }

22
Assets/Fungus/Flowchart/Scripts/EventHandlers/GameStarted.cs

@ -10,15 +10,15 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
[EventHandlerInfo("", [EventHandlerInfo("",
"Game Started", "Game Started",
"The block will execute when the game starts playing.")] "The block will execute when the game starts playing.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class GameStarted : EventHandler public class GameStarted : EventHandler
{ {
protected virtual void Start() protected virtual void Start()
{ {
ExecuteBlock(); ExecuteBlock();
} }
} }
} }

90
Assets/Fungus/Flowchart/Scripts/EventHandlers/KeyPressed.cs

@ -8,53 +8,53 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[EventHandlerInfo("Input", [EventHandlerInfo("Input",
"Key Pressed", "Key Pressed",
"The block will execute when a key press event occurs.")] "The block will execute when a key press event occurs.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class KeyPressed : EventHandler public class KeyPressed : EventHandler
{ {
public enum KeyPressType public enum KeyPressType
{ {
KeyDown, // Execute once when the key is pressed down KeyDown, // Execute once when the key is pressed down
KeyUp, // Execute once when the key is released KeyUp, // Execute once when the key is released
KeyRepeat // Execute once per frame when key is held down KeyRepeat // Execute once per frame when key is held down
} }
[Tooltip("The type of keypress to activate on")] [Tooltip("The type of keypress to activate on")]
public KeyPressType keyPressType; public KeyPressType keyPressType;
[Tooltip("Keycode of the key to activate on")] [Tooltip("Keycode of the key to activate on")]
public KeyCode keyCode; public KeyCode keyCode;
protected virtual void Update() protected virtual void Update()
{ {
switch (keyPressType) switch (keyPressType)
{ {
case KeyPressType.KeyDown: case KeyPressType.KeyDown:
if (Input.GetKeyDown(keyCode)) if (Input.GetKeyDown(keyCode))
{ {
ExecuteBlock(); ExecuteBlock();
} }
break; break;
case KeyPressType.KeyUp: case KeyPressType.KeyUp:
if (Input.GetKeyUp(keyCode)) if (Input.GetKeyUp(keyCode))
{ {
ExecuteBlock(); ExecuteBlock();
} }
break; break;
case KeyPressType.KeyRepeat: case KeyPressType.KeyRepeat:
if (Input.GetKey(keyCode)) if (Input.GetKey(keyCode))
{ {
ExecuteBlock(); ExecuteBlock();
} }
break; break;
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return keyCode.ToString(); return keyCode.ToString();
} }
} }
} }

40
Assets/Fungus/Flowchart/Scripts/EventHandlers/MessageReceived.cs

@ -8,27 +8,27 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[EventHandlerInfo("", [EventHandlerInfo("",
"Message Received", "Message Received",
"The block will execute when the specified message is received from a Send Message command.")] "The block will execute when the specified message is received from a Send Message command.")]
[AddComponentMenu("")] [AddComponentMenu("")]
public class MessageReceived : EventHandler public class MessageReceived : EventHandler
{ {
[Tooltip("Fungus message to listen for")] [Tooltip("Fungus message to listen for")]
public string message = ""; public string message = "";
public void OnSendFungusMessage(string message) public void OnSendFungusMessage(string message)
{ {
if (this.message == message) if (this.message == message)
{ {
ExecuteBlock(); ExecuteBlock();
} }
} }
public override string GetSummary() public override string GetSummary()
{ {
return message; return message;
} }
} }
} }

1606
Assets/Fungus/Flowchart/Scripts/Flowchart.cs

File diff suppressed because it is too large Load Diff

14
Assets/Fungus/Flowchart/Scripts/FungusState.cs

@ -9,12 +9,12 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
// Used by the Flowchart window to serialize the currently active Flowchart object // Used by the Flowchart window to serialize the currently active Flowchart object
// so that the same Flowchart can be displayed while editing & playing. // so that the same Flowchart can be displayed while editing & playing.
[AddComponentMenu("")] [AddComponentMenu("")]
public class FungusState : MonoBehaviour public class FungusState : MonoBehaviour
{ {
public Flowchart selectedFlowchart; public Flowchart selectedFlowchart;
} }
} }

10
Assets/Fungus/Flowchart/Scripts/Node.cs

@ -9,10 +9,10 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[AddComponentMenu("")] [AddComponentMenu("")]
public class Node : MonoBehaviour public class Node : MonoBehaviour
{ {
public Rect nodeRect = new Rect(0, 0, 120, 30); public Rect nodeRect = new Rect(0, 0, 120, 30);
} }
} }

166
Assets/Fungus/Flowchart/Scripts/SceneLoader.cs

@ -13,100 +13,100 @@ using System;
namespace Fungus namespace Fungus
{ {
/** /**
* Helper component for loading a new scene. * Helper component for loading a new scene.
* A fullscreen loading image is displayed while loading the new scene. * A fullscreen loading image is displayed while loading the new scene.
* All Rooms are destroyed and unused assets are released from memory before loading the new scene to minimize memory footprint. * All Rooms are destroyed and unused assets are released from memory before loading the new scene to minimize memory footprint.
* For streaming Web Player builds, the loading image will be displayed until the requested level has finished downloading. * For streaming Web Player builds, the loading image will be displayed until the requested level has finished downloading.
*/ */
public class SceneLoader : MonoBehaviour public class SceneLoader : MonoBehaviour
{ {
protected Texture2D loadingTexture; protected Texture2D loadingTexture;
protected string sceneToLoad; protected string sceneToLoad;
protected bool displayedImage; protected bool displayedImage;
/** /**
* Asynchronously load a new scene. * Asynchronously load a new scene.
* @param _sceneToLoad The name of the scene to load. Scenes must be added in project build settings. * @param _sceneToLoad The name of the scene to load. Scenes must be added in project build settings.
* @param _loadingTexture Loading image to display while loading the new scene. * @param _loadingTexture Loading image to display while loading the new scene.
*/ */
static public void LoadScene(string _sceneToLoad, Texture2D _loadingTexture) static public void LoadScene(string _sceneToLoad, Texture2D _loadingTexture)
{ {
// Unity does not provide a way to check if the named scene actually exists in the project. // Unity does not provide a way to check if the named scene actually exists in the project.
GameObject go = new GameObject("SceneLoader"); GameObject go = new GameObject("SceneLoader");
DontDestroyOnLoad(go); DontDestroyOnLoad(go);
SceneLoader sceneLoader = go.AddComponent<SceneLoader>(); SceneLoader sceneLoader = go.AddComponent<SceneLoader>();
sceneLoader.sceneToLoad = _sceneToLoad; sceneLoader.sceneToLoad = _sceneToLoad;
sceneLoader.loadingTexture = _loadingTexture; sceneLoader.loadingTexture = _loadingTexture;
} }
protected virtual void Start() protected virtual void Start()
{ {
StartCoroutine(DoLoadBlock()); StartCoroutine(DoLoadBlock());
} }
IEnumerator DoLoadBlock() IEnumerator DoLoadBlock()
{ {
// Wait until loading image has been displayed in OnGUI // Wait until loading image has been displayed in OnGUI
while (loadingTexture != null && while (loadingTexture != null &&
!displayedImage) !displayedImage)
{ {
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
} }
// Wait for objects to actually be destroyed at end of run loop // Wait for objects to actually be destroyed at end of run loop
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
// All Room assets should no longer be referenced now, so unload them. // All Room assets should no longer be referenced now, so unload them.
yield return Resources.UnloadUnusedAssets(); yield return Resources.UnloadUnusedAssets();
// Wait until scene has finished downloading (WebPlayer only) // Wait until scene has finished downloading (WebPlayer only)
while (!Application.CanStreamedLevelBeLoaded(sceneToLoad)) while (!Application.CanStreamedLevelBeLoaded(sceneToLoad))
{ {
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
} }
// Load the scene (happens at end of frame) // Load the scene (happens at end of frame)
#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 #if UNITY_5_0 || UNITY_5_1 || UNITY_5_2
Application.LoadLevel(sceneToLoad); Application.LoadLevel(sceneToLoad);
#else #else
SceneManager.LoadScene(sceneToLoad); SceneManager.LoadScene(sceneToLoad);
#endif #endif
yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame();
// Clean up any remaining unused assets // Clean up any remaining unused assets
Resources.UnloadUnusedAssets(); Resources.UnloadUnusedAssets();
// We're now finished with the SceneLoader // We're now finished with the SceneLoader
Destroy(gameObject); Destroy(gameObject);
} }
protected virtual void OnGUI() protected virtual void OnGUI()
{ {
if (loadingTexture == null) if (loadingTexture == null)
{ {
return; return;
} }
GUI.depth = -2000; GUI.depth = -2000;
float h = Screen.height; float h = Screen.height;
float w = (float)loadingTexture.width * (h / (float)loadingTexture.height); float w = (float)loadingTexture.width * (h / (float)loadingTexture.height);
float x = Screen.width / 2 - w / 2; float x = Screen.width / 2 - w / 2;
float y = 0; float y = 0;
Rect rect = new Rect(x, y, w, h); Rect rect = new Rect(x, y, w, h);
GUI.DrawTexture(rect, loadingTexture); GUI.DrawTexture(rect, loadingTexture);
if (Event.current.type == EventType.Repaint) if (Event.current.type == EventType.Repaint)
{ {
// Flag that image is now being shown // Flag that image is now being shown
displayedImage = true; displayedImage = true;
} }
} }
} }
} }

90
Assets/Fungus/Flowchart/Scripts/StringFormatter.cs

@ -11,53 +11,53 @@ using System;
namespace Fungus namespace Fungus
{ {
public class StringFormatter public class StringFormatter
{ {
public static string[] FormatEnumNames(Enum e, string firstLabel) public static string[] FormatEnumNames(Enum e, string firstLabel)
{ {
string[] enumLabels = Enum.GetNames(e.GetType()); string[] enumLabels = Enum.GetNames(e.GetType());
enumLabels[0] = firstLabel; enumLabels[0] = firstLabel;
for (int i=0; i<enumLabels.Length; i++) for (int i=0; i<enumLabels.Length; i++)
{ {
enumLabels[i] = SplitCamelCase(enumLabels[i]); enumLabels[i] = SplitCamelCase(enumLabels[i]);
} }
return enumLabels; return enumLabels;
} }
public static string SplitCamelCase(string text) public static string SplitCamelCase(string text)
{ {
if (string.IsNullOrEmpty(text)) if (string.IsNullOrEmpty(text))
{ {
return ""; return "";
} }
StringBuilder newText = new StringBuilder(text.Length * 2); StringBuilder newText = new StringBuilder(text.Length * 2);
newText.Append(text[0]); newText.Append(text[0]);
for (int i = 1; i < text.Length; i++) for (int i = 1; i < text.Length; i++)
{ {
if (char.IsUpper(text[i]) && text[i - 1] != ' ') if (char.IsUpper(text[i]) && text[i - 1] != ' ')
{ {
newText.Append(' '); newText.Append(' ');
} }
newText.Append(text[i]); newText.Append(text[i]);
} }
return newText.ToString(); return newText.ToString();
} }
public static bool IsNullOrWhiteSpace(string value) public static bool IsNullOrWhiteSpace(string value)
{ {
if (value != null) if (value != null)
{ {
for (int i = 0; i < value.Length; i++) for (int i = 0; i < value.Length; i++)
{ {
if (!char.IsWhiteSpace(value[i])) if (!char.IsWhiteSpace(value[i]))
{ {
return false; return false;
} }
} }
} }
return true; return true;
} }
} }
} }

140
Assets/Fungus/Flowchart/Scripts/Variable.cs

@ -10,74 +10,74 @@ using System.Collections.Generic;
namespace Fungus namespace Fungus
{ {
public enum VariableScope public enum VariableScope
{ {
Private, Private,
Public Public
} }
public class VariableInfoAttribute : Attribute public class VariableInfoAttribute : Attribute
{ {
public VariableInfoAttribute(string category, string variableType, int order = 0) public VariableInfoAttribute(string category, string variableType, int order = 0)
{ {
this.Category = category; this.Category = category;
this.VariableType = variableType; this.VariableType = variableType;
this.Order = order; this.Order = order;
} }
public string Category { get; set; } public string Category { get; set; }
public string VariableType { get; set; } public string VariableType { get; set; }
public int Order { get; set; } public int Order { get; set; }
} }
public class VariablePropertyAttribute : PropertyAttribute public class VariablePropertyAttribute : PropertyAttribute
{ {
public VariablePropertyAttribute (params System.Type[] variableTypes) public VariablePropertyAttribute (params System.Type[] variableTypes)
{ {
this.VariableTypes = variableTypes; this.VariableTypes = variableTypes;
} }
public VariablePropertyAttribute (string defaultText, params System.Type[] variableTypes) public VariablePropertyAttribute (string defaultText, params System.Type[] variableTypes)
{ {
this.defaultText = defaultText; this.defaultText = defaultText;
this.VariableTypes = variableTypes; this.VariableTypes = variableTypes;
} }
public String defaultText = "<None>"; public String defaultText = "<None>";
public System.Type[] VariableTypes { get; set; } public System.Type[] VariableTypes { get; set; }
} }
[RequireComponent(typeof(Flowchart))] [RequireComponent(typeof(Flowchart))]
public abstract class Variable : MonoBehaviour public abstract class Variable : MonoBehaviour
{ {
public VariableScope scope; public VariableScope scope;
public string key = ""; public string key = "";
public abstract void OnReset(); public abstract void OnReset();
} }
public abstract class VariableBase<T> : Variable public abstract class VariableBase<T> : Variable
{ {
public T value; public T value;
protected T startValue; protected T startValue;
public override void OnReset() public override void OnReset()
{ {
value = startValue; value = startValue;
} }
public override string ToString() public override string ToString()
{ {
return value.ToString(); return value.ToString();
} }
protected virtual void Start() protected virtual void Start()
{ {
// Remember the initial value so we can reset later on // Remember the initial value so we can reset later on
startValue = value; startValue = value;
} }
} }
} }

88
Assets/Fungus/Flowchart/Scripts/VariableTypes/AnimatorVariable.cs

@ -8,50 +8,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("Other", "Animator")] [VariableInfo("Other", "Animator")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class AnimatorVariable : VariableBase<Animator> public class AnimatorVariable : VariableBase<Animator>
{} {}
[System.Serializable] [System.Serializable]
public struct AnimatorData public struct AnimatorData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(AnimatorVariable))] [VariableProperty("<Value>", typeof(AnimatorVariable))]
public AnimatorVariable animatorRef; public AnimatorVariable animatorRef;
[SerializeField] [SerializeField]
public Animator animatorVal; public Animator animatorVal;
public AnimatorData(Animator v) public AnimatorData(Animator v)
{ {
animatorVal = v; animatorVal = v;
animatorRef = null; animatorRef = null;
} }
public static implicit operator Animator(AnimatorData animatorData) public static implicit operator Animator(AnimatorData animatorData)
{ {
return animatorData.Value; return animatorData.Value;
} }
public Animator Value public Animator Value
{ {
get { return (animatorRef == null) ? animatorVal : animatorRef.value; } get { return (animatorRef == null) ? animatorVal : animatorRef.value; }
set { if (animatorRef == null) { animatorVal = value; } else { animatorRef.value = value; } } set { if (animatorRef == null) { animatorVal = value; } else { animatorRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (animatorRef == null) if (animatorRef == null)
{ {
return animatorVal.ToString(); return animatorVal.ToString();
} }
else else
{ {
return animatorRef.key; return animatorRef.key;
} }
} }
} }
} }

88
Assets/Fungus/Flowchart/Scripts/VariableTypes/AudioSourceVariable.cs

@ -8,50 +8,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("Other", "AudioSource")] [VariableInfo("Other", "AudioSource")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class AudioSourceVariable : VariableBase<AudioSource> public class AudioSourceVariable : VariableBase<AudioSource>
{} {}
[System.Serializable] [System.Serializable]
public struct AudioSourceData public struct AudioSourceData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(AudioSourceVariable))] [VariableProperty("<Value>", typeof(AudioSourceVariable))]
public AudioSourceVariable audioSourceRef; public AudioSourceVariable audioSourceRef;
[SerializeField] [SerializeField]
public AudioSource audioSourceVal; public AudioSource audioSourceVal;
public AudioSourceData(AudioSource v) public AudioSourceData(AudioSource v)
{ {
audioSourceVal = v; audioSourceVal = v;
audioSourceRef = null; audioSourceRef = null;
} }
public static implicit operator AudioSource(AudioSourceData audioSourceData) public static implicit operator AudioSource(AudioSourceData audioSourceData)
{ {
return audioSourceData.Value; return audioSourceData.Value;
} }
public AudioSource Value public AudioSource Value
{ {
get { return (audioSourceRef == null) ? audioSourceVal : audioSourceRef.value; } get { return (audioSourceRef == null) ? audioSourceVal : audioSourceRef.value; }
set { if (audioSourceRef == null) { audioSourceVal = value; } else { audioSourceRef.value = value; } } set { if (audioSourceRef == null) { audioSourceVal = value; } else { audioSourceRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (audioSourceRef == null) if (audioSourceRef == null)
{ {
return audioSourceVal.ToString(); return audioSourceVal.ToString();
} }
else else
{ {
return audioSourceRef.key; return audioSourceRef.key;
} }
} }
} }
} }

112
Assets/Fungus/Flowchart/Scripts/VariableTypes/BooleanVariable.cs

@ -10,72 +10,72 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("", "Boolean")] [VariableInfo("", "Boolean")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class BooleanVariable : VariableBase<bool> public class BooleanVariable : VariableBase<bool>
{ {
public virtual bool Evaluate(CompareOperator compareOperator, bool booleanValue) public virtual bool Evaluate(CompareOperator compareOperator, bool booleanValue)
{ {
bool condition = false; bool condition = false;
bool lhs = value; bool lhs = value;
bool rhs = booleanValue; bool rhs = booleanValue;
switch (compareOperator) switch (compareOperator)
{ {
case CompareOperator.Equals: case CompareOperator.Equals:
condition = lhs == rhs; condition = lhs == rhs;
break; break;
case CompareOperator.NotEquals: case CompareOperator.NotEquals:
default: default:
condition = lhs != rhs; condition = lhs != rhs;
break; break;
} }
return condition; return condition;
} }
} }
[System.Serializable] [System.Serializable]
public struct BooleanData public struct BooleanData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(BooleanVariable))] [VariableProperty("<Value>", typeof(BooleanVariable))]
public BooleanVariable booleanRef; public BooleanVariable booleanRef;
[SerializeField] [SerializeField]
public bool booleanVal; public bool booleanVal;
public BooleanData(bool v) public BooleanData(bool v)
{ {
booleanVal = v; booleanVal = v;
booleanRef = null; booleanRef = null;
} }
public static implicit operator bool(BooleanData booleanData) public static implicit operator bool(BooleanData booleanData)
{ {
return booleanData.Value; return booleanData.Value;
} }
public bool Value public bool Value
{ {
get { return (booleanRef == null) ? booleanVal : booleanRef.value; } get { return (booleanRef == null) ? booleanVal : booleanRef.value; }
set { if (booleanRef == null) { booleanVal = value; } else { booleanRef.value = value; } } set { if (booleanRef == null) { booleanVal = value; } else { booleanRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (booleanRef == null) if (booleanRef == null)
{ {
return booleanVal.ToString(); return booleanVal.ToString();
} }
else else
{ {
return booleanRef.key; return booleanRef.key;
} }
} }
} }
} }

88
Assets/Fungus/Flowchart/Scripts/VariableTypes/ColorVariable.cs

@ -8,50 +8,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("Other", "Color")] [VariableInfo("Other", "Color")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class ColorVariable : VariableBase<Color> public class ColorVariable : VariableBase<Color>
{} {}
[System.Serializable] [System.Serializable]
public struct ColorData public struct ColorData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(ColorVariable))] [VariableProperty("<Value>", typeof(ColorVariable))]
public ColorVariable colorRef; public ColorVariable colorRef;
[SerializeField] [SerializeField]
public Color colorVal; public Color colorVal;
public ColorData(Color v) public ColorData(Color v)
{ {
colorVal = v; colorVal = v;
colorRef = null; colorRef = null;
} }
public static implicit operator Color(ColorData colorData) public static implicit operator Color(ColorData colorData)
{ {
return colorData.Value; return colorData.Value;
} }
public Color Value public Color Value
{ {
get { return (colorRef == null) ? colorVal : colorRef.value; } get { return (colorRef == null) ? colorVal : colorRef.value; }
set { if (colorRef == null) { colorVal = value; } else { colorRef.value = value; } } set { if (colorRef == null) { colorVal = value; } else { colorRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (colorRef == null) if (colorRef == null)
{ {
return colorVal.ToString(); return colorVal.ToString();
} }
else else
{ {
return colorRef.key; return colorRef.key;
} }
} }
} }
} }

134
Assets/Fungus/Flowchart/Scripts/VariableTypes/FloatVariable.cs

@ -8,82 +8,82 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("", "Float")] [VariableInfo("", "Float")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class FloatVariable : VariableBase<float> public class FloatVariable : VariableBase<float>
{ {
public virtual bool Evaluate(CompareOperator compareOperator, float floatValue) public virtual bool Evaluate(CompareOperator compareOperator, float floatValue)
{ {
float lhs = value; float lhs = value;
float rhs = floatValue; float rhs = floatValue;
bool condition = false; bool condition = false;
switch (compareOperator) switch (compareOperator)
{ {
case CompareOperator.Equals: case CompareOperator.Equals:
condition = lhs == rhs; condition = lhs == rhs;
break; break;
case CompareOperator.NotEquals: case CompareOperator.NotEquals:
condition = lhs != rhs; condition = lhs != rhs;
break; break;
case CompareOperator.LessThan: case CompareOperator.LessThan:
condition = lhs < rhs; condition = lhs < rhs;
break; break;
case CompareOperator.GreaterThan: case CompareOperator.GreaterThan:
condition = lhs > rhs; condition = lhs > rhs;
break; break;
case CompareOperator.LessThanOrEquals: case CompareOperator.LessThanOrEquals:
condition = lhs <= rhs; condition = lhs <= rhs;
break; break;
case CompareOperator.GreaterThanOrEquals: case CompareOperator.GreaterThanOrEquals:
condition = lhs >= rhs; condition = lhs >= rhs;
break; break;
} }
return condition; return condition;
} }
} }
[System.Serializable] [System.Serializable]
public struct FloatData public struct FloatData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(FloatVariable))] [VariableProperty("<Value>", typeof(FloatVariable))]
public FloatVariable floatRef; public FloatVariable floatRef;
[SerializeField] [SerializeField]
public float floatVal; public float floatVal;
public FloatData(float v) public FloatData(float v)
{ {
floatVal = v; floatVal = v;
floatRef = null; floatRef = null;
} }
public static implicit operator float(FloatData floatData) public static implicit operator float(FloatData floatData)
{ {
return floatData.Value; return floatData.Value;
} }
public float Value public float Value
{ {
get { return (floatRef == null) ? floatVal : floatRef.value; } get { return (floatRef == null) ? floatVal : floatRef.value; }
set { if (floatRef == null) { floatVal = value; } else { floatRef.value = value; } } set { if (floatRef == null) { floatVal = value; } else { floatRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (floatRef == null) if (floatRef == null)
{ {
return floatVal.ToString(); return floatVal.ToString();
} }
else else
{ {
return floatRef.key; return floatRef.key;
} }
} }
} }
} }

88
Assets/Fungus/Flowchart/Scripts/VariableTypes/GameObjectVariable.cs

@ -8,50 +8,50 @@ using System.Collections;
namespace Fungus namespace Fungus
{ {
[VariableInfo("Other", "GameObject")] [VariableInfo("Other", "GameObject")]
[AddComponentMenu("")] [AddComponentMenu("")]
[System.Serializable] [System.Serializable]
public class GameObjectVariable : VariableBase<GameObject> public class GameObjectVariable : VariableBase<GameObject>
{} {}
[System.Serializable] [System.Serializable]
public struct GameObjectData public struct GameObjectData
{ {
[SerializeField] [SerializeField]
[VariableProperty("<Value>", typeof(GameObjectVariable))] [VariableProperty("<Value>", typeof(GameObjectVariable))]
public GameObjectVariable gameObjectRef; public GameObjectVariable gameObjectRef;
[SerializeField] [SerializeField]
public GameObject gameObjectVal; public GameObject gameObjectVal;
public GameObjectData(GameObject v) public GameObjectData(GameObject v)
{ {
gameObjectVal = v; gameObjectVal = v;
gameObjectRef = null; gameObjectRef = null;
} }
public static implicit operator GameObject(GameObjectData gameObjectData) public static implicit operator GameObject(GameObjectData gameObjectData)
{ {
return gameObjectData.Value; return gameObjectData.Value;
} }
public GameObject Value public GameObject Value
{ {
get { return (gameObjectRef == null) ? gameObjectVal : gameObjectRef.value; } get { return (gameObjectRef == null) ? gameObjectVal : gameObjectRef.value; }
set { if (gameObjectRef == null) { gameObjectVal = value; } else { gameObjectRef.value = value; } } set { if (gameObjectRef == null) { gameObjectVal = value; } else { gameObjectRef.value = value; } }
} }
public string GetDescription() public string GetDescription()
{ {
if (gameObjectRef == null) if (gameObjectRef == null)
{ {
return gameObjectVal.ToString(); return gameObjectVal.ToString();
} }
else else
{ {
return gameObjectRef.key; return gameObjectRef.key;
} }
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save