forked from kaka3286/RoadRunner
299 lines
13 KiB
C#
299 lines
13 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEditorInternal;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Collections.Generic;
|
|
|
|
public class InputProviderGeneratorWindow : EditorWindow
|
|
{
|
|
private UnityEngine.Object vehicleControllerReference; // Can be MonoScript or MonoBehaviour
|
|
private string scriptName = "Input_Provider_Generated";
|
|
private Vector2 previewScrollPos;
|
|
private string previewScriptText = "";
|
|
|
|
private enum InputSettingMode { Direct, SeparateMethods, SingleMethod }
|
|
private InputSettingMode inputMode = InputSettingMode.Direct;
|
|
|
|
private string[] fieldNames, methodNames;
|
|
private int selectedAccelerationField, selectedSteerField, selectedHandbrakeField;
|
|
private int selectedAccelerationMethod, selectedSteerMethod, selectedHandbrakeMethod;
|
|
private int selectedSingleInputMethod;
|
|
|
|
// Order settings for single method mode using ReorderableList
|
|
private List<string> inputOrderList = new List<string> { "AccelerationInput", "SteerInput", "HandbrakeInput" };
|
|
private ReorderableList reorderableList;
|
|
|
|
private FieldInfo[] fields;
|
|
private MethodInfo[] methods;
|
|
private Type controllerType;
|
|
|
|
[MenuItem("Tools/Ash Assets/Omni Vehicle Ai/Input Provider Generator")]
|
|
private static void ShowWindow()
|
|
{
|
|
GetWindow<InputProviderGeneratorWindow>("Input Provider Generator");
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
reorderableList = new ReorderableList(inputOrderList, typeof(string), true, true, false, false);
|
|
reorderableList.drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Set Input Order for Single Method");
|
|
reorderableList.drawElementCallback = (rect, index, active, focused) =>
|
|
{
|
|
EditorGUI.LabelField(rect, inputOrderList[index]);
|
|
};
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.BeginVertical("box");
|
|
|
|
GUILayout.Label("Vehicle AI Input Provider Generator", EditorStyles.boldLabel);
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// Script or Component selection
|
|
vehicleControllerReference = EditorGUILayout.ObjectField("Vehicle Controller (Script or Component)", vehicleControllerReference, typeof(UnityEngine.Object), true);
|
|
|
|
if (vehicleControllerReference != null)
|
|
{
|
|
// Determine if the reference is a MonoScript or MonoBehaviour and get the class type accordingly
|
|
if (vehicleControllerReference is MonoScript monoScript)
|
|
{
|
|
controllerType = monoScript.GetClass();
|
|
}
|
|
else if (vehicleControllerReference is MonoBehaviour monoBehaviour)
|
|
{
|
|
controllerType = monoBehaviour.GetType();
|
|
}
|
|
else
|
|
{
|
|
controllerType = null;
|
|
}
|
|
|
|
// Check if the selected type is a valid MonoBehaviour
|
|
if (controllerType == null || !typeof(MonoBehaviour).IsAssignableFrom(controllerType))
|
|
{
|
|
EditorGUILayout.HelpBox("Selected object is not a valid MonoBehaviour script or component.", MessageType.Error);
|
|
}
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// Input setting mode
|
|
inputMode = (InputSettingMode)EditorGUILayout.EnumPopup("Input Mode", inputMode);
|
|
|
|
if (controllerType != null && typeof(MonoBehaviour).IsAssignableFrom(controllerType))
|
|
{
|
|
// Load relevant fields and methods based on the input mode
|
|
LoadRelevantFieldsAndMethods();
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// Display options based on the input mode
|
|
switch (inputMode)
|
|
{
|
|
case InputSettingMode.Direct:
|
|
DisplayDirectFieldSelection();
|
|
break;
|
|
case InputSettingMode.SeparateMethods:
|
|
DisplayMethodSelection();
|
|
break;
|
|
case InputSettingMode.SingleMethod:
|
|
DisplaySingleMethodSelection();
|
|
break;
|
|
}
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// Script name and preview generation
|
|
GUILayout.Label("Script Name", EditorStyles.boldLabel);
|
|
scriptName = EditorGUILayout.TextField(scriptName);
|
|
|
|
GUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Generate Preview", GUILayout.Height(30)))
|
|
{
|
|
previewScriptText = GenerateScriptPreview();
|
|
}
|
|
|
|
if (GUILayout.Button("Create Script", GUILayout.Height(30)))
|
|
{
|
|
CreateScript();
|
|
}
|
|
GUILayout.EndHorizontal();
|
|
|
|
GUILayout.Space(10);
|
|
|
|
// Preview section
|
|
GUILayout.Label("Script Preview", EditorStyles.boldLabel);
|
|
previewScrollPos = GUILayout.BeginScrollView(previewScrollPos, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
|
|
GUILayout.TextArea(previewScriptText, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
|
|
GUILayout.EndScrollView();
|
|
}
|
|
else if (controllerType == null)
|
|
{
|
|
EditorGUILayout.HelpBox("Please select a valid MonoBehaviour script or component.", MessageType.Warning);
|
|
}
|
|
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void LoadRelevantFieldsAndMethods()
|
|
{
|
|
fields = controllerType.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
if (inputMode == InputSettingMode.Direct)
|
|
{
|
|
fields = fields.Where(f => f.FieldType == typeof(float)).ToArray();
|
|
}
|
|
|
|
methods = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
if (inputMode == InputSettingMode.SeparateMethods)
|
|
{
|
|
methods = methods.Where(m => m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(float)).ToArray();
|
|
}
|
|
else if (inputMode == InputSettingMode.SingleMethod)
|
|
{
|
|
methods = methods.Where(m => m.GetParameters().Length == 3 && m.GetParameters().All(p => p.ParameterType == typeof(float))).ToArray();
|
|
}
|
|
|
|
fieldNames = fields.Select(f => f.Name).ToArray();
|
|
methodNames = methods.Select(m => m.Name).ToArray();
|
|
}
|
|
|
|
private void DisplayDirectFieldSelection()
|
|
{
|
|
if (fieldNames.Length == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No float fields found in the selected script or component.", MessageType.Warning);
|
|
return;
|
|
}
|
|
|
|
selectedAccelerationField = EditorGUILayout.Popup("Acceleration Field", selectedAccelerationField, fieldNames);
|
|
selectedSteerField = EditorGUILayout.Popup("Steer Field", selectedSteerField, fieldNames);
|
|
selectedHandbrakeField = EditorGUILayout.Popup("Handbrake Field", selectedHandbrakeField, fieldNames);
|
|
}
|
|
|
|
private void DisplayMethodSelection()
|
|
{
|
|
if (methodNames.Length == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No methods with a single float parameter found in the selected script or component.", MessageType.Warning);
|
|
return;
|
|
}
|
|
|
|
selectedAccelerationMethod = EditorGUILayout.Popup("Acceleration Method", selectedAccelerationMethod, methodNames);
|
|
selectedSteerMethod = EditorGUILayout.Popup("Steer Method", selectedSteerMethod, methodNames);
|
|
selectedHandbrakeMethod = EditorGUILayout.Popup("Handbrake Method", selectedHandbrakeMethod, methodNames);
|
|
}
|
|
|
|
private void DisplaySingleMethodSelection()
|
|
{
|
|
if (methodNames.Length == 0)
|
|
{
|
|
EditorGUILayout.HelpBox("No methods with exactly three float parameters found in the selected script or component.", MessageType.Warning);
|
|
return;
|
|
}
|
|
|
|
selectedSingleInputMethod = EditorGUILayout.Popup("Single Input Method", selectedSingleInputMethod, methodNames);
|
|
|
|
GUILayout.Space(10);
|
|
reorderableList.DoLayoutList();
|
|
}
|
|
|
|
private string GenerateScriptPreview()
|
|
{
|
|
StringBuilder scriptBuilder = new StringBuilder();
|
|
string controllerTypeName = controllerType.Name;
|
|
|
|
scriptBuilder.AppendLine("using UnityEngine;");
|
|
scriptBuilder.AppendLine();
|
|
scriptBuilder.AppendLine("namespace OmniVehicleAi");
|
|
scriptBuilder.AppendLine("{");
|
|
scriptBuilder.AppendLine($" public class {scriptName} : MonoBehaviour");
|
|
scriptBuilder.AppendLine(" {");
|
|
|
|
scriptBuilder.AppendLine($" public {controllerTypeName} vehicleController;");
|
|
scriptBuilder.AppendLine(" public AIVehicleController aiVehicleController;");
|
|
scriptBuilder.AppendLine();
|
|
scriptBuilder.AppendLine(" public enum InputType { Player, Ai };");
|
|
scriptBuilder.AppendLine(" public InputType inputType;");
|
|
scriptBuilder.AppendLine();
|
|
scriptBuilder.AppendLine(" public float AccelerationInput { get; private set; }");
|
|
scriptBuilder.AppendLine(" public float SteerInput { get; private set; }");
|
|
scriptBuilder.AppendLine(" public float HandbrakeInput { get; private set; }");
|
|
scriptBuilder.AppendLine();
|
|
|
|
scriptBuilder.AppendLine(" private void Update()");
|
|
scriptBuilder.AppendLine(" {");
|
|
scriptBuilder.AppendLine(" if (inputType == InputType.Player)");
|
|
scriptBuilder.AppendLine(" {");
|
|
scriptBuilder.AppendLine(" ProvidePlayerInput();");
|
|
scriptBuilder.AppendLine(" }");
|
|
scriptBuilder.AppendLine(" else");
|
|
scriptBuilder.AppendLine(" {");
|
|
scriptBuilder.AppendLine(" ProvideAiInput();");
|
|
scriptBuilder.AppendLine(" }");
|
|
scriptBuilder.AppendLine(" }");
|
|
scriptBuilder.AppendLine();
|
|
|
|
scriptBuilder.AppendLine(" private void ProvideAiInput()");
|
|
scriptBuilder.AppendLine(" {");
|
|
scriptBuilder.AppendLine(" SteerInput = aiVehicleController.GetSteerInput();");
|
|
scriptBuilder.AppendLine(" AccelerationInput = aiVehicleController.GetAccelerationInput();");
|
|
scriptBuilder.AppendLine(" HandbrakeInput = aiVehicleController.GetHandBrakeInput();");
|
|
|
|
if (inputMode == InputSettingMode.Direct)
|
|
{
|
|
scriptBuilder.AppendLine($" vehicleController.{fieldNames[selectedAccelerationField]} = AccelerationInput;");
|
|
scriptBuilder.AppendLine($" vehicleController.{fieldNames[selectedSteerField]} = SteerInput;");
|
|
scriptBuilder.AppendLine($" vehicleController.{fieldNames[selectedHandbrakeField]} = HandbrakeInput;");
|
|
}
|
|
else if (inputMode == InputSettingMode.SeparateMethods)
|
|
{
|
|
scriptBuilder.AppendLine($" vehicleController.{methodNames[selectedAccelerationMethod]}(AccelerationInput);");
|
|
scriptBuilder.AppendLine($" vehicleController.{methodNames[selectedSteerMethod]}(SteerInput);");
|
|
scriptBuilder.AppendLine($" vehicleController.{methodNames[selectedHandbrakeMethod]}(HandBrakeInput);");
|
|
}
|
|
else if (inputMode == InputSettingMode.SingleMethod)
|
|
{
|
|
scriptBuilder.AppendLine($" vehicleController.{methodNames[selectedSingleInputMethod]}(");
|
|
for (int i = 0; i < inputOrderList.Count; i++)
|
|
{
|
|
scriptBuilder.AppendLine($" {inputOrderList[i]}" + (i < inputOrderList.Count - 1 ? "," : ""));
|
|
}
|
|
scriptBuilder.AppendLine(" );");
|
|
}
|
|
|
|
scriptBuilder.AppendLine(" }");
|
|
|
|
scriptBuilder.AppendLine(" private void ProvidePlayerInput()");
|
|
scriptBuilder.AppendLine(" {");
|
|
scriptBuilder.AppendLine(" // Example Player inputs:");
|
|
scriptBuilder.AppendLine(" // AccelerationInput = Input.GetAxis(\"Vertical\");");
|
|
scriptBuilder.AppendLine(" // SteerInput = Input.GetAxis(\"Horizontal\");");
|
|
scriptBuilder.AppendLine(" // HandbrakeInput = Input.GetButton(\"Jump\") ? 1f : 0f;");
|
|
scriptBuilder.AppendLine(" }");
|
|
|
|
scriptBuilder.AppendLine(" }");
|
|
scriptBuilder.AppendLine("}");
|
|
|
|
return scriptBuilder.ToString();
|
|
}
|
|
|
|
private void CreateScript()
|
|
{
|
|
// Open a save panel to choose the location and filename
|
|
string path = EditorUtility.SaveFilePanelInProject("Save Input Provider Script", scriptName, "cs", "Please enter a file name to save the script.", "Assets/Ash Assets/Omni Vehicle Ai");
|
|
|
|
if (!string.IsNullOrEmpty(path))
|
|
{
|
|
System.IO.File.WriteAllText(path, previewScriptText);
|
|
AssetDatabase.Refresh();
|
|
}
|
|
}
|
|
}
|