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. 92
      Assets/Fungus/Audio/Editor/ControlAudioEditor.cs
  6. 492
      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. 1128
      Assets/Fungus/Camera/Scripts/CameraController.cs
  17. 122
      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. 112
      Assets/Fungus/Camera/Scripts/Commands/ShakeCamera.cs
  22. 114
      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. 68
      Assets/Fungus/Flowchart/Editor/AssetModProcessor.cs
  26. 2116
      Assets/Fungus/Flowchart/Editor/BlockEditor.cs
  27. 448
      Assets/Fungus/Flowchart/Editor/BlockInspector.cs
  28. 84
      Assets/Fungus/Flowchart/Editor/CallEditor.cs
  29. 414
      Assets/Fungus/Flowchart/Editor/CommandEditor.cs
  30. 870
      Assets/Fungus/Flowchart/Editor/CommandListAdaptor.cs
  31. 66
      Assets/Fungus/Flowchart/Editor/CustomGUI.cs
  32. 104
      Assets/Fungus/Flowchart/Editor/EditorExtensions.cs
  33. 134
      Assets/Fungus/Flowchart/Editor/EditorZoomArea.cs
  34. 98
      Assets/Fungus/Flowchart/Editor/EventHandlerEditor.cs
  35. 2
      Assets/Fungus/Flowchart/Editor/Extensions/SerializedPropertyExtensions.cs
  36. 538
      Assets/Fungus/Flowchart/Editor/FlowchartEditor.cs
  37. 120
      Assets/Fungus/Flowchart/Editor/FlowchartMenuItems.cs
  38. 1658
      Assets/Fungus/Flowchart/Editor/FlowchartWindow.cs
  39. 356
      Assets/Fungus/Flowchart/Editor/FungusEditorResources.cs
  40. 568
      Assets/Fungus/Flowchart/Editor/GLDraw.cs
  41. 164
      Assets/Fungus/Flowchart/Editor/IfEditor.cs
  42. 120
      Assets/Fungus/Flowchart/Editor/InvokeEventEditor.cs
  43. 856
      Assets/Fungus/Flowchart/Editor/InvokeMethodEditor.cs
  44. 122
      Assets/Fungus/Flowchart/Editor/LabelEditor.cs
  45. 296
      Assets/Fungus/Flowchart/Editor/SetVariableEditor.cs
  46. 656
      Assets/Fungus/Flowchart/Editor/VariableEditor.cs
  47. 366
      Assets/Fungus/Flowchart/Editor/VariableListAdaptor.cs
  48. 578
      Assets/Fungus/Flowchart/Scripts/Block.cs
  49. 428
      Assets/Fungus/Flowchart/Scripts/Command.cs
  50. 106
      Assets/Fungus/Flowchart/Scripts/CommandCopyBuffer.cs
  51. 114
      Assets/Fungus/Flowchart/Scripts/Commands/Break.cs
  52. 236
      Assets/Fungus/Flowchart/Scripts/Commands/Call.cs
  53. 108
      Assets/Fungus/Flowchart/Scripts/Commands/CallMethod.cs
  54. 56
      Assets/Fungus/Flowchart/Scripts/Commands/Comment.cs
  55. 84
      Assets/Fungus/Flowchart/Scripts/Commands/Condition.cs
  56. 100
      Assets/Fungus/Flowchart/Scripts/Commands/DebugLog.cs
  57. 80
      Assets/Fungus/Flowchart/Scripts/Commands/DeleteSaveKey.cs
  58. 82
      Assets/Fungus/Flowchart/Scripts/Commands/Destroy.cs
  59. 104
      Assets/Fungus/Flowchart/Scripts/Commands/Else.cs
  60. 116
      Assets/Fungus/Flowchart/Scripts/Commands/ElseIf.cs
  61. 66
      Assets/Fungus/Flowchart/Scripts/Commands/End.cs
  62. 380
      Assets/Fungus/Flowchart/Scripts/Commands/If.cs
  63. 250
      Assets/Fungus/Flowchart/Scripts/Commands/InvokeEvent.cs
  64. 714
      Assets/Fungus/Flowchart/Scripts/Commands/InvokeMethod.cs
  65. 74
      Assets/Fungus/Flowchart/Scripts/Commands/Jump.cs
  66. 42
      Assets/Fungus/Flowchart/Scripts/Commands/Label.cs
  67. 84
      Assets/Fungus/Flowchart/Scripts/Commands/LoadScene.cs
  68. 162
      Assets/Fungus/Flowchart/Scripts/Commands/LoadVariable.cs
  69. 50
      Assets/Fungus/Flowchart/Scripts/Commands/OpenURL.cs
  70. 34
      Assets/Fungus/Flowchart/Scripts/Commands/Quit.cs
  71. 92
      Assets/Fungus/Flowchart/Scripts/Commands/RandomFloat.cs
  72. 92
      Assets/Fungus/Flowchart/Scripts/Commands/RandomInteger.cs
  73. 88
      Assets/Fungus/Flowchart/Scripts/Commands/ReadTextFile.cs
  74. 40
      Assets/Fungus/Flowchart/Scripts/Commands/Reset.cs
  75. 180
      Assets/Fungus/Flowchart/Scripts/Commands/SaveVariable.cs
  76. 136
      Assets/Fungus/Flowchart/Scripts/Commands/SendMessage.cs
  77. 88
      Assets/Fungus/Flowchart/Scripts/Commands/SetActive.cs
  78. 56
      Assets/Fungus/Flowchart/Scripts/Commands/SetSaveProfile.cs
  79. 390
      Assets/Fungus/Flowchart/Scripts/Commands/SetVariable.cs
  80. 180
      Assets/Fungus/Flowchart/Scripts/Commands/SpawnObject.cs
  81. 30
      Assets/Fungus/Flowchart/Scripts/Commands/Stop.cs
  82. 96
      Assets/Fungus/Flowchart/Scripts/Commands/StopFlowchart.cs
  83. 90
      Assets/Fungus/Flowchart/Scripts/Commands/Wait.cs
  84. 96
      Assets/Fungus/Flowchart/Scripts/Commands/While.cs
  85. 118
      Assets/Fungus/Flowchart/Scripts/EventHandler.cs
  86. 36
      Assets/Fungus/Flowchart/Scripts/EventHandlers/FlowchartEnabled.cs
  87. 22
      Assets/Fungus/Flowchart/Scripts/EventHandlers/GameStarted.cs
  88. 90
      Assets/Fungus/Flowchart/Scripts/EventHandlers/KeyPressed.cs
  89. 40
      Assets/Fungus/Flowchart/Scripts/EventHandlers/MessageReceived.cs
  90. 1616
      Assets/Fungus/Flowchart/Scripts/Flowchart.cs
  91. 14
      Assets/Fungus/Flowchart/Scripts/FungusState.cs
  92. 10
      Assets/Fungus/Flowchart/Scripts/Node.cs
  93. 184
      Assets/Fungus/Flowchart/Scripts/SceneLoader.cs
  94. 92
      Assets/Fungus/Flowchart/Scripts/StringFormatter.cs
  95. 120
      Assets/Fungus/Flowchart/Scripts/Variable.cs
  96. 80
      Assets/Fungus/Flowchart/Scripts/VariableTypes/AnimatorVariable.cs
  97. 80
      Assets/Fungus/Flowchart/Scripts/VariableTypes/AudioSourceVariable.cs
  98. 120
      Assets/Fungus/Flowchart/Scripts/VariableTypes/BooleanVariable.cs
  99. 80
      Assets/Fungus/Flowchart/Scripts/VariableTypes/ColorVariable.cs
  100. 140
      Assets/Fungus/Flowchart/Scripts/VariableTypes/FloatVariable.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
{
[CommandInfo("Animation",
"Play Anim State",
"Plays a state of an animator according to the state name")]
[AddComponentMenu("")]
public class PlayAnimState : Command
{
[CommandInfo("Animation",
"Play Anim State",
"Plays a state of an animator according to the state name")]
[AddComponentMenu("")]
public class PlayAnimState : Command
{
[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")]
public StringData stateName = new StringData();
[Tooltip("Name of the state you want to play")]
public StringData stateName = new StringData();
[Tooltip("Layer to play animation on")]
public IntegerData layer = new IntegerData(-1);
public IntegerData layer = new IntegerData(-1);
[Tooltip("Start time of animation")]
public FloatData time = new FloatData(0f);
public FloatData time = new FloatData(0f);
public override void OnEnter()
{
if (animator.Value != null)
{
{
if (animator.Value != null)
{
animator.Value.Play(stateName.Value, layer.Value, time.Value);
}
}
Continue();
}
Continue();
}
public override string GetSummary()
{
if (animator.Value == null)
{
return "Error: No animator selected";
}
public override string GetSummary()
{
if (animator.Value == null)
{
return "Error: No animator selected";
}
return animator.Value.name + " (" + stateName.Value + ")";
}
}
public override Color GetButtonColor()
{
return new Color32(170, 204, 169, 255);
}
public override Color GetButtonColor()
{
return new Color32(170, 204, 169, 255);
}
}
}

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

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

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

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

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

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

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

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

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

@ -9,225 +9,225 @@ using System.Collections;
namespace Fungus
{
[CommandInfo("Audio",
"Control Audio",
"Plays, loops, or stops an audiosource. Any AudioSources with the same tag as the target Audio Source will automatically be stoped.")]
[ExecuteInEditMode]
public class ControlAudio : Command
{
public enum controlType
{
PlayOnce,
PlayLoop,
PauseLoop,
StopLoop,
ChangeVolume
}
[CommandInfo("Audio",
"Control Audio",
"Plays, loops, or stops an audiosource. Any AudioSources with the same tag as the target Audio Source will automatically be stoped.")]
[ExecuteInEditMode]
public class ControlAudio : Command
{
public enum controlType
{
PlayOnce,
PlayLoop,
PauseLoop,
StopLoop,
ChangeVolume
}
[Tooltip("What to do to audio")]
public controlType control;
[Tooltip("What to do to audio")]
public controlType control;
[Tooltip("Audio clip to play")]
public AudioSourceData _audioSource;
[Tooltip("Audio clip to play")]
public AudioSourceData _audioSource;
[Range(0,1)]
[Tooltip("Start audio at this volume")]
public float startVolume = 1;
[Range(0,1)]
[Tooltip("Start audio at this volume")]
public float startVolume = 1;
[Range(0,1)]
[Tooltip("End audio at this volume")]
public float endVolume = 1;
[Tooltip("Time to fade between current volume level and target volume level.")]
public float fadeDuration;
[Range(0,1)]
[Tooltip("End audio at this volume")]
public float endVolume = 1;
[Tooltip("Time to fade between current volume level and target volume level.")]
public float fadeDuration;
[Tooltip("Wait until this command has finished before executing the next command.")]
public bool waitUntilFinished = false;
public override void OnEnter()
{
if (_audioSource.Value == null)
{
Continue();
return;
}
[Tooltip("Wait until this command has finished before executing the next command.")]
public bool waitUntilFinished = false;
public override void OnEnter()
{
if (_audioSource.Value == null)
{
Continue();
return;
}
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();
}
}
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;
}
/**
* 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>());
}
}
}
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;
});
}
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);
_audioSource.Value.PlayOneShot(_audioSource.Value.clip);
if (waitUntilFinished)
{
StartCoroutine(WaitAndContinue());
}
}
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;
}
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();
}
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 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 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 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;
protected void ChangeVolume()
{
LeanTween.value(_audioSource.Value.gameObject,_audioSource.Value.volume,endVolume,fadeDuration
).setOnUpdate(
(float updateVolume)=>{
_audioSource.Value.volume = updateVolume;
}).setOnComplete(
()=>{
if (waitUntilFinished)
@ -235,58 +235,58 @@ namespace Fungus
Continue();
}
});
}
}
void AudioFinished()
{
if (waitUntilFinished)
{
Continue();
}
}
void AudioFinished()
{
if (waitUntilFinished)
{
Continue();
}
}
public override string GetSummary()
{
if (_audioSource.Value == null)
{
return "Error: No sound clip selected";
}
string fadeType = "";
if (fadeDuration > 0)
{
fadeType = " Fade out";
if (control != controlType.StopLoop)
{
fadeType = " Fade in volume to " + endVolume;
}
if (control == controlType.ChangeVolume)
{
fadeType = " to " + endVolume;
}
fadeType += " over " + fadeDuration + " seconds.";
}
return control.ToString() + " \"" + _audioSource.Value.name + "\"" + fadeType;
}
public override Color GetButtonColor()
{
return new Color32(242, 209, 176, 255);
}
public override string GetSummary()
{
if (_audioSource.Value == null)
{
return "Error: No sound clip selected";
}
string fadeType = "";
if (fadeDuration > 0)
{
fadeType = " Fade out";
if (control != controlType.StopLoop)
{
fadeType = " Fade in volume to " + endVolume;
}
if (control == controlType.ChangeVolume)
{
fadeType = " to " + endVolume;
}
fadeType += " over " + fadeDuration + " seconds.";
}
return control.ToString() + " \"" + _audioSource.Value.name + "\"" + fadeType;
}
public override Color GetButtonColor()
{
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()
{
if (audioSourceOLD != null)
{
_audioSource.Value = audioSourceOLD;
audioSourceOLD = null;
}
}
protected virtual void OnEnable()
{
if (audioSourceOLD != null)
{
_audioSource.Value = audioSourceOLD;
audioSourceOLD = null;
}
}
#endregion
}
#endregion
}
}

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

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

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

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

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

@ -6,25 +6,25 @@
namespace Fungus {
using System;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.Serialization;
[CommandInfo("Audio",
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class PlayUsfxrSound : Command
{
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class PlayUsfxrSound : Command
{
protected SfxrSynth _synth = new SfxrSynth();
[Tooltip("Transform to use for positional audio")]
[Tooltip("Transform to use for positional audio")]
public Transform ParentTransform = null;
[Tooltip("Settings string which describes the audio")]
public StringDataMulti _SettingsString = new StringDataMulti("");
[Tooltip("Settings string which describes the audio")]
public StringDataMulti _SettingsString = new StringDataMulti("");
[Tooltip("Time to wait before executing the next command")]
public float waitDuration = 0;
[Tooltip("Time to wait before executing the next command")]
public float waitDuration = 0;
//Call this if the settings have changed
protected void UpdateCache() {
@ -42,20 +42,20 @@
public override void OnEnter() {
_synth.SetParentTransform(ParentTransform);
_synth.Play();
if (waitDuration == 0f)
{
Continue();
}
else
{
Invoke ("DoWait", waitDuration);
}
if (waitDuration == 0f)
{
Continue();
}
else
{
Invoke ("DoWait", waitDuration);
}
}
protected void DoWait()
{
Continue();
}
protected void DoWait()
{
Continue();
}
public override string GetSummary() {
if (String.IsNullOrEmpty(_SettingsString.Value)) {
@ -71,19 +71,19 @@
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()
{
if (SettingsStringOLD != "")
{
_SettingsString.Value = SettingsStringOLD;
SettingsStringOLD = "";
}
}
protected virtual void OnEnable()
{
if (SettingsStringOLD != "")
{
_SettingsString.Value = SettingsStringOLD;
SettingsStringOLD = "";
}
}
#endregion
#endregion
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -13,219 +13,219 @@ using Rotorz.ReorderableList;
namespace Fungus
{
[CustomEditor (typeof(Command), true)]
public class CommandEditor : Editor
{
public static Command selectedCommand;
public static CommandInfoAttribute GetCommandInfo(System.Type commandType)
{
object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false);
foreach (object obj in attributes)
{
CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute;
if (commandInfoAttr != null)
{
return commandInfoAttr;
}
}
return null;
}
public virtual void DrawCommandInspectorGUI()
{
Command t = target as Command;
if (t == null)
{
return;
}
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (commandInfoAttr == null)
{
return;
}
GUILayout.BeginVertical(GUI.skin.box);
if (t.enabled)
{
if (flowchart.colorCommands)
{
GUI.backgroundColor = t.GetButtonColor();
}
else
{
GUI.backgroundColor = Color.white;
}
}
else
{
GUI.backgroundColor = Color.grey;
}
GUILayout.BeginHorizontal(GUI.skin.button);
string commandName = commandInfoAttr.CommandName;
GUILayout.Label(commandName, GUILayout.MinWidth(80), GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace();
GUILayout.Label(new GUIContent("(" + t.itemId + ")"));
GUILayout.Space(10);
GUI.backgroundColor = Color.white;
bool enabled = t.enabled;
enabled = GUILayout.Toggle(enabled, new GUIContent());
if (t.enabled != enabled)
{
Undo.RecordObject(t, "Set Enabled");
t.enabled = enabled;
}
GUILayout.EndHorizontal();
GUI.backgroundColor = Color.white;
EditorGUILayout.Separator();
DrawCommandGUI();
EditorGUILayout.Separator();
if (t.errorMessage.Length > 0)
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.normal.textColor = new Color(1,0,0);
EditorGUILayout.LabelField(new GUIContent("Error: " + t.errorMessage), style);
}
GUILayout.EndVertical();
// Display help text
CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (infoAttr != null)
{
EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info, true);
}
}
public virtual void DrawCommandGUI()
{
Command t = target as Command;
// Code below was copied from here
// 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.
// Doing so could cause block.commandList to contain null entries.
// To avoid this we manually display all properties, except for m_Script.
serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
if (!t.IsPropertyVisible(iterator.name))
{
continue;
}
if (iterator.isArray &&
t.IsReorderableArray(iterator.name))
{
ReorderableListGUI.Title(new GUIContent(iterator.displayName, iterator.tooltip));
ReorderableListGUI.ListField(iterator);
}
else
{
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
}
serializedObject.ApplyModifiedProperties();
}
[CustomEditor (typeof(Command), true)]
public class CommandEditor : Editor
{
public static Command selectedCommand;
public static CommandInfoAttribute GetCommandInfo(System.Type commandType)
{
object[] attributes = commandType.GetCustomAttributes(typeof(CommandInfoAttribute), false);
foreach (object obj in attributes)
{
CommandInfoAttribute commandInfoAttr = obj as CommandInfoAttribute;
if (commandInfoAttr != null)
{
return commandInfoAttr;
}
}
return null;
}
public virtual void DrawCommandInspectorGUI()
{
Command t = target as Command;
if (t == null)
{
return;
}
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
CommandInfoAttribute commandInfoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (commandInfoAttr == null)
{
return;
}
GUILayout.BeginVertical(GUI.skin.box);
if (t.enabled)
{
if (flowchart.colorCommands)
{
GUI.backgroundColor = t.GetButtonColor();
}
else
{
GUI.backgroundColor = Color.white;
}
}
else
{
GUI.backgroundColor = Color.grey;
}
GUILayout.BeginHorizontal(GUI.skin.button);
string commandName = commandInfoAttr.CommandName;
GUILayout.Label(commandName, GUILayout.MinWidth(80), GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace();
GUILayout.Label(new GUIContent("(" + t.itemId + ")"));
GUILayout.Space(10);
GUI.backgroundColor = Color.white;
bool enabled = t.enabled;
enabled = GUILayout.Toggle(enabled, new GUIContent());
if (t.enabled != enabled)
{
Undo.RecordObject(t, "Set Enabled");
t.enabled = enabled;
}
GUILayout.EndHorizontal();
GUI.backgroundColor = Color.white;
EditorGUILayout.Separator();
DrawCommandGUI();
EditorGUILayout.Separator();
if (t.errorMessage.Length > 0)
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.normal.textColor = new Color(1,0,0);
EditorGUILayout.LabelField(new GUIContent("Error: " + t.errorMessage), style);
}
GUILayout.EndVertical();
// Display help text
CommandInfoAttribute infoAttr = CommandEditor.GetCommandInfo(t.GetType());
if (infoAttr != null)
{
EditorGUILayout.HelpBox(infoAttr.HelpText, MessageType.Info, true);
}
}
public virtual void DrawCommandGUI()
{
Command t = target as Command;
// Code below was copied from here
// 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.
// Doing so could cause block.commandList to contain null entries.
// To avoid this we manually display all properties, except for m_Script.
serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
if (!t.IsPropertyVisible(iterator.name))
{
continue;
}
if (iterator.isArray &&
t.IsReorderableArray(iterator.name))
{
ReorderableListGUI.Title(new GUIContent(iterator.displayName, iterator.tooltip));
ReorderableListGUI.ListField(iterator);
}
else
{
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
}
serializedObject.ApplyModifiedProperties();
}
static public void ObjectField<T>(SerializedProperty property, GUIContent label, GUIContent nullLabel, List<T> objectList) where T : Object
{
if (property == null)
{
return;
}
List<GUIContent> objectNames = new List<GUIContent>();
T selectedObject = property.objectReferenceValue as T;
int selectedIndex = 0;
objectNames.Add(nullLabel);
for (int i = 0; i < objectList.Count; ++i)
{
if (objectList[i] == null) continue;
objectNames.Add(new GUIContent(objectList[i].name));
static public void ObjectField<T>(SerializedProperty property, GUIContent label, GUIContent nullLabel, List<T> objectList) where T : Object
{
if (property == null)
{
return;
}
List<GUIContent> objectNames = new List<GUIContent>();
T selectedObject = property.objectReferenceValue as T;
int selectedIndex = 0;
objectNames.Add(nullLabel);
for (int i = 0; i < objectList.Count; ++i)
{
if (objectList[i] == null) continue;
objectNames.Add(new GUIContent(objectList[i].name));
if (selectedObject == objectList[i])
{
selectedIndex = i + 1;
}
if (selectedObject == objectList[i])
{
selectedIndex = i + 1;
}
}
}
T result;
T result;
selectedIndex = EditorGUILayout.Popup(label, selectedIndex, objectNames.ToArray());
if (selectedIndex == 0)
{
result = null; // Null option
}
else
{
result = objectList[selectedIndex - 1];
}
property.objectReferenceValue = result;
}
selectedIndex = EditorGUILayout.Popup(label, selectedIndex, objectNames.ToArray());
if (selectedIndex == 0)
{
result = null; // Null option
}
else
{
result = objectList[selectedIndex - 1];
}
property.objectReferenceValue = result;
}
/**
* 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.
* 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.
* To use it, just call this function at the top of the OnEnable() method in your custom editor.
*/
protected virtual bool NullTargetCheck()
{
try
{
// The serializedObject accessor create a new SerializedObject if needed.
// However, this will fail with a null exception if the target object no longer exists.
#pragma warning disable 0219
SerializedObject so = serializedObject;
}
catch (System.NullReferenceException)
{
DestroyImmediate(this);
return true;
}
return false;
}
}
/**
* 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.
* 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.
* To use it, just call this function at the top of the OnEnable() method in your custom editor.
*/
protected virtual bool NullTargetCheck()
{
try
{
// The serializedObject accessor create a new SerializedObject if needed.
// However, this will fail with a null exception if the target object no longer exists.
#pragma warning disable 0219
SerializedObject so = serializedObject;
}
catch (System.NullReferenceException)
{
DestroyImmediate(this);
return true;
}
return false;
}
}
}

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

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

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

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

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

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

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

@ -10,82 +10,82 @@ using UnityEngine;
namespace Fungus
{
// Helper Rect extension methods
public static class RectExtensions
{
public static Vector2 TopLeft(this Rect rect)
{
return new Vector2(rect.xMin, rect.yMin);
}
// Helper Rect extension methods
public static class RectExtensions
{
public static Vector2 TopLeft(this Rect rect)
{
return new Vector2(rect.xMin, rect.yMin);
}
public static Rect ScaleSizeBy(this Rect rect, float scale)
{
return rect.ScaleSizeBy(scale, rect.center);
}
public static Rect ScaleSizeBy(this Rect rect, float scale)
{
return rect.ScaleSizeBy(scale, rect.center);
}
public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint)
{
Rect result = rect;
result.x -= pivotPoint.x;
result.y -= pivotPoint.y;
result.xMin *= scale;
result.xMax *= scale;
result.yMin *= scale;
result.yMax *= scale;
result.x += pivotPoint.x;
result.y += pivotPoint.y;
return result;
}
public static Rect ScaleSizeBy(this Rect rect, float scale, Vector2 pivotPoint)
{
Rect result = rect;
result.x -= pivotPoint.x;
result.y -= pivotPoint.y;
result.xMin *= scale;
result.xMax *= scale;
result.yMin *= scale;
result.yMax *= scale;
result.x += pivotPoint.x;
result.y += pivotPoint.y;
return result;
}
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale)
{
return rect.ScaleSizeBy(scale, rect.center);
}
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale)
{
return rect.ScaleSizeBy(scale, rect.center);
}
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint)
{
Rect result = rect;
result.x -= pivotPoint.x;
result.y -= pivotPoint.y;
result.xMin *= scale.x;
result.xMax *= scale.x;
result.yMin *= scale.y;
result.yMax *= scale.y;
result.x += pivotPoint.x;
result.y += pivotPoint.y;
return result;
}
}
public static Rect ScaleSizeBy(this Rect rect, Vector2 scale, Vector2 pivotPoint)
{
Rect result = rect;
result.x -= pivotPoint.x;
result.y -= pivotPoint.y;
result.xMin *= scale.x;
result.xMax *= scale.x;
result.yMin *= scale.y;
result.yMax *= scale.y;
result.x += pivotPoint.x;
result.y += pivotPoint.y;
return result;
}
}
public class EditorZoomArea
{
private const float kEditorWindowTabHeight = 21.0f;
private static Matrix4x4 _prevGuiMatrix;
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.
Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft());
clippedArea.y += kEditorWindowTabHeight;
GUI.BeginGroup(clippedArea);
_prevGuiMatrix = GUI.matrix;
public class EditorZoomArea
{
private const float kEditorWindowTabHeight = 21.0f;
private static Matrix4x4 _prevGuiMatrix;
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.
Rect clippedArea = screenCoordsArea.ScaleSizeBy(1.0f / zoomScale, screenCoordsArea.TopLeft());
clippedArea.y += kEditorWindowTabHeight;
GUI.BeginGroup(clippedArea);
_prevGuiMatrix = GUI.matrix;
Matrix4x4 translation = Matrix4x4.TRS(clippedArea.TopLeft(), Quaternion.identity, Vector3.one);
Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f));
GUI.matrix = translation * scale * translation.inverse * GUI.matrix;
Matrix4x4 scale = Matrix4x4.Scale(new Vector3(zoomScale, zoomScale, 1.0f));
GUI.matrix = translation * scale * translation.inverse * GUI.matrix;
return clippedArea;
}
public static void End()
{
GUI.matrix = _prevGuiMatrix;
GUI.EndGroup();
GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height));
}
}
}
public static void End()
{
GUI.matrix = _prevGuiMatrix;
GUI.EndGroup();
GUI.BeginGroup(new Rect(0.0f, kEditorWindowTabHeight, Screen.width, Screen.height));
}
}
}

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

@ -12,57 +12,57 @@ using System.Collections.Generic;
namespace Fungus
{
[CustomEditor (typeof(EventHandler), true)]
public class EventHandlerEditor : Editor
{
/**
* Returns the class attribute info for an event handler class.
*/
public static EventHandlerInfoAttribute GetEventHandlerInfo(System.Type eventHandlerType)
{
object[] attributes = eventHandlerType.GetCustomAttributes(typeof(EventHandlerInfoAttribute), false);
foreach (object obj in attributes)
{
EventHandlerInfoAttribute eventHandlerInfoAttr = obj as EventHandlerInfoAttribute;
if (eventHandlerInfoAttr != null)
{
return eventHandlerInfoAttr;
}
}
return null;
}
[CustomEditor (typeof(EventHandler), true)]
public class EventHandlerEditor : Editor
{
/**
* Returns the class attribute info for an event handler class.
*/
public static EventHandlerInfoAttribute GetEventHandlerInfo(System.Type eventHandlerType)
{
object[] attributes = eventHandlerType.GetCustomAttributes(typeof(EventHandlerInfoAttribute), false);
foreach (object obj in attributes)
{
EventHandlerInfoAttribute eventHandlerInfoAttr = obj as EventHandlerInfoAttribute;
if (eventHandlerInfoAttr != null)
{
return eventHandlerInfoAttr;
}
}
return null;
}
public virtual void DrawInspectorGUI()
{
// 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.
// To avoid this we manually display all properties, except for m_Script.
serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
public virtual void DrawInspectorGUI()
{
// 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.
// To avoid this we manually display all properties, except for m_Script.
serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
EventHandler t = target as EventHandler;
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType());
if (info != null &&
info.HelpText.Length > 0)
{
EditorGUILayout.HelpBox(info.HelpText, MessageType.Info);
}
EventHandler t = target as EventHandler;
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType());
if (info != null &&
info.HelpText.Length > 0)
{
EditorGUILayout.HelpBox(info.HelpText, MessageType.Info);
}
serializedObject.ApplyModifiedProperties();
}
}
serializedObject.ApplyModifiedProperties();
}
}
}

2
Assets/Fungus/Flowchart/Editor/Extensions/SerializedPropertyExtensions.cs

@ -39,7 +39,7 @@ namespace Fungus
case "ColorRGBA":
element.colorValue = Color.black;
break;
default:
if (element.type.StartsWith("PPtr"))
element.objectReferenceValue = null;

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

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

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

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

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

File diff suppressed because it is too large Load Diff

356
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
{
public class GLDraw
{
/*
* 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
*/
protected static bool clippingEnabled;
protected static Rect clippingBounds;
public static Material lineMaterial = null;
/* @ 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)
{
float r;
bool retval = true;
if (p < 0.0)
{
r = q / p;
if (r > u2)
retval = false;
else if (r > u1)
u1 = r;
}
else if (p > 0.0)
{
r = q / p;
if (r < u1)
retval = false;
else if (r < u2)
u2 = r;
}
else if (q < 0.0)
retval = false;
return retval;
}
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;
if (clip_test(-dx, p1.x - bounds.xMin, ref u1, ref u2))
{
if (clip_test(dx, bounds.xMax - p1.x, ref u1, ref u2))
{
dy = p2.y - p1.y;
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 (u2 < 1.0)
{
p2.x = p1.x + u2 * dx;
p2.y = p1.y + u2 * dy;
}
if (u1 > 0.0)
{
p1.x += u1 * dx;
p1.y += u1 * dy;
}
return true;
}
}
}
}
return false;
}
public static void BeginGroup(Rect position)
{
clippingEnabled = true;
clippingBounds = new Rect(0, 0, position.width, position.height);
GUI.BeginGroup(position);
}
public static void EndGroup()
{
GUI.EndGroup();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false;
}
public static Vector2 BeginScrollView(Rect position, Vector2 scrollPos, Rect viewRect, Rect clipRect)
{
clippingEnabled = true;
clippingBounds = clipRect;
return GUI.BeginScrollView(position, scrollPos, viewRect, GUIStyle.none, GUIStyle.none);
}
public static void EndScrollView()
{
GUI.EndScrollView();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false;
}
public static void CreateMaterial()
{
if (lineMaterial != null)
return;
lineMaterial = Resources.Load("GLLineDraw", typeof(Material)) as Material;
}
public static void DrawLine(Vector2 start, Vector2 end, Color color, float width)
{
if (Event.current == null)
return;
if (Event.current.type != EventType.repaint)
return;
if (clippingEnabled)
if (!segment_rect_intersection(clippingBounds, ref start, ref end))
return;
CreateMaterial();
lineMaterial.SetPass(0);
Vector3 startPt;
Vector3 endPt;
if (width == 1)
{
GL.Begin(GL.LINES);
GL.Color(color);
startPt = new Vector3(start.x, start.y, 0);
endPt = new Vector3(end.x, end.y, 0);
GL.Vertex(startPt);
GL.Vertex(endPt);
}
else
{
GL.Begin(GL.QUADS);
GL.Color(color);
startPt = new Vector3(end.y, start.x, 0);
endPt = new Vector3(start.y, end.x, 0);
Vector3 perpendicular = (startPt - endPt).normalized * width;
Vector3 v1 = new Vector3(start.x, start.y, 0);
Vector3 v2 = new Vector3(end.x, end.y, 0);
GL.Vertex(v1 - perpendicular);
GL.Vertex(v1 + perpendicular);
GL.Vertex(v2 + perpendicular);
GL.Vertex(v2 - perpendicular);
}
GL.End();
}
public static void DrawRect(Rect rect, Color color)
{
if (Event.current == null)
return;
if (Event.current.type != EventType.repaint)
return;
CreateMaterial();
// set the current material
lineMaterial.SetPass( 0 );
GL.Begin( GL.QUADS );
GL.Color( color );
GL.Vertex3( rect.xMin, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMax, 0 );
GL.Vertex3( rect.xMin, rect.yMax, 0 );
GL.End();
}
public static void DrawBox(Rect box, Color color, float width)
{
Vector2 p1 = new Vector2(box.xMin, box.yMin);
Vector2 p2 = new Vector2(box.xMax, box.yMin);
Vector2 p3 = new Vector2(box.xMax, box.yMax);
Vector2 p4 = new Vector2(box.xMin, box.yMax);
DrawLine(p1, p2, color, width);
DrawLine(p2, p3, color, width);
DrawLine(p3, p4, color, width);
DrawLine(p4, p1, color, 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);
DrawBox(box, color, width);
}
public static void DrawRoundedBox(Rect box, float radius, Color color, float width)
{
Vector2 p1, p2, p3, p4, p5, p6, p7, p8;
p1 = new Vector2(box.xMin + radius, box.yMin);
p2 = new Vector2(box.xMax - radius, box.yMin);
p3 = new Vector2(box.xMax, box.yMin + radius);
p4 = new Vector2(box.xMax, box.yMax - radius);
p5 = new Vector2(box.xMax - radius, box.yMax);
p6 = new Vector2(box.xMin + radius, box.yMax);
p7 = new Vector2(box.xMin, box.yMax - radius);
p8 = new Vector2(box.xMin, box.yMin + radius);
DrawLine(p1, p2, color, width);
DrawLine(p3, p4, color, width);
DrawLine(p5, p6, color, width);
DrawLine(p7, p8, color, width);
Vector2 t1, t2;
float halfRadius = radius / 2;
t1 = new Vector2(p8.x, p8.y + halfRadius);
t2 = new Vector2(p1.x - halfRadius, p1.y);
DrawBezier(p8, t1, p1, t2, color, width);
t1 = new Vector2(p2.x + halfRadius, p2.y);
t2 = new Vector2(p3.x, p3.y - halfRadius);
DrawBezier(p2, t1, p3, t2, color, width);
t1 = new Vector2(p4.x, p4.y + halfRadius);
t2 = new Vector2(p5.x + halfRadius, p5.y);
DrawBezier(p4, t1, p5, t2, color, width);
t1 = new Vector2(p6.x - halfRadius, p6.y);
t2 = new Vector2(p7.x, p7.y + halfRadius);
DrawBezier(p6, t1, p7, t2, color, width);
}
public static void DrawConnectingCurve(Vector2 start, Vector2 end, Color color, float width)
{
Vector2 distance = start - end;
Vector2 tangentA = start;
tangentA.x -= distance.x * 0.5f;
Vector2 tangentB = end;
tangentB.x += distance.x * 0.5f;
int segments = Mathf.FloorToInt((distance.magnitude / 20) * 3);
DrawBezier(start, tangentA, end, tangentB, color, width, segments);
Vector2 pA = CubeBezier(start, tangentA, end, tangentB, 0.6f);
Vector2 pB = CubeBezier(start, tangentA, end, tangentB, 0.7f);
float arrowHeadSize = 5;
Vector2 arrowPosA = pB;
Vector2 arrowPosB = arrowPosA;
Vector2 arrowPosC = arrowPosA;
Vector2 dir = (pB - pA).normalized;
arrowPosB.x += dir.y * arrowHeadSize;
arrowPosB.y -= dir.x * arrowHeadSize;
arrowPosB -= dir * arrowHeadSize;
arrowPosC.x -= dir.y * arrowHeadSize;
arrowPosC.y += dir.x * arrowHeadSize;
arrowPosC -= dir * arrowHeadSize;
DrawLine(arrowPosA, arrowPosB, 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)
{
int segments = Mathf.FloorToInt((start - end).magnitude / 20) * 3; // Three segments per distance of 20
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)
{
Vector2 startVector = CubeBezier(start, startTangent, end, endTangent, 0);
for (int i = 1; i <= segments; i++)
{
Vector2 endVector = CubeBezier(start, startTangent, end, endTangent, i / (float)segments);
DrawLine(startVector, endVector, color, width);
startVector = endVector;
}
}
private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t)
{
float rt = 1 - t;
float rtt = rt * t;
return rt * rt * rt * s + 3 * rt * rtt * st + 3 * rtt * t * et + t * t * t * e;
}
}
public class GLDraw
{
/*
* 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
*/
protected static bool clippingEnabled;
protected static Rect clippingBounds;
public static Material lineMaterial = null;
/* @ 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)
{
float r;
bool retval = true;
if (p < 0.0)
{
r = q / p;
if (r > u2)
retval = false;
else if (r > u1)
u1 = r;
}
else if (p > 0.0)
{
r = q / p;
if (r < u1)
retval = false;
else if (r < u2)
u2 = r;
}
else if (q < 0.0)
retval = false;
return retval;
}
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;
if (clip_test(-dx, p1.x - bounds.xMin, ref u1, ref u2))
{
if (clip_test(dx, bounds.xMax - p1.x, ref u1, ref u2))
{
dy = p2.y - p1.y;
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 (u2 < 1.0)
{
p2.x = p1.x + u2 * dx;
p2.y = p1.y + u2 * dy;
}
if (u1 > 0.0)
{
p1.x += u1 * dx;
p1.y += u1 * dy;
}
return true;
}
}
}
}
return false;
}
public static void BeginGroup(Rect position)
{
clippingEnabled = true;
clippingBounds = new Rect(0, 0, position.width, position.height);
GUI.BeginGroup(position);
}
public static void EndGroup()
{
GUI.EndGroup();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false;
}
public static Vector2 BeginScrollView(Rect position, Vector2 scrollPos, Rect viewRect, Rect clipRect)
{
clippingEnabled = true;
clippingBounds = clipRect;
return GUI.BeginScrollView(position, scrollPos, viewRect, GUIStyle.none, GUIStyle.none);
}
public static void EndScrollView()
{
GUI.EndScrollView();
clippingBounds = new Rect(0, 0, Screen.width, Screen.height);
clippingEnabled = false;
}
public static void CreateMaterial()
{
if (lineMaterial != null)
return;
lineMaterial = Resources.Load("GLLineDraw", typeof(Material)) as Material;
}
public static void DrawLine(Vector2 start, Vector2 end, Color color, float width)
{
if (Event.current == null)
return;
if (Event.current.type != EventType.repaint)
return;
if (clippingEnabled)
if (!segment_rect_intersection(clippingBounds, ref start, ref end))
return;
CreateMaterial();
lineMaterial.SetPass(0);
Vector3 startPt;
Vector3 endPt;
if (width == 1)
{
GL.Begin(GL.LINES);
GL.Color(color);
startPt = new Vector3(start.x, start.y, 0);
endPt = new Vector3(end.x, end.y, 0);
GL.Vertex(startPt);
GL.Vertex(endPt);
}
else
{
GL.Begin(GL.QUADS);
GL.Color(color);
startPt = new Vector3(end.y, start.x, 0);
endPt = new Vector3(start.y, end.x, 0);
Vector3 perpendicular = (startPt - endPt).normalized * width;
Vector3 v1 = new Vector3(start.x, start.y, 0);
Vector3 v2 = new Vector3(end.x, end.y, 0);
GL.Vertex(v1 - perpendicular);
GL.Vertex(v1 + perpendicular);
GL.Vertex(v2 + perpendicular);
GL.Vertex(v2 - perpendicular);
}
GL.End();
}
public static void DrawRect(Rect rect, Color color)
{
if (Event.current == null)
return;
if (Event.current.type != EventType.repaint)
return;
CreateMaterial();
// set the current material
lineMaterial.SetPass( 0 );
GL.Begin( GL.QUADS );
GL.Color( color );
GL.Vertex3( rect.xMin, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMin, 0 );
GL.Vertex3( rect.xMax, rect.yMax, 0 );
GL.Vertex3( rect.xMin, rect.yMax, 0 );
GL.End();
}
public static void DrawBox(Rect box, Color color, float width)
{
Vector2 p1 = new Vector2(box.xMin, box.yMin);
Vector2 p2 = new Vector2(box.xMax, box.yMin);
Vector2 p3 = new Vector2(box.xMax, box.yMax);
Vector2 p4 = new Vector2(box.xMin, box.yMax);
DrawLine(p1, p2, color, width);
DrawLine(p2, p3, color, width);
DrawLine(p3, p4, color, width);
DrawLine(p4, p1, color, 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);
DrawBox(box, color, width);
}
public static void DrawRoundedBox(Rect box, float radius, Color color, float width)
{
Vector2 p1, p2, p3, p4, p5, p6, p7, p8;
p1 = new Vector2(box.xMin + radius, box.yMin);
p2 = new Vector2(box.xMax - radius, box.yMin);
p3 = new Vector2(box.xMax, box.yMin + radius);
p4 = new Vector2(box.xMax, box.yMax - radius);
p5 = new Vector2(box.xMax - radius, box.yMax);
p6 = new Vector2(box.xMin + radius, box.yMax);
p7 = new Vector2(box.xMin, box.yMax - radius);
p8 = new Vector2(box.xMin, box.yMin + radius);
DrawLine(p1, p2, color, width);
DrawLine(p3, p4, color, width);
DrawLine(p5, p6, color, width);
DrawLine(p7, p8, color, width);
Vector2 t1, t2;
float halfRadius = radius / 2;
t1 = new Vector2(p8.x, p8.y + halfRadius);
t2 = new Vector2(p1.x - halfRadius, p1.y);
DrawBezier(p8, t1, p1, t2, color, width);
t1 = new Vector2(p2.x + halfRadius, p2.y);
t2 = new Vector2(p3.x, p3.y - halfRadius);
DrawBezier(p2, t1, p3, t2, color, width);
t1 = new Vector2(p4.x, p4.y + halfRadius);
t2 = new Vector2(p5.x + halfRadius, p5.y);
DrawBezier(p4, t1, p5, t2, color, width);
t1 = new Vector2(p6.x - halfRadius, p6.y);
t2 = new Vector2(p7.x, p7.y + halfRadius);
DrawBezier(p6, t1, p7, t2, color, width);
}
public static void DrawConnectingCurve(Vector2 start, Vector2 end, Color color, float width)
{
Vector2 distance = start - end;
Vector2 tangentA = start;
tangentA.x -= distance.x * 0.5f;
Vector2 tangentB = end;
tangentB.x += distance.x * 0.5f;
int segments = Mathf.FloorToInt((distance.magnitude / 20) * 3);
DrawBezier(start, tangentA, end, tangentB, color, width, segments);
Vector2 pA = CubeBezier(start, tangentA, end, tangentB, 0.6f);
Vector2 pB = CubeBezier(start, tangentA, end, tangentB, 0.7f);
float arrowHeadSize = 5;
Vector2 arrowPosA = pB;
Vector2 arrowPosB = arrowPosA;
Vector2 arrowPosC = arrowPosA;
Vector2 dir = (pB - pA).normalized;
arrowPosB.x += dir.y * arrowHeadSize;
arrowPosB.y -= dir.x * arrowHeadSize;
arrowPosB -= dir * arrowHeadSize;
arrowPosC.x -= dir.y * arrowHeadSize;
arrowPosC.y += dir.x * arrowHeadSize;
arrowPosC -= dir * arrowHeadSize;
DrawLine(arrowPosA, arrowPosB, 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)
{
int segments = Mathf.FloorToInt((start - end).magnitude / 20) * 3; // Three segments per distance of 20
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)
{
Vector2 startVector = CubeBezier(start, startTangent, end, endTangent, 0);
for (int i = 1; i <= segments; i++)
{
Vector2 endVector = CubeBezier(start, startTangent, end, endTangent, i / (float)segments);
DrawLine(startVector, endVector, color, width);
startVector = endVector;
}
}
private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t)
{
float rt = 1 - t;
float rtt = rt * t;
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
{
[CustomEditor (typeof(If), true)]
public class IfEditor : CommandEditor
{
protected SerializedProperty variableProp;
protected SerializedProperty compareOperatorProp;
protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp;
protected virtual void OnEnable()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
variableProp = serializedObject.FindProperty("variable");
compareOperatorProp = serializedObject.FindProperty("compareOperator");
booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
If t = target as If;
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null)
{
serializedObject.ApplyModifiedProperties();
return;
}
Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorList = new List<GUIContent>();
operatorList.Add(new GUIContent("=="));
operatorList.Add(new GUIContent("!="));
if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
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,
operatorList.ToArray());
if (variableType == typeof(BooleanVariable))
{
EditorGUILayout.PropertyField(booleanDataProp);
}
else if (variableType == typeof(IntegerVariable))
{
EditorGUILayout.PropertyField(integerDataProp);
}
else if (variableType == typeof(FloatVariable))
{
EditorGUILayout.PropertyField(floatDataProp);
}
else if (variableType == typeof(StringVariable))
{
EditorGUILayout.PropertyField(stringDataProp);
}
serializedObject.ApplyModifiedProperties();
}
}
[CustomEditor (typeof(If), true)]
public class IfEditor : CommandEditor
{
protected SerializedProperty variableProp;
protected SerializedProperty compareOperatorProp;
protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp;
protected virtual void OnEnable()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
variableProp = serializedObject.FindProperty("variable");
compareOperatorProp = serializedObject.FindProperty("compareOperator");
booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
If t = target as If;
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null)
{
serializedObject.ApplyModifiedProperties();
return;
}
Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorList = new List<GUIContent>();
operatorList.Add(new GUIContent("=="));
operatorList.Add(new GUIContent("!="));
if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
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,
operatorList.ToArray());
if (variableType == typeof(BooleanVariable))
{
EditorGUILayout.PropertyField(booleanDataProp);
}
else if (variableType == typeof(IntegerVariable))
{
EditorGUILayout.PropertyField(integerDataProp);
}
else if (variableType == typeof(FloatVariable))
{
EditorGUILayout.PropertyField(floatDataProp);
}
else if (variableType == typeof(StringVariable))
{
EditorGUILayout.PropertyField(stringDataProp);
}
serializedObject.ApplyModifiedProperties();
}
}
}

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

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

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

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

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

@ -13,74 +13,74 @@ using System.Linq;
namespace Fungus
{
[CustomEditor (typeof(Label))]
public class LabelEditor : CommandEditor
{
protected SerializedProperty keyProp;
static public void LabelField(SerializedProperty property,
GUIContent labelText,
Block block)
{
List<string> labelKeys = new List<string>();
List<Label> labelObjects = new List<Label>();
labelKeys.Add("<None>");
labelObjects.Add(null);
Label selectedLabel = property.objectReferenceValue as Label;
[CustomEditor (typeof(Label))]
public class LabelEditor : CommandEditor
{
protected SerializedProperty keyProp;
static public void LabelField(SerializedProperty property,
GUIContent labelText,
Block block)
{
List<string> labelKeys = new List<string>();
List<Label> labelObjects = new List<Label>();
labelKeys.Add("<None>");
labelObjects.Add(null);
Label selectedLabel = property.objectReferenceValue as Label;
int index = 0;
int selectedIndex = 0;
foreach (Command command in block.commandList)
{
Label label = command as Label;
if (label == null)
{
continue;
}
int index = 0;
int selectedIndex = 0;
foreach (Command command in block.commandList)
{
Label label = command as Label;
if (label == null)
{
continue;
}
labelKeys.Add(label.key);
labelObjects.Add(label);
index++;
if (label == selectedLabel)
{
selectedIndex = index;
}
}
labelKeys.Add(label.key);
labelObjects.Add(label);
index++;
if (label == selectedLabel)
{
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()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
protected virtual void OnEnable()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
keyProp = serializedObject.FindProperty("key");
}
public override void DrawCommandGUI()
{
Label t = target as Label;
keyProp = serializedObject.FindProperty("key");
}
public override void DrawCommandGUI()
{
Label t = target as Label;
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
serializedObject.Update();
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
serializedObject.Update();
EditorGUILayout.PropertyField(keyProp);
keyProp.stringValue = flowchart.GetUniqueLabelKey(keyProp.stringValue, t);
EditorGUILayout.PropertyField(keyProp);
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
{
[CustomEditor (typeof(SetVariable))]
public class SetVariableEditor : CommandEditor
{
protected SerializedProperty variableProp;
protected SerializedProperty setOperatorProp;
protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp;
protected virtual void OnEnable()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
variableProp = serializedObject.FindProperty("variable");
setOperatorProp = serializedObject.FindProperty("setOperator");
booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
SetVariable t = target as SetVariable;
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null)
{
serializedObject.ApplyModifiedProperties();
return;
}
Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorsList = new List<GUIContent>();
operatorsList.Add(new GUIContent("="));
if (variableType == typeof(BooleanVariable))
{
operatorsList.Add(new GUIContent("=!"));
}
else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
operatorsList.Add(new GUIContent("+="));
operatorsList.Add(new GUIContent("-="));
operatorsList.Add(new GUIContent("*="));
operatorsList.Add(new GUIContent("/="));
}
int selectedIndex = 0;
switch (t.setOperator)
{
default:
case SetVariable.SetOperator.Assign:
selectedIndex = 0;
break;
case SetVariable.SetOperator.Negate:
selectedIndex = 1;
break;
case SetVariable.SetOperator.Add:
selectedIndex = 1;
break;
case SetVariable.SetOperator.Subtract:
selectedIndex = 2;
break;
case SetVariable.SetOperator.Multiply:
selectedIndex = 3;
break;
case SetVariable.SetOperator.Divide:
selectedIndex = 4;
break;
}
selectedIndex = EditorGUILayout.Popup(new GUIContent("Operation", "Arithmetic operator to use"), selectedIndex, operatorsList.ToArray());
SetVariable.SetOperator setOperator = SetVariable.SetOperator.Assign;
if (variableType == typeof(BooleanVariable) ||
variableType == typeof(StringVariable))
{
switch (selectedIndex)
{
default:
case 0:
setOperator = SetVariable.SetOperator.Assign;
break;
case 1:
setOperator = SetVariable.SetOperator.Negate;
break;
}
}
else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
switch (selectedIndex)
{
default:
case 0:
setOperator = SetVariable.SetOperator.Assign;
break;
case 1:
setOperator = SetVariable.SetOperator.Add;
break;
case 2:
setOperator = SetVariable.SetOperator.Subtract;
break;
case 3:
setOperator = SetVariable.SetOperator.Multiply;
break;
case 4:
setOperator = SetVariable.SetOperator.Divide;
break;
}
}
setOperatorProp.enumValueIndex = (int)setOperator;
if (variableType == typeof(BooleanVariable))
{
EditorGUILayout.PropertyField(booleanDataProp, new GUIContent("Boolean"));
}
else if (variableType == typeof(IntegerVariable))
{
EditorGUILayout.PropertyField(integerDataProp, new GUIContent("Integer"));
}
else if (variableType == typeof(FloatVariable))
{
EditorGUILayout.PropertyField(floatDataProp, new GUIContent("Float"));
}
else if (variableType == typeof(StringVariable))
{
EditorGUILayout.PropertyField(stringDataProp, new GUIContent("String"));
}
serializedObject.ApplyModifiedProperties();
}
}
[CustomEditor (typeof(SetVariable))]
public class SetVariableEditor : CommandEditor
{
protected SerializedProperty variableProp;
protected SerializedProperty setOperatorProp;
protected SerializedProperty booleanDataProp;
protected SerializedProperty integerDataProp;
protected SerializedProperty floatDataProp;
protected SerializedProperty stringDataProp;
protected virtual void OnEnable()
{
if (NullTargetCheck()) // Check for an orphaned editor instance
return;
variableProp = serializedObject.FindProperty("variable");
setOperatorProp = serializedObject.FindProperty("setOperator");
booleanDataProp = serializedObject.FindProperty("booleanData");
integerDataProp = serializedObject.FindProperty("integerData");
floatDataProp = serializedObject.FindProperty("floatData");
stringDataProp = serializedObject.FindProperty("stringData");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
SetVariable t = target as SetVariable;
Flowchart flowchart = t.GetFlowchart();
if (flowchart == null)
{
return;
}
EditorGUILayout.PropertyField(variableProp);
if (variableProp.objectReferenceValue == null)
{
serializedObject.ApplyModifiedProperties();
return;
}
Variable selectedVariable = variableProp.objectReferenceValue as Variable;
System.Type variableType = selectedVariable.GetType();
List<GUIContent> operatorsList = new List<GUIContent>();
operatorsList.Add(new GUIContent("="));
if (variableType == typeof(BooleanVariable))
{
operatorsList.Add(new GUIContent("=!"));
}
else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
operatorsList.Add(new GUIContent("+="));
operatorsList.Add(new GUIContent("-="));
operatorsList.Add(new GUIContent("*="));
operatorsList.Add(new GUIContent("/="));
}
int selectedIndex = 0;
switch (t.setOperator)
{
default:
case SetVariable.SetOperator.Assign:
selectedIndex = 0;
break;
case SetVariable.SetOperator.Negate:
selectedIndex = 1;
break;
case SetVariable.SetOperator.Add:
selectedIndex = 1;
break;
case SetVariable.SetOperator.Subtract:
selectedIndex = 2;
break;
case SetVariable.SetOperator.Multiply:
selectedIndex = 3;
break;
case SetVariable.SetOperator.Divide:
selectedIndex = 4;
break;
}
selectedIndex = EditorGUILayout.Popup(new GUIContent("Operation", "Arithmetic operator to use"), selectedIndex, operatorsList.ToArray());
SetVariable.SetOperator setOperator = SetVariable.SetOperator.Assign;
if (variableType == typeof(BooleanVariable) ||
variableType == typeof(StringVariable))
{
switch (selectedIndex)
{
default:
case 0:
setOperator = SetVariable.SetOperator.Assign;
break;
case 1:
setOperator = SetVariable.SetOperator.Negate;
break;
}
}
else if (variableType == typeof(IntegerVariable) ||
variableType == typeof(FloatVariable))
{
switch (selectedIndex)
{
default:
case 0:
setOperator = SetVariable.SetOperator.Assign;
break;
case 1:
setOperator = SetVariable.SetOperator.Add;
break;
case 2:
setOperator = SetVariable.SetOperator.Subtract;
break;
case 3:
setOperator = SetVariable.SetOperator.Multiply;
break;
case 4:
setOperator = SetVariable.SetOperator.Divide;
break;
}
}
setOperatorProp.enumValueIndex = (int)setOperator;
if (variableType == typeof(BooleanVariable))
{
EditorGUILayout.PropertyField(booleanDataProp, new GUIContent("Boolean"));
}
else if (variableType == typeof(IntegerVariable))
{
EditorGUILayout.PropertyField(integerDataProp, new GUIContent("Integer"));
}
else if (variableType == typeof(FloatVariable))
{
EditorGUILayout.PropertyField(floatDataProp, new GUIContent("Float"));
}
else if (variableType == typeof(StringVariable))
{
EditorGUILayout.PropertyField(stringDataProp, new GUIContent("String"));
}
serializedObject.ApplyModifiedProperties();
}
}
}

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

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

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

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

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

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

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

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

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

@ -9,63 +9,63 @@ using System.Collections;
namespace Fungus
{
[AddComponentMenu("")]
public class CommandCopyBuffer : Block
{
protected static CommandCopyBuffer instance;
/**
* Returns the CommandCopyBuffer singleton instance.
* Will create a CommandCopyBuffer game object if none currently exists.
*/
static public CommandCopyBuffer GetInstance()
{
if (instance == null)
{
// 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
GameObject go = GameObject.Find("_CommandCopyBuffer");
if (go == null)
{
go = new GameObject("_CommandCopyBuffer");
go.hideFlags = HideFlags.HideAndDontSave;
}
[AddComponentMenu("")]
public class CommandCopyBuffer : Block
{
protected static CommandCopyBuffer instance;
/**
* Returns the CommandCopyBuffer singleton instance.
* Will create a CommandCopyBuffer game object if none currently exists.
*/
static public CommandCopyBuffer GetInstance()
{
if (instance == null)
{
// 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
GameObject go = GameObject.Find("_CommandCopyBuffer");
if (go == null)
{
go = new GameObject("_CommandCopyBuffer");
go.hideFlags = HideFlags.HideAndDontSave;
}
instance = go.GetComponent<CommandCopyBuffer>();
if (instance == null)
{
instance = go.AddComponent<CommandCopyBuffer>();
}
}
return instance;
}
instance = go.GetComponent<CommandCopyBuffer>();
if (instance == null)
{
instance = go.AddComponent<CommandCopyBuffer>();
}
}
return instance;
}
protected virtual void Start()
{
if (Application.isPlaying)
{
Destroy(this.gameObject);
}
}
protected virtual void Start()
{
if (Application.isPlaying)
{
Destroy(this.gameObject);
}
}
public virtual bool HasCommands()
{
return GetCommands().Length > 0;
}
public virtual bool HasCommands()
{
return GetCommands().Length > 0;
}
public virtual Command[] GetCommands()
{
return GetComponents<Command>();
}
public virtual Command[] GetCommands()
{
return GetComponents<Command>();
}
public virtual void Clear()
{
foreach (Command command in GetCommands())
{
DestroyImmediate(command);
}
}
}
public virtual void Clear()
{
foreach (Command command in GetCommands())
{
DestroyImmediate(command);
}
}
}
}

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

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

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

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

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

@ -8,69 +8,69 @@ using System.Collections;
namespace Fungus
{
// 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.
// 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.
[CommandInfo("Scripting",
"Call Method",
"Calls a named method on a GameObject using the GameObject.SendMessage() system.")]
[AddComponentMenu("")]
public class CallMethod : Command
{
[Tooltip("Target monobehavior which contains the method we want to call")]
public GameObject targetObject;
[CommandInfo("Scripting",
"Call Method",
"Calls a named method on a GameObject using the GameObject.SendMessage() system.")]
[AddComponentMenu("")]
public class CallMethod : Command
{
[Tooltip("Target monobehavior which contains the method we want to call")]
public GameObject targetObject;
[Tooltip("Name of the method to call")]
public string methodName = "";
[Tooltip("Name of the method to call")]
public string methodName = "";
[Tooltip("Delay (in seconds) before the method will be called")]
public float delay;
[Tooltip("Delay (in seconds) before the method will be called")]
public float delay;
public override void OnEnter()
{
if (targetObject == null ||
methodName.Length == 0)
{
Continue();
return;
}
public override void OnEnter()
{
if (targetObject == null ||
methodName.Length == 0)
{
Continue();
return;
}
if (delay == 0f)
{
CallTheMethod();
}
else
{
Invoke("CallTheMethod", delay);
}
if (delay == 0f)
{
CallTheMethod();
}
else
{
Invoke("CallTheMethod", delay);
}
Continue();
}
Continue();
}
protected virtual void CallTheMethod()
{
targetObject.SendMessage(methodName, SendMessageOptions.DontRequireReceiver);
}
protected virtual void CallTheMethod()
{
targetObject.SendMessage(methodName, SendMessageOptions.DontRequireReceiver);
}
public override string GetSummary()
{
if (targetObject == null)
{
return "Error: No target GameObject specified";
}
public override string GetSummary()
{
if (targetObject == null)
{
return "Error: No target GameObject specified";
}
if (methodName.Length == 0)
{
return "Error: No named method specified";
}
if (methodName.Length == 0)
{
return "Error: No named method specified";
}
return targetObject.name + " : " + methodName;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
return targetObject.name + " : " + methodName;
}
public override Color GetButtonColor()
{
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
{
[CommandInfo("",
"Comment",
"Use comments to record design notes and reminders about your game.")]
[AddComponentMenu("")]
public class Comment : Command
{
[Tooltip("Name of Commenter")]
public string commenterName = "";
[CommandInfo("",
"Comment",
"Use comments to record design notes and reminders about your game.")]
[AddComponentMenu("")]
public class Comment : Command
{
[Tooltip("Name of Commenter")]
public string commenterName = "";
[Tooltip("Text to display for this comment")]
[TextArea(2,4)]
public string commentText = "";
[Tooltip("Text to display for this comment")]
[TextArea(2,4)]
public string commentText = "";
public override void OnEnter()
{
Continue();
}
public override void OnEnter()
{
Continue();
}
public override string GetSummary()
{
if (commenterName != "")
{
return commenterName + ": " + commentText;
}
return commentText;
}
public override string GetSummary()
{
if (commenterName != "")
{
return commenterName + ": " + commentText;
}
return commentText;
}
public override Color GetButtonColor()
{
return new Color32(220, 220, 220, 255);
}
}
public override Color GetButtonColor()
{
return new Color32(220, 220, 220, 255);
}
}
}

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

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

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

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

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

@ -9,47 +9,47 @@ using System.Collections;
namespace Fungus
{
[CommandInfo("Variable",
"Delete Save Key",
"Deletes a saved value from permanent storage.")]
[AddComponentMenu("")]
public class DeleteSaveKey : Command
{
[Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")]
public string key = "";
[CommandInfo("Variable",
"Delete Save Key",
"Deletes a saved value from permanent storage.")]
[AddComponentMenu("")]
public class DeleteSaveKey : Command
{
[Tooltip("Name of the saved value. Supports variable substition e.g. \"player_{$PlayerNumber}")]
public string key = "";
public override void OnEnter()
{
if (key == "")
{
Continue();
return;
}
Flowchart flowchart = GetFlowchart();
// Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
PlayerPrefs.DeleteKey(prefsKey);
public override void OnEnter()
{
if (key == "")
{
Continue();
return;
}
Flowchart flowchart = GetFlowchart();
// Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
PlayerPrefs.DeleteKey(prefsKey);
Continue();
}
public override string GetSummary()
{
if (key.Length == 0)
{
return "Error: No stored value key selected";
}
Continue();
}
public override string GetSummary()
{
if (key.Length == 0)
{
return "Error: No stored value key selected";
}
return key;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
return key;
}
public override Color GetButtonColor()
{
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
{
[CommandInfo("Scripting",
"Destroy",
"Destroys a specified game object in the scene.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class Destroy : Command
{
[Tooltip("Reference to game object to destroy")]
public GameObjectData _targetGameObject;
[CommandInfo("Scripting",
"Destroy",
"Destroys a specified game object in the scene.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class Destroy : Command
{
[Tooltip("Reference to game object to destroy")]
public GameObjectData _targetGameObject;
public override void OnEnter()
{
if (_targetGameObject.Value != null)
{
Destroy(_targetGameObject.Value);
}
public override void OnEnter()
{
if (_targetGameObject.Value != null)
{
Destroy(_targetGameObject.Value);
}
Continue();
}
Continue();
}
public override string GetSummary()
{
if (_targetGameObject.Value == null)
{
return "Error: No game object selected";
}
public override string GetSummary()
{
if (_targetGameObject.Value == null)
{
return "Error: No game object selected";
}
return _targetGameObject.Value.name;
}
return _targetGameObject.Value.name;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override Color GetButtonColor()
{
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()
{
if (targetGameObjectOLD != null)
{
_targetGameObject.Value = targetGameObjectOLD;
targetGameObjectOLD = null;
}
}
protected virtual void OnEnable()
{
if (targetGameObjectOLD != null)
{
_targetGameObject.Value = targetGameObjectOLD;
targetGameObjectOLD = null;
}
}
#endregion
}
#endregion
}
}

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

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

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

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

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

@ -10,130 +10,130 @@ using UnityEngine.Events;
namespace Fungus
{
[CommandInfo("Scripting",
"Invoke Event",
"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.")]
[AddComponentMenu("")]
// This command uses the UnityEvent system to call methods in script.
// http://docs.unity3d.com/Manual/UnityEvents.html
public class InvokeEvent : Command
{
[Serializable] public class BooleanEvent : UnityEvent<bool> {}
[Serializable] public class IntegerEvent : UnityEvent<int> {}
[Serializable] public class FloatEvent : UnityEvent<float> {}
[Serializable] public class StringEvent : UnityEvent<string> {}
public enum InvokeType
{
Static, // Call a method with an optional constant value parameter
DynamicBoolean, // Call a method with an optional boolean 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
DynamicString // Call a method with an optional string constant / variable parameter
}
[Tooltip("Delay (in seconds) before the methods will be called")]
public float delay;
public InvokeType invokeType;
[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();
[Tooltip("Boolean parameter to pass to the invoked methods.")]
public BooleanData booleanParameter;
[Tooltip("List of methods to call. Supports methods with one boolean parameter.")]
public BooleanEvent booleanEvent = new BooleanEvent();
[Tooltip("Integer parameter to pass to the invoked methods.")]
public IntegerData integerParameter;
[Tooltip("List of methods to call. Supports methods with one integer parameter.")]
public IntegerEvent integerEvent = new IntegerEvent();
[Tooltip("Float parameter to pass to the invoked methods.")]
public FloatData floatParameter;
[Tooltip("List of methods to call. Supports methods with one float parameter.")]
public FloatEvent floatEvent = new FloatEvent();
[Tooltip("String parameter to pass to the invoked methods.")]
public StringDataMulti stringParameter;
[Tooltip("List of methods to call. Supports methods with one string parameter.")]
public StringEvent stringEvent = new StringEvent();
public override void OnEnter()
{
if (delay == 0f)
{
DoInvoke();
}
else
{
Invoke("DoInvoke", delay);
}
Continue();
}
protected virtual void DoInvoke()
{
switch (invokeType)
{
default:
case InvokeType.Static:
staticEvent.Invoke();
break;
case InvokeType.DynamicBoolean:
booleanEvent.Invoke(booleanParameter);
break;
case InvokeType.DynamicInteger:
integerEvent.Invoke(integerParameter);
break;
case InvokeType.DynamicFloat:
floatEvent.Invoke(floatParameter);
break;
case InvokeType.DynamicString:
stringEvent.Invoke(stringParameter);
break;
}
}
public override string GetSummary()
{
string summary = invokeType.ToString() + " ";
switch (invokeType)
{
default:
case InvokeType.Static:
summary += staticEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicBoolean:
summary += booleanEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicInteger:
summary += integerEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicFloat:
summary += floatEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicString:
summary += stringEvent.GetPersistentEventCount();
break;
}
return summary + " methods";
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
[CommandInfo("Scripting",
"Invoke Event",
"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.")]
[AddComponentMenu("")]
// This command uses the UnityEvent system to call methods in script.
// http://docs.unity3d.com/Manual/UnityEvents.html
public class InvokeEvent : Command
{
[Serializable] public class BooleanEvent : UnityEvent<bool> {}
[Serializable] public class IntegerEvent : UnityEvent<int> {}
[Serializable] public class FloatEvent : UnityEvent<float> {}
[Serializable] public class StringEvent : UnityEvent<string> {}
public enum InvokeType
{
Static, // Call a method with an optional constant value parameter
DynamicBoolean, // Call a method with an optional boolean 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
DynamicString // Call a method with an optional string constant / variable parameter
}
[Tooltip("Delay (in seconds) before the methods will be called")]
public float delay;
public InvokeType invokeType;
[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();
[Tooltip("Boolean parameter to pass to the invoked methods.")]
public BooleanData booleanParameter;
[Tooltip("List of methods to call. Supports methods with one boolean parameter.")]
public BooleanEvent booleanEvent = new BooleanEvent();
[Tooltip("Integer parameter to pass to the invoked methods.")]
public IntegerData integerParameter;
[Tooltip("List of methods to call. Supports methods with one integer parameter.")]
public IntegerEvent integerEvent = new IntegerEvent();
[Tooltip("Float parameter to pass to the invoked methods.")]
public FloatData floatParameter;
[Tooltip("List of methods to call. Supports methods with one float parameter.")]
public FloatEvent floatEvent = new FloatEvent();
[Tooltip("String parameter to pass to the invoked methods.")]
public StringDataMulti stringParameter;
[Tooltip("List of methods to call. Supports methods with one string parameter.")]
public StringEvent stringEvent = new StringEvent();
public override void OnEnter()
{
if (delay == 0f)
{
DoInvoke();
}
else
{
Invoke("DoInvoke", delay);
}
Continue();
}
protected virtual void DoInvoke()
{
switch (invokeType)
{
default:
case InvokeType.Static:
staticEvent.Invoke();
break;
case InvokeType.DynamicBoolean:
booleanEvent.Invoke(booleanParameter);
break;
case InvokeType.DynamicInteger:
integerEvent.Invoke(integerParameter);
break;
case InvokeType.DynamicFloat:
floatEvent.Invoke(floatParameter);
break;
case InvokeType.DynamicString:
stringEvent.Invoke(stringParameter);
break;
}
}
public override string GetSummary()
{
string summary = invokeType.ToString() + " ";
switch (invokeType)
{
default:
case InvokeType.Static:
summary += staticEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicBoolean:
summary += booleanEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicInteger:
summary += integerEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicFloat:
summary += floatEvent.GetPersistentEventCount();
break;
case InvokeType.DynamicString:
summary += stringEvent.GetPersistentEventCount();
break;
}
return summary + " methods";
}
public override Color GetButtonColor()
{
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
{
[CommandInfo("Scripting",
"Invoke Method",
"Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")]
public class InvokeMethod : Command
{
[Tooltip("GameObject containing the component method to be invoked")]
public GameObject targetObject;
[HideInInspector]
[Tooltip("Name of assembly containing the target component")]
public string targetComponentAssemblyName;
[HideInInspector]
[Tooltip("Full name of the target component")]
public string targetComponentFullname;
[HideInInspector]
[Tooltip("Display name of the target component")]
public string targetComponentText;
[HideInInspector]
[Tooltip("Name of target method to invoke on the target component")]
public string targetMethod;
[HideInInspector]
[Tooltip("Display name of target method to invoke on the target component")]
public string targetMethodText;
[HideInInspector]
[Tooltip("List of parameters to pass to the invoked method")]
public InvokeMethodParameter[] methodParameters;
[HideInInspector]
[Tooltip("If true, store the return value in a flowchart variable of the same type.")]
public bool saveReturnValue;
[HideInInspector]
[Tooltip("Name of Fungus variable to store the return value in")]
public string returnValueVariableKey;
[HideInInspector]
[Tooltip("The type of the return value")]
public string returnValueType;
[HideInInspector]
[Tooltip("If true, list all inherited methods for the component")]
public bool showInherited;
[HideInInspector]
[Tooltip("The coroutine call behavior for methods that return IEnumerator")]
public Fungus.Call.CallMode callMode;
protected Type componentType;
protected Component objComponent;
protected Type[] parameterTypes = null;
protected MethodInfo objMethod;
protected virtual void Awake()
{
if (componentType == null)
{
componentType = ReflectionHelper.GetType(targetComponentAssemblyName);
}
if (objComponent == null)
{
objComponent = targetObject.GetComponent(componentType);
}
if (parameterTypes == null)
{
parameterTypes = GetParameterTypes();
}
if (objMethod == null)
{
objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes);
}
}
public override void OnEnter()
{
try
{
if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod))
{
Continue();
return;
}
if (returnValueType != "System.Collections.IEnumerator")
{
var objReturnValue = objMethod.Invoke(objComponent, GetParameterValues());
if (saveReturnValue)
{
SetVariable(returnValueVariableKey, objReturnValue, returnValueType);
}
Continue();
}
else
{
StartCoroutine(ExecuteCoroutine());
if (callMode == Call.CallMode.Continue)
{
Continue();
}
else if(callMode == Call.CallMode.Stop)
{
StopParentBlock();
}
}
}
catch (System.Exception ex)
{
Debug.LogError("Error: " + ex.Message);
}
}
protected virtual IEnumerator ExecuteCoroutine()
{
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
if (callMode == Call.CallMode.WaitUntilFinished)
{
Continue();
}
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override string GetSummary()
{
if (targetObject == null)
{
return "Error: targetObject is not assigned";
}
return targetObject.name + "." + targetComponentText + "." + targetMethodText;
}
protected System.Type[] GetParameterTypes()
{
System.Type[] types = new System.Type[methodParameters.Length];
for (int i = 0; i < methodParameters.Length; i++)
{
var item = methodParameters[i];
var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname);
types[i] = objType;
}
return types;
}
protected object[] GetParameterValues()
{
object[] values = new object[methodParameters.Length];
var flowChart = GetFlowchart();
for (int i = 0; i < methodParameters.Length; i++)
{
var item = methodParameters[i];
if (string.IsNullOrEmpty(item.variableKey))
{
values[i] = item.objValue.GetValue();
}
else
{
object objValue = null;
switch (item.objValue.typeFullname)
{
case "System.Int32":
[CommandInfo("Scripting",
"Invoke Method",
"Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")]
public class InvokeMethod : Command
{
[Tooltip("GameObject containing the component method to be invoked")]
public GameObject targetObject;
[HideInInspector]
[Tooltip("Name of assembly containing the target component")]
public string targetComponentAssemblyName;
[HideInInspector]
[Tooltip("Full name of the target component")]
public string targetComponentFullname;
[HideInInspector]
[Tooltip("Display name of the target component")]
public string targetComponentText;
[HideInInspector]
[Tooltip("Name of target method to invoke on the target component")]
public string targetMethod;
[HideInInspector]
[Tooltip("Display name of target method to invoke on the target component")]
public string targetMethodText;
[HideInInspector]
[Tooltip("List of parameters to pass to the invoked method")]
public InvokeMethodParameter[] methodParameters;
[HideInInspector]
[Tooltip("If true, store the return value in a flowchart variable of the same type.")]
public bool saveReturnValue;
[HideInInspector]
[Tooltip("Name of Fungus variable to store the return value in")]
public string returnValueVariableKey;
[HideInInspector]
[Tooltip("The type of the return value")]
public string returnValueType;
[HideInInspector]
[Tooltip("If true, list all inherited methods for the component")]
public bool showInherited;
[HideInInspector]
[Tooltip("The coroutine call behavior for methods that return IEnumerator")]
public Fungus.Call.CallMode callMode;
protected Type componentType;
protected Component objComponent;
protected Type[] parameterTypes = null;
protected MethodInfo objMethod;
protected virtual void Awake()
{
if (componentType == null)
{
componentType = ReflectionHelper.GetType(targetComponentAssemblyName);
}
if (objComponent == null)
{
objComponent = targetObject.GetComponent(componentType);
}
if (parameterTypes == null)
{
parameterTypes = GetParameterTypes();
}
if (objMethod == null)
{
objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes);
}
}
public override void OnEnter()
{
try
{
if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod))
{
Continue();
return;
}
if (returnValueType != "System.Collections.IEnumerator")
{
var objReturnValue = objMethod.Invoke(objComponent, GetParameterValues());
if (saveReturnValue)
{
SetVariable(returnValueVariableKey, objReturnValue, returnValueType);
}
Continue();
}
else
{
StartCoroutine(ExecuteCoroutine());
if (callMode == Call.CallMode.Continue)
{
Continue();
}
else if(callMode == Call.CallMode.Stop)
{
StopParentBlock();
}
}
}
catch (System.Exception ex)
{
Debug.LogError("Error: " + ex.Message);
}
}
protected virtual IEnumerator ExecuteCoroutine()
{
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
if (callMode == Call.CallMode.WaitUntilFinished)
{
Continue();
}
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override string GetSummary()
{
if (targetObject == null)
{
return "Error: targetObject is not assigned";
}
return targetObject.name + "." + targetComponentText + "." + targetMethodText;
}
protected System.Type[] GetParameterTypes()
{
System.Type[] types = new System.Type[methodParameters.Length];
for (int i = 0; i < methodParameters.Length; i++)
{
var item = methodParameters[i];
var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname);
types[i] = objType;
}
return types;
}
protected object[] GetParameterValues()
{
object[] values = new object[methodParameters.Length];
var flowChart = GetFlowchart();
for (int i = 0; i < methodParameters.Length; i++)
{
var item = methodParameters[i];
if (string.IsNullOrEmpty(item.variableKey))
{
values[i] = item.objValue.GetValue();
}
else
{
object objValue = null;
switch (item.objValue.typeFullname)
{
case "System.Int32":
var intvalue = flowChart.GetVariable<IntegerVariable>(item.variableKey);
if (intvalue != null)
objValue = intvalue.value;
@ -205,7 +205,7 @@ namespace Fungus
if (boolean != null)
objValue = boolean.value;
break;
case "System.Single":
case "System.Single":
var floatvalue = flowChart.GetVariable<FloatVariable>(item.variableKey);
if (floatvalue != null)
objValue = floatvalue.value;
@ -216,187 +216,187 @@ namespace Fungus
objValue = stringvalue.value;
break;
case "UnityEngine.Color":
var color = flowChart.GetVariable<ColorVariable>(item.variableKey);
if (color != null)
objValue = color.value;
break;
case "UnityEngine.GameObject":
var gameObject = flowChart.GetVariable<GameObjectVariable>(item.variableKey);
if (gameObject != null)
objValue = gameObject.value;
break;
case "UnityEngine.Material":
var material = flowChart.GetVariable<MaterialVariable>(item.variableKey);
if (material != null)
objValue = material.value;
break;
case "UnityEngine.Sprite":
var sprite = flowChart.GetVariable<SpriteVariable>(item.variableKey);
if (sprite != null)
objValue = sprite.value;
break;
case "UnityEngine.Texture":
var texture = flowChart.GetVariable<TextureVariable>(item.variableKey);
if (texture != null)
objValue = texture.value;
break;
case "UnityEngine.Vector2":
var vector2 = flowChart.GetVariable<Vector2Variable>(item.variableKey);
if (vector2 != null)
objValue = vector2.value;
break;
case "UnityEngine.Vector3":
var vector3 = flowChart.GetVariable<Vector3Variable>(item.variableKey);
if (vector3 != null)
objValue = vector3.value;
break;
default:
var obj = flowChart.GetVariable<ObjectVariable>(item.variableKey);
if (obj != null)
objValue = obj.value;
break;
}
values[i] = objValue;
}
}
return values;
}
protected void SetVariable(string key, object value, string returnType)
{
var flowChart = GetFlowchart();
switch (returnType)
{
case "System.Int32":
var color = flowChart.GetVariable<ColorVariable>(item.variableKey);
if (color != null)
objValue = color.value;
break;
case "UnityEngine.GameObject":
var gameObject = flowChart.GetVariable<GameObjectVariable>(item.variableKey);
if (gameObject != null)
objValue = gameObject.value;
break;
case "UnityEngine.Material":
var material = flowChart.GetVariable<MaterialVariable>(item.variableKey);
if (material != null)
objValue = material.value;
break;
case "UnityEngine.Sprite":
var sprite = flowChart.GetVariable<SpriteVariable>(item.variableKey);
if (sprite != null)
objValue = sprite.value;
break;
case "UnityEngine.Texture":
var texture = flowChart.GetVariable<TextureVariable>(item.variableKey);
if (texture != null)
objValue = texture.value;
break;
case "UnityEngine.Vector2":
var vector2 = flowChart.GetVariable<Vector2Variable>(item.variableKey);
if (vector2 != null)
objValue = vector2.value;
break;
case "UnityEngine.Vector3":
var vector3 = flowChart.GetVariable<Vector3Variable>(item.variableKey);
if (vector3 != null)
objValue = vector3.value;
break;
default:
var obj = flowChart.GetVariable<ObjectVariable>(item.variableKey);
if (obj != null)
objValue = obj.value;
break;
}
values[i] = objValue;
}
}
return values;
}
protected void SetVariable(string key, object value, string returnType)
{
var flowChart = GetFlowchart();
switch (returnType)
{
case "System.Int32":
flowChart.GetVariable<IntegerVariable>(key).value = (int)value;
break;
case "System.Boolean":
case "System.Boolean":
flowChart.GetVariable<BooleanVariable>(key).value = (bool)value;
break;
case "System.Single":
break;
case "System.Single":
flowChart.GetVariable<FloatVariable>(key).value = (float)value;
break;
case "System.String":
case "System.String":
flowChart.GetVariable<StringVariable>(key).value = (string)value;
break;
case "UnityEngine.Color":
flowChart.GetVariable<ColorVariable>(key).value = (UnityEngine.Color)value;
break;
case "UnityEngine.GameObject":
flowChart.GetVariable<GameObjectVariable>(key).value = (UnityEngine.GameObject)value;
break;
case "UnityEngine.Material":
flowChart.GetVariable<MaterialVariable>(key).value = (UnityEngine.Material)value;
break;
case "UnityEngine.Sprite":
flowChart.GetVariable<SpriteVariable>(key).value = (UnityEngine.Sprite)value;
break;
case "UnityEngine.Texture":
flowChart.GetVariable<TextureVariable>(key).value = (UnityEngine.Texture)value;
break;
case "UnityEngine.Vector2":
flowChart.GetVariable<Vector2Variable>(key).value = (UnityEngine.Vector2)value;
break;
case "UnityEngine.Vector3":
flowChart.GetVariable<Vector3Variable>(key).value = (UnityEngine.Vector3)value;
break;
default:
flowChart.GetVariable<ObjectVariable>(key).value = (UnityEngine.Object)value;
break;
}
}
}
[System.Serializable]
public class InvokeMethodParameter
{
[SerializeField]
public ObjectValue objValue;
[SerializeField]
public string variableKey;
}
[System.Serializable]
public class ObjectValue
{
public string typeAssemblyname;
public string typeFullname;
public int intValue;
public bool boolValue;
public float floatValue;
public string stringValue;
public Color colorValue;
public GameObject gameObjectValue;
public Material materialValue;
public UnityEngine.Object objectValue;
public Sprite spriteValue;
public Texture textureValue;
public Vector2 vector2Value;
public Vector3 vector3Value;
public object GetValue()
{
switch (typeFullname)
{
case "System.Int32":
return intValue;
case "System.Boolean":
return boolValue;
case "System.Single":
return floatValue;
case "System.String":
return stringValue;
case "UnityEngine.Color":
return colorValue;
case "UnityEngine.GameObject":
return gameObjectValue;
case "UnityEngine.Material":
return materialValue;
case "UnityEngine.Sprite":
return spriteValue;
case "UnityEngine.Texture":
return textureValue;
case "UnityEngine.Vector2":
return vector2Value;
case "UnityEngine.Vector3":
return vector3Value;
default:
var objType = ReflectionHelper.GetType(typeAssemblyname);
if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
{
return objectValue;
}
else if (objType.IsEnum())
return System.Enum.ToObject(objType, intValue);
break;
}
return null;
}
}
public static class ReflectionHelper
{
static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>();
public static System.Type GetType(string typeName)
{
if (types.ContainsKey(typeName))
return types[typeName];
types[typeName] = System.Type.GetType(typeName);
return types[typeName];
}
}
case "UnityEngine.Color":
flowChart.GetVariable<ColorVariable>(key).value = (UnityEngine.Color)value;
break;
case "UnityEngine.GameObject":
flowChart.GetVariable<GameObjectVariable>(key).value = (UnityEngine.GameObject)value;
break;
case "UnityEngine.Material":
flowChart.GetVariable<MaterialVariable>(key).value = (UnityEngine.Material)value;
break;
case "UnityEngine.Sprite":
flowChart.GetVariable<SpriteVariable>(key).value = (UnityEngine.Sprite)value;
break;
case "UnityEngine.Texture":
flowChart.GetVariable<TextureVariable>(key).value = (UnityEngine.Texture)value;
break;
case "UnityEngine.Vector2":
flowChart.GetVariable<Vector2Variable>(key).value = (UnityEngine.Vector2)value;
break;
case "UnityEngine.Vector3":
flowChart.GetVariable<Vector3Variable>(key).value = (UnityEngine.Vector3)value;
break;
default:
flowChart.GetVariable<ObjectVariable>(key).value = (UnityEngine.Object)value;
break;
}
}
}
[System.Serializable]
public class InvokeMethodParameter
{
[SerializeField]
public ObjectValue objValue;
[SerializeField]
public string variableKey;
}
[System.Serializable]
public class ObjectValue
{
public string typeAssemblyname;
public string typeFullname;
public int intValue;
public bool boolValue;
public float floatValue;
public string stringValue;
public Color colorValue;
public GameObject gameObjectValue;
public Material materialValue;
public UnityEngine.Object objectValue;
public Sprite spriteValue;
public Texture textureValue;
public Vector2 vector2Value;
public Vector3 vector3Value;
public object GetValue()
{
switch (typeFullname)
{
case "System.Int32":
return intValue;
case "System.Boolean":
return boolValue;
case "System.Single":
return floatValue;
case "System.String":
return stringValue;
case "UnityEngine.Color":
return colorValue;
case "UnityEngine.GameObject":
return gameObjectValue;
case "UnityEngine.Material":
return materialValue;
case "UnityEngine.Sprite":
return spriteValue;
case "UnityEngine.Texture":
return textureValue;
case "UnityEngine.Vector2":
return vector2Value;
case "UnityEngine.Vector3":
return vector3Value;
default:
var objType = ReflectionHelper.GetType(typeAssemblyname);
if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
{
return objectValue;
}
else if (objType.IsEnum())
return System.Enum.ToObject(objType, intValue);
break;
}
return null;
}
}
public static class ReflectionHelper
{
static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>();
public static System.Type GetType(string typeName)
{
if (types.ContainsKey(typeName))
return types[typeName];
types[typeName] = System.Type.GetType(typeName);
return types[typeName];
}
}
}

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

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

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

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

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

@ -10,56 +10,56 @@ using System.Collections;
namespace Fungus
{
[CommandInfo("Flow",
"Load Scene",
"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 " +
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class LoadScene : Command
{
[Tooltip("Name of the scene to load. The scene must also be added to the build settings.")]
public StringData _sceneName = new StringData("");
[CommandInfo("Flow",
"Load Scene",
"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 " +
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class LoadScene : Command
{
[Tooltip("Name of the scene to load. The scene must also be added to the build settings.")]
public StringData _sceneName = new StringData("");
[Tooltip("Image to display while loading the scene")]
public Texture2D loadingImage;
[Tooltip("Image to display while loading the scene")]
public Texture2D loadingImage;
public override void OnEnter()
{
SceneLoader.LoadScene(_sceneName.Value, loadingImage);
}
public override void OnEnter()
{
SceneLoader.LoadScene(_sceneName.Value, loadingImage);
}
public override string GetSummary()
{
if (_sceneName.Value.Length == 0)
{
return "Error: No scene name selected";
}
public override string GetSummary()
{
if (_sceneName.Value.Length == 0)
{
return "Error: No scene name selected";
}
return _sceneName;
}
return _sceneName;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override Color GetButtonColor()
{
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()
{
if (sceneNameOLD != "")
{
_sceneName.Value = sceneNameOLD;
sceneNameOLD = "";
}
}
protected virtual void OnEnable()
{
if (sceneNameOLD != "")
{
_sceneName.Value = sceneNameOLD;
sceneNameOLD = "";
}
}
#endregion
}
#endregion
}
}

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

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

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

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

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

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

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

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

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

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

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

@ -10,56 +10,56 @@ using Fungus;
namespace Fungus
{
[CommandInfo("Variable",
"Read Text File",
"Reads in a text file and stores the contents in a string variable")]
public class ReadTextFile : Command
{
[Tooltip("Text file to read into the string variable")]
public TextAsset textFile;
[CommandInfo("Variable",
"Read Text File",
"Reads in a text file and stores the contents in a string variable")]
public class ReadTextFile : Command
{
[Tooltip("Text file to read into the string variable")]
public TextAsset textFile;
[Tooltip("String variable to store the tex file contents in")]
[VariableProperty(typeof(StringVariable))]
public StringVariable stringVariable;
[Tooltip("String variable to store the tex file contents in")]
[VariableProperty(typeof(StringVariable))]
public StringVariable stringVariable;
public override void OnEnter()
{
if (textFile == null ||
stringVariable == null)
{
Continue();
return;
}
public override void OnEnter()
{
if (textFile == null ||
stringVariable == null)
{
Continue();
return;
}
stringVariable.value = textFile.text;
stringVariable.value = textFile.text;
Continue();
}
Continue();
}
public override string GetSummary()
{
if (stringVariable == null)
{
return "Error: Variable not selected";
}
public override string GetSummary()
{
if (stringVariable == null)
{
return "Error: Variable not selected";
}
if (textFile == null)
{
return "Error: Text file not selected";
}
if (textFile == null)
{
return "Error: Text file not selected";
}
return stringVariable.key;
}
public override bool HasReference(Variable variable)
{
return (variable == stringVariable);
}
public override Color GetButtonColor()
{
return new Color32(253, 253, 150, 255);
}
}
return stringVariable.key;
}
public override bool HasReference(Variable variable)
{
return (variable == stringVariable);
}
public override Color GetButtonColor()
{
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
{
[CommandInfo("Variable",
"Reset",
"Resets the state of all commands and variables in the Flowchart.")]
[AddComponentMenu("")]
public class Reset : Command
{
[Tooltip("Reset state of all commands in the script")]
public bool resetCommands = true;
[CommandInfo("Variable",
"Reset",
"Resets the state of all commands and variables in the Flowchart.")]
[AddComponentMenu("")]
public class Reset : Command
{
[Tooltip("Reset state of all commands in the script")]
public bool resetCommands = true;
[Tooltip("Reset variables back to their default values")]
public bool resetVariables = true;
[Tooltip("Reset variables back to their default values")]
public bool resetVariables = true;
public override void OnEnter()
{
GetFlowchart().Reset(resetCommands, resetVariables);
Continue();
}
public override void OnEnter()
{
GetFlowchart().Reset(resetCommands, resetVariables);
Continue();
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
}

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

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

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

@ -9,85 +9,85 @@ using System.Collections;
namespace Fungus
{
[CommandInfo("Flow",
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class SendMessage : Command
{
public enum MessageTarget
{
SameFlowchart,
AllFlowcharts
}
[CommandInfo("Flow",
"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.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class SendMessage : Command
{
public enum MessageTarget
{
SameFlowchart,
AllFlowcharts
}
[Tooltip("Target flowchart(s) to send the message to")]
public MessageTarget messageTarget;
[Tooltip("Target flowchart(s) to send the message to")]
public MessageTarget messageTarget;
[Tooltip("Name of the message to send")]
public StringData _message = new StringData("");
[Tooltip("Name of the message to send")]
public StringData _message = new StringData("");
public override void OnEnter()
{
if (_message.Value.Length == 0)
{
Continue();
return;
}
public override void OnEnter()
{
if (_message.Value.Length == 0)
{
Continue();
return;
}
Flowchart flowchart = GetFlowchart();
Flowchart flowchart = GetFlowchart();
MessageReceived[] receivers = null;
if (messageTarget == MessageTarget.SameFlowchart)
{
receivers = flowchart.GetComponents<MessageReceived>();
}
else
{
receivers = GameObject.FindObjectsOfType<MessageReceived>();
}
MessageReceived[] receivers = null;
if (messageTarget == MessageTarget.SameFlowchart)
{
receivers = flowchart.GetComponents<MessageReceived>();
}
else
{
receivers = GameObject.FindObjectsOfType<MessageReceived>();
}
if (receivers != null)
{
foreach (MessageReceived receiver in receivers)
{
receiver.OnSendFungusMessage(_message.Value);
}
}
if (receivers != null)
{
foreach (MessageReceived receiver in receivers)
{
receiver.OnSendFungusMessage(_message.Value);
}
}
Continue();
}
Continue();
}
public override string GetSummary()
{
if (_message.Value.Length == 0)
{
return "Error: No message specified";
}
return _message.Value;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override string GetSummary()
{
if (_message.Value.Length == 0)
{
return "Error: No message specified";
}
return _message.Value;
}
public override Color GetButtonColor()
{
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()
{
if (messageOLD != "")
{
_message.Value = messageOLD;
messageOLD = "";
}
}
protected virtual void OnEnable()
{
if (messageOLD != "")
{
_message.Value = messageOLD;
messageOLD = "";
}
}
#endregion
}
#endregion
}
}

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

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

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

@ -9,36 +9,36 @@ using System.Collections;
namespace Fungus
{
[CommandInfo("Variable",
"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.")]
[AddComponentMenu("")]
public class SetSaveProfile : Command
{
/**
* Shared save profile name used by SaveVariable and LoadVariable.
*/
public static string saveProfile = "";
[CommandInfo("Variable",
"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.")]
[AddComponentMenu("")]
public class SetSaveProfile : Command
{
/**
* Shared save profile name used by SaveVariable and LoadVariable.
*/
public static string saveProfile = "";
[Tooltip("Name of save profile to make active.")]
public string saveProfileName = "";
[Tooltip("Name of save profile to make active.")]
public string saveProfileName = "";
public override void OnEnter()
{
saveProfile = saveProfileName;
public override void OnEnter()
{
saveProfile = saveProfileName;
Continue();
}
public override string GetSummary()
{
return saveProfileName;
}
Continue();
}
public override string GetSummary()
{
return saveProfileName;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
}

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

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

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

@ -9,95 +9,95 @@ using System.Collections;
namespace Fungus
{
// 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.
[CommandInfo("Scripting",
"Spawn Object",
"Spawns a new object based on a reference to a scene or prefab game object.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class SpawnObject : Command
{
[Tooltip("Game object to copy when spawning. Can be a scene object or a prefab.")]
public GameObjectData _sourceObject;
[Tooltip("Transform to use for position of newly spawned object.")]
public TransformData _parentTransform;
[Tooltip("Local position of newly spawned object.")]
public Vector3Data _spawnPosition;
[Tooltip("Local rotation of newly spawned object.")]
public Vector3Data _spawnRotation;
public override void OnEnter()
{
if (_sourceObject.Value == null)
{
Continue();
return;
}
GameObject newObject = GameObject.Instantiate(_sourceObject.Value);
if (_parentTransform.Value != null)
{
newObject.transform.parent = _parentTransform.Value;
}
newObject.transform.localPosition = _spawnPosition.Value;
newObject.transform.localRotation = Quaternion.Euler(_spawnRotation.Value);
Continue();
}
public override string GetSummary()
{
if (_sourceObject.Value == null)
{
return "Error: No source GameObject specified";
}
return _sourceObject.Value.name;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
#region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("sourceObject")] public GameObject sourceObjectOLD;
[HideInInspector] [FormerlySerializedAs("parentTransform")] public Transform parentTransformOLD;
[HideInInspector] [FormerlySerializedAs("spawnPosition")] public Vector3 spawnPositionOLD;
[HideInInspector] [FormerlySerializedAs("spawnRotation")] public Vector3 spawnRotationOLD;
protected virtual void OnEnable()
{
if (sourceObjectOLD != null)
{
_sourceObject.Value = sourceObjectOLD;
sourceObjectOLD = null;
}
if (parentTransformOLD != null)
{
_parentTransform.Value = parentTransformOLD;
parentTransformOLD = null;
}
if (spawnPositionOLD != default(Vector3))
{
_spawnPosition.Value = spawnPositionOLD;
spawnPositionOLD = default(Vector3);
}
if (spawnRotationOLD != default(Vector3))
{
_spawnRotation.Value = spawnRotationOLD;
spawnRotationOLD = default(Vector3);
}
}
#endregion
}
// 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.
[CommandInfo("Scripting",
"Spawn Object",
"Spawns a new object based on a reference to a scene or prefab game object.")]
[AddComponentMenu("")]
[ExecuteInEditMode]
public class SpawnObject : Command
{
[Tooltip("Game object to copy when spawning. Can be a scene object or a prefab.")]
public GameObjectData _sourceObject;
[Tooltip("Transform to use for position of newly spawned object.")]
public TransformData _parentTransform;
[Tooltip("Local position of newly spawned object.")]
public Vector3Data _spawnPosition;
[Tooltip("Local rotation of newly spawned object.")]
public Vector3Data _spawnRotation;
public override void OnEnter()
{
if (_sourceObject.Value == null)
{
Continue();
return;
}
GameObject newObject = GameObject.Instantiate(_sourceObject.Value);
if (_parentTransform.Value != null)
{
newObject.transform.parent = _parentTransform.Value;
}
newObject.transform.localPosition = _spawnPosition.Value;
newObject.transform.localRotation = Quaternion.Euler(_spawnRotation.Value);
Continue();
}
public override string GetSummary()
{
if (_sourceObject.Value == null)
{
return "Error: No source GameObject specified";
}
return _sourceObject.Value.name;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
#region Backwards compatibility
[HideInInspector] [FormerlySerializedAs("sourceObject")] public GameObject sourceObjectOLD;
[HideInInspector] [FormerlySerializedAs("parentTransform")] public Transform parentTransformOLD;
[HideInInspector] [FormerlySerializedAs("spawnPosition")] public Vector3 spawnPositionOLD;
[HideInInspector] [FormerlySerializedAs("spawnRotation")] public Vector3 spawnRotationOLD;
protected virtual void OnEnable()
{
if (sourceObjectOLD != null)
{
_sourceObject.Value = sourceObjectOLD;
sourceObjectOLD = null;
}
if (parentTransformOLD != null)
{
_parentTransform.Value = parentTransformOLD;
parentTransformOLD = null;
}
if (spawnPositionOLD != default(Vector3))
{
_spawnPosition.Value = spawnPositionOLD;
spawnPositionOLD = default(Vector3);
}
if (spawnRotationOLD != default(Vector3))
{
_spawnRotation.Value = spawnRotationOLD;
spawnRotationOLD = default(Vector3);
}
}
#endregion
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1616
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
{
// Used by the Flowchart window to serialize the currently active Flowchart object
// so that the same Flowchart can be displayed while editing & playing.
[AddComponentMenu("")]
public class FungusState : MonoBehaviour
{
public Flowchart selectedFlowchart;
}
// Used by the Flowchart window to serialize the currently active Flowchart object
// so that the same Flowchart can be displayed while editing & playing.
[AddComponentMenu("")]
public class FungusState : MonoBehaviour
{
public Flowchart selectedFlowchart;
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save