Files
beyond/Assets/ThirdParty/Invector-AIController/Scripts/Editor/vAICoverAreaEditor.cs
2024-11-20 15:21:28 +01:00

376 lines
18 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace Invector.vCharacterController.AI.Cover
{
[CustomEditor(typeof(vAICoverArea))]
public class vAICoverAreaEditor : vEditorBase
{
[MenuItem("GameObject/Invector/FSM AI/New Cover Area", false, -100)]
[MenuItem("Invector/FSM AI/Components/New Cover Area")]
static void CreateNewCoverArea()
{
var cA = new GameObject("CoverArea", typeof(vAICoverArea));
SceneView view = SceneView.lastActiveSceneView;
if (SceneView.lastActiveSceneView == null)
throw new UnityException("The Scene View can't be access");
Vector3 spawnPos = view.camera.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 5f));
cA.transform.position = spawnPos;
Selection.activeGameObject = cA.gameObject;
}
public vAICoverArea coverArea;
public Transform currentSelectedP;
public vAICoverArea.CoverLine currentSelecteLine;
public int indexSelected;
public bool isFistPointSelected;
private void OnSceneGUI()
{
if (!coverArea) return;
var color = Handles.color;
if (coverArea.coverLines.Count > 0)
{
coverArea.coverLines[0].p1.localPosition = Vector3.zero;
if (canEdit && Handles.Button(coverArea.coverLines[0].p2.position, Quaternion.identity, 0.1f, 0.1f, Handles.SphereHandleCap))
{
currentSelectedP = coverArea.coverLines[0].p2;
currentSelecteLine = coverArea.coverLines[0];
indexSelected = 0;
isFistPointSelected = false;
Repaint();
}
for (int i = 0; i < coverArea.coverLines.Count; i++)
{
Handles.color = Color.white;
if (i > 0 && coverArea.coverLines[0].p1 != coverArea.coverLines[i].p2)
if (canEdit && Handles.Button(coverArea.coverLines[i].p2.position, Quaternion.identity, 0.1f, 0.1f, Handles.SphereHandleCap))
{
currentSelectedP = coverArea.coverLines[i].p2;
currentSelecteLine = coverArea.coverLines[i];
indexSelected = i; isFistPointSelected = false; Repaint();
}
HandleCoverPoints(coverArea.coverLines[i]);
Handles.color = Color.white;
}
}
if (canEdit && currentSelectedP && coverArea.coverLines.Count>0 && coverArea.coverLines[0].p1!= currentSelectedP)
{
Handles.SphereHandleCap(0, currentSelectedP.position, Quaternion.identity, 0.2f, EventType.Repaint);
currentSelectedP.position = Handles.DoPositionHandle(currentSelectedP.position, Quaternion.identity);
if (currentSelectedP.position.y < coverArea.transform.position.y)
{
var p = currentSelectedP.position;
p.y = coverArea.transform.position.y;
currentSelectedP.position = p;
}
}
Handles.color = color;
if (canEdit && coverArea.coverLines.Count > 1)
{
if (coverArea.closeLine)
{
var firstP = coverArea.coverLines[0].p1;
var lastP = coverArea.coverLines[coverArea.coverLines.Count - 1].p2;
if (lastP != firstP)
{
DestroyImmediate(lastP.gameObject);
coverArea.coverLines[coverArea.coverLines.Count - 1].p2 = firstP;
currentSelectedP = coverArea.coverLines[0].p1;
currentSelecteLine = coverArea.coverLines[0];
indexSelected = 0;
}
}
else
{
var firstP = coverArea.coverLines[0].p1;
var lastP = coverArea.coverLines[coverArea.coverLines.Count - 1].p2;
if (lastP == firstP)
{
coverArea.coverLines[coverArea.coverLines.Count - 1].p2 = new GameObject("P2_" + coverArea.coverLines.Count).transform;
coverArea.coverLines[coverArea.coverLines.Count - 1].p2.hideFlags = HideFlags.HideInHierarchy;
coverArea.coverLines[coverArea.coverLines.Count - 1].p2.parent = coverArea.transform;
coverArea.coverLines[coverArea.coverLines.Count - 1].p2.position = firstP.position + (coverArea.coverLines[coverArea.coverLines.Count - 1].p1.position - firstP.position) * 0.5f;
currentSelectedP = coverArea.coverLines[coverArea.coverLines.Count - 1].p2;
currentSelecteLine = coverArea.coverLines[coverArea.coverLines.Count - 1];
indexSelected = coverArea.coverLines.Count - 1;
}
}
}
Handles.color = color;
}
protected override void OnEnable()
{
base.OnEnable();
coverArea = target as vAICoverArea;
currentSelectedP = null;
currentSelecteLine = null;
indexSelected = 0;
}
private void OnDisable()
{
coverArea = null;
currentSelectedP = null;
indexSelected = 0;
}
public void HandleCoverPoints(vAICoverArea.CoverLine coverLine)
{
var p1 = coverLine.p1.position;
var p2 = coverLine.p2.position;
var right = (p2 - p1);
var linearRight = right;
linearRight.y = 0;
var pLength = right.magnitude+0.02f;
var changeForwardButtonPos = (p1+ p2) * 0.5f;
Handles.color = Color.blue;
if (Handles.Button(changeForwardButtonPos + Vector3.up * ((coverArea.colliderHeight * 0.5f) + coverArea.centerY), Quaternion.LookRotation(coverLine.forward != Vector3.zero ? coverLine.forward:Vector3.down), pLength >= coverArea.colliderWidth ?0.5f:0, pLength >= coverArea.colliderWidth?0.5f:0, Handles.ArrowHandleCap))
coverLine.inverse = !coverLine.inverse;
Handles.color = Color.white;
var cpCount = (int)(pLength / coverArea.colliderWidth);
var realWidth = ((pLength / (float)cpCount));
right.Normalize();
linearRight.Normalize();
var forward = Quaternion.AngleAxis(-90, coverArea.transform.up) * linearRight;
var startP = p1 + (right * (coverArea.colliderWidth * 0.5f));
if (cpCount == 1) startP = (p1 + p2) * 0.5f;
coverLine.forward = coverLine.inverse ? -forward : forward;
if (coverLine.coverPoints.Count < cpCount)
{
var countDif = cpCount - coverLine.coverPoints.Count;
for (int i = 0; i < countDif; i++)
{
coverLine.coverPoints.Add(CreateCoverPoint());
}
}
else if (coverLine.coverPoints.Count > cpCount)
{
var countDif = coverLine.coverPoints.Count - cpCount;
for (int i = 0; i < countDif; i++)
{
var cp = coverLine.coverPoints[coverLine.coverPoints.Count - 1];
DestroyImmediate(cp.gameObject);
coverLine.coverPoints.RemoveAt(coverLine.coverPoints.Count - 1);
}
}
DrawCoverPoint(coverLine, right, realWidth, startP);
}
private void DrawCoverPoint(vAICoverArea.CoverLine coverLine, Vector3 right, float realWidth, Vector3 startP)
{
var rec = new Rect();
var matrix = Handles.matrix;
for (int i = 0; i < coverLine.coverPoints.Count; i++)
{
if (coverLine.coverPoints[i].transform.parent == null || coverLine.coverPoints[i].transform.parent!= coverArea.transform) coverLine.coverPoints[i].transform.parent = coverArea.transform;
if (coverLine.coverPoints[i].boxCollider == null)
{
CreateBoxColider(coverLine.coverPoints[i]);
break;
}
coverLine.coverPoints[i].transform.position = startP + (right * (realWidth * i));
coverLine.coverPoints[i].transform.rotation = Quaternion.LookRotation(coverLine.forward);
coverLine.coverPoints[i].boxCollider.size = new Vector3(coverArea.colliderWidth, coverArea.colliderHeight, coverArea.colliderThickness);
coverLine.coverPoints[i].boxCollider.center = Vector3.up * coverArea.centerY + Vector3.forward * coverArea.centerZ;
if(coverArea.drawTargetPosition)
{
Handles.color = Color.green * 0.8f;
Handles.DrawSolidDisc(coverLine.coverPoints[i].posePosition, Vector3.up, 0.25f);
Handles.color = Color.green * 0.4f;
Handles.DrawSolidArc(coverLine.coverPoints[i].posePosition, coverLine.coverPoints[i].transform.forward, coverLine.coverPoints[i].transform.right, 180, 0.25f);
Handles.DrawSolidArc(coverLine.coverPoints[i].posePosition, -coverLine.coverPoints[i].transform.right, coverLine.coverPoints[i].transform.forward, 180, 0.25f);
Handles.color = Color.white;
Handles.DrawWireDisc(coverLine.coverPoints[i].posePosition, Vector3.up, 0.25f);
Handles.DrawWireArc(coverLine.coverPoints[i].posePosition, coverLine.coverPoints[i].transform.forward, coverLine.coverPoints[i].transform.right, 180, 0.25f);
Handles.DrawWireArc(coverLine.coverPoints[i].posePosition, -coverLine.coverPoints[i].transform.right, coverLine.coverPoints[i].transform.forward, 180, 0.25f);
}
Handles.color = Color.white * 0.8f;
rec.position = new Vector2(coverLine.coverPoints[i].boxCollider.center.x - coverLine.coverPoints[i].boxCollider.size.x * 0.5f, coverLine.coverPoints[i].boxCollider.center.y - coverLine.coverPoints[i].boxCollider.size.y * 0.5f);
rec.size = new Vector2(coverLine.coverPoints[i].boxCollider.size.x, coverLine.coverPoints[i].boxCollider.size.y);
Matrix4x4 m = Matrix4x4.TRS(coverLine.coverPoints[i].transform.position, coverLine.coverPoints[i].transform.rotation, coverLine.coverPoints[i].transform.lossyScale);
Handles.matrix = m;
Handles.DrawWireCube(coverLine.coverPoints[i].boxCollider.center, coverLine.coverPoints[i].boxCollider.size);
m = Matrix4x4.TRS(coverLine.coverPoints[i].transform.position + coverLine.coverPoints[i].transform.forward * (coverArea.centerZ + (coverArea.colliderThickness * 0.5f)), coverLine.coverPoints[i].transform.rotation, coverLine.coverPoints[i].transform.lossyScale);
Handles.matrix = m;
Handles.color = Color.white;
Handles.DrawSolidRectangleWithOutline(rec, Color.green * .25f , Color.green * 1 );
Handles.matrix = matrix;
Handles.color = Color.green * 0.8f;
var normalStartP = coverLine.coverPoints[i].boxCollider.bounds.center + coverLine.coverPoints[i].transform.forward * (coverArea.colliderThickness * 0.5f);
Handles.ArrowHandleCap(0, normalStartP, coverLine.coverPoints[i].transform.rotation, .25f, EventType.Repaint);
}
}
public vAICoverPoint CreateCoverPoint()
{
var obj = new GameObject("CoverPoint", typeof(BoxCollider));
obj.transform.parent = coverArea.transform;
return obj.AddComponent<vAICoverPoint>();
}
public void CreateCoverline()
{
var coverline = new vAICoverArea.CoverLine();
if (coverArea.coverLines.Count == 0)
{
coverline.p1 = new GameObject("P1_0").transform;
coverline.p1.hideFlags = HideFlags.HideInHierarchy;
coverline.p1.parent = coverArea.transform;
coverline.p1.position = coverArea.transform.position;
}
else
{
coverline.p1 = coverArea.coverLines[coverArea.coverLines.Count - 1].p2;
}
coverline.p2 = new GameObject("P2_" + coverArea.coverLines.Count).transform;
coverline.p2.hideFlags = HideFlags.HideInHierarchy;
coverline.p2.parent = coverArea.transform;
var p2Position = coverline.p1.position;
if (coverArea.coverLines.Count > 0)
p2Position += (coverline.p1.position - coverArea.coverLines[coverArea.coverLines.Count - 1].p1.position).normalized * coverArea.colliderWidth * 2.1f ;
else
{
p2Position += coverArea.transform.right * coverArea.colliderWidth * 2.1f;
}
coverline.p2.position = p2Position;
coverArea.coverLines.Add(coverline);
currentSelecteLine = coverline;
indexSelected = coverArea.coverLines.Count - 1;
currentSelectedP = coverline.p2;
HandleCoverPoints(coverline);
}
public void RemoveLine()
{
var lines = coverArea.coverLines.Count;
if (indexSelected > 0 && indexSelected < lines - 1)
{
var a = coverArea.coverLines[indexSelected];
var b = coverArea.coverLines[indexSelected + 1];
b.p1 = a.p1;
DestroyPointOfLine(a);
indexSelected = indexSelected % coverArea.coverLines.Count;
currentSelectedP = coverArea.coverLines[indexSelected].p2;
currentSelecteLine = coverArea.coverLines[indexSelected];
}
else if (lines - 1 >= 0 && indexSelected == lines - 1)
{
var a = coverArea.coverLines[indexSelected];
DestroyPointOfLine(a);
indexSelected = lines - 2;
currentSelectedP = coverArea.coverLines[indexSelected].p2;
currentSelecteLine = coverArea.coverLines[indexSelected];
}
else if (indexSelected == 0 && lines > 1)
{
var a = coverArea.coverLines[indexSelected];
var b = coverArea.coverLines[indexSelected + 1];
a.p2 = b.p2;
DestroyPointOfLine(b, false);
}
}
public void DestroyPointOfLine(vAICoverArea.CoverLine line, bool p2 = true)
{
var needToDestroy = line.coverPoints;
var destroyP = p2 ? line.p2 : line.p1;
coverArea.coverLines.Remove(line);
DestroyImmediate(destroyP.gameObject);
for (int i = 0; i < needToDestroy.Count; i++)
{
if (needToDestroy[i] != null && needToDestroy[i].gameObject)
DestroyImmediate(needToDestroy[i].gameObject);
}
}
public bool canEdit
{
get
{
GameObject prefab = PrefabUtility.GetOutermostPrefabInstanceRoot(coverArea.gameObject);
return !prefab || UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null;
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
GUILayout.BeginVertical(skin.box);
base.OnInspectorGUI();
if (!canEdit)
{
EditorGUILayout.HelpBox("This area is in Prefab Instance\n Unpack or Open prefab to edit the cover points", MessageType.Error);
}
else
if (coverArea)
{
GUI.enabled = !coverArea.closeLine;
if (GUILayout.Button("Add New Point") || coverArea.coverLines.Count == 0)
{
CreateCoverline();
coverArea.closeLine = false;
serializedObject.ApplyModifiedProperties();
SceneView.RepaintAll();
}
GUILayout.BeginHorizontal(skin.box);
GUI.enabled = coverArea.coverLines.Count > 2;
if (GUILayout.Button(coverArea.closeLine ? "Desconnect End" : "Connect End"))
{
coverArea.closeLine = !coverArea.closeLine; serializedObject.ApplyModifiedProperties(); SceneView.RepaintAll();
}
GUI.enabled = ((!coverArea.closeLine || coverArea.coverLines.Count > 3) && !isFistPointSelected && coverArea.coverLines.Count > 1 && (indexSelected < coverArea.coverLines.Count && coverArea.coverLines[indexSelected] != null));
if (GUILayout.Button("Dell Selected"))
{
RemoveLine();
serializedObject.ApplyModifiedProperties();
SceneView.RepaintAll();
}
GUILayout.EndHorizontal();
GUI.enabled = true;
}
GUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
public void CreateBoxColider(vAICoverPoint target)
{
BoxCollider c = null;
c = target.gameObject.GetComponent<BoxCollider>();
if (!c) c = target.gameObject.AddComponent<BoxCollider>();
target.boxCollider = c;
}
}
}