Removed mono projects.
@ -1,6 +0,0 @@
|
|||||||
<Project Sdk="Godot.NET.Sdk/3.3.0">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<RootNamespace>Demo</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
@ -1,19 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 2012
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2.5D Demo with C#", "2.5D Demo with C#.csproj", "{5CA791DB-5050-44D0-989B-41D559AB1D50}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
ExportDebug|Any CPU = ExportDebug|Any CPU
|
|
||||||
ExportRelease|Any CPU = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
|
|
||||||
{5CA791DB-5050-44D0-989B-41D559AB1D50}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,41 +0,0 @@
|
|||||||
# 2.5D Demo Project with C#
|
|
||||||
|
|
||||||
This demo project shows a way to create a 2.5D game
|
|
||||||
in Godot by mixing 2D and 3D nodes. It also adds a
|
|
||||||
2.5D editor viewport for easily editing 2.5D levels.
|
|
||||||
|
|
||||||
Language: [C#](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/index.html) and a little bit of GDScript
|
|
||||||
|
|
||||||
Renderer: GLES 2
|
|
||||||
|
|
||||||
Note: There is a GDScript version available [here](https://github.com/godotengine/godot-demo-projects/tree/master/misc/2.5d).
|
|
||||||
|
|
||||||
## How does it work?
|
|
||||||
|
|
||||||
Custom node types are added in a Godot plugin to allow 2.5D objects. Node25D serves as the base for all 2.5D objects. Its first child must be a 3D Spatial, which is used to calculate its position. Then, add a 2D Sprite (or similar) to display the object.
|
|
||||||
|
|
||||||
Inside of Node25D, new structs called Basis25D and Transform25D are used to calculate the 2D position from the 3D position. For getting a 3D position, this project uses KinematicBody and StaticBody (3D), but these only exist for math - the camera is 2D and all sprites are 2D. You are able to use any Spatial node for math.
|
|
||||||
|
|
||||||
Several view modes are implemented, including top down, front side, 45 degree, isometric, and two oblique modes. To implement a different view angle, all you need to do is create a new Basis25D, use it in all your Node25D transforms, and of course create sprites to display that object in 2D.
|
|
||||||
|
|
||||||
The plugin also adds YSort25D to sort Node25D nodes, and ShadowMath25D for calculating a shadow (a simple KinematicBody that tries to cast downward).
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
||||||
![Forty Five Degrees](../../misc/2.5d/screenshots/forty_five.png)
|
|
||||||
|
|
||||||
![Isometric](../../misc/2.5d/screenshots/isometric.png)
|
|
||||||
|
|
||||||
![Oblique Z](../../misc/2.5d/screenshots/oblique_z.png)
|
|
||||||
|
|
||||||
![Oblique Y](../../misc/2.5d/screenshots/oblique_y.png)
|
|
||||||
|
|
||||||
![Front Side](../../misc/2.5d/screenshots/front_side.png)
|
|
||||||
|
|
||||||
![Cube](../../misc/2.5d/screenshots/cube.png)
|
|
||||||
|
|
||||||
![2.5D Editor Viewport](../../misc/2.5d/screenshots/editor.png)
|
|
||||||
|
|
||||||
## Music License
|
|
||||||
|
|
||||||
`assets/mr_mrs_robot.ogg` Copyright © circa 2008 Juan Linietsky, CC-BY: Attribution.
|
|
@ -1,207 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
#if GODOT_REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Basis25D structure for performing 2.5D transform math.
|
|
||||||
/// Note: All code assumes that Y is UP in 3D, and DOWN in 2D.
|
|
||||||
/// A top-down view has a Y axis component of (0, 0), with a Z axis component of (0, 1).
|
|
||||||
/// For a front side view, Y is (0, -1) and Z is (0, 0).
|
|
||||||
/// Remember that Godot's 2D mode has the Y axis pointing DOWN on the screen.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct Basis25D : IEquatable<Basis25D>
|
|
||||||
{
|
|
||||||
// Also matrix columns, the directions to move on screen for each unit change in 3D.
|
|
||||||
public Vector2 x;
|
|
||||||
public Vector2 y;
|
|
||||||
public Vector2 z;
|
|
||||||
|
|
||||||
// Also matrix rows, the parts of each vector that contribute to moving in a screen direction.
|
|
||||||
// Setting a row to zero means no movement in that direction.
|
|
||||||
public Vector3 Row0
|
|
||||||
{
|
|
||||||
get { return new Vector3(x.x, y.x, z.x); }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
x.x = value.x;
|
|
||||||
y.x = value.y;
|
|
||||||
z.x = value.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3 Row1
|
|
||||||
{
|
|
||||||
get { return new Vector3(x.y, y.y, z.y); }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
x.y = value.x;
|
|
||||||
y.y = value.y;
|
|
||||||
z.y = value.z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector2 this[int columnIndex]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (columnIndex)
|
|
||||||
{
|
|
||||||
case 0: return x;
|
|
||||||
case 1: return y;
|
|
||||||
case 2: return z;
|
|
||||||
default: throw new IndexOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
switch (columnIndex)
|
|
||||||
{
|
|
||||||
case 0: x = value; return;
|
|
||||||
case 1: y = value; return;
|
|
||||||
case 2: z = value; return;
|
|
||||||
default: throw new IndexOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public real_t this[int columnIndex, int rowIndex]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this[columnIndex][rowIndex];
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Vector2 v = this[columnIndex];
|
|
||||||
v[rowIndex] = value;
|
|
||||||
this[columnIndex] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly Basis25D _topDown = new Basis25D(1, 0, 0, 0, 0, 1);
|
|
||||||
private static readonly Basis25D _frontSide = new Basis25D(1, 0, 0, -1, 0, 0);
|
|
||||||
private static readonly Basis25D _fortyFive = new Basis25D(1, 0, 0, -0.70710678118f, 0, 0.70710678118f);
|
|
||||||
private static readonly Basis25D _isometric = new Basis25D(0.86602540378f, 0.5f, 0, -1, -0.86602540378f, 0.5f);
|
|
||||||
private static readonly Basis25D _obliqueY = new Basis25D(1, 0, -0.70710678118f, -0.70710678118f, 0, 1);
|
|
||||||
private static readonly Basis25D _obliqueZ = new Basis25D(1, 0, 0, -1, -0.70710678118f, 0.70710678118f);
|
|
||||||
|
|
||||||
public static Basis25D TopDown { get { return _topDown; } }
|
|
||||||
public static Basis25D FrontSide { get { return _frontSide; } }
|
|
||||||
public static Basis25D FortyFive { get { return _fortyFive; } }
|
|
||||||
public static Basis25D Isometric { get { return _isometric; } }
|
|
||||||
public static Basis25D ObliqueY { get { return _obliqueY; } }
|
|
||||||
public static Basis25D ObliqueZ { get { return _obliqueZ; } }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a Dimetric Basis25D from the angle between the Y axis and the others.
|
|
||||||
/// Dimetric(Tau/3) or Dimetric(2.09439510239) is the same as Isometric.
|
|
||||||
/// Try to keep this number away from a multiple of Tau/4 (or Pi/2) radians.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="angle">The angle, in radians, between the Y axis and the X/Z axes.</param>
|
|
||||||
public static Basis25D Dimetric(real_t angle)
|
|
||||||
{
|
|
||||||
real_t sin = Mathf.Sin(angle);
|
|
||||||
real_t cos = Mathf.Cos(angle);
|
|
||||||
return new Basis25D(sin, -cos, 0, -1, -sin, -cos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
public Basis25D(Basis25D b)
|
|
||||||
{
|
|
||||||
x = b.x;
|
|
||||||
y = b.y;
|
|
||||||
z = b.z;
|
|
||||||
}
|
|
||||||
public Basis25D(Vector2 xAxis, Vector2 yAxis, Vector2 zAxis)
|
|
||||||
{
|
|
||||||
x = xAxis;
|
|
||||||
y = yAxis;
|
|
||||||
z = zAxis;
|
|
||||||
}
|
|
||||||
public Basis25D(real_t xx, real_t xy, real_t yx, real_t yy, real_t zx, real_t zy)
|
|
||||||
{
|
|
||||||
x = new Vector2(xx, xy);
|
|
||||||
y = new Vector2(yx, yy);
|
|
||||||
z = new Vector2(zx, zy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Basis25D operator *(Basis25D b, real_t s)
|
|
||||||
{
|
|
||||||
b.x *= s;
|
|
||||||
b.y *= s;
|
|
||||||
b.z *= s;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Basis25D operator /(Basis25D b, real_t s)
|
|
||||||
{
|
|
||||||
b.x /= s;
|
|
||||||
b.y /= s;
|
|
||||||
b.z /= s;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(Basis25D left, Basis25D right)
|
|
||||||
{
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(Basis25D left, Basis25D right)
|
|
||||||
{
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is Basis25D)
|
|
||||||
{
|
|
||||||
return Equals((Basis25D)obj);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(Basis25D other)
|
|
||||||
{
|
|
||||||
return x.Equals(other.x) && y.Equals(other.y) && z.Equals(other.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEqualApprox(Basis25D other)
|
|
||||||
{
|
|
||||||
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && z.IsEqualApprox(other.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
string s = String.Format("({0}, {1}, {2})", new object[]
|
|
||||||
{
|
|
||||||
x.ToString(),
|
|
||||||
y.ToString(),
|
|
||||||
z.ToString()
|
|
||||||
});
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ToString(string format)
|
|
||||||
{
|
|
||||||
string s = String.Format("({0}, {1}, {2})", new object[]
|
|
||||||
{
|
|
||||||
x.ToString(format),
|
|
||||||
y.ToString(format),
|
|
||||||
z.ToString(format)
|
|
||||||
});
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,183 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using System;
|
|
||||||
#if REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
[Tool]
|
|
||||||
public class Node25D : Node2D, IComparable<Node25D>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The number of 2D units in one 3D unit. Ideally, but not necessarily, an integer.
|
|
||||||
/// </summary>
|
|
||||||
public const int SCALE = 32;
|
|
||||||
|
|
||||||
[Export] public Vector3 spatialPosition
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (spatialNode == null)
|
|
||||||
{
|
|
||||||
spatialNode = GetChild<Spatial>(0);
|
|
||||||
}
|
|
||||||
return spatialNode.Translation;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
transform25D.spatialPosition = value;
|
|
||||||
if (spatialNode != null)
|
|
||||||
{
|
|
||||||
spatialNode.Translation = value;
|
|
||||||
}
|
|
||||||
else if (GetChildCount() > 0)
|
|
||||||
{
|
|
||||||
spatialNode = GetChild<Spatial>(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Spatial 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call this method in _Ready, or before Node25DProcess is run.
|
|
||||||
/// </summary>
|
|
||||||
protected void Node25DReady()
|
|
||||||
{
|
|
||||||
if (GetChildCount() > 0)
|
|
||||||
{
|
|
||||||
spatialNode = GetChild<Spatial>(0);
|
|
||||||
}
|
|
||||||
// Changing the basis here will change the default for all Node25D instances.
|
|
||||||
transform25D = new Transform25D(Basis25D.FortyFive * SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call this method in _Process, or whenever the position of this object changes.
|
|
||||||
/// </summary>
|
|
||||||
protected void Node25DProcess()
|
|
||||||
{
|
|
||||||
if (transform25D.basis == new Basis25D())
|
|
||||||
{
|
|
||||||
SetViewMode(0);
|
|
||||||
}
|
|
||||||
CheckViewMode();
|
|
||||||
if (spatialNode != null)
|
|
||||||
{
|
|
||||||
transform25D.spatialPosition = spatialNode.Translation;
|
|
||||||
}
|
|
||||||
else if (GetChildCount() > 0)
|
|
||||||
{
|
|
||||||
spatialNode = GetChild<Spatial>(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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
#if REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a simple shadow below an object.
|
|
||||||
/// Place this ShadowMath25D node as a child of a Shadow25D, which
|
|
||||||
/// is below the target object in the scene tree (not as a child).
|
|
||||||
/// </summary>
|
|
||||||
[Tool]
|
|
||||||
public class ShadowMath25D : KinematicBody
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum distance below objects that shadows will appear.
|
|
||||||
/// </summary>
|
|
||||||
public real_t shadowLength = 1000;
|
|
||||||
private Node25D shadowRoot;
|
|
||||||
private Spatial targetMath;
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
shadowRoot = GetParent<Node25D>();
|
|
||||||
int index = shadowRoot.GetPositionInParent();
|
|
||||||
targetMath = shadowRoot.GetParent().GetChild<Node25D>(index - 1).GetChild<Spatial>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Process(real_t delta)
|
|
||||||
{
|
|
||||||
if (targetMath == null)
|
|
||||||
{
|
|
||||||
if (shadowRoot != null)
|
|
||||||
{
|
|
||||||
shadowRoot.Visible = false;
|
|
||||||
}
|
|
||||||
return; // Shadow is not in a valid place.
|
|
||||||
}
|
|
||||||
|
|
||||||
Translation = targetMath.Translation;
|
|
||||||
var k = MoveAndCollide(Vector3.Down * shadowLength);
|
|
||||||
if (k == null)
|
|
||||||
{
|
|
||||||
shadowRoot.Visible = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shadowRoot.Visible = true;
|
|
||||||
GlobalTransform = Transform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the 2D transformation from a 3D position and a Basis25D.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct Transform25D : IEquatable<Transform25D>
|
|
||||||
{
|
|
||||||
// Public fields store information that is used to calculate the properties.
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls how the 3D position is transformed into 2D.
|
|
||||||
/// </summary>
|
|
||||||
public Basis25D basis;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 3D position of the object. Should be updated on every frame before everything else.
|
|
||||||
/// </summary>
|
|
||||||
public Vector3 spatialPosition;
|
|
||||||
|
|
||||||
// Public properties calculate on-the-fly.
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 2D transformation of this object. Slower than FlatPosition.
|
|
||||||
/// </summary>
|
|
||||||
public Transform2D FlatTransform
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Transform2D(0, FlatPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 2D position of this object.
|
|
||||||
/// </summary>
|
|
||||||
public Vector2 FlatPosition
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Vector2 pos = spatialPosition.x * basis.x;
|
|
||||||
pos += spatialPosition.y * basis.y;
|
|
||||||
pos += spatialPosition.z * basis.z;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
public Transform25D(Transform25D transform25D)
|
|
||||||
{
|
|
||||||
basis = transform25D.basis;
|
|
||||||
spatialPosition = transform25D.spatialPosition;
|
|
||||||
}
|
|
||||||
public Transform25D(Basis25D basis25D)
|
|
||||||
{
|
|
||||||
basis = basis25D;
|
|
||||||
spatialPosition = Vector3.Zero;
|
|
||||||
}
|
|
||||||
public Transform25D(Basis25D basis25D, Vector3 position3D)
|
|
||||||
{
|
|
||||||
basis = basis25D;
|
|
||||||
spatialPosition = position3D;
|
|
||||||
}
|
|
||||||
public Transform25D(Vector2 xAxis, Vector2 yAxis, Vector2 zAxis)
|
|
||||||
{
|
|
||||||
basis = new Basis25D(xAxis, yAxis, zAxis);
|
|
||||||
spatialPosition = Vector3.Zero;
|
|
||||||
}
|
|
||||||
public Transform25D(Vector2 xAxis, Vector2 yAxis, Vector2 zAxis, Vector3 position3D)
|
|
||||||
{
|
|
||||||
basis = new Basis25D(xAxis, yAxis, zAxis);
|
|
||||||
spatialPosition = position3D;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(Transform25D left, Transform25D right)
|
|
||||||
{
|
|
||||||
return left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(Transform25D left, Transform25D right)
|
|
||||||
{
|
|
||||||
return !left.Equals(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is Transform25D)
|
|
||||||
{
|
|
||||||
return Equals((Transform25D)obj);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(Transform25D other)
|
|
||||||
{
|
|
||||||
return basis.Equals(other.basis) && spatialPosition.Equals(other.spatialPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEqualApprox(Transform25D other)
|
|
||||||
{
|
|
||||||
return basis.IsEqualApprox(other.basis) && spatialPosition.IsEqualApprox(other.spatialPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return basis.GetHashCode() ^ spatialPosition.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
string s = String.Format("({0}, {1})", new object[]
|
|
||||||
{
|
|
||||||
basis.ToString(),
|
|
||||||
spatialPosition.ToString()
|
|
||||||
});
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ToString(string format)
|
|
||||||
{
|
|
||||||
string s = String.Format("({0}, {1})", new object[]
|
|
||||||
{
|
|
||||||
basis.ToString(format),
|
|
||||||
spatialPosition.ToString(format)
|
|
||||||
});
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
#if REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Assigns Z-index values to Node25D children.
|
|
||||||
/// </summary>
|
|
||||||
[Tool] // Commented out because it sometimes crashes the editor when running the game...
|
|
||||||
public class YSort25D : Node // Note: NOT Node2D, Node25D, or YSort
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Whether or not to automatically call Sort() in _Process().
|
|
||||||
/// </summary>
|
|
||||||
[Export]
|
|
||||||
public bool sortEnabled = true;
|
|
||||||
|
|
||||||
public override void _Process(real_t delta)
|
|
||||||
{
|
|
||||||
if (sortEnabled)
|
|
||||||
{
|
|
||||||
Sort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call this method in _Process, or whenever you want to sort children.
|
|
||||||
/// </summary>
|
|
||||||
public void Sort()
|
|
||||||
{
|
|
||||||
var children = GetParent().GetChildren();
|
|
||||||
if (children.Count > 4000)
|
|
||||||
{
|
|
||||||
GD.PrintErr("Sorting failed: Max number of YSort25D nodes is 4000.");
|
|
||||||
}
|
|
||||||
List<Node25D> node25dChildren = new List<Node25D>();
|
|
||||||
|
|
||||||
foreach (Node n in children)
|
|
||||||
{
|
|
||||||
if (n is Node25D node25d)
|
|
||||||
{
|
|
||||||
node25dChildren.Add(node25d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node25dChildren.Sort();
|
|
||||||
|
|
||||||
int zIndex = -4000;
|
|
||||||
for (int i = 0; i < node25dChildren.Count; i++)
|
|
||||||
{
|
|
||||||
node25dChildren[i].ZIndex = zIndex;
|
|
||||||
// Increment by 2 each time, to allow for shadows in-between.
|
|
||||||
// This does mean that we have a limit of 4000 total sorted Node25Ds.
|
|
||||||
zIndex += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 1.6 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/kinematic_body_25d.png-791432e863e44720a1390f5b1fbf09be.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/kinematic_body_25d.png"
|
|
||||||
dest_files=[ "res://.import/kinematic_body_25d.png-791432e863e44720a1390f5b1fbf09be.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 1.8 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/node_25d.png-ecf0b5959e83c044c288582c27f3f4c9.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/node_25d.png"
|
|
||||||
dest_files=[ "res://.import/node_25d.png-ecf0b5959e83c044c288582c27f3f4c9.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 293 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/node_25d_icon.png-c9b692824a2a2a3ddca2c0df67f60add.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/node_25d_icon.png"
|
|
||||||
dest_files=[ "res://.import/node_25d_icon.png-c9b692824a2a2a3ddca2c0df67f60add.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 2.1 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/shadow_math_25d.png-0cd88127f233ec7b6b2959e12e9f275a.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/shadow_math_25d.png"
|
|
||||||
dest_files=[ "res://.import/shadow_math_25d.png-0cd88127f233ec7b6b2959e12e9f275a.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 461 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/shadow_math_25d_icon.png-4dbc225f4d5f7ef06072b06e2f163301.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/shadow_math_25d_icon.png"
|
|
||||||
dest_files=[ "res://.import/shadow_math_25d_icon.png-4dbc225f4d5f7ef06072b06e2f163301.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1 +0,0 @@
|
|||||||
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m3.9844 1.002c-.2594998.003622-.5074296.1079777-.69141.29102l-2 2c-.39044859.3905113-.39044859 1.0235887 0 1.4141.3905113.3904486 1.0235887.3904486 1.4141 0l.29297-.29297v8.5859c1.5095036-.849214 1.5209705-.753534 2.00004-1.99996v-6.5859l.29297.29297c.3905113.3904486 1.0235887.3904486 1.4141 0 .3904486-.3905113.3904486-1.0235887 0-1.4141l-2-2c-.1916481-.1906987-.4523394-.29568076-.72266-.29102z"/><path d="m3.9844 14.999848c-.2594998-.003622-.5074296-.107978-.69141-.29102l-2-2c-.39044859-.390511-.39044859-1.023589 0-1.4141.3905113-.390449 1.0235887-.390449 1.4141 0l.29297.29297v-4.5829568h8.5859l-.29297-.29297c-.390449-.3905113-.390449-1.0235887 0-1.4141.390511-.3904485 1.023589-.3904485 1.4141 0l2 2c.390393.3905342.390393 1.0235659 0 1.4141l-2 1.9999998c-.191165.190217-.451053.295161-.7207.29102-.26018-.0031-.508903-.107502-.69336-.29102-.390449-.390511-.390449-1.0235885 0-1.4140998l.29297-.29297h-6.5859v2.5829568l.29297-.29297c.3905113-.390449 1.0235887-.390449 1.4141 0 .3904486.390511.3904486 1.023589 0 1.4141l-2 2c-.1916481.190699-.4523394.295681-.72266.29102z"/></g></svg>
|
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/viewport_25d.svg-104006b56693c8e3ae613ee52de431c7.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/viewport_25d.svg"
|
|
||||||
dest_files=[ "res://.import/viewport_25d.svg-104006b56693c8e3ae613ee52de431c7.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 360 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/y_sort_25d.png-d7ffa1c0d05a9139ab514ec27ad8da9d.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/y_sort_25d.png"
|
|
||||||
dest_files=[ "res://.import/y_sort_25d.png-d7ffa1c0d05a9139ab514ec27ad8da9d.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 241 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/y_sort_25d_icon.png-852bb2b2c54661e1957a46372d9a6d8f.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://addons/node25d-cs/icons/y_sort_25d_icon.png"
|
|
||||||
dest_files=[ "res://.import/y_sort_25d_icon.png-852bb2b2c54661e1957a46372d9a6d8f.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,228 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
|
|
||||||
// This is identical to the GDScript version, yet it doesn't work.
|
|
||||||
[Tool]
|
|
||||||
public class Viewport25D : Control
|
|
||||||
{
|
|
||||||
private int zoomLevel = 0;
|
|
||||||
private bool isPanning = false;
|
|
||||||
private Vector2 panCenter;
|
|
||||||
private Vector2 viewportCenter;
|
|
||||||
private int viewModeIndex = 0;
|
|
||||||
|
|
||||||
// The type or namespace name 'EditorInterface' could not be found (are you missing a using directive or an assembly reference?)
|
|
||||||
// No idea why this error shows up in VS Code. It builds fine...
|
|
||||||
public EditorInterface editorInterface; // Set in node25d_plugin.gd
|
|
||||||
private bool moving = false;
|
|
||||||
|
|
||||||
private Viewport viewport2d;
|
|
||||||
private Viewport viewportOverlay;
|
|
||||||
private ButtonGroup viewModeButtonGroup;
|
|
||||||
private Label zoomLabel;
|
|
||||||
private PackedScene gizmo25dScene;
|
|
||||||
|
|
||||||
public async override void _Ready()
|
|
||||||
{
|
|
||||||
// Give Godot a chance to fully load the scene. Should take two frames.
|
|
||||||
await ToSignal(GetTree(), "idle_frame");
|
|
||||||
await ToSignal(GetTree(), "idle_frame");
|
|
||||||
var editedSceneRoot = GetTree().EditedSceneRoot;
|
|
||||||
if (editedSceneRoot == null)
|
|
||||||
{
|
|
||||||
// Godot hasn't finished loading yet, so try loading the plugin again.
|
|
||||||
//editorInterface.SetPluginEnabled("node25d", false);
|
|
||||||
//editorInterface.SetPluginEnabled("node25d", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Alright, we're loaded up. Now check if we have a valid world and assign it.
|
|
||||||
var world2d = editedSceneRoot.GetViewport().World2d;
|
|
||||||
if (world2d == GetViewport().World2d)
|
|
||||||
{
|
|
||||||
return; // This is the MainScreen25D scene opened in the editor!
|
|
||||||
}
|
|
||||||
viewport2d.World2d = world2d;
|
|
||||||
|
|
||||||
// Onready vars.
|
|
||||||
viewport2d = GetNode<Viewport>("Viewport2D");
|
|
||||||
viewportOverlay = GetNode<Viewport>("ViewportOverlay");
|
|
||||||
viewModeButtonGroup = GetParent().GetNode("TopBar").GetNode("ViewModeButtons").GetNode<Button>("45Degree").Group;
|
|
||||||
zoomLabel = GetParent().GetNode("TopBar").GetNode("Zoom").GetNode<Label>("ZoomPercent");
|
|
||||||
gizmo25dScene = ResourceLoader.Load<PackedScene>("res://addons/node25d/main_screen/gizmo_25d.tscn");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void _Process(float delta)
|
|
||||||
{
|
|
||||||
if (editorInterface == null) // Something's not right... bail!
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// View mode polling.
|
|
||||||
var viewModeChangedThisFrame = false;
|
|
||||||
var newViewMode = viewModeButtonGroup.GetPressedButton().GetIndex();
|
|
||||||
if (viewModeIndex != newViewMode)
|
|
||||||
{
|
|
||||||
viewModeIndex = newViewMode;
|
|
||||||
viewModeChangedThisFrame = true;
|
|
||||||
RecursiveChangeViewMode(GetTree().EditedSceneRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zooming.
|
|
||||||
if (Input.IsMouseButtonPressed((int)ButtonList.WheelUp))
|
|
||||||
{
|
|
||||||
zoomLevel += 1;
|
|
||||||
}
|
|
||||||
else if (Input.IsMouseButtonPressed((int)ButtonList.WheelDown))
|
|
||||||
{
|
|
||||||
zoomLevel -= 1;
|
|
||||||
}
|
|
||||||
float zoom = GetZoomAmount();
|
|
||||||
|
|
||||||
// Viewport size.
|
|
||||||
Vector2 size = GetGlobalRect().Size;
|
|
||||||
viewport2d.Size = size;
|
|
||||||
|
|
||||||
// Viewport transform.
|
|
||||||
Transform2D viewportTrans = Transform2D.Identity;
|
|
||||||
viewportTrans.x *= zoom;
|
|
||||||
viewportTrans.y *= zoom;
|
|
||||||
viewportTrans.origin = viewportTrans.BasisXform(viewportCenter) + size / 2;
|
|
||||||
viewport2d.CanvasTransform = viewportTrans;
|
|
||||||
viewportOverlay.CanvasTransform = viewportTrans;
|
|
||||||
|
|
||||||
// Delete unused gizmos.
|
|
||||||
var selection = editorInterface.GetSelection().GetSelectedNodes();
|
|
||||||
var overlayChildren = viewportOverlay.GetChildren();
|
|
||||||
foreach (Gizmo25D overlayChild in overlayChildren)
|
|
||||||
{
|
|
||||||
bool contains = false;
|
|
||||||
foreach (Node selected in selection)
|
|
||||||
{
|
|
||||||
if (selected == overlayChild.node25d && !viewModeChangedThisFrame)
|
|
||||||
{
|
|
||||||
contains = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!contains)
|
|
||||||
{
|
|
||||||
overlayChild.QueueFree();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add new gizmos.
|
|
||||||
foreach (Node sel in selection)
|
|
||||||
{
|
|
||||||
if (sel is Node25D selected)
|
|
||||||
{
|
|
||||||
var newNode = true;
|
|
||||||
foreach (Gizmo25D overlayChild2 in overlayChildren)
|
|
||||||
{
|
|
||||||
if (selected == overlayChild2.node25d)
|
|
||||||
{
|
|
||||||
newNode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newNode)
|
|
||||||
{
|
|
||||||
Gizmo25D gizmo = (Gizmo25D)gizmo25dScene.Instance();
|
|
||||||
viewportOverlay.AddChild(gizmo);
|
|
||||||
gizmo.node25d = selected;
|
|
||||||
gizmo.Initialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This only accepts input when the mouse is inside of the 2.5D viewport.
|
|
||||||
public override void _GuiInput(InputEvent inputEvent)
|
|
||||||
{
|
|
||||||
if (inputEvent is InputEventMouseButton mouseButtonEvent)
|
|
||||||
{
|
|
||||||
if (mouseButtonEvent.IsPressed())
|
|
||||||
{
|
|
||||||
if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.WheelUp)
|
|
||||||
{
|
|
||||||
zoomLevel += 1;
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
else if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.WheelDown)
|
|
||||||
{
|
|
||||||
zoomLevel -= 1;
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
else if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.Middle)
|
|
||||||
{
|
|
||||||
isPanning = true;
|
|
||||||
panCenter = viewportCenter - mouseButtonEvent.Position;
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
else if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.Left)
|
|
||||||
{
|
|
||||||
var overlayChildren2 = viewportOverlay.GetChildren();
|
|
||||||
foreach (Gizmo25D overlayChild in overlayChildren2)
|
|
||||||
{
|
|
||||||
overlayChild.wantsToMove = true;
|
|
||||||
}
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.Middle)
|
|
||||||
{
|
|
||||||
isPanning = false;
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
else if ((ButtonList)mouseButtonEvent.ButtonIndex == ButtonList.Left)
|
|
||||||
{
|
|
||||||
var overlayChildren3 = viewportOverlay.GetChildren();
|
|
||||||
foreach (Gizmo25D overlayChild in overlayChildren3)
|
|
||||||
{
|
|
||||||
overlayChild.wantsToMove = false;
|
|
||||||
}
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (inputEvent is InputEventMouseMotion mouseEvent)
|
|
||||||
{
|
|
||||||
if (isPanning)
|
|
||||||
{
|
|
||||||
viewportCenter = panCenter + mouseEvent.Position;
|
|
||||||
AcceptEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RecursiveChangeViewMode(Node currentNode)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
if (currentNode.HasMethod("SetViewMode"))
|
|
||||||
{
|
|
||||||
//currentNode.SetViewMode(viewModeIndex);
|
|
||||||
}
|
|
||||||
foreach (Node child in currentNode.GetChildren())
|
|
||||||
{
|
|
||||||
RecursiveChangeViewMode(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private float GetZoomAmount()
|
|
||||||
{
|
|
||||||
float zoomAmount = Mathf.Pow(1.05476607648f, zoomLevel); // 13th root of 2
|
|
||||||
zoomLabel.Text = Mathf.Round(zoomAmount * 1000) / 10 + "%";
|
|
||||||
return zoomAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnZoomOutPressed()
|
|
||||||
{
|
|
||||||
zoomLevel -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnZoomInPressed()
|
|
||||||
{
|
|
||||||
zoomLevel += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnZoomResetPressed()
|
|
||||||
{
|
|
||||||
zoomLevel = 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
|
|
||||||
// This is identical to the GDScript version, yet it doesn't work.
|
|
||||||
[Tool]
|
|
||||||
public class Gizmo25D : Node2D
|
|
||||||
{
|
|
||||||
// Not pixel perfect for all axes in all modes, but works well enough.
|
|
||||||
// Rounding is not done until after the movement is finished.
|
|
||||||
private const bool RoughlyRoundToPixels = true;
|
|
||||||
|
|
||||||
// Set when the node is created.
|
|
||||||
public Node25D node25d;
|
|
||||||
public Spatial spatialNode;
|
|
||||||
|
|
||||||
// Input from Viewport25D, represents if the mouse is clicked.
|
|
||||||
public bool wantsToMove = false;
|
|
||||||
|
|
||||||
// Used to control the state of movement.
|
|
||||||
private bool _moving = false;
|
|
||||||
private Vector2 _startPosition = Vector2.Zero;
|
|
||||||
|
|
||||||
// Stores state of closest or currently used axis.
|
|
||||||
private int dominantAxis;
|
|
||||||
|
|
||||||
private Node2D linesRoot;
|
|
||||||
private Line2D[] lines = new Line2D[3];
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
linesRoot = GetChild<Node2D>(0);
|
|
||||||
lines[0] = linesRoot.GetChild<Line2D>(0);
|
|
||||||
lines[1] = linesRoot.GetChild<Line2D>(1);
|
|
||||||
lines[2] = linesRoot.GetChild<Line2D>(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Process(float delta)
|
|
||||||
{
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
return; // Somehow this node hasn't been set up yet.
|
|
||||||
}
|
|
||||||
if (node25d == null)
|
|
||||||
{
|
|
||||||
return; // We're most likely viewing the Gizmo25D scene.
|
|
||||||
}
|
|
||||||
// While getting the mouse position works in any viewport, it doesn't do
|
|
||||||
// anything significant unless the mouse is in the 2.5D viewport.
|
|
||||||
Vector2 mousePosition = GetLocalMousePosition();
|
|
||||||
if (!_moving)
|
|
||||||
{
|
|
||||||
// If the mouse is farther than this many pixels, it won't grab anything.
|
|
||||||
float closestDistance = 20.0f;
|
|
||||||
dominantAxis = -1;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
// Unrelated, but needs a loop too.
|
|
||||||
Color modulateLine = lines[i].Modulate;
|
|
||||||
modulateLine.a = 0.8f;
|
|
||||||
lines[i].Modulate = modulateLine;
|
|
||||||
|
|
||||||
var distance = DistanceToSegmentAtIndex(i, mousePosition);
|
|
||||||
if (distance < closestDistance)
|
|
||||||
{
|
|
||||||
closestDistance = distance;
|
|
||||||
dominantAxis = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dominantAxis == -1)
|
|
||||||
{
|
|
||||||
// If we're not hovering over a line, ensure they are placed correctly.
|
|
||||||
linesRoot.GlobalPosition = node25d.GlobalPosition;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Color modulate = lines[dominantAxis].Modulate;
|
|
||||||
modulate.a = 1;
|
|
||||||
lines[dominantAxis].Modulate = modulate;
|
|
||||||
|
|
||||||
if (!wantsToMove)
|
|
||||||
{
|
|
||||||
_moving = false;
|
|
||||||
}
|
|
||||||
else if (wantsToMove && !_moving)
|
|
||||||
{
|
|
||||||
_moving = true;
|
|
||||||
_startPosition = mousePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_moving)
|
|
||||||
{
|
|
||||||
// Change modulate of unselected axes.
|
|
||||||
modulate = lines[(dominantAxis + 1) % 3].Modulate;
|
|
||||||
modulate.a = 0.5f;
|
|
||||||
lines[(dominantAxis + 1) % 3].Modulate = modulate;
|
|
||||||
lines[(dominantAxis + 2) % 3].Modulate = modulate;
|
|
||||||
|
|
||||||
// Calculate mouse movement and reset for next frame.
|
|
||||||
var mouseDiff = mousePosition - _startPosition;
|
|
||||||
_startPosition = mousePosition;
|
|
||||||
// Calculate movement.
|
|
||||||
var projectedDiff = mouseDiff.Project(lines[dominantAxis].Points[1]);
|
|
||||||
var movement = projectedDiff.Length() / Node25D.SCALE;
|
|
||||||
if (Mathf.IsEqualApprox(Mathf.Pi, projectedDiff.AngleTo(lines[dominantAxis].Points[1])))
|
|
||||||
{
|
|
||||||
movement *= -1;
|
|
||||||
}
|
|
||||||
// Apply movement.
|
|
||||||
Transform t = spatialNode.Transform;
|
|
||||||
t.origin += t.basis[dominantAxis] * movement;
|
|
||||||
spatialNode.Transform = t;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Make sure the gizmo is located at the object.
|
|
||||||
GlobalPosition = node25d.GlobalPosition;
|
|
||||||
if (RoughlyRoundToPixels)
|
|
||||||
{
|
|
||||||
Transform t = spatialNode.Transform;
|
|
||||||
t.origin = (t.origin * Node25D.SCALE).Round() / Node25D.SCALE;
|
|
||||||
spatialNode.Transform = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Move the gizmo lines appropriately.
|
|
||||||
linesRoot.GlobalPosition = node25d.GlobalPosition;
|
|
||||||
node25d.PropertyListChangedNotify();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes after _ready due to the onready vars, called manually in Viewport25D.gd.
|
|
||||||
// Sets up the points based on the basis values of the Node25D.
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
var basis = node25d.Basis25D;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
lines[i].Points[1] = basis[i] * 3;
|
|
||||||
}
|
|
||||||
GlobalPosition = node25d.GlobalPosition;
|
|
||||||
spatialNode = node25d.GetChild<Spatial>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Figures out if the mouse is very close to a segment. This method is
|
|
||||||
// specialized for this script, it assumes that each segment starts at
|
|
||||||
// (0, 0) and it provides a deadzone around the origin.
|
|
||||||
private float DistanceToSegmentAtIndex(int index, Vector2 point)
|
|
||||||
{
|
|
||||||
if (lines == null)
|
|
||||||
{
|
|
||||||
return Mathf.Inf;
|
|
||||||
}
|
|
||||||
if (point.LengthSquared() < 400)
|
|
||||||
{
|
|
||||||
return Mathf.Inf;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 segmentEnd = lines[index].Points[1];
|
|
||||||
float lengthSquared = segmentEnd.LengthSquared();
|
|
||||||
if (lengthSquared < 400)
|
|
||||||
{
|
|
||||||
return Mathf.Inf;
|
|
||||||
}
|
|
||||||
|
|
||||||
var t = Mathf.Clamp(point.Dot(segmentEnd) / lengthSquared, 0, 1);
|
|
||||||
var projection = t * segmentEnd;
|
|
||||||
return point.DistanceTo(projection);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/main_screen/Gizmo25D.cs" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="Gizmo25D" type="Node2D"]
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="Lines" type="Node2D" parent="."]
|
|
||||||
|
|
||||||
[node name="X" type="Line2D" parent="Lines"]
|
|
||||||
modulate = Color( 1, 1, 1, 0.8 )
|
|
||||||
points = PoolVector2Array( 0, 0, 100, 0 )
|
|
||||||
default_color = Color( 0.91, 0.273, 0, 1 )
|
|
||||||
|
|
||||||
[node name="Y" type="Line2D" parent="Lines"]
|
|
||||||
modulate = Color( 1, 1, 1, 0.8 )
|
|
||||||
points = PoolVector2Array( 0, 0, 0, -100 )
|
|
||||||
default_color = Color( 0, 0.91, 0.273, 1 )
|
|
||||||
|
|
||||||
[node name="Z" type="Line2D" parent="Lines"]
|
|
||||||
modulate = Color( 1, 1, 1, 0.8 )
|
|
||||||
points = PoolVector2Array( 0, 0, 0, 100 )
|
|
||||||
default_color = Color( 0.3, 0, 1, 1 )
|
|
@ -1,173 +0,0 @@
|
|||||||
[gd_scene load_steps=5 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/main_screen/viewport_25d.gd" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/main_screen/view_mode_button_group.tres" type="ButtonGroup" id=2]
|
|
||||||
|
|
||||||
[sub_resource type="ViewportTexture" id=1]
|
|
||||||
viewport_path = NodePath("Viewport25D/Viewport2D")
|
|
||||||
|
|
||||||
[sub_resource type="ViewportTexture" id=2]
|
|
||||||
viewport_path = NodePath("Viewport25D/ViewportOverlay")
|
|
||||||
|
|
||||||
[node name="MainScreen25D" type="VBoxContainer"]
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 3
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="TopBar" type="HBoxContainer" parent="."]
|
|
||||||
margin_right = 1600.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
rect_min_size = Vector2( 0, 32 )
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
|
|
||||||
[node name="ViewModeButtons" type="HBoxContainer" parent="TopBar"]
|
|
||||||
margin_right = 798.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
|
|
||||||
[node name="45Degree" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_right = 94.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
pressed = true
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "45 Degree"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="Isometric" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_left = 98.0
|
|
||||||
margin_right = 188.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "Isometric"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="TopDown" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_left = 192.0
|
|
||||||
margin_right = 283.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "Top Down"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="FrontSide" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_left = 287.0
|
|
||||||
margin_right = 379.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "Front Side"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="ObliqueY" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_left = 383.0
|
|
||||||
margin_right = 473.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "Oblique Y"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="ObliqueZ" type="CheckBox" parent="TopBar/ViewModeButtons"]
|
|
||||||
margin_left = 477.0
|
|
||||||
margin_right = 568.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
group = ExtResource( 2 )
|
|
||||||
text = "Oblique Z"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="Zoom" type="HBoxContainer" parent="TopBar"]
|
|
||||||
margin_left = 802.0
|
|
||||||
margin_right = 1600.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
alignment = 2
|
|
||||||
|
|
||||||
[node name="ZoomOut" type="Button" parent="TopBar/Zoom"]
|
|
||||||
margin_left = 680.0
|
|
||||||
margin_right = 710.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
rect_min_size = Vector2( 30, 0 )
|
|
||||||
text = "-"
|
|
||||||
|
|
||||||
[node name="ZoomPercent" type="Label" parent="TopBar/Zoom"]
|
|
||||||
margin_left = 714.0
|
|
||||||
margin_top = 9.0
|
|
||||||
margin_right = 764.0
|
|
||||||
margin_bottom = 23.0
|
|
||||||
rect_min_size = Vector2( 50, 0 )
|
|
||||||
text = "100%"
|
|
||||||
align = 1
|
|
||||||
clip_text = true
|
|
||||||
|
|
||||||
[node name="ZoomReset" type="Button" parent="TopBar/Zoom/ZoomPercent"]
|
|
||||||
modulate = Color( 1, 1, 1, 0 )
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="ZoomIn" type="Button" parent="TopBar/Zoom"]
|
|
||||||
margin_left = 768.0
|
|
||||||
margin_right = 798.0
|
|
||||||
margin_bottom = 32.0
|
|
||||||
rect_min_size = Vector2( 30, 0 )
|
|
||||||
text = "+"
|
|
||||||
|
|
||||||
[node name="Viewport25D" type="ColorRect" parent="."]
|
|
||||||
margin_top = 36.0
|
|
||||||
margin_right = 1600.0
|
|
||||||
margin_bottom = 900.0
|
|
||||||
rect_clip_content = true
|
|
||||||
size_flags_horizontal = 3
|
|
||||||
size_flags_vertical = 3
|
|
||||||
color = Color( 0.301961, 0.301961, 0.301961, 1 )
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="Viewport2D" type="Viewport" parent="Viewport25D"]
|
|
||||||
size = Vector2( 1600, 864 )
|
|
||||||
transparent_bg = true
|
|
||||||
disable_3d = true
|
|
||||||
usage = 1
|
|
||||||
render_target_v_flip = true
|
|
||||||
|
|
||||||
[node name="ViewportOverlay" type="Viewport" parent="Viewport25D"]
|
|
||||||
size = Vector2( 1600, 864 )
|
|
||||||
transparent_bg = true
|
|
||||||
disable_3d = true
|
|
||||||
usage = 1
|
|
||||||
render_target_v_flip = true
|
|
||||||
|
|
||||||
[node name="ViewportTexture" type="TextureRect" parent="Viewport25D"]
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
texture = SubResource( 1 )
|
|
||||||
expand = true
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="Overlay" type="TextureRect" parent="Viewport25D/ViewportTexture"]
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
texture = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
[connection signal="pressed" from="TopBar/Zoom/ZoomOut" to="Viewport25D" method="_on_ZoomOut_pressed"]
|
|
||||||
[connection signal="pressed" from="TopBar/Zoom/ZoomPercent/ZoomReset" to="Viewport25D" method="_on_ZoomReset_pressed"]
|
|
||||||
[connection signal="pressed" from="TopBar/Zoom/ZoomIn" to="Viewport25D" method="_on_ZoomIn_pressed"]
|
|
@ -1,3 +0,0 @@
|
|||||||
[gd_resource type="ButtonGroup" format=2]
|
|
||||||
|
|
||||||
[resource]
|
|
@ -1,149 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Control
|
|
||||||
|
|
||||||
var zoom_level := 0
|
|
||||||
var is_panning = false
|
|
||||||
var pan_center: Vector2
|
|
||||||
var viewport_center: Vector2
|
|
||||||
var view_mode_index := 0
|
|
||||||
|
|
||||||
var editor_interface: EditorInterface # Set in node25d_plugin.gd
|
|
||||||
var moving = false
|
|
||||||
|
|
||||||
onready var viewport_2d = $Viewport2D
|
|
||||||
onready var viewport_overlay = $ViewportOverlay
|
|
||||||
onready var view_mode_button_group: ButtonGroup = $"../TopBar/ViewModeButtons/45Degree".group
|
|
||||||
onready var zoom_label: Label = $"../TopBar/Zoom/ZoomPercent"
|
|
||||||
onready var gizmo_25d_scene = preload("res://addons/node25d-cs/main_screen/gizmo_25d.tscn")
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
# Give Godot a chance to fully load the scene. Should take two frames.
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
var edited_scene_root = get_tree().edited_scene_root
|
|
||||||
if not edited_scene_root:
|
|
||||||
# Godot hasn't finished loading yet, so try loading the plugin again.
|
|
||||||
editor_interface.set_plugin_enabled("node25d", false)
|
|
||||||
editor_interface.set_plugin_enabled("node25d", true)
|
|
||||||
return
|
|
||||||
# Alright, we're loaded up. Now check if we have a valid world and assign it.
|
|
||||||
var world_2d = edited_scene_root.get_viewport().world_2d
|
|
||||||
if world_2d == get_viewport().world_2d:
|
|
||||||
return # This is the MainScreen25D scene opened in the editor!
|
|
||||||
viewport_2d.world_2d = world_2d
|
|
||||||
|
|
||||||
|
|
||||||
func _process(delta):
|
|
||||||
if not editor_interface: # Something's not right... bail!
|
|
||||||
return
|
|
||||||
|
|
||||||
# View mode polling.
|
|
||||||
var view_mode_changed_this_frame = false
|
|
||||||
var new_view_mode = view_mode_button_group.get_pressed_button().get_index()
|
|
||||||
if view_mode_index != new_view_mode:
|
|
||||||
view_mode_index = new_view_mode
|
|
||||||
view_mode_changed_this_frame = true
|
|
||||||
_recursive_change_view_mode(get_tree().edited_scene_root)
|
|
||||||
|
|
||||||
# Zooming.
|
|
||||||
if Input.is_mouse_button_pressed(BUTTON_WHEEL_UP):
|
|
||||||
zoom_level += 1
|
|
||||||
elif Input.is_mouse_button_pressed(BUTTON_WHEEL_DOWN):
|
|
||||||
zoom_level -= 1
|
|
||||||
var zoom = _get_zoom_amount()
|
|
||||||
|
|
||||||
# Viewport size.
|
|
||||||
var size = get_global_rect().size
|
|
||||||
viewport_2d.size = size
|
|
||||||
|
|
||||||
# Viewport transform.
|
|
||||||
var viewport_trans = Transform2D.IDENTITY
|
|
||||||
viewport_trans.x *= zoom
|
|
||||||
viewport_trans.y *= zoom
|
|
||||||
viewport_trans.origin = viewport_trans.basis_xform(viewport_center) + size / 2
|
|
||||||
viewport_2d.canvas_transform = viewport_trans
|
|
||||||
viewport_overlay.canvas_transform = viewport_trans
|
|
||||||
|
|
||||||
# Delete unused gizmos.
|
|
||||||
var selection = editor_interface.get_selection().get_selected_nodes()
|
|
||||||
var overlay_children = viewport_overlay.get_children()
|
|
||||||
for overlay_child in overlay_children:
|
|
||||||
var contains = false
|
|
||||||
for selected in selection:
|
|
||||||
if selected == overlay_child.get("node25d") and not view_mode_changed_this_frame:
|
|
||||||
contains = true
|
|
||||||
if not contains:
|
|
||||||
overlay_child.queue_free()
|
|
||||||
|
|
||||||
# Add new gizmos.
|
|
||||||
for selected in selection:
|
|
||||||
if selected.has_method("Node25DReady"):
|
|
||||||
var new = true
|
|
||||||
for overlay_child in overlay_children:
|
|
||||||
if selected == overlay_child.get("node25d"):
|
|
||||||
new = false
|
|
||||||
if new:
|
|
||||||
var gizmo = gizmo_25d_scene.instance()
|
|
||||||
viewport_overlay.add_child(gizmo)
|
|
||||||
gizmo.set("node25d", selected)
|
|
||||||
gizmo.call("Initialize")
|
|
||||||
|
|
||||||
|
|
||||||
# This only accepts input when the mouse is inside of the 2.5D viewport.
|
|
||||||
func _gui_input(event):
|
|
||||||
if event is InputEventMouseButton:
|
|
||||||
if event.is_pressed():
|
|
||||||
if event.button_index == BUTTON_WHEEL_UP:
|
|
||||||
zoom_level += 1
|
|
||||||
accept_event()
|
|
||||||
elif event.button_index == BUTTON_WHEEL_DOWN:
|
|
||||||
zoom_level -= 1
|
|
||||||
accept_event()
|
|
||||||
elif event.button_index == BUTTON_MIDDLE:
|
|
||||||
is_panning = true
|
|
||||||
pan_center = viewport_center - event.position
|
|
||||||
accept_event()
|
|
||||||
elif event.button_index == BUTTON_LEFT:
|
|
||||||
var overlay_children = viewport_overlay.get_children()
|
|
||||||
for overlay_child in overlay_children:
|
|
||||||
overlay_child.set("wantsToMove", true)
|
|
||||||
accept_event()
|
|
||||||
elif event.button_index == BUTTON_MIDDLE:
|
|
||||||
is_panning = false
|
|
||||||
accept_event()
|
|
||||||
elif event.button_index == BUTTON_LEFT:
|
|
||||||
var overlay_children = viewport_overlay.get_children()
|
|
||||||
for overlay_child in overlay_children:
|
|
||||||
overlay_child.set("wantsToMove", false)
|
|
||||||
accept_event()
|
|
||||||
elif event is InputEventMouseMotion:
|
|
||||||
if is_panning:
|
|
||||||
viewport_center = pan_center + event.position
|
|
||||||
accept_event()
|
|
||||||
|
|
||||||
|
|
||||||
func _recursive_change_view_mode(current_node):
|
|
||||||
if current_node.has_method("set_view_mode"):
|
|
||||||
current_node.set_view_mode(view_mode_index) # GDScript.
|
|
||||||
if current_node.has_method("SetViewMode"):
|
|
||||||
current_node.call("SetViewMode", view_mode_index) # C#.
|
|
||||||
for child in current_node.get_children():
|
|
||||||
_recursive_change_view_mode(child)
|
|
||||||
|
|
||||||
|
|
||||||
func _get_zoom_amount():
|
|
||||||
var zoom_amount = pow(1.05476607648, zoom_level) # 13th root of 2.
|
|
||||||
zoom_label.text = str(round(zoom_amount * 1000) / 10) + "%"
|
|
||||||
return zoom_amount
|
|
||||||
|
|
||||||
|
|
||||||
func _on_ZoomOut_pressed():
|
|
||||||
zoom_level -= 1
|
|
||||||
|
|
||||||
|
|
||||||
func _on_ZoomIn_pressed():
|
|
||||||
zoom_level += 1
|
|
||||||
|
|
||||||
|
|
||||||
func _on_ZoomReset_pressed():
|
|
||||||
zoom_level = 0
|
|
@ -1,50 +0,0 @@
|
|||||||
tool
|
|
||||||
extends EditorPlugin
|
|
||||||
|
|
||||||
const MainPanel = preload("res://addons/node25d-cs/main_screen/main_screen_25d.tscn")
|
|
||||||
|
|
||||||
var main_panel_instance
|
|
||||||
|
|
||||||
func _enter_tree():
|
|
||||||
main_panel_instance = MainPanel.instance()
|
|
||||||
#main_panel_instance.get_child(1).set("editorInterface", get_editor_interface()) # For C#
|
|
||||||
main_panel_instance.get_child(1).editor_interface = get_editor_interface()
|
|
||||||
|
|
||||||
# Add the main panel to the editor's main viewport.
|
|
||||||
get_editor_interface().get_editor_viewport().add_child(main_panel_instance)
|
|
||||||
|
|
||||||
# Hide the main panel.
|
|
||||||
make_visible(false)
|
|
||||||
|
|
||||||
# When this plugin node enters tree, add the custom types.
|
|
||||||
add_custom_type("Node25D", "Node2D", preload("Node25D.cs"), preload("icons/node_25d_icon.png"))
|
|
||||||
add_custom_type("YSort25D", "Node", preload("YSort25D.cs"), preload("icons/y_sort_25d_icon.png"))
|
|
||||||
add_custom_type("ShadowMath25D", "KinematicBody", preload("ShadowMath25D.cs"), preload("icons/shadow_math_25d_icon.png"))
|
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree():
|
|
||||||
main_panel_instance.queue_free()
|
|
||||||
|
|
||||||
# When the plugin node exits the tree, remove the custom types.
|
|
||||||
remove_custom_type("ShadowMath25D")
|
|
||||||
remove_custom_type("YSort25D")
|
|
||||||
remove_custom_type("Node25D")
|
|
||||||
|
|
||||||
|
|
||||||
func has_main_screen():
|
|
||||||
return true
|
|
||||||
|
|
||||||
|
|
||||||
func make_visible(visible):
|
|
||||||
if visible:
|
|
||||||
main_panel_instance.show()
|
|
||||||
else:
|
|
||||||
main_panel_instance.hide()
|
|
||||||
|
|
||||||
|
|
||||||
func get_plugin_name():
|
|
||||||
return "2.5D"
|
|
||||||
|
|
||||||
|
|
||||||
func get_plugin_icon():
|
|
||||||
return preload("res://addons/node25d-cs/icons/viewport_25d.svg")
|
|
@ -1,7 +0,0 @@
|
|||||||
[plugin]
|
|
||||||
|
|
||||||
name="Node25D (C#)"
|
|
||||||
description="Adds Node25D"
|
|
||||||
author="Aaron Franke"
|
|
||||||
version="1.0"
|
|
||||||
script="node25d_plugin.gd"
|
|
@ -1,72 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
|
|
||||||
public class CubeMath : Spatial
|
|
||||||
{
|
|
||||||
private static PackedScene cubePointScene = ResourceLoader.Load<PackedScene>("res://assets/cube/cube_point.tscn");
|
|
||||||
|
|
||||||
private bool _isParentReady = false;
|
|
||||||
private Node2D _parent;
|
|
||||||
private Spatial[] _cubePointsMath = new Spatial[27]; // The math node of each 2.5D cube point
|
|
||||||
private Spatial[] _cubeMathSpatials = new Spatial[27]; // The CubeMath children that find position.
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
_parent = GetParent<Node2D>();
|
|
||||||
|
|
||||||
// Initialize the cube
|
|
||||||
for (int i = 0; i < 27; i++)
|
|
||||||
{
|
|
||||||
int a = (i / 9) - 1;
|
|
||||||
int b = (i / 3) % 3 - 1;
|
|
||||||
int c = (i % 3) - 1;
|
|
||||||
Vector3 spatialPosition = 5 * (a * Vector3.Right + b * Vector3.Up + c * Vector3.Back);
|
|
||||||
|
|
||||||
_cubeMathSpatials[i] = new Spatial();
|
|
||||||
_cubeMathSpatials[i].Translation = spatialPosition;
|
|
||||||
_cubeMathSpatials[i].Name = "CubeMath #" + i + ", " + a + " " + b + " " + c;
|
|
||||||
AddChild(_cubeMathSpatials[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Process(float delta)
|
|
||||||
{
|
|
||||||
if (Input.IsActionPressed("exit"))
|
|
||||||
{
|
|
||||||
GetTree().Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.IsActionJustPressed("view_cube_demo"))
|
|
||||||
{
|
|
||||||
GetTree().ChangeScene("res://assets/demo_scene.tscn");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isParentReady)
|
|
||||||
{
|
|
||||||
RotateX(delta * (Input.GetActionStrength("move_back") - Input.GetActionStrength("move_forward")));
|
|
||||||
RotateY(delta * (Input.GetActionStrength("move_right") - Input.GetActionStrength("move_left")));
|
|
||||||
RotateZ(delta * (Input.GetActionStrength("move_counterclockwise") - Input.GetActionStrength("move_clockwise")));
|
|
||||||
if (Input.IsActionJustPressed("reset_position"))
|
|
||||||
{
|
|
||||||
Transform = Transform.Identity;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 27; i++)
|
|
||||||
{
|
|
||||||
_cubePointsMath[i].GlobalTransform = _cubeMathSpatials[i].GlobalTransform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This code block will be run only once. It's not in _Ready() because the parent isn't set up there.
|
|
||||||
for (int i = 0; i < 27; i++)
|
|
||||||
{
|
|
||||||
PackedScene myCubePointScene = cubePointScene.Duplicate(true) as PackedScene;
|
|
||||||
Node25D cubePoint = myCubePointScene.Instance() as Node25D;
|
|
||||||
cubePoint.Name = "CubePoint #" + i;
|
|
||||||
_cubePointsMath[i] = cubePoint.GetChild<Spatial>(0);
|
|
||||||
_parent.AddChild(cubePoint);
|
|
||||||
}
|
|
||||||
_isParentReady = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
[gd_scene load_steps=4 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/YSort25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://assets/ui/overlay_cube.tscn" type="PackedScene" id=3]
|
|
||||||
[ext_resource path="res://assets/cube/CubeMath.cs" type="Script" id=4]
|
|
||||||
|
|
||||||
[node name="Cube" type="Node2D"]
|
|
||||||
|
|
||||||
[node name="Overlay" parent="." instance=ExtResource( 3 )]
|
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
|
||||||
current = true
|
|
||||||
|
|
||||||
[node name="CubeMath" type="Spatial" parent="."]
|
|
||||||
script = ExtResource( 4 )
|
|
||||||
|
|
||||||
[node name="YSort25D" type="Node" parent="."]
|
|
||||||
script = ExtResource( 1 )
|
|
@ -1,17 +0,0 @@
|
|||||||
[gd_scene load_steps=4 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/Node25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/node_25d_icon.png" type="Texture" id=2]
|
|
||||||
[ext_resource path="res://assets/cube/godot.png" type="Texture" id=3]
|
|
||||||
|
|
||||||
[node name="CubePoint" type="Node2D"]
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 2 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, 0, 0 )
|
|
||||||
|
|
||||||
[node name="CubePointMath" type="Spatial" parent="."]
|
|
||||||
|
|
||||||
[node name="CubePointSprite" type="Sprite" parent="."]
|
|
||||||
texture = ExtResource( 3 )
|
|
Before Width: | Height: | Size: 2.1 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/godot.png-a942b208c71d1b44958f34d302d011ec.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/cube/godot.png"
|
|
||||||
dest_files=[ "res://.import/godot.png-a942b208c71d1b44958f34d302d011ec.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,619 +0,0 @@
|
|||||||
[gd_scene load_steps=14 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/YSort25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://assets/mr_mrs_robot.ogg" type="AudioStream" id=2]
|
|
||||||
[ext_resource path="res://assets/ui/overlay.tscn" type="PackedScene" id=3]
|
|
||||||
[ext_resource path="res://assets/player/player_25d.tscn" type="PackedScene" id=4]
|
|
||||||
[ext_resource path="res://assets/shadow/shadow_25d.tscn" type="PackedScene" id=5]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/Node25D.cs" type="Script" id=6]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/node_25d_icon.png" type="Texture" id=7]
|
|
||||||
[ext_resource path="res://assets/platform/textures/forty_five.png" type="Texture" id=8]
|
|
||||||
[ext_resource path="res://assets/platform/platform_sprite.gd" type="Script" id=9]
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=1]
|
|
||||||
extents = Vector3( 5, 0.5, 5 )
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=2]
|
|
||||||
extents = Vector3( 5, 0.5, 5 )
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=3]
|
|
||||||
extents = Vector3( 5, 0.5, 5 )
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=4]
|
|
||||||
extents = Vector3( 5, 0.5, 5 )
|
|
||||||
|
|
||||||
[node name="DemoScene" type="Node2D"]
|
|
||||||
|
|
||||||
[node name="Overlay" parent="." instance=ExtResource( 3 )]
|
|
||||||
|
|
||||||
[node name="Player25D" parent="." instance=ExtResource( 4 )]
|
|
||||||
z_index = -3952
|
|
||||||
|
|
||||||
[node name="Shadow25D" parent="." instance=ExtResource( 5 )]
|
|
||||||
visible = true
|
|
||||||
position = Vector2( 1.00261e-06, 11.2685 )
|
|
||||||
z_index = -3958
|
|
||||||
spatialPosition = Vector3( 3.13315e-08, -0.498, 3.13315e-08 )
|
|
||||||
|
|
||||||
[node name="Platform0" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -256, -113.137 )
|
|
||||||
z_index = -3954
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -8, 5, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform0"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 5, 0 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform0/PlatformMath"]
|
|
||||||
shape = SubResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform0"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform1" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -256, -339.411 )
|
|
||||||
z_index = -3956
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -8, 5, -10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform1"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 5, -10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform1/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform1"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform2" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 0, 22.6274 )
|
|
||||||
z_index = -3962
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, -1, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform2"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform2/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform2"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform3" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 22.6274 )
|
|
||||||
z_index = -3960
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -1, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform3"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -1, 0 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform3/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform3"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform4" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 0, -203.647 )
|
|
||||||
z_index = -3966
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, -1, -10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform4"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, -10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform4/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform4"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform5" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, -113.137 )
|
|
||||||
z_index = -3984
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, -10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform5"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, -10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform5/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform5"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform6" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 113.137 )
|
|
||||||
z_index = -3980
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform6"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, 0 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform6/PlatformMath"]
|
|
||||||
shape = SubResource( 2 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform6"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform7" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 339.411 )
|
|
||||||
z_index = -3978
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, 10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform7"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, 10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform7/PlatformMath"]
|
|
||||||
shape = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform7"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform8" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 565.685 )
|
|
||||||
z_index = -3976
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, 20 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform8"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, 20 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform8/PlatformMath"]
|
|
||||||
shape = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform8"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform21" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 791.96 )
|
|
||||||
z_index = -3972
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, 30 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform21"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, 30 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform21/PlatformMath"]
|
|
||||||
shape = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform21"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform22" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 320, 1018.23 )
|
|
||||||
z_index = -3970
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 10, -5, 40 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform22"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 10, -5, 40 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform22/PlatformMath"]
|
|
||||||
shape = SubResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform22"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform9" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 640, 339.411 )
|
|
||||||
z_index = -3974
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 20, -5, 10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform9"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 20, -5, 10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform9/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform9"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform10" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 896, 294.156 )
|
|
||||||
z_index = -3994
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 28, -10, 3 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform10"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 28, -10, 3 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform10/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform10"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform11" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 896, 520.431 )
|
|
||||||
z_index = -3990
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 28, -10, 13 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform11"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 28, -10, 13 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform11/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform11"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform12" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 896, 746.705 )
|
|
||||||
z_index = -3988
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 28, -10, 23 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform12"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 28, -10, 23 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform12/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform12"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform13" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 576, 746.705 )
|
|
||||||
z_index = -3992
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 18, -10, 23 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform13"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 18, -10, 23 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform13/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform13"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform14" type="Node2D" parent="."]
|
|
||||||
position = Vector2( 256, 746.705 )
|
|
||||||
z_index = -3996
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 8, -10, 23 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform14"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 8, -10, 23 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform14/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform14"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform15" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -64, 746.705 )
|
|
||||||
z_index = -3998
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -2, -10, 23 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform15"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -10, 23 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform15/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform15"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform23" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -384, 746.705 )
|
|
||||||
z_index = -4000
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -12, -10, 23 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform23"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -12, -10, 23 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform23/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform23"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform16" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -320, 565.685 )
|
|
||||||
z_index = -3982
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -10, -5, 20 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform16"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -10, -5, 20 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform16/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform16"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform19" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -320, 339.411 )
|
|
||||||
z_index = -3986
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -10, -5, 10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform19"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -10, -5, 10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform19/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform19"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform17" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -480, 248.902 )
|
|
||||||
z_index = -3964
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -15, -1, 10 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform17"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -15, -1, 10 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform17/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform17"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="Platform18" type="Node2D" parent="."]
|
|
||||||
position = Vector2( -480, 22.6274 )
|
|
||||||
z_index = -3968
|
|
||||||
script = ExtResource( 6 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 7 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( -15, -1, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="Platform18"]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -15, -1, 0 )
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="Platform18/PlatformMath"]
|
|
||||||
shape = SubResource( 4 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="Platform18"]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 8 )
|
|
||||||
script = ExtResource( 9 )
|
|
||||||
|
|
||||||
[node name="YSort25D" type="Node" parent="."]
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
|
|
||||||
stream = ExtResource( 2 )
|
|
||||||
volume_db = -20.0
|
|
||||||
autoplay = true
|
|
@ -1,15 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="ogg_vorbis"
|
|
||||||
type="AudioStreamOGGVorbis"
|
|
||||||
path="res://.import/mr_mrs_robot.ogg-04d8a930124c76b878f30fed4f47903c.oggstr"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/mr_mrs_robot.ogg"
|
|
||||||
dest_files=[ "res://.import/mr_mrs_robot.ogg-04d8a930124c76b878f30fed4f47903c.oggstr" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
loop=true
|
|
||||||
loop_offset=0
|
|
@ -1,32 +0,0 @@
|
|||||||
[gd_scene load_steps=6 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/Node25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/node_25d_icon.png" type="Texture" id=2]
|
|
||||||
[ext_resource path="res://assets/platform/textures/forty_five.png" type="Texture" id=3]
|
|
||||||
[ext_resource path="res://assets/platform/platform_sprite.gd" type="Script" id=4]
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=1]
|
|
||||||
extents = Vector3( 5, 0.5, 5 )
|
|
||||||
|
|
||||||
[node name="Platform" type="Node2D"]
|
|
||||||
z_index = -3954
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 2 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, 0, 0 )
|
|
||||||
|
|
||||||
[node name="PlatformMath" type="StaticBody" parent="."]
|
|
||||||
collision_layer = 1048575
|
|
||||||
collision_mask = 1048575
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="PlatformMath"]
|
|
||||||
shape = SubResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlatformSprite" type="Sprite" parent="."]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 3 )
|
|
||||||
script = ExtResource( 4 )
|
|
@ -1,40 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Sprite
|
|
||||||
|
|
||||||
onready var _forty_five = preload("res://assets/platform/textures/forty_five.png")
|
|
||||||
onready var _isometric = preload("res://assets/platform/textures/isometric.png")
|
|
||||||
onready var _top_down = preload("res://assets/platform/textures/top_down.png")
|
|
||||||
onready var _front_side = preload("res://assets/platform/textures/front_side.png")
|
|
||||||
onready var _oblique_y = preload("res://assets/platform/textures/oblique_y.png")
|
|
||||||
onready var _oblique_z = preload("res://assets/platform/textures/oblique_z.png")
|
|
||||||
|
|
||||||
func _process(_delta):
|
|
||||||
if not Engine.editor_hint:
|
|
||||||
if Input.is_action_pressed("forty_five_mode"):
|
|
||||||
set_view_mode(0)
|
|
||||||
elif Input.is_action_pressed("isometric_mode"):
|
|
||||||
set_view_mode(1)
|
|
||||||
elif Input.is_action_pressed("top_down_mode"):
|
|
||||||
set_view_mode(2)
|
|
||||||
elif Input.is_action_pressed("front_side_mode"):
|
|
||||||
set_view_mode(3)
|
|
||||||
elif Input.is_action_pressed("oblique_y_mode"):
|
|
||||||
set_view_mode(4)
|
|
||||||
elif Input.is_action_pressed("oblique_z_mode"):
|
|
||||||
set_view_mode(5)
|
|
||||||
|
|
||||||
|
|
||||||
func set_view_mode(view_mode_index):
|
|
||||||
match view_mode_index:
|
|
||||||
0: # 45 Degrees
|
|
||||||
texture = _forty_five;
|
|
||||||
1: # Isometric
|
|
||||||
texture = _isometric
|
|
||||||
2: # Top Down
|
|
||||||
texture = _top_down
|
|
||||||
3: # Front Side
|
|
||||||
texture = _front_side
|
|
||||||
4: # Oblique Y
|
|
||||||
texture = _oblique_y
|
|
||||||
5: # Oblique Z
|
|
||||||
texture = _oblique_z
|
|
Before Width: | Height: | Size: 812 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/forty_five.png-d90cd8ed1241c4a5270d87a83aafe24d.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/forty_five.png"
|
|
||||||
dest_files=[ "res://.import/forty_five.png-d90cd8ed1241c4a5270d87a83aafe24d.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 161 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/front_side.png-057b43bb7270572907c729580068368b.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/front_side.png"
|
|
||||||
dest_files=[ "res://.import/front_side.png-057b43bb7270572907c729580068368b.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 16 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/isometric.png-364f65b60f600b10cfb048c20ea82124.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/isometric.png"
|
|
||||||
dest_files=[ "res://.import/isometric.png-364f65b60f600b10cfb048c20ea82124.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 735 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/oblique_y.png-ed89b3ef35707993300443a84f7ebbd1.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/oblique_y.png"
|
|
||||||
dest_files=[ "res://.import/oblique_y.png-ed89b3ef35707993300443a84f7ebbd1.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 2.7 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/oblique_z.png-270f041a55370c5ba68850a072597e97.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/oblique_z.png"
|
|
||||||
dest_files=[ "res://.import/oblique_z.png-270f041a55370c5ba68850a072597e97.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 298 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/top_down.png-3df3f4c204d6337fdc9aa208196ed940.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/platform/textures/top_down.png"
|
|
||||||
dest_files=[ "res://.import/top_down.png-3df3f4c204d6337fdc9aa208196ed940.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,95 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
#if REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles Player-specific behavior like moving. We calculate such things with KinematicBody.
|
|
||||||
/// </summary>
|
|
||||||
public class PlayerMath25D : KinematicBody
|
|
||||||
{
|
|
||||||
private Node25D _parent;
|
|
||||||
public real_t verticalSpeed = 0;
|
|
||||||
public bool isometricControls = true;
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
_parent = GetParent<Node25D>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Process(real_t delta)
|
|
||||||
{
|
|
||||||
if (Input.IsActionPressed("exit"))
|
|
||||||
{
|
|
||||||
GetTree().Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.IsActionJustPressed("view_cube_demo"))
|
|
||||||
{
|
|
||||||
GetTree().ChangeScene("res://assets/cube/cube.tscn");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.IsActionJustPressed("toggle_isometric_controls"))
|
|
||||||
{
|
|
||||||
isometricControls = !isometricControls;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("reset_position"))
|
|
||||||
{
|
|
||||||
Transform = new Transform(Basis.Identity, Vector3.Up * 10);
|
|
||||||
verticalSpeed = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HorizontalMovement(delta);
|
|
||||||
VerticalMovement(delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks WASD and Shift for horizontal movement via MoveAndSlide.
|
|
||||||
/// </summary>
|
|
||||||
private void HorizontalMovement(real_t delta)
|
|
||||||
{
|
|
||||||
Vector3 localX = Vector3.Right;
|
|
||||||
Vector3 localZ = Vector3.Back;
|
|
||||||
|
|
||||||
if (isometricControls && _parent.Basis25D.x.IsEqualApprox(Basis25D.Isometric.x * Node25D.SCALE))
|
|
||||||
{
|
|
||||||
localX = new Vector3(0.70710678118f, 0, -0.70710678118f);
|
|
||||||
localZ = new Vector3(0.70710678118f, 0, 0.70710678118f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gather player input and add directional movement to a Vector3 variable.
|
|
||||||
Vector2 movementVec2 = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
|
|
||||||
Vector3 moveDir = localX * movementVec2.x + localZ * movementVec2.y;
|
|
||||||
|
|
||||||
moveDir = moveDir * delta * 600;
|
|
||||||
if (Input.IsActionPressed("movement_modifier"))
|
|
||||||
{
|
|
||||||
moveDir /= 2;
|
|
||||||
}
|
|
||||||
MoveAndSlide(moveDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks Jump and applies gravity and vertical speed via MoveAndCollide.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="delta">Time delta since last call</param>
|
|
||||||
private void VerticalMovement(real_t delta)
|
|
||||||
{
|
|
||||||
if (Input.IsActionJustPressed("jump"))
|
|
||||||
{
|
|
||||||
verticalSpeed = 1.25f;
|
|
||||||
}
|
|
||||||
verticalSpeed -= delta * 5; // Gravity
|
|
||||||
var k = MoveAndCollide(Vector3.Up * verticalSpeed);
|
|
||||||
if (k != null)
|
|
||||||
{
|
|
||||||
verticalSpeed = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,237 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
#if REAL_T_IS_DOUBLE
|
|
||||||
using real_t = System.Double;
|
|
||||||
#else
|
|
||||||
using real_t = System.Single;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[Tool]
|
|
||||||
public class PlayerSprite : Sprite
|
|
||||||
{
|
|
||||||
private static Texture _stand = ResourceLoader.Load<Texture>("res://assets/player/textures/stand.png");
|
|
||||||
private static Texture _jump = ResourceLoader.Load<Texture>("res://assets/player/textures/jump.png");
|
|
||||||
private static Texture _run = ResourceLoader.Load<Texture>("res://assets/player/textures/run.png");
|
|
||||||
private const int FRAMERATE = 15;
|
|
||||||
|
|
||||||
private int _direction;
|
|
||||||
private float _progress;
|
|
||||||
private Node25D _parent;
|
|
||||||
private PlayerMath25D _parentMath;
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
_parent = GetParent<Node25D>();
|
|
||||||
_parentMath = _parent.GetChild<PlayerMath25D>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Process(real_t delta)
|
|
||||||
{
|
|
||||||
if (Engine.EditorHint)
|
|
||||||
{
|
|
||||||
return; // Don't run this in the editor.
|
|
||||||
}
|
|
||||||
SpriteBasis();
|
|
||||||
bool movement = CheckMovement(); // Always run to get direction, but don't always use return bool.
|
|
||||||
|
|
||||||
// Test-only move and collide, check if the player is on the ground.
|
|
||||||
var k = _parentMath.MoveAndCollide(Vector3.Down * 10 * delta, true, true, true);
|
|
||||||
if (k != null)
|
|
||||||
{
|
|
||||||
if (movement)
|
|
||||||
{
|
|
||||||
// TODO: https://github.com/godotengine/godot/issues/28748
|
|
||||||
Hframes = 6;
|
|
||||||
Texture = _run;
|
|
||||||
if (Input.IsActionPressed("movement_modifier"))
|
|
||||||
{
|
|
||||||
delta /= 2;
|
|
||||||
}
|
|
||||||
_progress = (_progress + FRAMERATE * delta) % 6;
|
|
||||||
Frame = _direction * 6 + (int)_progress;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Hframes = 1;
|
|
||||||
Texture = _stand;
|
|
||||||
_progress = 0;
|
|
||||||
Frame = _direction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Hframes = 2;
|
|
||||||
Texture = _jump;
|
|
||||||
_progress = 0;
|
|
||||||
int jumping = _parentMath.verticalSpeed < 0 ? 1 : 0;
|
|
||||||
Frame = _direction * 2 + jumping;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetViewMode(int viewModeIndex)
|
|
||||||
{
|
|
||||||
Transform2D t = Transform;
|
|
||||||
switch (viewModeIndex)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
t.x = new Vector2(1, 0);
|
|
||||||
t.y = new Vector2(0, 0.75f);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
t.x = new Vector2(1, 0);
|
|
||||||
t.y = new Vector2(0, 1);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
t.x = new Vector2(1, 0);
|
|
||||||
t.y = new Vector2(0, 0.5f);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
t.x = new Vector2(1, 0);
|
|
||||||
t.y = new Vector2(0, 1);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
t.x = new Vector2(1, 0);
|
|
||||||
t.y = new Vector2(0.75f, 0.75f);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
t.x = new Vector2(1, 0.25f);
|
|
||||||
t.y = new Vector2(0, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Transform = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Change the basis of the sprite to try and make it fit multiple view modes.
|
|
||||||
/// </summary>
|
|
||||||
private void SpriteBasis()
|
|
||||||
{
|
|
||||||
if (!Engine.EditorHint)
|
|
||||||
{
|
|
||||||
if (Input.IsActionPressed("forty_five_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(0);
|
|
||||||
}
|
|
||||||
else if (Input.IsActionPressed("isometric_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(1);
|
|
||||||
}
|
|
||||||
else if (Input.IsActionPressed("top_down_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(2);
|
|
||||||
}
|
|
||||||
else if (Input.IsActionPressed("front_side_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(3);
|
|
||||||
}
|
|
||||||
else if (Input.IsActionPressed("oblique_y_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(4);
|
|
||||||
}
|
|
||||||
else if (Input.IsActionPressed("oblique_z_mode"))
|
|
||||||
{
|
|
||||||
SetViewMode(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// There might be a more efficient way to do this, but I can't think of it.
|
|
||||||
private bool CheckMovement()
|
|
||||||
{
|
|
||||||
// Gather player input and store movement to these int variables. Note: These indeed have to be integers.
|
|
||||||
int x = 0;
|
|
||||||
int z = 0;
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("move_right"))
|
|
||||||
{
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_left"))
|
|
||||||
{
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_forward"))
|
|
||||||
{
|
|
||||||
z--;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_back"))
|
|
||||||
{
|
|
||||||
z++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for isometric controls and add more to movement accordingly.
|
|
||||||
// For efficiency, only check the X axis since this X axis value isn't used anywhere else.
|
|
||||||
if (!_parentMath.isometricControls && _parent.Basis25D.x.IsEqualApprox(Basis25D.Isometric.x * Node25D.SCALE))
|
|
||||||
{
|
|
||||||
if (Input.IsActionPressed("move_right"))
|
|
||||||
{
|
|
||||||
z++;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_left"))
|
|
||||||
{
|
|
||||||
z--;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_forward"))
|
|
||||||
{
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
if (Input.IsActionPressed("move_back"))
|
|
||||||
{
|
|
||||||
x--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the direction based on which inputs were pressed.
|
|
||||||
if (x == 0)
|
|
||||||
{
|
|
||||||
if (z == 0)
|
|
||||||
{
|
|
||||||
return false; // No movement
|
|
||||||
}
|
|
||||||
else if (z > 0)
|
|
||||||
{
|
|
||||||
_direction = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_direction = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (x > 0)
|
|
||||||
{
|
|
||||||
if (z == 0)
|
|
||||||
{
|
|
||||||
_direction = 2;
|
|
||||||
FlipH = true;
|
|
||||||
}
|
|
||||||
else if (z > 0)
|
|
||||||
{
|
|
||||||
_direction = 1;
|
|
||||||
FlipH = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_direction = 3;
|
|
||||||
FlipH = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (z == 0)
|
|
||||||
{
|
|
||||||
_direction = 2;
|
|
||||||
FlipH = false;
|
|
||||||
}
|
|
||||||
else if (z > 0)
|
|
||||||
{
|
|
||||||
_direction = 1;
|
|
||||||
FlipH = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_direction = 3;
|
|
||||||
FlipH = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // There is movement
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
[gd_scene load_steps=7 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/Node25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/node_25d_icon.png" type="Texture" id=2]
|
|
||||||
[ext_resource path="res://assets/player/PlayerMath25D.cs" type="Script" id=3]
|
|
||||||
[ext_resource path="res://assets/player/textures/stand.png" type="Texture" id=4]
|
|
||||||
[ext_resource path="res://assets/player/PlayerSprite.cs" type="Script" id=5]
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=1]
|
|
||||||
extents = Vector3( 0.5, 1, 0.5 )
|
|
||||||
|
|
||||||
[node name="Player25D" type="Node2D"]
|
|
||||||
position = Vector2( 0, -226.274 )
|
|
||||||
z_index = 100
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 2 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, 10, 0 )
|
|
||||||
|
|
||||||
[node name="PlayerMath25D" type="KinematicBody" parent="."]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0 )
|
|
||||||
script = ExtResource( 3 )
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="PlayerMath25D"]
|
|
||||||
shape = SubResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="PlayerSprite" type="Sprite" parent="."]
|
|
||||||
scale = Vector2( 1, 0.75 )
|
|
||||||
z_index = 1
|
|
||||||
texture = ExtResource( 4 )
|
|
||||||
vframes = 5
|
|
||||||
script = ExtResource( 5 )
|
|
||||||
|
|
||||||
[node name="PlayerCamera" type="Camera2D" parent="PlayerSprite"]
|
|
||||||
current = true
|
|
Before Width: | Height: | Size: 3.7 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/jump.png-ee91d86ec39d8c1dde239a382e843e86.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/player/textures/jump.png"
|
|
||||||
dest_files=[ "res://.import/jump.png-ee91d86ec39d8c1dde239a382e843e86.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 7.8 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/run.png-6110949046e0632be1a9b1c8ac504217.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/player/textures/run.png"
|
|
||||||
dest_files=[ "res://.import/run.png-6110949046e0632be1a9b1c8ac504217.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 1.8 KiB |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/stand.png-4d65e60dbd5f40d1f70da6aa2507ebe3.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/player/textures/stand.png"
|
|
||||||
dest_files=[ "res://.import/stand.png-4d65e60dbd5f40d1f70da6aa2507ebe3.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,39 +0,0 @@
|
|||||||
[gd_scene load_steps=8 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://addons/node25d-cs/Node25D.cs" type="Script" id=1]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/node_25d_icon.png" type="Texture" id=2]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/ShadowMath25D.cs" type="Script" id=3]
|
|
||||||
[ext_resource path="res://addons/node25d-cs/icons/shadow_math_25d_icon.png" type="Texture" id=4]
|
|
||||||
[ext_resource path="res://assets/shadow/textures/forty_five.png" type="Texture" id=5]
|
|
||||||
[ext_resource path="res://assets/shadow/shadow_sprite.gd" type="Script" id=6]
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape" id=1]
|
|
||||||
extents = Vector3( 0.5, 0.001, 0.5 )
|
|
||||||
|
|
||||||
[node name="Shadow25D" type="Node2D"]
|
|
||||||
visible = false
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 2 )
|
|
||||||
}
|
|
||||||
spatialPosition = Vector3( 0, 10, 0 )
|
|
||||||
|
|
||||||
[node name="ShadowMath25D" type="KinematicBody" parent="."]
|
|
||||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0 )
|
|
||||||
collision_layer = 16
|
|
||||||
collision_mask = 16
|
|
||||||
script = ExtResource( 3 )
|
|
||||||
__meta__ = {
|
|
||||||
"_editor_icon": ExtResource( 4 )
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="CollisionShape" type="CollisionShape" parent="ShadowMath25D"]
|
|
||||||
shape = SubResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_lock_": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="ShadowSprite" type="Sprite" parent="."]
|
|
||||||
scale = Vector2( 0.5, 0.5 )
|
|
||||||
texture = ExtResource( 5 )
|
|
||||||
script = ExtResource( 6 )
|
|
@ -1,40 +0,0 @@
|
|||||||
tool
|
|
||||||
extends Sprite
|
|
||||||
|
|
||||||
onready var _forty_five = preload("res://assets/shadow/textures/forty_five.png")
|
|
||||||
onready var _isometric = preload("res://assets/shadow/textures/isometric.png")
|
|
||||||
onready var _top_down = preload("res://assets/shadow/textures/top_down.png")
|
|
||||||
onready var _front_side = preload("res://assets/shadow/textures/front_side.png")
|
|
||||||
onready var _oblique_y = preload("res://assets/shadow/textures/oblique_y.png")
|
|
||||||
onready var _oblique_z = preload("res://assets/shadow/textures/oblique_z.png")
|
|
||||||
|
|
||||||
func _process(_delta):
|
|
||||||
if not Engine.editor_hint:
|
|
||||||
if Input.is_action_pressed("forty_five_mode"):
|
|
||||||
set_view_mode(0)
|
|
||||||
elif Input.is_action_pressed("isometric_mode"):
|
|
||||||
set_view_mode(1)
|
|
||||||
elif Input.is_action_pressed("top_down_mode"):
|
|
||||||
set_view_mode(2)
|
|
||||||
elif Input.is_action_pressed("front_side_mode"):
|
|
||||||
set_view_mode(3)
|
|
||||||
elif Input.is_action_pressed("oblique_y_mode"):
|
|
||||||
set_view_mode(4)
|
|
||||||
elif Input.is_action_pressed("oblique_z_mode"):
|
|
||||||
set_view_mode(5)
|
|
||||||
|
|
||||||
|
|
||||||
func set_view_mode(view_mode_index):
|
|
||||||
match view_mode_index:
|
|
||||||
0: # 45 Degrees
|
|
||||||
texture = _forty_five;
|
|
||||||
1: # Isometric
|
|
||||||
texture = _isometric
|
|
||||||
2: # Top Down
|
|
||||||
texture = _top_down
|
|
||||||
3: # Front Side
|
|
||||||
texture = _front_side
|
|
||||||
4: # Oblique Y
|
|
||||||
texture = _oblique_y
|
|
||||||
5: # Oblique Z
|
|
||||||
texture = _oblique_z
|
|
Before Width: | Height: | Size: 396 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/forty_five.png-22dcfa54db51531b3612f686997a3fbe.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/forty_five.png"
|
|
||||||
dest_files=[ "res://.import/forty_five.png-22dcfa54db51531b3612f686997a3fbe.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 84 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/front_side.png-1470842d27848ecf4de63924b0b98f42.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/front_side.png"
|
|
||||||
dest_files=[ "res://.import/front_side.png-1470842d27848ecf4de63924b0b98f42.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 266 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/isometric.png-1a91c869806816b66a8fb886d4801f31.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/isometric.png"
|
|
||||||
dest_files=[ "res://.import/isometric.png-1a91c869806816b66a8fb886d4801f31.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 353 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/oblique_y.png-47d60a179a2cdeff15364f0e389e6008.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/oblique_y.png"
|
|
||||||
dest_files=[ "res://.import/oblique_y.png-47d60a179a2cdeff15364f0e389e6008.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 639 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/oblique_z.png-d8378bf8b95f890e76162d62a82022de.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/oblique_z.png"
|
|
||||||
dest_files=[ "res://.import/oblique_z.png-d8378bf8b95f890e76162d62a82022de.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
Before Width: | Height: | Size: 87 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/top_down.png-a3a98721249636eff54d8113d6075229.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://assets/shadow/textures/top_down.png"
|
|
||||||
dest_files=[ "res://.import/top_down.png-a3a98721249636eff54d8113d6075229.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,5 +0,0 @@
|
|||||||
extends Control
|
|
||||||
|
|
||||||
func _process(_delta):
|
|
||||||
if Input.is_action_just_pressed("toggle_control_hints"):
|
|
||||||
visible = not visible
|
|
@ -1,28 +0,0 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://assets/ui/control_hints.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="Overlay" type="CanvasLayer"]
|
|
||||||
|
|
||||||
[node name="ControlHints" type="CenterContainer" parent="."]
|
|
||||||
anchor_right = 1.0
|
|
||||||
margin_bottom = 200.0
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="ControlHints"]
|
|
||||||
margin_left = 348.0
|
|
||||||
margin_top = 25.0
|
|
||||||
margin_right = 1251.0
|
|
||||||
margin_bottom = 175.0
|
|
||||||
rect_min_size = Vector2( 500, 50 )
|
|
||||||
text = "
|
|
||||||
Controls: WASD to move, Space to jump, R to reset, Shift to walk, T to toggle isometric controls, C to view cube demo, Tab to toggle hints.
|
|
||||||
|
|
||||||
UIOJKL to change view mode. U = Forty Five deg, I = Isometric,
|
|
||||||
O = Top Down, J = Front Side, K = Oblique Y, L = Oblique Z
|
|
||||||
|
|
||||||
Not every view mode is meant to be good, it's just to showcase what the system can do.
|
|
||||||
In actual games, shadows, resizing, parallax, and other hints of depth could be added to make the world seem more 3D.
|
|
||||||
"
|
|
||||||
align = 1
|
|
||||||
valign = 1
|
|
@ -1,28 +0,0 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://assets/ui/control_hints.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[node name="Overlay" type="CanvasLayer"]
|
|
||||||
|
|
||||||
[node name="ControlHints" type="CenterContainer" parent="."]
|
|
||||||
anchor_right = 1.0
|
|
||||||
margin_bottom = 200.0
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="ControlHints"]
|
|
||||||
margin_left = 416.0
|
|
||||||
margin_top = 25.0
|
|
||||||
margin_right = 1183.0
|
|
||||||
margin_bottom = 175.0
|
|
||||||
rect_min_size = Vector2( 500, 50 )
|
|
||||||
text = "
|
|
||||||
Controls: WASDQE to rotate, R to reset, C to return to the world, Tab to toggle hints.
|
|
||||||
|
|
||||||
UIOKL to change view mode. U = Forty Five deg, I = Isometric,
|
|
||||||
O = Top Down, K = Oblique Y, L = Oblique Z
|
|
||||||
|
|
||||||
Not every view mode is meant to be good, it's just to showcase what the system can do.
|
|
||||||
In actual games, shadows, resizing, parallax, and other hints of depth could be added to make the world seem more 3D.
|
|
||||||
"
|
|
||||||
align = 1
|
|
||||||
valign = 1
|
|
Before Width: | Height: | Size: 262 B |
@ -1,35 +0,0 @@
|
|||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="StreamTexture"
|
|
||||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://icon.png"
|
|
||||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_mode=0
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
flags/repeat=0
|
|
||||||
flags/filter=true
|
|
||||||
flags/mipmaps=false
|
|
||||||
flags/anisotropic=false
|
|
||||||
flags/srgb=2
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/HDR_as_SRGB=false
|
|
||||||
process/invert_color=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
stream=false
|
|
||||||
size_limit=0
|
|
||||||
detect_3d=true
|
|
||||||
svg/scale=1.0
|
|
@ -1,172 +0,0 @@
|
|||||||
; Engine configuration file.
|
|
||||||
; It's best edited using the editor UI and not directly,
|
|
||||||
; since the parameters that go here are not all obvious.
|
|
||||||
;
|
|
||||||
; Format:
|
|
||||||
; [section] ; section goes between []
|
|
||||||
; param=value ; assign values to parameters
|
|
||||||
|
|
||||||
config_version=4
|
|
||||||
|
|
||||||
[application]
|
|
||||||
|
|
||||||
config/name="2.5D Demo with C#"
|
|
||||||
config/description="This demo project shows a way to create a 2.5D game
|
|
||||||
in Godot by mixing 2D and 3D nodes. It also adds a
|
|
||||||
2.5D editor viewport for easily editing 2.5D levels."
|
|
||||||
run/main_scene="res://assets/demo_scene.tscn"
|
|
||||||
config/icon="res://icon.png"
|
|
||||||
|
|
||||||
[display]
|
|
||||||
|
|
||||||
window/size/width=1600
|
|
||||||
window/size/height=900
|
|
||||||
|
|
||||||
[editor_plugins]
|
|
||||||
|
|
||||||
enabled=PoolStringArray( "node25d-cs" )
|
|
||||||
|
|
||||||
[input]
|
|
||||||
|
|
||||||
move_right={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
move_left={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
move_forward={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
move_back={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
movement_modifier={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777348,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
jump={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777350,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
reset_position={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":82,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777222,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
forty_five_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":85,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777354,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
isometric_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":73,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777355,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
top_down_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":79,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777356,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
front_side_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":74,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777351,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
oblique_y_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":75,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777352,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":4,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
oblique_z_mode={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":76,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777353,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":5,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
toggle_isometric_controls={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":84,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":8,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777349,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
toggle_control_hints={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777218,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777347,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":10,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
move_clockwise={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":69,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777359,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":7,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
move_counterclockwise={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":81,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777357,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":6,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
view_cube_demo={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":67,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777358,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
exit={
|
|
||||||
"deadzone": 0.5,
|
|
||||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
|
|
||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
[physics]
|
|
||||||
|
|
||||||
3d/physics_engine="Bullet"
|
|
||||||
|
|
||||||
[rendering]
|
|
||||||
|
|
||||||
quality/driver/driver_name="GLES2"
|
|
||||||
vram_compression/import_etc=true
|
|
||||||
vram_compression/import_etc2=false
|
|
Before Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 42 KiB |
@ -1,14 +0,0 @@
|
|||||||
# Mono Demos
|
|
||||||
|
|
||||||
These demos are written in [C#](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/index.html).
|
|
||||||
You must have the Mono version of Godot to run these.
|
|
||||||
|
|
||||||
Languages: All have [C#](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/index.html),
|
|
||||||
2.5D has some GDScript
|
|
||||||
|
|
||||||
Renderers: Dodge the Creeps is GLES 3, rest are GLES 2
|
|
||||||
|
|
||||||
# Note: Godot 3.2.3 or newer is required
|
|
||||||
|
|
||||||
While most of the demos work with any 3.2.x version, these demos require
|
|
||||||
at least Godot 3.2.3 since there are large C#-specific changes in 3.2.3.
|
|
@ -1,6 +0,0 @@
|
|||||||
<Project Sdk="Godot.NET.Sdk/3.3.0">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<RootNamespace>AndroidIAP</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
@ -1,19 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 2012
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android in-app purchases with C#", "Android in-app purchases with C#.csproj", "{480953C3-B1FD-42F6-8A07-51A3F69024D7}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
ExportDebug|Any CPU = ExportDebug|Any CPU
|
|
||||||
ExportRelease|Any CPU = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
|
|
||||||
{480953C3-B1FD-42F6-8A07-51A3F69024D7}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,67 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
// https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode
|
|
||||||
public enum BillingResponseCode
|
|
||||||
{
|
|
||||||
// The request has reached the maximum timeout before Google Play responds.
|
|
||||||
ServiceTimeout = -3,
|
|
||||||
|
|
||||||
// Requested feature is not supported by Play Store on the current device.
|
|
||||||
FeatureNotSupported = -2,
|
|
||||||
|
|
||||||
// Play Store service is not connected now - potentially transient state.
|
|
||||||
ServiceDisconnected = -1,
|
|
||||||
|
|
||||||
// Success
|
|
||||||
Ok = 0,
|
|
||||||
|
|
||||||
// User pressed back or canceled a dialog
|
|
||||||
UserCanceled = 1,
|
|
||||||
|
|
||||||
// Network connection is down
|
|
||||||
ServiceUnavailable = 2,
|
|
||||||
|
|
||||||
// Billing API version is not supported for the type requested
|
|
||||||
BillingUnavailable = 3,
|
|
||||||
|
|
||||||
// Requested product is not available for purchase
|
|
||||||
ItemUnavailable = 4,
|
|
||||||
|
|
||||||
// Invalid arguments provided to the API.
|
|
||||||
DeveloperError = 5,
|
|
||||||
|
|
||||||
// Fatal error during the API action
|
|
||||||
Error = 6,
|
|
||||||
|
|
||||||
// Failure to purchase since item is already owned
|
|
||||||
ItemAlreadyOwned = 7,
|
|
||||||
|
|
||||||
// Failure to consume since item is not owned
|
|
||||||
ItemNotOwned = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BillingResult
|
|
||||||
{
|
|
||||||
public BillingResult() { }
|
|
||||||
public BillingResult(Dictionary billingResult)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Status = (int)billingResult["status"];
|
|
||||||
ResponseCode = (billingResult.Contains("response_code") ? (BillingResponseCode?)billingResult["response_code"] : null);
|
|
||||||
DebugMessage = (billingResult.Contains("debug_message") ? (string)billingResult["debug_message"] : null);
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
GD.Print("BillingResult: ", ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Status { get; set; }
|
|
||||||
public BillingResponseCode? ResponseCode { get; set; }
|
|
||||||
public string DebugMessage { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
using Godot.Collections;
|
|
||||||
using Godot;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
public enum PurchaseType
|
|
||||||
{
|
|
||||||
InApp,
|
|
||||||
Subs,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GooglePlayBilling : Node
|
|
||||||
{
|
|
||||||
[Signal] public delegate void Connected();
|
|
||||||
[Signal] public delegate void Disconnected();
|
|
||||||
[Signal] public delegate void ConnectError(int code, string message);
|
|
||||||
[Signal] public delegate void SkuDetailsQueryCompleted(Array skuDetails);
|
|
||||||
[Signal] public delegate void SkuDetailsQueryError(int code, string message, string[] querySkuDetails);
|
|
||||||
[Signal] public delegate void PurchasesUpdated(Array purchases);
|
|
||||||
[Signal] public delegate void PurchaseError(int code, string message);
|
|
||||||
[Signal] public delegate void PurchaseAcknowledged(string purchaseToken);
|
|
||||||
[Signal] public delegate void PurchaseAcknowledgementError(int code, string message);
|
|
||||||
[Signal] public delegate void PurchaseConsumed(string purchaseToken);
|
|
||||||
[Signal] public delegate void PurchaseConsumptionError(int code, string message, string purchaseToken);
|
|
||||||
|
|
||||||
[Export] public bool AutoReconnect { get; set; }
|
|
||||||
[Export] public bool AutoConnect { get; set; }
|
|
||||||
|
|
||||||
public bool IsAvailable { get; private set; }
|
|
||||||
|
|
||||||
private Object _payment;
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
if (Engine.HasSingleton("GodotGooglePlayBilling"))
|
|
||||||
{
|
|
||||||
IsAvailable = true;
|
|
||||||
_payment = Engine.GetSingleton("GodotGooglePlayBilling");
|
|
||||||
// These are all signals supported by the API
|
|
||||||
// You can drop some of these based on your needs
|
|
||||||
_payment.Connect("connected", this, nameof(OnGodotGooglePlayBilling_connected)); // No params
|
|
||||||
_payment.Connect("disconnected", this, nameof(OnGodotGooglePlayBilling_disconnected)); // No params
|
|
||||||
_payment.Connect("connect_error", this, nameof(OnGodotGooglePlayBilling_connect_error)); // Response ID (int), Debug message (string)
|
|
||||||
_payment.Connect("sku_details_query_completed", this, nameof(OnGodotGooglePlayBilling_sku_details_query_completed)); // SKUs (Array of Dictionary)
|
|
||||||
_payment.Connect("sku_details_query_error", this, nameof(OnGodotGooglePlayBilling_sku_details_query_error)); // Response ID (int), Debug message (string), Queried SKUs (string[])
|
|
||||||
_payment.Connect("purchases_updated", this, nameof(OnGodotGooglePlayBilling_purchases_updated)); // Purchases (Array of Dictionary)
|
|
||||||
_payment.Connect("purchase_error", this, nameof(OnGodotGooglePlayBilling_purchase_error)); // Response ID (int), Debug message (string)
|
|
||||||
_payment.Connect("purchase_acknowledged", this, nameof(OnGodotGooglePlayBilling_purchase_acknowledged)); // Purchase token (string)
|
|
||||||
_payment.Connect("purchase_acknowledgement_error", this, nameof(OnGodotGooglePlayBilling_purchase_acknowledgement_error)); // Response ID (int), Debug message (string), Purchase token (string)
|
|
||||||
_payment.Connect("purchase_consumed", this, nameof(OnGodotGooglePlayBilling_purchase_consumed)); // Purchase token (string)
|
|
||||||
_payment.Connect("purchase_consumption_error", this, nameof(OnGodotGooglePlayBilling_purchase_consumption_error)); // Response ID (int), Debug message (string), Purchase token (string)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IsAvailable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region GooglePlayBilling Methods
|
|
||||||
|
|
||||||
public void StartConnection() => _payment?.Call("startConnection");
|
|
||||||
|
|
||||||
public void EndConnection() => _payment?.Call("endConnection");
|
|
||||||
|
|
||||||
public void QuerySkuDetails(string[] querySkuDetails, PurchaseType type) => _payment?.Call("querySkuDetails", querySkuDetails, $"{type}".ToLower());
|
|
||||||
|
|
||||||
public bool IsReady() => (_payment?.Call("isReady") as bool?) ?? false;
|
|
||||||
|
|
||||||
public void AcknowledgePurchase(string purchaseToken) => _payment?.Call("acknowledgePurchase", purchaseToken);
|
|
||||||
|
|
||||||
public void ConsumePurchase(string purchaseToken) => _payment?.Call("consumePurchase", purchaseToken);
|
|
||||||
|
|
||||||
public BillingResult Purchase(string sku)
|
|
||||||
{
|
|
||||||
if (_payment == null) return null;
|
|
||||||
var result = (Dictionary)_payment.Call("purchase", sku);
|
|
||||||
return new BillingResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PurchasesResult QueryPurchases(PurchaseType purchaseType)
|
|
||||||
{
|
|
||||||
if (_payment == null) return null;
|
|
||||||
var result = (Dictionary)_payment.Call("queryPurchases", $"{purchaseType}".ToLower());
|
|
||||||
return new PurchasesResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region GodotGooglePlayBilling Signals
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_connected() => EmitSignal(nameof(Connected));
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_disconnected() => EmitSignal(nameof(Disconnected));
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_connect_error(int code, string message) => EmitSignal(nameof(ConnectError), code, message);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_sku_details_query_completed(Array skuDetails) => EmitSignal(nameof(SkuDetailsQueryCompleted), skuDetails);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_sku_details_query_error(int code, string message, string[] querySkuDetails) => EmitSignal(nameof(SkuDetailsQueryError), code, message, querySkuDetails);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchases_updated(Array purchases) => EmitSignal(nameof(PurchasesUpdated), purchases);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchase_error(int code, string message) => EmitSignal(nameof(PurchaseError), code, message);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchase_acknowledged(string purchaseToken) => EmitSignal(nameof(PurchaseAcknowledged), purchaseToken);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchase_acknowledgement_error(int code, string message) => EmitSignal(nameof(PurchaseAcknowledgementError), code, message);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchase_consumed(string purchaseToken) => EmitSignal(nameof(PurchaseConsumed), purchaseToken);
|
|
||||||
|
|
||||||
private void OnGodotGooglePlayBilling_purchase_consumption_error(int code, string message, string purchaseToken) => EmitSignal(nameof(PurchaseConsumptionError), code, message, purchaseToken);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
public static class GooglePlayBillingUtils
|
|
||||||
{
|
|
||||||
public static Purchase[] ConvertPurchaseDictionaryArray(Array arrPurchases)
|
|
||||||
{
|
|
||||||
if (arrPurchases == null) return null;
|
|
||||||
var purchases = new Purchase[arrPurchases.Count];
|
|
||||||
for (int i = 0; i < arrPurchases.Count; i++)
|
|
||||||
{
|
|
||||||
purchases[i] = new Purchase((Dictionary)arrPurchases[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return purchases;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SkuDetails[] ConvertSkuDetailsDictionaryArray(Array arrSkuDetails)
|
|
||||||
{
|
|
||||||
if (arrSkuDetails == null) return null;
|
|
||||||
var skusDetails = new SkuDetails[arrSkuDetails.Count];
|
|
||||||
for (int i = 0; i < arrSkuDetails.Count; i++)
|
|
||||||
{
|
|
||||||
skusDetails[i] = new SkuDetails((Dictionary)arrSkuDetails[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return skusDetails;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
// https://developer.android.com/reference/com/android/billingclient/api/Purchase.PurchaseState
|
|
||||||
public enum PurchaseState
|
|
||||||
{
|
|
||||||
UnspecifiedState = 0,
|
|
||||||
Purchased = 1,
|
|
||||||
Pending = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Purchase
|
|
||||||
{
|
|
||||||
public Purchase() { }
|
|
||||||
|
|
||||||
public Purchase(Dictionary purchase)
|
|
||||||
{
|
|
||||||
foreach (var key in purchase.Keys)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case "order_id":
|
|
||||||
OrderId = (string)purchase[key];
|
|
||||||
break;
|
|
||||||
case "package_name":
|
|
||||||
PackageName = (string)purchase[key];
|
|
||||||
break;
|
|
||||||
case "purchase_state":
|
|
||||||
PurchaseState = (PurchaseState)purchase[key];
|
|
||||||
break;
|
|
||||||
case "purchase_time":
|
|
||||||
PurchaseTime = Convert.ToInt64(purchase[key]);
|
|
||||||
break;
|
|
||||||
case "purchase_token":
|
|
||||||
PurchaseToken = (string)purchase[key];
|
|
||||||
break;
|
|
||||||
case "signature":
|
|
||||||
Signature = (string)purchase[key];
|
|
||||||
break;
|
|
||||||
case "sku":
|
|
||||||
Sku = (string)purchase[key];
|
|
||||||
break;
|
|
||||||
case "is_acknowledged":
|
|
||||||
IsAcknowledged = (bool)purchase[key];
|
|
||||||
break;
|
|
||||||
case "is_auto_renewing":
|
|
||||||
IsAutoRenewing = (bool)purchase[key];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
GD.Print("Error: ", purchase[key], " -> ", ex.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string OrderId { get; set; }
|
|
||||||
public string PackageName { get; set; }
|
|
||||||
public PurchaseState PurchaseState { get; set; }
|
|
||||||
public long PurchaseTime { get; set; }
|
|
||||||
public string PurchaseToken { get; set; }
|
|
||||||
public string Signature { get; set; }
|
|
||||||
public string Sku { get; set; }
|
|
||||||
public bool IsAcknowledged { get; set; }
|
|
||||||
public bool IsAutoRenewing { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
public class PurchasesResult : BillingResult
|
|
||||||
{
|
|
||||||
public PurchasesResult() { }
|
|
||||||
public PurchasesResult(Dictionary purchasesResult)
|
|
||||||
: base(purchasesResult)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Purchases = (purchasesResult.Contains("purchases") ? GooglePlayBillingUtils.ConvertPurchaseDictionaryArray((Array)purchasesResult["purchases"]) : null);
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
GD.Print("PurchasesResult: ", ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Purchase[] Purchases { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Godot;
|
|
||||||
using Godot.Collections;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling
|
|
||||||
{
|
|
||||||
public class SkuDetails
|
|
||||||
{
|
|
||||||
public SkuDetails() { }
|
|
||||||
|
|
||||||
public SkuDetails(Dictionary skuDetails)
|
|
||||||
{
|
|
||||||
foreach (var key in skuDetails.Keys)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case "sku":
|
|
||||||
Sku = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "title":
|
|
||||||
Title = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "description":
|
|
||||||
Description = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "price":
|
|
||||||
Price = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "price_currency_code":
|
|
||||||
PriceCurrencyCode = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "price_amount_micros":
|
|
||||||
PriceAmountMicros = Convert.ToInt64(skuDetails[key]);
|
|
||||||
break;
|
|
||||||
case "free_trial_period":
|
|
||||||
FreeTrialPeriod = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "icon_url":
|
|
||||||
IconUrl = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "introductory_price":
|
|
||||||
IntroductoryPrice = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "introductory_price_amount_micros":
|
|
||||||
IntroductoryPriceAmountMicros = Convert.ToInt64(skuDetails[key]);
|
|
||||||
break;
|
|
||||||
case "introductory_price_cycles":
|
|
||||||
IntroductoryPriceCycles = (int)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "introductory_price_period":
|
|
||||||
IntroductoryPricePeriod = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "original_price":
|
|
||||||
OriginalPrice = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "original_price_amount_micros":
|
|
||||||
OriginalPriceAmountMicros = Convert.ToInt64(skuDetails[key]);
|
|
||||||
break;
|
|
||||||
case "subscription_period":
|
|
||||||
SubscriptionPeriod = (string)skuDetails[key];
|
|
||||||
break;
|
|
||||||
case "type":
|
|
||||||
switch(skuDetails[key])
|
|
||||||
{
|
|
||||||
case "inapp":
|
|
||||||
Type = PurchaseType.InApp;
|
|
||||||
break;
|
|
||||||
case "subs":
|
|
||||||
Type = PurchaseType.Subs;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
GD.Print("Error: ", skuDetails[key], " -> ", ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Sku { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string Price { get; set; }
|
|
||||||
public string PriceCurrencyCode { get; set; }
|
|
||||||
public long PriceAmountMicros { get; set; }
|
|
||||||
public string FreeTrialPeriod { get; set; }
|
|
||||||
public string IconUrl { get; set; }
|
|
||||||
public string IntroductoryPrice { get; set; }
|
|
||||||
public long IntroductoryPriceAmountMicros { get; set; }
|
|
||||||
public int IntroductoryPriceCycles { get; set; }
|
|
||||||
public string IntroductoryPricePeriod { get; set; }
|
|
||||||
public string OriginalPrice { get; set; }
|
|
||||||
public long OriginalPriceAmountMicros { get; set; }
|
|
||||||
public string SubscriptionPeriod { get; set; }
|
|
||||||
public PurchaseType Type { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,190 +0,0 @@
|
|||||||
using AndroidInAppPurchasesWithCSharp.GodotGooglePlayBilling;
|
|
||||||
using Godot;
|
|
||||||
using System.Linq;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace AndroidInAppPurchasesWithCSharp
|
|
||||||
{
|
|
||||||
public class Main : Control
|
|
||||||
{
|
|
||||||
const string TestItemSku = "my_in_app_purchase_sku";
|
|
||||||
|
|
||||||
private AcceptDialog _alertDialog;
|
|
||||||
private Label _label;
|
|
||||||
|
|
||||||
private GooglePlayBilling _payment;
|
|
||||||
|
|
||||||
private string _testItemPurchaseToken;
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
_payment = GetNode<GooglePlayBilling>("GooglePlayBilling");
|
|
||||||
_alertDialog = GetNode<AcceptDialog>("AlertDialog");
|
|
||||||
_label = GetNode<Label>("Label");
|
|
||||||
|
|
||||||
if (_payment.IsAvailable)
|
|
||||||
{
|
|
||||||
_label.Text += $"\n\n\nTest item SKU: {TestItemSku}";
|
|
||||||
|
|
||||||
// No params.
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.Connected), this, nameof(OnConnected));
|
|
||||||
// No params.
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.Disconnected), this, nameof(OnDisconnected));
|
|
||||||
// Response ID (int), Debug message (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.ConnectError), this, nameof(OnConnectError));
|
|
||||||
// Purchases (Dictionary[]).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchasesUpdated), this, nameof(OnPurchasesUpdated));
|
|
||||||
// Response ID (int), Debug message (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchaseError), this, nameof(OnPurchaseError));
|
|
||||||
// SKUs (Dictionary[]).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.SkuDetailsQueryCompleted), this, nameof(OnSkuDetailsQueryCompleted));
|
|
||||||
// Response ID (int), Debug message (string), Queried SKUs (string[]).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.SkuDetailsQueryError), this, nameof(OnSkuDetailsQueryError));
|
|
||||||
// Purchase token (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchaseAcknowledged), this, nameof(OnPurchaseAcknowledged));
|
|
||||||
// Response ID (int), Debug message (string), Purchase token (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchaseAcknowledgementError), this, nameof(OnPurchaseAcknowledgementError));
|
|
||||||
// Purchase token (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchaseConsumed), this, nameof(OnPurchaseConsumed));
|
|
||||||
// Response ID (int), Debug message (string), Purchase token (string).
|
|
||||||
_payment.Connect(nameof(GooglePlayBilling.PurchaseConsumptionError), this, nameof(OnPurchaseConsumptionError));
|
|
||||||
_payment.StartConnection();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ShowAlert("Android IAP support is not enabled. Make sure you have enabled 'Custom Build' and installed and enabled the GodotGooglePlayBilling plugin in your Android export settings! This application will not work.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowAlert(string text)
|
|
||||||
{
|
|
||||||
_alertDialog.DialogText = text;
|
|
||||||
_alertDialog.PopupCentered();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnConnected()
|
|
||||||
{
|
|
||||||
GD.Print("PurchaseManager connected");
|
|
||||||
|
|
||||||
// We must acknowledge all puchases.
|
|
||||||
// See https://developer.android.com/google/play/billing/integrate#process for more information
|
|
||||||
var purchasesResult = _payment.QueryPurchases(PurchaseType.InApp);
|
|
||||||
if (purchasesResult.Status == (int)Error.Ok)
|
|
||||||
{
|
|
||||||
foreach (var purchase in purchasesResult.Purchases)
|
|
||||||
{
|
|
||||||
if (!purchase.IsAcknowledged)
|
|
||||||
{
|
|
||||||
GD.Print($"Purchase {purchase.Sku} has not been acknowledged. Acknowledging...");
|
|
||||||
_payment.AcknowledgePurchase(purchase.PurchaseToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GD.Print($"Purchase query failed: {purchasesResult.ResponseCode} - {purchasesResult.DebugMessage}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnDisconnected()
|
|
||||||
{
|
|
||||||
ShowAlert("GodotGooglePlayBilling disconnected. Will try to reconnect in 10s...");
|
|
||||||
await ToSignal(GetTree().CreateTimer(10), "timeout");
|
|
||||||
_payment.StartConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnConnectError(int code, string message)
|
|
||||||
{
|
|
||||||
ShowAlert("PurchaseManager connect error");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchasesUpdated(Godot.Collections.Array arrPurchases)
|
|
||||||
{
|
|
||||||
GD.Print($"Purchases updated: {JSON.Print(arrPurchases)}");
|
|
||||||
|
|
||||||
// See OnConnected
|
|
||||||
var purchases = GooglePlayBillingUtils.ConvertPurchaseDictionaryArray(arrPurchases);
|
|
||||||
|
|
||||||
foreach (var purchase in purchases)
|
|
||||||
{
|
|
||||||
if (!purchase.IsAcknowledged)
|
|
||||||
{
|
|
||||||
GD.Print($"Purchase {purchase.Sku} has not been acknowledged. Acknowledging...");
|
|
||||||
_payment.AcknowledgePurchase(purchase.PurchaseToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (purchases.Length > 0)
|
|
||||||
{
|
|
||||||
_testItemPurchaseToken = purchases.Last().PurchaseToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseError(int code, string message)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase error {code}: {message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSkuDetailsQueryCompleted(Godot.Collections.Array arrSkuDetails)
|
|
||||||
{
|
|
||||||
ShowAlert(JSON.Print(arrSkuDetails));
|
|
||||||
|
|
||||||
var skuDetails = GooglePlayBillingUtils.ConvertSkuDetailsDictionaryArray(arrSkuDetails);
|
|
||||||
foreach (var skuDetail in skuDetails)
|
|
||||||
{
|
|
||||||
GD.Print($"Sku {skuDetail.Sku}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSkuDetailsQueryError(int code, string message, string[] querySkuDetails)
|
|
||||||
{
|
|
||||||
ShowAlert($"SKU details query error {code}: {message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseAcknowledged(string purchaseToken)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase acknowledged: {purchaseToken}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseAcknowledgementError(int code, string message)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase acknowledgement error {code}: {message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseConsumed(string purchaseToken)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase consumed successfully: {purchaseToken}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseConsumptionError(int code, string message, string purchaseToken)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase acknowledgement error {code}: {message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// GUI
|
|
||||||
private void OnQuerySkuDetailsButton_pressed()
|
|
||||||
{
|
|
||||||
_payment.QuerySkuDetails(new string[] { TestItemSku }, PurchaseType.InApp); // Use "subs" for subscriptions.
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPurchaseButton_pressed()
|
|
||||||
{
|
|
||||||
var response = _payment.Purchase(TestItemSku);
|
|
||||||
if (response != null && response.Status != (int)Error.Ok)
|
|
||||||
{
|
|
||||||
ShowAlert($"Purchase error {response.ResponseCode} {response.DebugMessage}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnConsumeButton_pressed()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_testItemPurchaseToken))
|
|
||||||
{
|
|
||||||
ShowAlert("You need to set 'test_item_purchase_token' first! (either by hand or in code)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_payment.ConsumePurchase(_testItemPurchaseToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|