<commit_before>using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Rotorz.ReorderableList;

namespace Fungus
{

	[CustomEditor (typeof(Sequence))]
	public class SequenceEditor : Editor 
	{
		protected class AddCommandOperation
		{
			public Sequence sequence;
			public Type commandType;
			public int index;
		}

		protected SerializedProperty sequenceNameProp;

		public virtual void OnEnable()
		{
			sequenceNameProp = serializedObject.FindProperty("sequenceName");

			/*
			// Strip out any null commands from the command list
			// This can happen if a command class is removed or renamed
			serializedObject.Update();
			SerializedProperty commandListProperty = serializedObject.FindProperty("commandList");
			for (int i = commandListProperty.arraySize - 1; i >= 0; --i)
			{
				SerializedProperty commandProperty = commandListProperty.GetArrayElementAtIndex(i);
				if (commandProperty.objectReferenceValue == null)
				{
					commandListProperty.DeleteArrayElementAtIndex(i);
				}
			}
			serializedObject.ApplyModifiedProperties();
			*/
		}

		public virtual void DrawInspectorGUI(FungusScript fungusScript)
		{
			serializedObject.Update();

			EditorGUILayout.PropertyField(sequenceNameProp);
			EditorGUILayout.Separator();

			serializedObject.ApplyModifiedProperties();
		}

		public virtual void DrawCommandListGUI(FungusScript fungusScript)
		{
			serializedObject.Update();

			Sequence sequence = target as Sequence;
			UpdateIndentLevels(sequence);

			sequence.nodeRect.width = 240;

			ReorderableListGUI.Title(sequence.sequenceName);
			SerializedProperty commandListProperty = serializedObject.FindProperty("commandList");
			CommandListAdaptor adaptor = new CommandListAdaptor(commandListProperty, 0);
			adaptor.nodeRect = sequence.nodeRect;

			ReorderableListFlags flags = ReorderableListFlags.HideAddButton | ReorderableListFlags.HideRemoveButtons | ReorderableListFlags.DisableContextMenu;
			ReorderableListControl.DrawControlFromState(adaptor, null, flags);

			Rect bottomBoxRect = GUILayoutUtility.GetRect(sequence.nodeRect.width, 20);
			bottomBoxRect.y -= 7;
			bottomBoxRect.x += 5;
			bottomBoxRect.width -= 10;
			if (sequence.commandList.Count == 0)
			{
				bottomBoxRect.y -= 16;
			}

			GUIStyle boxStyle = new GUIStyle();
			boxStyle.border = new RectOffset(2, 2, 2, 1);
			boxStyle.margin = new RectOffset(5, 5, 5, 0);
			boxStyle.padding = new RectOffset(5, 5, 0, 0);
			boxStyle.alignment = TextAnchor.MiddleLeft;
			boxStyle.normal.background = FungusEditorResources.texTitleBackground;
			boxStyle.normal.textColor = EditorGUIUtility.isProSkin
										? new Color(0.8f, 0.8f, 0.8f)
										: new Color(0.2f, 0.2f, 0.2f);

			GUI.Box(bottomBoxRect, "", boxStyle);

			if (!Application.isPlaying &&
			    sequence == fungusScript.selectedSequence)
			{
				// Show add command button
				{
					Rect plusRect = bottomBoxRect;
					plusRect.x = plusRect.width - 19;
					plusRect.y += 2;
					plusRect.width = 16;
					plusRect.height = 16;

					if (GUI.Button(plusRect, FungusEditorResources.texAddButton, new GUIStyle()))
					{
						ShowCommandMenu();
					}
				}

				// Show delete sequence button
				{
					Rect deleteRect = new Rect();
					deleteRect.x = sequence.nodeRect.width - 28;
					deleteRect.y = 7;
					deleteRect.width = 16;
					deleteRect.height = 16;
					
					if (GUI.Button(deleteRect, "", new GUIStyle("WinBtnCloseWin")))
					{
						FungusScriptWindow.DeleteSequence();
					}
				}
			}

			serializedObject.ApplyModifiedProperties();

			if (!Application.isPlaying)
			{
				if (Event.current.button == 1 && 
				    Event.current.type == EventType.MouseDown)
				{
					// Set a flag to show the context menu on the new display frame
					// This gives the sequence list display a chance to update
					FungusScriptWindow.showContextMenu = true;
					Event.current.Use();
				}
			}
		}

		protected virtual void UpdateIndentLevels(Sequence sequence)
		{
			int indentLevel = 0;
			foreach(Command command in sequence.commandList)
			{
				indentLevel += command.GetPreIndent();
				command.indentLevel = Math.Max(indentLevel, 0);
				indentLevel += command.GetPostIndent();
			}
		}

		static public void SequenceField(SerializedProperty property, GUIContent label, GUIContent nullLabel, FungusScript fungusScript)
		{
			if (fungusScript == null)
			{
				return;
			}

			Sequence sequence = property.objectReferenceValue as Sequence;
		
			// Build dictionary of child sequences
			List<GUIContent> sequenceNames = new List<GUIContent>();
			
			int selectedIndex = 0;
			sequenceNames.Add(nullLabel);
			Sequence[] sequences = fungusScript.GetComponentsInChildren<Sequence>(true);
			for (int i = 0; i < sequences.Length; ++i)
			{
				sequenceNames.Add(new GUIContent(sequences[i].sequenceName));
				
				if (sequence == sequences[i])
				{
					selectedIndex = i + 1;
				}
			}<commit_msg>Fixed null reference exceptions when deleting a command class<commit_after>using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Rotorz.ReorderableList;

namespace Fungus
{

	[CustomEditor (typeof(Sequence))]
	public class SequenceEditor : Editor 
	{
		protected class AddCommandOperation
		{
			public Sequence sequence;
			public Type commandType;
			public int index;
		}

		public virtual void DrawInspectorGUI(FungusScript fungusScript)
		{
			serializedObject.Update();

			// We acquire the serialized properties in the draw methods instead of in OnEnable as otherwise
			// deleting or renaming a command class would generate a bunch of null reference exceptions.
			SerializedProperty sequenceNameProp = serializedObject.FindProperty("sequenceName");

			EditorGUILayout.PropertyField(sequenceNameProp);
			EditorGUILayout.Separator();

			serializedObject.ApplyModifiedProperties();
		}

		public virtual void DrawCommandListGUI(FungusScript fungusScript)
		{
			serializedObject.Update();

			Sequence sequence = target as Sequence;
			UpdateIndentLevels(sequence);

			sequence.nodeRect.width = 240;

			SerializedProperty commandListProperty = serializedObject.FindProperty("commandList");

			ReorderableListGUI.Title(sequence.sequenceName);
			CommandListAdaptor adaptor = new CommandListAdaptor(commandListProperty, 0);
			adaptor.nodeRect = sequence.nodeRect;

			ReorderableListFlags flags = ReorderableListFlags.HideAddButton | ReorderableListFlags.HideRemoveButtons | ReorderableListFlags.DisableContextMenu;
			ReorderableListControl.DrawControlFromState(adaptor, null, flags);

			Rect bottomBoxRect = GUILayoutUtility.GetRect(sequence.nodeRect.width, 20);
			bottomBoxRect.y -= 7;
			bottomBoxRect.x += 5;
			bottomBoxRect.width -= 10;
			if (sequence.commandList.Count == 0)
			{
				bottomBoxRect.y -= 16;
			}

			GUIStyle boxStyle = new GUIStyle();
			boxStyle.border = new RectOffset(2, 2, 2, 1);
			boxStyle.margin = new RectOffset(5, 5, 5, 0);
			boxStyle.padding = new RectOffset(5, 5, 0, 0);
			boxStyle.alignment = TextAnchor.MiddleLeft;
			boxStyle.normal.background = FungusEditorResources.texTitleBackground;
			boxStyle.normal.textColor = EditorGUIUtility.isProSkin
										? new Color(0.8f, 0.8f, 0.8f)
										: new Color(0.2f, 0.2f, 0.2f);

			GUI.Box(bottomBoxRect, "", boxStyle);

			if (!Application.isPlaying &&
			    sequence == fungusScript.selectedSequence)
			{
				// Show add command button
				{
					Rect plusRect = bottomBoxRect;
					plusRect.x = plusRect.width - 19;
					plusRect.y += 2;
					plusRect.width = 16;
					plusRect.height = 16;

					if (GUI.Button(plusRect, FungusEditorResources.texAddButton, new GUIStyle()))
					{
						ShowCommandMenu();
					}
				}

				// Show delete sequence button
				{
					Rect deleteRect = new Rect();
					deleteRect.x = sequence.nodeRect.width - 28;
					deleteRect.y = 7;
					deleteRect.width = 16;
					deleteRect.height = 16;
					
					if (GUI.Button(deleteRect, "", new GUIStyle("WinBtnCloseWin")))
					{
						FungusScriptWindow.DeleteSequence();
					}
				}
			}

			// Remove any null entries in the command list.
			// This can happen when a command class is deleted or renamed.
			for (int i = commandListProperty.arraySize - 1; i >= 0; --i)
			{
				SerializedProperty commandProperty = commandListProperty.GetArrayElementAtIndex(i);
				if (commandProperty.objectReferenceValue == null)
				{
					commandListProperty.DeleteArrayElementAtIndex(i);
				}
			}

			serializedObject.ApplyModifiedProperties();

			if (!Application.isPlaying)
			{
				if (Event.current.button == 1 && 
				    Event.current.type == EventType.MouseDown)
				{
					// Set a flag to show the context menu on the new display frame
					// This gives the sequence list display a chance to update
					FungusScriptWindow.showContextMenu = true;
					Event.current.Use();
				}
			}
		}

		protected virtual void UpdateIndentLevels(Sequence sequence)
		{
			int indentLevel = 0;
			foreach(Command command in sequence.commandList)
			{
				if (command == null)
				{
					continue;
				}

				indentLevel += command.GetPreIndent();
				command.indentLevel = Math.Max(indentLevel, 0);
				indentLevel += command.GetPostIndent();
			}
		}

		static public void SequenceField(SerializedProperty property, GUIContent label, GUIContent nullLabel, FungusScript fungusScript)
		{
			if (fungusScript == null)
			{
				return;
			}

			Sequence sequence = property.objectReferenceValue as Sequence;
		
			// Build dictionary of child sequences
			List<GUIContent> sequenceNames = new List<GUIContent>();
			
			int selectedIndex = 0;
			sequenceNames.Add(nullLabel);
			Sequence[] sequences = fungusScript.GetComponentsInChildren<Sequence>(true);
			for (int i = 0; i < sequences.Length; ++i)
			{
				sequenceNames.Add(new GUIContent(sequences[i].sequenceName));
				
				if (sequence == sequences[i])
				{
					selectedIndex = i + 1;
				}
			}
{'fraction_non_alphanumeric': 0.09705823494096458, 'fraction_numerical': 0.01180708425055033, 'mean_word_length': 3.5246717971933, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '973500', 'n_tokens_mistral': 3792, 'n_tokens_neox': 2905, 'n_words': 689}