using Godot;
using System;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
///
/// This node converts a 3D position to 2D using a 2.5D transformation matrix.
/// The transformation of its 2D form is controlled by its 3D child.
///
[Tool]
public partial class Node25D : Node2D, IComparable
{
///
/// The number of 2D units in one 3D unit. Ideally, but not necessarily, an integer.
///
public const int SCALE = 32;
[Export] public Vector3 spatialPosition
{
get
{
if (spatialNode == null)
{
spatialNode = GetChild(0);
}
return spatialNode.Position;
}
set
{
transform25D.spatialPosition = value;
if (spatialNode != null)
{
spatialNode.Position = value;
}
else if (GetChildCount() > 0)
{
spatialNode = GetChild(0);
}
}
}
private Node3D spatialNode;
private Transform25D transform25D;
public Basis25D Basis25D
{
get { return transform25D.basis; }
}
public Transform25D Transform25D
{
get { return transform25D; }
}
public override void _Ready()
{
Node25DReady();
}
public override void _Process(real_t delta)
{
Node25DProcess();
}
///
/// Call this method in _Ready, or before Node25DProcess is run.
///
protected void Node25DReady()
{
if (GetChildCount() > 0)
{
spatialNode = GetChild(0);
}
// Changing the basis here will change the default for all Node25D instances.
transform25D = new Transform25D(Basis25D.FortyFive * SCALE);
}
///
/// Call this method in _Process, or whenever the position of this object changes.
///
protected void Node25DProcess()
{
if (transform25D.basis == new Basis25D())
{
SetViewMode(0);
}
CheckViewMode();
if (spatialNode != null)
{
transform25D.spatialPosition = spatialNode.Position;
}
else if (GetChildCount() > 0)
{
spatialNode = GetChild(0);
}
GlobalPosition = transform25D.FlatPosition;
}
public void SetViewMode(int viewModeIndex)
{
switch (viewModeIndex)
{
case 0:
transform25D.basis = Basis25D.FortyFive * SCALE;
break;
case 1:
transform25D.basis = Basis25D.Isometric * SCALE;
break;
case 2:
transform25D.basis = Basis25D.TopDown * SCALE;
break;
case 3:
transform25D.basis = Basis25D.FrontSide * SCALE;
break;
case 4:
transform25D.basis = Basis25D.ObliqueY * SCALE;
break;
case 5:
transform25D.basis = Basis25D.ObliqueZ * SCALE;
break;
}
}
private void CheckViewMode()
{
if (!Engine.EditorHint)
{
if (Input.IsActionJustPressed("forty_five_mode"))
{
SetViewMode(0);
}
else if (Input.IsActionJustPressed("isometric_mode"))
{
SetViewMode(1);
}
else if (Input.IsActionJustPressed("top_down_mode"))
{
SetViewMode(2);
}
else if (Input.IsActionJustPressed("front_side_mode"))
{
SetViewMode(3);
}
else if (Input.IsActionJustPressed("oblique_y_mode"))
{
SetViewMode(4);
}
else if (Input.IsActionJustPressed("oblique_z_mode"))
{
SetViewMode(5);
}
}
}
public int CompareTo(object obj)
{
if (obj is Node25D)
{
return CompareTo((Node25D)obj);
}
return 1;
}
public int CompareTo(Node25D other)
{
real_t thisIndex = transform25D.spatialPosition.y + 0.001f * (transform25D.spatialPosition.x + transform25D.spatialPosition.z);
real_t otherIndex = other.transform25D.spatialPosition.y + 0.001f * (other.transform25D.spatialPosition.x + other.transform25D.spatialPosition.z);
real_t diff = thisIndex - otherIndex;
if (diff > 0)
{
return 1;
}
if (diff < 0)
{
return -1;
}
return 0;
}
}