using FIMSpace.Generating.Planning.PlannerNodes;
using FIMSpace.Graph;
using UnityEngine;
using FIMSpace.Generating.Rules;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace FIMSpace.Generating.Planning.ModNodes.Cells
{
public class MR_LineCheckCells : PlannerRuleBase
{
public override string GetDisplayName(float maxWidth = 120) { return wasCreated ? " Line Check Cells" : "Line Check Cells"; }
public override string GetNodeTooltipDescription { get { return "Checking for cells state in the line in all 4 directions.\nUseful for generating object with scale-aligned to reach wall on the other side of the grid."; } }
public override Color GetNodeColor() { return new Color(0.64f, 0.9f, 0.0f, 0.9f); }
public override bool IsFoldable { get { return true; } }
public override Vector2 NodeSize { get { return new Vector2(232, 140 + extraNodeHeight); } }
int extraNodeHeight = 0;
public override bool DrawInputConnector { get { return true; } }
public override bool DrawOutputConnector { get { return true; } }
public enum EPurpose
{
ChooseNearestDir, ChooseNearestDir_NoZero, ChooseFarthestDir, CustomDirection
}
public EPurpose CheckResult = EPurpose.ChooseNearestDir_NoZero;
[Port(EPortPinType.Output, EPortNameDisplay.Default, EPortValueDisplay.NotEditable)] public IntPort CellsDistance;
public ESR_Space StopAt = ESR_Space.OutOfGrid;
[HideInInspector][Port(EPortPinType.Output)] public PGGVector3Port Direction;
[HideInInspector][Port(EPortPinType.Input)] public PGGStringPort Tag;
[HideInInspector] public ESR_Details CheckMode = ESR_Details.Tag;
[HideInInspector][Port(EPortPinType.Output)] public PGGModCellPort FinalCell;
[HideInInspector][Tooltip("Checking only directions which back cell is out of grid")] public bool BackEmptyOnly = false;
[Tooltip("Max cells count check distance")]
[HideInInspector] public int MaxDistance = 64;
[HideInInspector][Port(EPortPinType.Input)] public PGGVector3Port CustomDirection;
float nearest = float.MaxValue;
float farthest = float.MinValue;
string tag = "";
FieldCell preCell = null;
FieldCell targetCell = null;
FieldCell choosedCell = null;
bool wasOutOfGridCell = false;
public override void Execute(PlanGenerationPrint print, PlannerResult newResult)
{
if (MG_Cell == null) return;
nearest = int.MaxValue;
farthest = int.MinValue;
choosedCell = null;
wasOutOfGridCell = false;
tag = "";
preCell = null;
targetCell = null;
FinalCell.Clear();
Tag.TriggerReadPort(true);
tag = Tag.GetInputValue;
if (CheckResult == EPurpose.CustomDirection)
{
CustomDirection.TriggerReadPort(true);
Vector3Int dir = CustomDirection.GetInputValue.V3toV3Int();
bool skip = false;
if (BackEmptyOnly)
{
FieldCell bCell = MG_Grid.GetCell(MG_Cell.Pos - dir, false);
if (!FGenerators.IsNull(bCell))
if (bCell.InTargetGridArea) skip = true;
}
if (!skip)
{
for (int d = 1; d < MaxDistance; d++)
{
bool breakCheck = CheckCellAt(dir, d);
if (breakCheck) break;
}
if ( StopAt == ESR_Space.OutOfGrid && wasOutOfGridCell == false)
{
choosedCell = null;
}
else if (FGenerators.NotNull(preCell))
{
choosedCell = preCell;
}
}
}
else
{
for (int r = 0; r < 4; r++)
{
preCell = null;
targetCell = null;
wasOutOfGridCell = false;
Vector3Int dir = new Vector3Int(0, 0, 0);
if (r == 0) dir.z = 1;
else if (r == 1) dir.x = 1;
else if (r == 2) dir.z = -1;
else if (r == 3) dir.x = -1;
if (BackEmptyOnly)
{
FieldCell bCell = MG_Grid.GetCell(MG_Cell.Pos - dir, false);
if (!FGenerators.IsNull(bCell))
{
if (bCell.InTargetGridArea) continue;
}
}
for (int d = 1; d < MaxDistance; d++)
{
bool breakCheck = CheckCellAt(dir, d);
if (breakCheck) break;
}
if (FGenerators.NotNull(preCell))
{
float distance = (preCell.Pos - MG_Cell.Pos).magnitude;
if (CheckResult == EPurpose.ChooseFarthestDir)
{
if (CheckResult == EPurpose.ChooseNearestDir_NoZero) if (distance < 2) continue;
if (distance > farthest)
{
choosedCell = preCell;
farthest = distance;
}
}
else
{
if (distance < nearest)
{
nearest = distance;
choosedCell = preCell;
}
}
}
}
}
if (FGenerators.NotNull(choosedCell))
{
FinalCell.ProvideFullCellData(choosedCell);
Vector3 diff = choosedCell.Pos - MG_Cell.Pos;
CellsDistance.Value = Mathf.RoundToInt(diff.magnitude);
Direction.Value = diff.normalized;
}
}
/// True if loop should break
bool CheckCellAt(Vector3Int offset, int d)
{
Vector3Int cellPos = MG_Cell.Pos + offset * d;
FGenGraph grid = MG_Grid;
var cell = grid.GetCell(cellPos, false);
if (FGenerators.IsNull(cell)) { CheckCell(cell); wasOutOfGridCell = true; return true; }
if (cell.InTargetGridArea == false) { CheckCell(cell); wasOutOfGridCell = true; return true; }
CheckCell(cell);
if (StopAt == ESR_Space.Occupied || StopAt == ESR_Space.InGrid)
{
if (string.IsNullOrWhiteSpace(tag))
{
return true;
}
else
{
if (FGenerators.NotNull(SpawnRuleBase.GetSpawnDataWithSpecifics(cell, tag, CheckMode)))
{
return true;
}
}
}
return false;
}
void CheckCell(FieldCell cell)
{
preCell = targetCell;
targetCell = cell;
}
#region Editor Code
#if UNITY_EDITOR
SerializedProperty sp = null;
SerializedProperty spTag = null;
SerializedProperty spDir = null;
SerializedProperty spCustDir = null;
public override void Editor_OnNodeBodyGUI(ScriptableObject setup)
{
base.Editor_OnNodeBodyGUI(setup);
baseSerializedObject.Update();
Direction.AllowDragWire = false;
CustomDirection.AllowDragWire = false;
extraNodeHeight = 0;
if (CheckResult == EPurpose.CustomDirection)
{
if (spCustDir == null) spCustDir = baseSerializedObject.FindProperty("CustomDirection");
EditorGUILayout.PropertyField(spCustDir);
CustomDirection.AllowDragWire = true;
}
else
{
if (spDir == null) spDir = baseSerializedObject.FindProperty("Direction");
EditorGUILayout.PropertyField(spDir);
Direction.AllowDragWire = true;
}
if (StopAt == ESR_Space.InGrid || StopAt == ESR_Space.Occupied)
{
if (spTag == null) spTag = baseSerializedObject.FindProperty("Tag");
EditorGUILayout.PropertyField(spTag);
var spc = spTag.Copy(); spc.Next(false);
EditorGUILayout.PropertyField(spc);
extraNodeHeight += 38;
}
if (_EditorFoldout)
{
if (sp == null) sp = baseSerializedObject.FindProperty("FinalCell");
EditorGUILayout.PropertyField(sp);
var spc = sp.Copy(); spc.Next(false);
EditorGUILayout.PropertyField(spc);
spc.Next(false); EditorGUILayout.PropertyField(spc);
FinalCell.AllowDragWire = true;
extraNodeHeight += 58;
}
else
{
FinalCell.AllowDragWire = false;
}
baseSerializedObject.ApplyModifiedProperties();
}
#endif
#endregion
}
}