diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..c04eb75f2a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. +# Owners can be @users, @org/teams or emails + +/misc/2.5d @aaronfranke +/mono/2.5d @aaronfranke diff --git a/misc/2.5d/README.md b/misc/2.5d/README.md new file mode 100644 index 0000000000..01b3d95d45 --- /dev/null +++ b/misc/2.5d/README.md @@ -0,0 +1,35 @@ +# 2.5D Demo Project (GDScript) + +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. + +Note: There is a Mono C# version available [here](https://github.com/godotengine/godot-demo-projects/tree/master/mono/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, a 2.5D transformation matrix made of three Vector2 is 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 set of basis vectors in Node25D, use it on all instances, 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](screenshots/forty_five.png) + +![Isometric](screenshots/isometric.png) + +![Oblique Z](screenshots/oblique_z.png) + +![Oblique Y](screenshots/oblique_y.png) + +![Front Side](screenshots/front_side.png) + +![Cube](screenshots/cube.png) + +![2.5D Editor Viewport](screenshots/editor.png) + +## Music License + +`assets/mr_mrs_robot.ogg` Copyright © circa 2008 Juan Linietsky, CC-BY: Attribution. diff --git a/misc/2.5d/addons/node25d/.broken-gdscripts/Basis25D.gd b/misc/2.5d/addons/node25d/.broken-gdscripts/Basis25D.gd new file mode 100644 index 0000000000..6b7817fd09 --- /dev/null +++ b/misc/2.5d/addons/node25d/.broken-gdscripts/Basis25D.gd @@ -0,0 +1,52 @@ +# Currently broken unless Godot makes this kind of thing possible: +# https://github.com/godotengine/godot/issues/21461 +# https://github.com/godotengine/godot-proposals/issues/279 + +# Basis25D structure for performing 2.5D transform math. +# Note: All code assumes that Y is UP in 3D, and DOWN in 2D. +# Meaning, 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. + +class_name Basis25D + +var x: Vector2 = Vector2() +var y: Vector2 = Vector2() +var z: Vector2 = Vector2() + +static func top_down(): + return init(1, 0, 0, 0, 0, 1) + +static func front_side(): + return init(1, 0, 0, -1, 0, 0) + +static func forty_five(): + return init(1, 0, 0, -0.70710678118, 0, 0.70710678118) + +static func isometric(): + return init(0.86602540378, 0.5, 0, -1, -0.86602540378, 0.5) + +static func oblique_y(): + return init(1, 0, -1, -1, 0, 1) + +static func oblique_z(): + return init(1, 0, 0, -1, -1, 1) + +# Creates a Dimetric Basis25D from the angle between the Y axis and the others. +# Dimetric(2.09439510239) is the same as Isometric. +# Try to keep this number away from a multiple of Tau/4 (or Pi/2) radians. +static func dimetric(angle): + var sine = sin(angle) + var cosine = cos(angle) + return init(sine, -cosine, 0, -1, -sine, -cosine) + +static func init(xx, xy, yx, yy, zx, zy): + var xv = Vector2(xx, xy) + var yv = Vector2(yx, yy) + var zv = Vector2(zx, zy) + return Basis25D.new(xv, yv, zv) + +func _init(xAxis: Vector2, yAxis: Vector2, zAxis: Vector2): + x = xAxis + y = yAxis + z = zAxis diff --git a/misc/2.5d/addons/node25d/.broken-gdscripts/Transform25D.gd b/misc/2.5d/addons/node25d/.broken-gdscripts/Transform25D.gd new file mode 100644 index 0000000000..d4ed88102f --- /dev/null +++ b/misc/2.5d/addons/node25d/.broken-gdscripts/Transform25D.gd @@ -0,0 +1,22 @@ +# Currently broken unless Godot makes this kind of thing possible: +# https://github.com/godotengine/godot/issues/21461 +# https://github.com/godotengine/godot-proposals/issues/279 + +# Calculates the 2D transformation from a 3D position and a Basis25D. + +class_name Transform25D + +var spatial_position: Vector3 = Vector3() +var basis #: Basis25D + +func flat_transform(): + return Transform2D(0, flat_position()) + +func flat_position(): + var pos = spatial_position.x * basis.x + pos += spatial_position.y * basis.y + pos += spatial_position.z * basis.z + return pos + +func _init(basis25d): + basis = basis25d diff --git a/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png b/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png new file mode 100644 index 0000000000..2780a094fb Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png differ diff --git a/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png.import b/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png.import new file mode 100644 index 0000000000..cfa964d52d --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/kinematic_body_25d.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/kinematic_body_25d.png-c455d5ccb8ec7543b62fff6e803eee7c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/kinematic_body_25d.png" +dest_files=[ "res://.import/kinematic_body_25d.png-c455d5ccb8ec7543b62fff6e803eee7c.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/node_25d.png b/misc/2.5d/addons/node25d/icons/node_25d.png new file mode 100644 index 0000000000..ede1d823fd Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/node_25d.png differ diff --git a/misc/2.5d/addons/node25d/icons/node_25d.png.import b/misc/2.5d/addons/node25d/icons/node_25d.png.import new file mode 100644 index 0000000000..1eba533ef1 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/node_25d.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/node_25d.png-72e45d8600ccbde01c6d9ad51f5fc530.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/node_25d.png" +dest_files=[ "res://.import/node_25d.png-72e45d8600ccbde01c6d9ad51f5fc530.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/node_25d_icon.png b/misc/2.5d/addons/node25d/icons/node_25d_icon.png new file mode 100644 index 0000000000..12b13bb58b Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/node_25d_icon.png differ diff --git a/misc/2.5d/addons/node25d/icons/node_25d_icon.png.import b/misc/2.5d/addons/node25d/icons/node_25d_icon.png.import new file mode 100644 index 0000000000..29f4dda834 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/node_25d_icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/node_25d_icon.png-2ad780313818706789bbb15408797db2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/node_25d_icon.png" +dest_files=[ "res://.import/node_25d_icon.png-2ad780313818706789bbb15408797db2.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/shadow_math_25d.png b/misc/2.5d/addons/node25d/icons/shadow_math_25d.png new file mode 100644 index 0000000000..0dbc8c4b05 Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/shadow_math_25d.png differ diff --git a/misc/2.5d/addons/node25d/icons/shadow_math_25d.png.import b/misc/2.5d/addons/node25d/icons/shadow_math_25d.png.import new file mode 100644 index 0000000000..54046259e2 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/shadow_math_25d.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/shadow_math_25d.png-333790a3285ee4c26792088985815eba.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/shadow_math_25d.png" +dest_files=[ "res://.import/shadow_math_25d.png-333790a3285ee4c26792088985815eba.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png b/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png new file mode 100644 index 0000000000..ae13ea3823 Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png differ diff --git a/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png.import b/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png.import new file mode 100644 index 0000000000..3c8a11d040 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/shadow_math_25d_icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/shadow_math_25d_icon.png-f286bd905218b9a04121a430c1fdd042.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/shadow_math_25d_icon.png" +dest_files=[ "res://.import/shadow_math_25d_icon.png-f286bd905218b9a04121a430c1fdd042.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/viewport_25d.svg b/misc/2.5d/addons/node25d/icons/viewport_25d.svg new file mode 100644 index 0000000000..22bd96ec2d --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/viewport_25d.svg @@ -0,0 +1 @@ + diff --git a/misc/2.5d/addons/node25d/icons/viewport_25d.svg.import b/misc/2.5d/addons/node25d/icons/viewport_25d.svg.import new file mode 100644 index 0000000000..72df11da53 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/viewport_25d.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/viewport_25d.svg-5df077fb699779f821141e20086cbf11.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/viewport_25d.svg" +dest_files=[ "res://.import/viewport_25d.svg-5df077fb699779f821141e20086cbf11.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/y_sort_25d.png b/misc/2.5d/addons/node25d/icons/y_sort_25d.png new file mode 100644 index 0000000000..e37e57502d Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/y_sort_25d.png differ diff --git a/misc/2.5d/addons/node25d/icons/y_sort_25d.png.import b/misc/2.5d/addons/node25d/icons/y_sort_25d.png.import new file mode 100644 index 0000000000..64a7c359da --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/y_sort_25d.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/y_sort_25d.png-2e15f3765afd8b0136201cb9dea4049b.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/y_sort_25d.png" +dest_files=[ "res://.import/y_sort_25d.png-2e15f3765afd8b0136201cb9dea4049b.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png b/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png new file mode 100644 index 0000000000..1e362220e2 Binary files /dev/null and b/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png differ diff --git a/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png.import b/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png.import new file mode 100644 index 0000000000..f1dab61a48 --- /dev/null +++ b/misc/2.5d/addons/node25d/icons/y_sort_25d_icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/y_sort_25d_icon.png-48050bfa8b299992a68b4f1e12bd5d44.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/node25d/icons/y_sort_25d_icon.png" +dest_files=[ "res://.import/y_sort_25d_icon.png-48050bfa8b299992a68b4f1e12bd5d44.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd new file mode 100644 index 0000000000..54a386c144 --- /dev/null +++ b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd @@ -0,0 +1,105 @@ +tool +extends Node2D + +# Not pixel perfect for all axes in all modes, but works well enough. +# Rounding is not done until after the movement is finished. +const ROUGHLY_ROUND_TO_PIXELS = true + +# Set when the node is created. +var node_25d: Node25D +var spatial_node + +# Input from Viewport25D, represents if the mouse is clicked. +var wants_to_move = false + +# Used to control the state of movement. +var _moving = false +var _start_position = Vector2() + +# Stores state of closest or currently used axis. +var dominant_axis + +onready var lines_root = $Lines +onready var lines = [$Lines/X, $Lines/Y, $Lines/Z] + +func _process(_delta): + if !lines: + return # Somehow this node hasn't been set up yet. + if !node_25d: + 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. + var mouse_position = get_local_mouse_position() + if !_moving: + # If the mouse is farther than this many pixels, it won't grab anything. + var closest_distance = 20.0 + dominant_axis = -1 + for i in range(3): + lines[i].modulate.a = 0.8 # Unrelated, but needs a loop too. + var distance = _distance_to_segment_at_index(i, mouse_position) + if distance < closest_distance: + closest_distance = distance + dominant_axis = i + if dominant_axis == -1: + # If we're not hovering over a line, ensure they are placed correctly. + lines_root.global_position = node_25d.global_position + return + + lines[dominant_axis].modulate.a = 1 + if !wants_to_move: + _moving = false + elif wants_to_move and !_moving: + _moving = true + _start_position = mouse_position + + if _moving: + # Change modulate of unselected axes. + lines[(dominant_axis + 1) % 3].modulate.a = 0.5 + lines[(dominant_axis + 2) % 3].modulate.a = 0.5 + # Calculate mouse movement and reset for next frame. + var mouse_diff = mouse_position - _start_position + _start_position = mouse_position + # Calculate movement. + var projected_diff = mouse_diff.project(lines[dominant_axis].points[1]) + var movement = projected_diff.length() / Node25D.SCALE + if is_equal_approx(PI, projected_diff.angle_to(lines[dominant_axis].points[1])): + movement *= -1 + # Apply movement. + spatial_node.transform.origin += spatial_node.transform.basis[dominant_axis] * movement + else: + # Make sure the gizmo is located at the object. + global_position = node_25d.global_position + if ROUGHLY_ROUND_TO_PIXELS: + spatial_node.transform.origin = (spatial_node.transform.origin * Node25D.SCALE).round() / Node25D.SCALE + # Move the gizmo lines appropriately. + lines_root.global_position = node_25d.global_position + node_25d.property_list_changed_notify() + + +# 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. +func initialize(): + var basis = node_25d.get_basis() + for i in range(3): + lines[i].points[1] = basis[i] * 3 + global_position = node_25d.global_position + spatial_node = node_25d.get_child(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. +func _distance_to_segment_at_index(index, point): + if !lines: + return INF + if point.length_squared() < 400: + return INF + + var segment_end = lines[index].points[1] + var length_squared = segment_end.length_squared() + if length_squared < 400: + return INF + + var t = clamp(point.dot(segment_end) / length_squared, 0, 1) + var projection = t * segment_end + return point.distance_to(projection) diff --git a/misc/2.5d/addons/node25d/main_screen/gizmo_25d.tscn b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.tscn new file mode 100644 index 0000000000..5a565dc62b --- /dev/null +++ b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/node25d/main_screen/gizmo_25d.gd" 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 ) diff --git a/misc/2.5d/addons/node25d/main_screen/main_screen_25d.tscn b/misc/2.5d/addons/node25d/main_screen/main_screen_25d.tscn new file mode 100644 index 0000000000..a4ea542096 --- /dev/null +++ b/misc/2.5d/addons/node25d/main_screen/main_screen_25d.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://addons/node25d/main_screen/viewport_25d.gd" type="Script" id=1] +[ext_resource path="res://addons/node25d/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"] diff --git a/misc/2.5d/addons/node25d/main_screen/view_mode_button_group.tres b/misc/2.5d/addons/node25d/main_screen/view_mode_button_group.tres new file mode 100644 index 0000000000..0e55d74023 --- /dev/null +++ b/misc/2.5d/addons/node25d/main_screen/view_mode_button_group.tres @@ -0,0 +1,3 @@ +[gd_resource type="ButtonGroup" format=2] + +[resource] diff --git a/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd b/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd new file mode 100644 index 0000000000..c6d83d6690 --- /dev/null +++ b/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd @@ -0,0 +1,147 @@ +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/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 !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 !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.node_25d and !view_mode_changed_this_frame: + contains = true + if !contains: + overlay_child.queue_free() + + # Add new gizmos. + for selected in selection: + if selected is Node25D: + var new = true + for overlay_child in overlay_children: + if selected == overlay_child.node_25d: + new = false + if new: + var gizmo = gizmo_25d_scene.instance() + viewport_overlay.add_child(gizmo) + gizmo.node_25d = selected + gizmo.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.wants_to_move = 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.wants_to_move = 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) + 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 diff --git a/misc/2.5d/addons/node25d/node25d_plugin.gd b/misc/2.5d/addons/node25d/node25d_plugin.gd new file mode 100644 index 0000000000..a5d179e7d2 --- /dev/null +++ b/misc/2.5d/addons/node25d/node25d_plugin.gd @@ -0,0 +1,47 @@ +tool +extends EditorPlugin + +const MainPanel = preload("res://addons/node25d/main_screen/main_screen_25d.tscn") + +var main_panel_instance + +func _enter_tree(): + main_panel_instance = MainPanel.instance() + 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("node_25d.gd"), preload("icons/node_25d_icon.png")) + add_custom_type("YSort25D", "Node", preload("y_sort_25d.gd"), preload("icons/y_sort_25d_icon.png")) + add_custom_type("ShadowMath25D", "KinematicBody", preload("shadow_math_25d.gd"), 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/icons/viewport_25d.svg") diff --git a/misc/2.5d/addons/node25d/node_25d.gd b/misc/2.5d/addons/node25d/node_25d.gd new file mode 100644 index 0000000000..be8b00b67f --- /dev/null +++ b/misc/2.5d/addons/node25d/node_25d.gd @@ -0,0 +1,131 @@ +# This node converts a 3D position to 2D using a 2.5D transformation matrix. +# The transformation of its 2D form is controlled by its 3D child. +tool +extends Node2D +class_name Node25D, "res://addons/node25d/icons/node_25d_icon.png" + +# SCALE is the number of 2D units in one 3D unit. Ideally, but not necessarily, an integer. +const SCALE = 32 + +# Exported spatial position for editor usage. +export(Vector3) var spatial_position setget set_spatial_position, get_spatial_position + +# GDScript throws errors when Basis25D is its own structure. +# There is a broken implementation in a hidden folder. +# https://github.com/godotengine/godot/issues/21461 +# https://github.com/godotengine/godot-proposals/issues/279 +var _basisX: Vector2 +var _basisY: Vector2 +var _basisZ: Vector2 + +# Cache the spatial stuff for internal use. +var _spatial_position: Vector3 +var _spatial_node: Spatial + + +# These are separated in case anyone wishes to easily extend Node25D. +func _ready(): + Node25D_ready() + + +func _process(_delta): + Node25D_process() + + +# Call this method in _ready, or before Node25D_process is first ran. +func Node25D_ready(): + _spatial_node = get_child(0) + # Changing the values here will change the default for all Node25D instances. + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(0, -0.70710678118) + _basisZ = SCALE * Vector2(0, 0.70710678118) + + +# Call this method in _process, or whenever the position of this object changes. +func Node25D_process(): + _check_view_mode() + if _spatial_node == null: + return + _spatial_position = _spatial_node.translation + + var flat_pos = _spatial_position.x * _basisX + flat_pos += _spatial_position.y * _basisY + flat_pos += _spatial_position.z * _basisZ + + global_position = flat_pos + + +func get_basis(): + return [_basisX, _basisY, _basisZ] + + +func get_spatial_position(): + if !_spatial_node: + _spatial_node = get_child(0) + return _spatial_node.translation + + +func set_spatial_position(value): + _spatial_position = value + if _spatial_node: + _spatial_node.translation = value + elif get_child_count() > 0: + _spatial_node = get_child(0) + + +# Change the basis based on the view_mode_index argument. +# This can be changed or removed in actual games where you only need one view mode. +func set_view_mode(view_mode_index): + match view_mode_index: + 0: # 45 Degrees + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(0, -0.70710678118) + _basisZ = SCALE * Vector2(0, 0.70710678118) + 1: # Isometric + _basisX = SCALE * Vector2(0.86602540378, 0.5) + _basisY = SCALE * Vector2(0, -1) + _basisZ = SCALE * Vector2(-0.86602540378, 0.5) + 2: # Top Down + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(0, 0) + _basisZ = SCALE * Vector2(0, 1) + 3: # Front Side + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(0, -1) + _basisZ = SCALE * Vector2(0, 0) + 4: # Oblique Y + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(-0.70710678118, -0.70710678118) + _basisZ = SCALE * Vector2(0, 1) + 5: # Oblique Z + _basisX = SCALE * Vector2(1, 0) + _basisY = SCALE * Vector2(0, -1) + _basisZ = SCALE * Vector2(-0.70710678118, 0.70710678118) + + +# Check if anyone presses the view mode buttons and change the basis accordingly. +# This can be changed or removed in actual games where you only need one view mode. +func _check_view_mode(): + if Input.is_action_just_pressed("forty_five_mode"): + set_view_mode(0) + elif Input.is_action_just_pressed("isometric_mode"): + set_view_mode(1) + elif Input.is_action_just_pressed("top_down_mode"): + set_view_mode(2) + elif Input.is_action_just_pressed("front_side_mode"): + set_view_mode(3) + elif Input.is_action_just_pressed("oblique_y_mode"): + set_view_mode(4) + elif Input.is_action_just_pressed("oblique_z_mode"): + set_view_mode(5) + + +# Used by YSort25D +static func y_sort(a: Node25D, b: Node25D): + return a._spatial_position.y < b._spatial_position.y + + +static func y_sort_slight_xz(a: Node25D, b: Node25D): + var a_index = a._spatial_position.y + 0.001 * (a._spatial_position.x + a._spatial_position.z) + var b_index = b._spatial_position.y + 0.001 * (b._spatial_position.x + b._spatial_position.z) + return a_index < b_index diff --git a/misc/2.5d/addons/node25d/plugin.cfg b/misc/2.5d/addons/node25d/plugin.cfg new file mode 100644 index 0000000000..3336dfa810 --- /dev/null +++ b/misc/2.5d/addons/node25d/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Node25D" +description="Adds Node25D" +author="Aaron Franke" +version="1.0" +script="node25d_plugin.gd" diff --git a/misc/2.5d/addons/node25d/shadow_math_25d.gd b/misc/2.5d/addons/node25d/shadow_math_25d.gd new file mode 100644 index 0000000000..8df0182abb --- /dev/null +++ b/misc/2.5d/addons/node25d/shadow_math_25d.gd @@ -0,0 +1,33 @@ +# 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). +tool +extends KinematicBody +class_name ShadowMath25D, "res://addons/node25d/icons/shadow_math_25d_icon.png" + +# The maximum distance below objects that shadows will appear (in 3D units). +var shadow_length = 1000.0 +var _shadow_root: Node25D +var _target_math: Spatial + + +func _ready(): + _shadow_root = get_parent() + var index = _shadow_root.get_position_in_parent() + if (index > 0): # Else, Shadow is not in a valid place. + _target_math = _shadow_root.get_parent().get_child(index - 1).get_child(0) + + +func _process(_delta): + if _target_math == null: + if _shadow_root != null: + _shadow_root.visible = false + return # Shadow is not in a valid place or you're viewing the Shadow25D scene. + + translation = _target_math.translation + var k = move_and_collide(Vector3.DOWN * shadow_length) + if k == null: + _shadow_root.visible = false + else: + _shadow_root.visible = true + global_transform = transform diff --git a/misc/2.5d/addons/node25d/y_sort_25d.gd b/misc/2.5d/addons/node25d/y_sort_25d.gd new file mode 100644 index 0000000000..1f289820c4 --- /dev/null +++ b/misc/2.5d/addons/node25d/y_sort_25d.gd @@ -0,0 +1,46 @@ +# Sorts all Node25D children of its parent. +# This is different from the C# version of this project +# because the execution order is different and otherwise +# sorting is delayed by one frame. +tool +extends Node # Note: NOT Node2D, Node25D, or YSort +class_name YSort25D, "res://addons/node25d/icons/y_sort_25d_icon.png" + +# Whether or not to automatically call sort() in _process(). +export(bool) var sort_enabled := true +var _parent_node: Node2D # NOT Node25D + + +func _ready(): + _parent_node = get_parent() + + +func _process(_delta): + if sort_enabled: + sort() + + +# Call this method in _process, or whenever you want to sort children. +func sort(): + if _parent_node == null: + return # _ready() hasn't been run yet + var parent_children = _parent_node.get_children() + if parent_children.size() > 4000: + # The Z index only goes from -4096 to 4096, and we want room for objects having multiple layers. + printerr("Sorting failed: Max number of YSort25D nodes is 4000.") + return + + # We only want to get Node25D children. + # Currently, it also grabs Node2D children. + var node25d_nodes = [] + for n in parent_children: + if n.get_class() == "Node2D": + node25d_nodes.append(n) + node25d_nodes.sort_custom(Node25D, "y_sort_slight_xz") + + var z_index = -4000 + for i in range(0, node25d_nodes.size()): + node25d_nodes[i].z_index = z_index + # Increment by 2 each time, to allow for shadows in-between. + # This does mean that we have a limit of 4000 total sorted Node25Ds. + z_index += 2 diff --git a/misc/2.5d/assets/cube/cube.tscn b/misc/2.5d/assets/cube/cube.tscn new file mode 100644 index 0000000000..6034f1c8bc --- /dev/null +++ b/misc/2.5d/assets/cube/cube.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://addons/node25d/icons/y_sort_25d_icon.png" type="Texture" id=1] +[ext_resource path="res://assets/ui/overlay_cube.tscn" type="PackedScene" id=2] +[ext_resource path="res://assets/cube/cube_math.gd" type="Script" id=3] +[ext_resource path="res://addons/node25d/y_sort_25d.gd" type="Script" id=4] + +[node name="Cube" type="Node2D"] + +[node name="Overlay" parent="." instance=ExtResource( 2 )] + +[node name="Camera2D" type="Camera2D" parent="."] +current = true + +[node name="CubeMath" type="Spatial" parent="."] +script = ExtResource( 3 ) + +[node name="YSort25D" type="Node" parent="."] +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 1 ) +} diff --git a/misc/2.5d/assets/cube/cube_math.gd b/misc/2.5d/assets/cube/cube_math.gd new file mode 100644 index 0000000000..bde261fbb0 --- /dev/null +++ b/misc/2.5d/assets/cube/cube_math.gd @@ -0,0 +1,52 @@ +extends Spatial + +onready var _cube_point_scene: PackedScene = preload("res://assets/cube/cube_point.tscn") + +onready var _parent = get_parent() +var _is_parent_ready := false +var _cube_points_math = [] +var _cube_math_spatials = [] + +func _ready(): + _parent = get_parent() + + for i in range(27): + # warning-ignore:integer_division + var a: int = (i / 9) - 1 + # warning-ignore:integer_division + var b: int = (i / 3) % 3 - 1 + var c: int = (i % 3) - 1 + var spatial_position: Vector3 = 5 * (a * Vector3.RIGHT + b * Vector3.UP + c * Vector3.BACK) + _cube_math_spatials.append(Spatial.new()) + _cube_math_spatials[i].translation = spatial_position + _cube_math_spatials[i].name = "CubeMath #" + str(i) + ", " + str(a) + " " + str(b) + " " + str(c) + add_child(_cube_math_spatials[i]) + + +func _process(delta): + if Input.is_action_pressed("exit"): + get_tree().quit() + + if Input.is_action_just_pressed("view_cube_demo"): + # warning-ignore:return_value_discarded + get_tree().change_scene("res://assets/demo_scene.tscn") + return + + if _is_parent_ready: + if Input.is_action_just_pressed("reset_position"): + transform = Transform.IDENTITY + else: + rotate_x(delta * (Input.get_action_strength("move_back") - Input.get_action_strength("move_forward"))) + rotate_y(delta * (Input.get_action_strength("move_right") - Input.get_action_strength("move_left"))) + rotate_z(delta * (Input.get_action_strength("move_counterclockwise") - Input.get_action_strength("move_clockwise"))) + for i in range(27): + _cube_points_math[i].global_transform = _cube_math_spatials[i].global_transform + else: + # This code block will be run only once. It's not in _ready() because the parent isn't set up there. + for i in range(27): + var my_cube_point_scene = _cube_point_scene.duplicate(true) + var cube_point = my_cube_point_scene.instance() + cube_point.name = "CubePoint #" + str(i) + _cube_points_math.append(cube_point.get_child(0)) + _parent.add_child(cube_point) + _is_parent_ready = true diff --git a/misc/2.5d/assets/cube/cube_point.tscn b/misc/2.5d/assets/cube/cube_point.tscn new file mode 100644 index 0000000000..d880e9fb02 --- /dev/null +++ b/misc/2.5d/assets/cube/cube_point.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=1] +[ext_resource path="res://addons/node25d/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 ) +} + +[node name="CubePointMath" type="Spatial" parent="."] + +[node name="CubePointSprite" type="Sprite" parent="."] +texture = ExtResource( 3 ) diff --git a/misc/2.5d/assets/cube/godot.png b/misc/2.5d/assets/cube/godot.png new file mode 100644 index 0000000000..b66446484e Binary files /dev/null and b/misc/2.5d/assets/cube/godot.png differ diff --git a/misc/2.5d/assets/cube/godot.png.import b/misc/2.5d/assets/cube/godot.png.import new file mode 100644 index 0000000000..0cc11e6bc9 --- /dev/null +++ b/misc/2.5d/assets/cube/godot.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/demo_scene.tscn b/misc/2.5d/assets/demo_scene.tscn new file mode 100644 index 0000000000..aed9dbabcc --- /dev/null +++ b/misc/2.5d/assets/demo_scene.tscn @@ -0,0 +1,621 @@ +[gd_scene load_steps=14 format=2] + +[ext_resource path="res://assets/ui/overlay.tscn" type="PackedScene" id=1] +[ext_resource path="res://assets/player/player_25d.tscn" type="PackedScene" id=2] +[ext_resource path="res://assets/shadow/shadow_25d.tscn" type="PackedScene" id=3] +[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=4] +[ext_resource path="res://addons/node25d/icons/node_25d_icon.png" type="Texture" id=5] +[ext_resource path="res://assets/platform/textures/forty_five.png" type="Texture" id=6] +[ext_resource path="res://assets/platform/platform_sprite.gd" type="Script" id=7] +[ext_resource path="res://addons/node25d/y_sort_25d.gd" type="Script" id=8] +[ext_resource path="res://addons/node25d/icons/y_sort_25d_icon.png" type="Texture" id=9] +[ext_resource path="res://assets/mr_mrs_robot.ogg" type="AudioStream" id=10] + +[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 ) + +[node name="DemoScene" type="Node2D"] + +[node name="Overlay" parent="." instance=ExtResource( 1 )] + +[node name="Player25D" parent="." instance=ExtResource( 2 )] +position = Vector2( 0, -226.274 ) +z_index = -3952 + +[node name="Shadow25D" parent="." instance=ExtResource( 3 )] +visible = true +position = Vector2( 1.00261e-06, 11.2685 ) +z_index = -3958 +spatial_position = 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( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 6 ) +script = ExtResource( 7 ) + +[node name="Platform1" type="Node2D" parent="."] +position = Vector2( -256, -339.411 ) +z_index = -3956 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform1"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform2" type="Node2D" parent="."] +position = Vector2( 0, 22.6274 ) +z_index = -3962 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform2"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform3" type="Node2D" parent="."] +position = Vector2( 320, 22.6274 ) +z_index = -3960 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform3"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform4" type="Node2D" parent="."] +position = Vector2( 0, -203.647 ) +z_index = -3966 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform4"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform5" type="Node2D" parent="."] +position = Vector2( 320, -113.137 ) +z_index = -3984 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform5"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform6" type="Node2D" parent="."] +position = Vector2( 320, 113.137 ) +z_index = -3982 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 1 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform6"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform7" type="Node2D" parent="."] +position = Vector2( 320, 339.411 ) +z_index = -3978 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 2 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform7"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform20" type="Node2D" parent="."] +position = Vector2( 320, 565.685 ) +z_index = -3976 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = Vector3( 10, -5, 20 ) + +[node name="PlatformMath" type="StaticBody" parent="Platform20"] +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="Platform20/PlatformMath"] +shape = SubResource( 2 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform20"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform21" type="Node2D" parent="."] +position = Vector2( 320, 791.96 ) +z_index = -3972 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 2 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform21"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform22" type="Node2D" parent="."] +position = Vector2( 320, 1018.23 ) +z_index = -3970 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 2 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform22"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform9" type="Node2D" parent="."] +position = Vector2( 640, 339.411 ) +z_index = -3974 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform9"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform10" type="Node2D" parent="."] +position = Vector2( 896, 294.156 ) +z_index = -3994 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform10"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform11" type="Node2D" parent="."] +position = Vector2( 896, 520.431 ) +z_index = -3992 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform11"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform12" type="Node2D" parent="."] +position = Vector2( 896, 746.705 ) +z_index = -3988 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform12"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform13" type="Node2D" parent="."] +position = Vector2( 576, 746.705 ) +z_index = -3990 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform13"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform14" type="Node2D" parent="."] +position = Vector2( 256, 746.705 ) +z_index = -3996 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform14"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform15" type="Node2D" parent="."] +position = Vector2( -64, 746.705 ) +z_index = -3998 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform15"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform23" type="Node2D" parent="."] +position = Vector2( -384, 746.705 ) +z_index = -4000 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform23"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform16" type="Node2D" parent="."] +position = Vector2( -320, 565.685 ) +z_index = -3980 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform16"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform19" type="Node2D" parent="."] +position = Vector2( -320, 339.411 ) +z_index = -3986 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform19"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform17" type="Node2D" parent="."] +position = Vector2( -480, 248.902 ) +z_index = -3964 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform17"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="Platform18" type="Node2D" parent="."] +position = Vector2( -480, 22.6274 ) +z_index = -3968 +script = ExtResource( 4 ) +__meta__ = { +"_editor_icon": ExtResource( 5 ) +} +spatial_position = 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( 3 ) +__meta__ = { +"_edit_lock_": true +} + +[node name="PlatformSprite" type="Sprite" parent="Platform18"] +scale = Vector2( 0.5, 0.5 ) +texture = ExtResource( 6 ) +script = ExtResource( 7 ) + +[node name="YSort25D" type="Node" parent="."] +script = ExtResource( 8 ) +__meta__ = { +"_editor_icon": ExtResource( 9 ) +} + +[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource( 10 ) +volume_db = -20.0 +autoplay = true diff --git a/misc/2.5d/assets/mr_mrs_robot.ogg b/misc/2.5d/assets/mr_mrs_robot.ogg new file mode 100644 index 0000000000..76c5e8a5b3 Binary files /dev/null and b/misc/2.5d/assets/mr_mrs_robot.ogg differ diff --git a/misc/2.5d/assets/mr_mrs_robot.ogg.import b/misc/2.5d/assets/mr_mrs_robot.ogg.import new file mode 100644 index 0000000000..96d6caf4bb --- /dev/null +++ b/misc/2.5d/assets/mr_mrs_robot.ogg.import @@ -0,0 +1,15 @@ +[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 diff --git a/misc/2.5d/assets/platform/platform.tscn b/misc/2.5d/assets/platform/platform.tscn new file mode 100644 index 0000000000..5885e6bbbe --- /dev/null +++ b/misc/2.5d/assets/platform/platform.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=1] +[ext_resource path="res://addons/node25d/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 = -3996 +script = ExtResource( 1 ) +__meta__ = { +"_editor_icon": ExtResource( 2 ) +} + +[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 ) diff --git a/misc/2.5d/assets/platform/platform_sprite.gd b/misc/2.5d/assets/platform/platform_sprite.gd new file mode 100644 index 0000000000..4b6dcb43cf --- /dev/null +++ b/misc/2.5d/assets/platform/platform_sprite.gd @@ -0,0 +1,39 @@ +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 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 diff --git a/misc/2.5d/assets/platform/textures/forty_five.png b/misc/2.5d/assets/platform/textures/forty_five.png new file mode 100644 index 0000000000..e4422bb3d1 Binary files /dev/null and b/misc/2.5d/assets/platform/textures/forty_five.png differ diff --git a/misc/2.5d/assets/platform/textures/forty_five.png.import b/misc/2.5d/assets/platform/textures/forty_five.png.import new file mode 100644 index 0000000000..3fbd8972a6 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/forty_five.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/fortyfive.png.import b/misc/2.5d/assets/platform/textures/fortyfive.png.import new file mode 100644 index 0000000000..f2b0448b5b --- /dev/null +++ b/misc/2.5d/assets/platform/textures/fortyfive.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/fortyfive.png-ed5c66b01afe0b53153c3d09ee5b6584.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/platform/textures/fortyfive.png" +dest_files=[ "res://.import/fortyfive.png-ed5c66b01afe0b53153c3d09ee5b6584.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/front_side.png b/misc/2.5d/assets/platform/textures/front_side.png new file mode 100644 index 0000000000..aa3bdd7858 Binary files /dev/null and b/misc/2.5d/assets/platform/textures/front_side.png differ diff --git a/misc/2.5d/assets/platform/textures/front_side.png.import b/misc/2.5d/assets/platform/textures/front_side.png.import new file mode 100644 index 0000000000..eb4230ffbe --- /dev/null +++ b/misc/2.5d/assets/platform/textures/front_side.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/frontside.png.import b/misc/2.5d/assets/platform/textures/frontside.png.import new file mode 100644 index 0000000000..00089ecae2 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/frontside.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/frontside.png-59d804a7bfdefb2229c160b22085f140.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/platform/textures/frontside.png" +dest_files=[ "res://.import/frontside.png-59d804a7bfdefb2229c160b22085f140.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/isometric.png b/misc/2.5d/assets/platform/textures/isometric.png new file mode 100644 index 0000000000..7045d86bf7 Binary files /dev/null and b/misc/2.5d/assets/platform/textures/isometric.png differ diff --git a/misc/2.5d/assets/platform/textures/isometric.png.import b/misc/2.5d/assets/platform/textures/isometric.png.import new file mode 100644 index 0000000000..e722a8d6e2 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/isometric.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/obliqueY.png.import b/misc/2.5d/assets/platform/textures/obliqueY.png.import new file mode 100644 index 0000000000..9ef359977a --- /dev/null +++ b/misc/2.5d/assets/platform/textures/obliqueY.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/obliqueY.png-835238e1a682fa9039cff7ef5cfcacd4.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/platform/textures/obliqueY.png" +dest_files=[ "res://.import/obliqueY.png-835238e1a682fa9039cff7ef5cfcacd4.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/obliqueZ.png.import b/misc/2.5d/assets/platform/textures/obliqueZ.png.import new file mode 100644 index 0000000000..ac8ea96549 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/obliqueZ.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/obliqueZ.png-ccf2b8e0c4fa1369940c3976d1e9a334.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/platform/textures/obliqueZ.png" +dest_files=[ "res://.import/obliqueZ.png-ccf2b8e0c4fa1369940c3976d1e9a334.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/oblique_y.png b/misc/2.5d/assets/platform/textures/oblique_y.png new file mode 100644 index 0000000000..1b0b0d24bf Binary files /dev/null and b/misc/2.5d/assets/platform/textures/oblique_y.png differ diff --git a/misc/2.5d/assets/platform/textures/oblique_y.png.import b/misc/2.5d/assets/platform/textures/oblique_y.png.import new file mode 100644 index 0000000000..d7c1330f26 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/oblique_y.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/oblique_z.png b/misc/2.5d/assets/platform/textures/oblique_z.png new file mode 100644 index 0000000000..a859ccb6e1 Binary files /dev/null and b/misc/2.5d/assets/platform/textures/oblique_z.png differ diff --git a/misc/2.5d/assets/platform/textures/oblique_z.png.import b/misc/2.5d/assets/platform/textures/oblique_z.png.import new file mode 100644 index 0000000000..044a1c0f38 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/oblique_z.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/top_down.png b/misc/2.5d/assets/platform/textures/top_down.png new file mode 100644 index 0000000000..53f9b83ee7 Binary files /dev/null and b/misc/2.5d/assets/platform/textures/top_down.png differ diff --git a/misc/2.5d/assets/platform/textures/top_down.png.import b/misc/2.5d/assets/platform/textures/top_down.png.import new file mode 100644 index 0000000000..fccd60c82a --- /dev/null +++ b/misc/2.5d/assets/platform/textures/top_down.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/platform/textures/topdown.png.import b/misc/2.5d/assets/platform/textures/topdown.png.import new file mode 100644 index 0000000000..65f68479b4 --- /dev/null +++ b/misc/2.5d/assets/platform/textures/topdown.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/topdown.png-66f9d3553daec51a7ec6739d98ef44ef.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/platform/textures/topdown.png" +dest_files=[ "res://.import/topdown.png-66f9d3553daec51a7ec6739d98ef44ef.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/player/player_25d.tscn b/misc/2.5d/assets/player/player_25d.tscn new file mode 100644 index 0000000000..eec8f300fb --- /dev/null +++ b/misc/2.5d/assets/player/player_25d.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=1] +[ext_resource path="res://addons/node25d/icons/node_25d_icon.png" type="Texture" id=2] +[ext_resource path="res://assets/player/player_math_25d.gd" type="Script" id=3] +[ext_resource path="res://assets/player/textures/jump.png" type="Texture" id=4] +[ext_resource path="res://assets/player/player_sprite.gd" 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 ) +} +spatial_position = 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 ) +offset = Vector2( 0, 4 ) +vframes = 5 +hframes = 2 +script = ExtResource( 5 ) + +[node name="PlayerCamera" type="Camera2D" parent="PlayerSprite"] +current = true diff --git a/misc/2.5d/assets/player/player_math_25d.gd b/misc/2.5d/assets/player/player_math_25d.gd new file mode 100644 index 0000000000..adf0e6fce4 --- /dev/null +++ b/misc/2.5d/assets/player/player_math_25d.gd @@ -0,0 +1,58 @@ +# Handles Player-specific behavior like moving. We calculate such things with KinematicBody. +extends KinematicBody +class_name PlayerMath25D # No icon necessary + +var vertical_speed := 0.0 +var isometric_controls := true +onready var _parent_node25d: Node25D = get_parent() + +func _process(delta): + if Input.is_action_pressed("exit"): + get_tree().quit() + + if Input.is_action_just_pressed("view_cube_demo"): + #warning-ignore:return_value_discarded + get_tree().change_scene("res://assets/cube/cube.tscn") + return + + if Input.is_action_just_pressed("toggle_isometric_controls"): + isometric_controls = !isometric_controls + if Input.is_action_just_pressed("reset_position"): + transform = Transform(Basis(), Vector3.UP * 10) + vertical_speed = 0 + else: + _horizontal_movement(delta) + _vertical_movement(delta) + + +# Checks WASD and Shift for horizontal movement via move_and_slide. +func _horizontal_movement(delta): + var localX = Vector3.RIGHT + var localZ = Vector3.BACK + + if isometric_controls && is_equal_approx(Node25D.SCALE * 0.86602540378, _parent_node25d.get_basis()[0].x): + localX = Vector3(0.70710678118, 0, -0.70710678118) + localZ = Vector3(0.70710678118, 0, 0.70710678118) + + # Gather player input and add directional movement to a Vector3 variable. + var move_dir = Vector3() + move_dir += localX * (Input.get_action_strength("move_right") - Input.get_action_strength("move_left")) + move_dir += localZ * (Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")) + + move_dir = move_dir.normalized() * delta * 600; + if Input.is_action_pressed("movement_modifier"): + move_dir /= 2; + + #warning-ignore:return_value_discarded + move_and_slide(move_dir) + + +# Checks Jump and applies gravity and vertical speed via move_and_collide. +func _vertical_movement(delta): + var localY = Vector3.UP + if Input.is_action_just_pressed("jump"): + vertical_speed = 1.25 + vertical_speed -= delta * 5 # Gravity + var k = move_and_collide(localY * vertical_speed); + if k != null: + vertical_speed = 0 diff --git a/misc/2.5d/assets/player/player_sprite.gd b/misc/2.5d/assets/player/player_sprite.gd new file mode 100644 index 0000000000..aef9362edc --- /dev/null +++ b/misc/2.5d/assets/player/player_sprite.gd @@ -0,0 +1,143 @@ +tool +extends Sprite + +onready var _stand = preload("res://assets/player/textures/stand.png") +onready var _jump = preload("res://assets/player/textures/jump.png") +onready var _run = preload("res://assets/player/textures/run.png") + +const FRAMERATE = 15 + +var _direction := 0 +var _progress := 0.0 +var _parent_node25d: Node25D +var _parent_math: PlayerMath25D + +func _ready(): + _parent_node25d = get_parent() + _parent_math = _parent_node25d.get_child(0) + + +func _process(delta): + if Engine.is_editor_hint(): + return # Don't run this in the editor. + + _sprite_basis() + var movement = _check_movement() # 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 = _parent_math.move_and_collide(Vector3.DOWN * 10 * delta, true, true, true) + if k != null: + if movement: + hframes = 6 + texture = _run + if (Input.is_action_pressed("movement_modifier")): + delta /= 2 + _progress = fmod((_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 + var jumping = 1 if _parent_math.vertical_speed < 0 else 0 + frame = _direction * 2 + jumping + + +func set_view_mode(view_mode_index): + match view_mode_index: + 0: # 45 Degrees + transform.x = Vector2(1, 0) + transform.y = Vector2(0, 0.75) + 1: # Isometric + transform.x = Vector2(1, 0) + transform.y = Vector2(0, 1) + 2: # Top Down + transform.x = Vector2(1, 0) + transform.y = Vector2(0, 0.5) + 3: # Front Side + transform.x = Vector2(1, 0) + transform.y = Vector2(0, 1) + 4: # Oblique Y + transform.x = Vector2(1, 0) + transform.y = Vector2(0.75, 0.75) + 5: # Oblique Z + transform.x = Vector2(1, 0.25) + transform.y = Vector2(0, 1) + + +# Change the 2D basis of the sprite to try and make it "fit" multiple view modes. +func _sprite_basis(): + 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) + + +# This method returns a bool but if true it also outputs to the direction variable. +func _check_movement() -> bool: + # Gather player input and store movement to these int variables. Note: These indeed have to be integers. + var x := 0 + var z := 0 + + if Input.is_action_pressed("move_right"): + x += 1 + if Input.is_action_pressed("move_left"): + x -= 1 + if Input.is_action_pressed("move_forward"): + z -= 1 + if Input.is_action_pressed("move_back"): + z += 1 + + # 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 !_parent_math.isometric_controls && is_equal_approx(Node25D.SCALE * 0.86602540378, _parent_node25d.get_basis()[0].x): + if Input.is_action_pressed("move_right"): + z += 1 + if Input.is_action_pressed("move_left"): + z -= 1 + if Input.is_action_pressed("move_forward"): + x += 1 + if Input.is_action_pressed("move_back"): + x -= 1 + + # Set the direction based on which inputs were pressed. + if x == 0: + if z == 0: + return false # No movement. + elif z > 0: + _direction = 0 + else: + _direction = 4 + elif x > 0: + if z == 0: + _direction = 2 + flip_h = true + elif z > 0: + _direction = 1 + flip_h = true + else: + _direction = 3 + flip_h = true + else: + if z == 0: + _direction = 2 + flip_h = false + elif z > 0: + _direction = 1 + flip_h = false + else: + _direction = 3 + flip_h = false + return true # There is movement. diff --git a/misc/2.5d/assets/player/textures/jump.png b/misc/2.5d/assets/player/textures/jump.png new file mode 100755 index 0000000000..809467dadd Binary files /dev/null and b/misc/2.5d/assets/player/textures/jump.png differ diff --git a/misc/2.5d/assets/player/textures/jump.png.import b/misc/2.5d/assets/player/textures/jump.png.import new file mode 100644 index 0000000000..bdbb55e431 --- /dev/null +++ b/misc/2.5d/assets/player/textures/jump.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/player/textures/run.png b/misc/2.5d/assets/player/textures/run.png new file mode 100644 index 0000000000..900742aea3 Binary files /dev/null and b/misc/2.5d/assets/player/textures/run.png differ diff --git a/misc/2.5d/assets/player/textures/run.png.import b/misc/2.5d/assets/player/textures/run.png.import new file mode 100644 index 0000000000..90a63b5175 --- /dev/null +++ b/misc/2.5d/assets/player/textures/run.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/player/textures/stand.png b/misc/2.5d/assets/player/textures/stand.png new file mode 100644 index 0000000000..1fbc364fda Binary files /dev/null and b/misc/2.5d/assets/player/textures/stand.png differ diff --git a/misc/2.5d/assets/player/textures/stand.png.import b/misc/2.5d/assets/player/textures/stand.png.import new file mode 100644 index 0000000000..8525343755 --- /dev/null +++ b/misc/2.5d/assets/player/textures/stand.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/shadow_25d.tscn b/misc/2.5d/assets/shadow/shadow_25d.tscn new file mode 100644 index 0000000000..ea6164851a --- /dev/null +++ b/misc/2.5d/assets/shadow/shadow_25d.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=1] +[ext_resource path="res://addons/node25d/icons/node_25d_icon.png" type="Texture" id=2] +[ext_resource path="res://addons/node25d/shadow_math_25d.gd" type="Script" id=3] +[ext_resource path="res://addons/node25d/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 +position = Vector2( 0, 22401.1 ) +script = ExtResource( 1 ) +__meta__ = { +"_editor_icon": ExtResource( 2 ) +} +spatial_position = Vector3( 0, -990, 0 ) + +[node name="ShadowMath25D" type="KinematicBody" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -990, 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 ) diff --git a/misc/2.5d/assets/shadow/shadow_sprite.gd b/misc/2.5d/assets/shadow/shadow_sprite.gd new file mode 100644 index 0000000000..f3e4b55270 --- /dev/null +++ b/misc/2.5d/assets/shadow/shadow_sprite.gd @@ -0,0 +1,39 @@ +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 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 diff --git a/misc/2.5d/assets/shadow/textures/forty_five.png b/misc/2.5d/assets/shadow/textures/forty_five.png new file mode 100644 index 0000000000..ab28eea280 Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/forty_five.png differ diff --git a/misc/2.5d/assets/shadow/textures/forty_five.png.import b/misc/2.5d/assets/shadow/textures/forty_five.png.import new file mode 100644 index 0000000000..cd931cd007 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/forty_five.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/fortyfive.png.import b/misc/2.5d/assets/shadow/textures/fortyfive.png.import new file mode 100644 index 0000000000..0a1e44de89 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/fortyfive.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/fortyfive.png-efb54d3840c2ab97f9652a523a4e1e58.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/shadow/textures/fortyfive.png" +dest_files=[ "res://.import/fortyfive.png-efb54d3840c2ab97f9652a523a4e1e58.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/front_side.png b/misc/2.5d/assets/shadow/textures/front_side.png new file mode 100644 index 0000000000..8af59aa74a Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/front_side.png differ diff --git a/misc/2.5d/assets/shadow/textures/front_side.png.import b/misc/2.5d/assets/shadow/textures/front_side.png.import new file mode 100644 index 0000000000..d43de4b075 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/front_side.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/frontside.png.import b/misc/2.5d/assets/shadow/textures/frontside.png.import new file mode 100644 index 0000000000..f692468b6b --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/frontside.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/frontside.png-aab37f0cda9f5e8056a5178bf22351fb.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/shadow/textures/frontside.png" +dest_files=[ "res://.import/frontside.png-aab37f0cda9f5e8056a5178bf22351fb.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/isometric.png b/misc/2.5d/assets/shadow/textures/isometric.png new file mode 100644 index 0000000000..3b50ae08fb Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/isometric.png differ diff --git a/misc/2.5d/assets/shadow/textures/isometric.png.import b/misc/2.5d/assets/shadow/textures/isometric.png.import new file mode 100644 index 0000000000..9c56cf1f70 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/isometric.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/oblique_y.png b/misc/2.5d/assets/shadow/textures/oblique_y.png new file mode 100644 index 0000000000..f48cf507ec Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/oblique_y.png differ diff --git a/misc/2.5d/assets/shadow/textures/oblique_y.png.import b/misc/2.5d/assets/shadow/textures/oblique_y.png.import new file mode 100644 index 0000000000..eccac431d8 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/oblique_y.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/oblique_z.png b/misc/2.5d/assets/shadow/textures/oblique_z.png new file mode 100644 index 0000000000..0df5de9db0 Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/oblique_z.png differ diff --git a/misc/2.5d/assets/shadow/textures/oblique_z.png.import b/misc/2.5d/assets/shadow/textures/oblique_z.png.import new file mode 100644 index 0000000000..e781a965eb --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/oblique_z.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/top_down.png b/misc/2.5d/assets/shadow/textures/top_down.png new file mode 100644 index 0000000000..5cf9a46f48 Binary files /dev/null and b/misc/2.5d/assets/shadow/textures/top_down.png differ diff --git a/misc/2.5d/assets/shadow/textures/top_down.png.import b/misc/2.5d/assets/shadow/textures/top_down.png.import new file mode 100644 index 0000000000..1817944c99 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/top_down.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/shadow/textures/topdown.png.import b/misc/2.5d/assets/shadow/textures/topdown.png.import new file mode 100644 index 0000000000..c618104ec5 --- /dev/null +++ b/misc/2.5d/assets/shadow/textures/topdown.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/topdown.png-967f612d383afa56cee62320ceaf8a99.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/shadow/textures/topdown.png" +dest_files=[ "res://.import/topdown.png-967f612d383afa56cee62320ceaf8a99.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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/assets/ui/control_hints.gd b/misc/2.5d/assets/ui/control_hints.gd new file mode 100644 index 0000000000..5f8d21f74e --- /dev/null +++ b/misc/2.5d/assets/ui/control_hints.gd @@ -0,0 +1,5 @@ +extends Control + +func _process(_delta): + if Input.is_action_just_pressed("toggle_control_hints"): + visible = !visible diff --git a/misc/2.5d/assets/ui/overlay.tscn b/misc/2.5d/assets/ui/overlay.tscn new file mode 100644 index 0000000000..cc5d123f4f --- /dev/null +++ b/misc/2.5d/assets/ui/overlay.tscn @@ -0,0 +1,28 @@ +[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 diff --git a/misc/2.5d/assets/ui/overlay_cube.tscn b/misc/2.5d/assets/ui/overlay_cube.tscn new file mode 100644 index 0000000000..4cd80f1e80 --- /dev/null +++ b/misc/2.5d/assets/ui/overlay_cube.tscn @@ -0,0 +1,28 @@ +[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 diff --git a/misc/2.5d/default_env.tres b/misc/2.5d/default_env.tres new file mode 100644 index 0000000000..20207a4aa2 --- /dev/null +++ b/misc/2.5d/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/misc/2.5d/icon.png b/misc/2.5d/icon.png new file mode 100644 index 0000000000..d8efa1a073 Binary files /dev/null and b/misc/2.5d/icon.png differ diff --git a/misc/2.5d/icon.png.import b/misc/2.5d/icon.png.import new file mode 100644 index 0000000000..96cbf4629a --- /dev/null +++ b/misc/2.5d/icon.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/misc/2.5d/project.godot b/misc/2.5d/project.godot new file mode 100644 index 0000000000..a46f1aef09 --- /dev/null +++ b/misc/2.5d/project.godot @@ -0,0 +1,196 @@ +; 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 + +_global_script_classes=[ { +"base": "Node2D", +"class": "Node25D", +"language": "GDScript", +"path": "res://addons/node25d/node_25d.gd" +}, { +"base": "KinematicBody", +"class": "PlayerMath25D", +"language": "GDScript", +"path": "res://assets/player/player_math_25d.gd" +}, { +"base": "KinematicBody", +"class": "ShadowMath25D", +"language": "GDScript", +"path": "res://addons/node25d/shadow_math_25d.gd" +}, { +"base": "Node", +"class": "YSort25D", +"language": "GDScript", +"path": "res://addons/node25d/y_sort_25d.gd" +} ] +_global_script_class_icons={ +"Node25D": "res://addons/node25d/icons/node_25d_icon.png", +"PlayerMath25D": "", +"ShadowMath25D": "res://addons/node25d/icons/shadow_math_25d_icon.png", +"YSort25D": "res://addons/node25d/icons/y_sort_25d_icon.png" +} + +[application] + +config/name="2.5D Demo (GDScript)" +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" ) + +[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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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" +environment/default_environment="res://default_env.tres" diff --git a/misc/2.5d/screenshots/.gdignore b/misc/2.5d/screenshots/.gdignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/misc/2.5d/screenshots/cube.png b/misc/2.5d/screenshots/cube.png new file mode 100644 index 0000000000..47c4f575f7 Binary files /dev/null and b/misc/2.5d/screenshots/cube.png differ diff --git a/misc/2.5d/screenshots/editor.png b/misc/2.5d/screenshots/editor.png new file mode 100644 index 0000000000..369ef3289b Binary files /dev/null and b/misc/2.5d/screenshots/editor.png differ diff --git a/misc/2.5d/screenshots/forty_five.png b/misc/2.5d/screenshots/forty_five.png new file mode 100644 index 0000000000..e593aaadac Binary files /dev/null and b/misc/2.5d/screenshots/forty_five.png differ diff --git a/misc/2.5d/screenshots/front_side.png b/misc/2.5d/screenshots/front_side.png new file mode 100644 index 0000000000..a3e97338e6 Binary files /dev/null and b/misc/2.5d/screenshots/front_side.png differ diff --git a/misc/2.5d/screenshots/isometric.png b/misc/2.5d/screenshots/isometric.png new file mode 100644 index 0000000000..41ca63dd87 Binary files /dev/null and b/misc/2.5d/screenshots/isometric.png differ diff --git a/misc/2.5d/screenshots/oblique_y.png b/misc/2.5d/screenshots/oblique_y.png new file mode 100644 index 0000000000..415276e188 Binary files /dev/null and b/misc/2.5d/screenshots/oblique_y.png differ diff --git a/misc/2.5d/screenshots/oblique_z.png b/misc/2.5d/screenshots/oblique_z.png new file mode 100644 index 0000000000..65be79e247 Binary files /dev/null and b/misc/2.5d/screenshots/oblique_z.png differ diff --git a/mono/2.5d/2.5D Demo (Mono C#).csproj b/mono/2.5d/2.5D Demo (Mono C#).csproj new file mode 100644 index 0000000000..0dbfc3d109 --- /dev/null +++ b/mono/2.5d/2.5D Demo (Mono C#).csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + {5CA791DB-5050-44D0-989B-41D559AB1D50} + Library + .mono/temp/bin/$(Configuration) + Empty.DMono + 2.5D Demo (Mono C#) + v4.5 + .mono/temp/obj + $(BaseIntermediateOutputPath)/$(Configuration) + Debug + Release + + + true + portable + false + $(GodotDefineConstants);GODOT;DEBUG; + prompt + 4 + false + + + portable + true + $(GodotDefineConstants);GODOT; + prompt + 4 + false + + + true + portable + false + $(GodotDefineConstants);GODOT;DEBUG;TOOLS; + prompt + 4 + false + + + + False + $(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/GodotSharp.dll + + + False + $(ProjectDir)/.mono/assemblies/$(ApiConfiguration)/GodotSharpEditor.dll + + + + + + + + + + + + + + + + + diff --git a/mono/2.5d/2.5D Demo (Mono C#).sln b/mono/2.5d/2.5D Demo (Mono C#).sln new file mode 100644 index 0000000000..d979d4573d --- /dev/null +++ b/mono/2.5d/2.5D Demo (Mono C#).sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2.5D Demo (Mono C#)", "2.5D Demo (Mono C#).csproj", "{5CA791DB-5050-44D0-989B-41D559AB1D50}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Tools|Any CPU = Tools|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}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CA791DB-5050-44D0-989B-41D559AB1D50}.Release|Any CPU.Build.0 = Release|Any CPU + {5CA791DB-5050-44D0-989B-41D559AB1D50}.Tools|Any CPU.ActiveCfg = Tools|Any CPU + {5CA791DB-5050-44D0-989B-41D559AB1D50}.Tools|Any CPU.Build.0 = Tools|Any CPU + EndGlobalSection +EndGlobal diff --git a/mono/2.5d/Properties/AssemblyInfo.cs b/mono/2.5d/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..c562b72271 --- /dev/null +++ b/mono/2.5d/Properties/AssemblyInfo.cs @@ -0,0 +1,25 @@ +using System.Reflection; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("2.5D Demo (Mono C#)")] +[assembly: AssemblyDescription("2.5D demo project for Godot, Mono C# version.")] +[assembly: AssemblyConfiguration("Debug")] +[assembly: AssemblyCompany("Godot")] +[assembly: AssemblyProduct("Godot Demo Projects")] +[assembly: AssemblyCopyright("Copyright © 2020 Aaron Franke, Godot Engine contributors")] +[assembly: AssemblyTrademark("Godot Engine")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/mono/2.5d/README.md b/mono/2.5d/README.md new file mode 100644 index 0000000000..d190e25352 --- /dev/null +++ b/mono/2.5d/README.md @@ -0,0 +1,35 @@ +# 2.5D Demo Project (Mono 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. + +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. diff --git a/mono/2.5d/addons/node25d-cs/Basis25D.cs b/mono/2.5d/addons/node25d-cs/Basis25D.cs new file mode 100644 index 0000000000..d5f82b0603 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/Basis25D.cs @@ -0,0 +1,207 @@ +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 + +/// +/// 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. +/// +[Serializable] +[StructLayout(LayoutKind.Sequential)] +public struct Basis25D : IEquatable +{ + // 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; } } + + /// + /// 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. + /// + /// The angle, in radians, between the Y axis and the X/Z axes. + 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; + } +} diff --git a/mono/2.5d/addons/node25d-cs/Node25D.cs b/mono/2.5d/addons/node25d-cs/Node25D.cs new file mode 100644 index 0000000000..bdfc9d9029 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/Node25D.cs @@ -0,0 +1,181 @@ +using Godot; +using System; +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +/// +/// This node converts a 3D position to 2D using a 2.5D transformation matrix. +/// The transformation of its 2D form is controlled by its 3D child. +/// +[Tool] +public class Node25D : Node2D, IComparable +{ + /// + /// The number of 2D units in one 3D unit. Ideally, but not necessarily, an integer. + /// + public const int SCALE = 32; + + [Export] public Vector3 spatialPosition + { + get + { + if (spatialNode == null) + { + spatialNode = GetChild(0); + } + return spatialNode.Translation; + } + set + { + transform25D.spatialPosition = value; + if (spatialNode != null) + { + spatialNode.Translation = value; + } + else if (GetChildCount() > 0) + { + spatialNode = GetChild(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(); + } + + /// + /// Call this method in _Ready, or before Node25DProcess is run. + /// + protected void Node25DReady() + { + if (GetChildCount() > 0) + { + spatialNode = GetChild(0); + } + // Changing the basis here will change the default for all Node25D instances. + transform25D = new Transform25D(Basis25D.FortyFive * SCALE); + } + + /// + /// Call this method in _Process, or whenever the position of this object changes. + /// + protected void Node25DProcess() + { + if (transform25D.basis == new Basis25D()) + { + SetViewMode(0); + } + CheckViewMode(); + if (spatialNode != null) + { + transform25D.spatialPosition = spatialNode.Translation; + } + else if (GetChildCount() > 0) + { + spatialNode = GetChild(0); + } + + GlobalPosition = transform25D.FlatPosition; + } + + public void SetViewMode(int viewModeIndex) + { + switch (viewModeIndex) + { + case 0: + transform25D.basis = Basis25D.FortyFive * SCALE; + break; + case 1: + transform25D.basis = Basis25D.Isometric * SCALE; + break; + case 2: + transform25D.basis = Basis25D.TopDown * SCALE; + break; + case 3: + transform25D.basis = Basis25D.FrontSide * SCALE; + break; + case 4: + transform25D.basis = Basis25D.ObliqueY * SCALE; + break; + case 5: + transform25D.basis = Basis25D.ObliqueZ * SCALE; + break; + } + } + + private void CheckViewMode() + { + if (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; + } + +} diff --git a/mono/2.5d/addons/node25d-cs/ShadowMath25D.cs b/mono/2.5d/addons/node25d-cs/ShadowMath25D.cs new file mode 100644 index 0000000000..64b8061f22 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/ShadowMath25D.cs @@ -0,0 +1,54 @@ +using Godot; +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +/// +/// 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). +/// +[Tool] +public class ShadowMath25D : KinematicBody +{ + /// + /// The maximum distance below objects that shadows will appear. + /// + public real_t shadowLength = 1000; + private Node25D shadowRoot; + private Spatial targetMath; + + public override void _Ready() + { + shadowRoot = GetParent(); + int index = shadowRoot.GetPositionInParent(); + targetMath = shadowRoot.GetParent().GetChild(index - 1).GetChild(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; + } + } + +} diff --git a/mono/2.5d/addons/node25d-cs/Transform25D.cs b/mono/2.5d/addons/node25d-cs/Transform25D.cs new file mode 100644 index 0000000000..2c41e2c3e4 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/Transform25D.cs @@ -0,0 +1,131 @@ +using Godot; +using System; +using System.Runtime.InteropServices; + +/// +/// Calculates the 2D transformation from a 3D position and a Basis25D. +/// +[Serializable] +[StructLayout(LayoutKind.Sequential)] +public struct Transform25D : IEquatable +{ + // Public fields store information that is used to calculate the properties. + + /// + /// Controls how the 3D position is transformed into 2D. + /// + public Basis25D basis; + + /// + /// The 3D position of the object. Should be updated on every frame before everything else. + /// + public Vector3 spatialPosition; + + // Public properties calculate on-the-fly. + + /// + /// The 2D transformation of this object. Slower than FlatPosition. + /// + public Transform2D FlatTransform + { + get + { + return new Transform2D(0, FlatPosition); + } + } + + /// + /// The 2D position of this object. + /// + 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; + } +} diff --git a/mono/2.5d/addons/node25d-cs/YSort25D.cs b/mono/2.5d/addons/node25d-cs/YSort25D.cs new file mode 100644 index 0000000000..9b1506c0be --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/YSort25D.cs @@ -0,0 +1,60 @@ +using Godot; +using System.Collections.Generic; +#if REAL_T_IS_DOUBLE +using real_t = System.Double; +#else +using real_t = System.Single; +#endif + +/// +/// Assigns Z-index values to Node25D children. +/// +[Tool] // Commented out because it sometimes crashes the editor when running the game... +public class YSort25D : Node // Note: NOT Node2D, Node25D, or YSort +{ + /// + /// Whether or not to automatically call Sort() in _Process(). + /// + [Export] + public bool sortEnabled = true; + + public override void _Process(real_t delta) + { + if (sortEnabled) + { + Sort(); + } + } + + /// + /// Call this method in _Process, or whenever you want to sort children. + /// + public void Sort() + { + var children = GetParent().GetChildren(); + if (children.Count > 4000) + { + GD.PrintErr("Sorting failed: Max number of YSort25D nodes is 4000."); + } + List node25dChildren = new List(); + + 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; + } + } +} diff --git a/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png b/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png new file mode 100644 index 0000000000..2780a094fb Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png.import b/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png.import new file mode 100644 index 0000000000..56b6b828e0 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/kinematic_body_25d.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/node_25d.png b/mono/2.5d/addons/node25d-cs/icons/node_25d.png new file mode 100644 index 0000000000..ede1d823fd Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/node_25d.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/node_25d.png.import b/mono/2.5d/addons/node25d-cs/icons/node_25d.png.import new file mode 100644 index 0000000000..571965ba5a --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/node_25d.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png b/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png new file mode 100644 index 0000000000..12b13bb58b Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png.import b/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png.import new file mode 100644 index 0000000000..1142ec2a1c --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/node_25d_icon.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png new file mode 100644 index 0000000000..0dbc8c4b05 Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png.import b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png.import new file mode 100644 index 0000000000..131ab1ffda --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png new file mode 100644 index 0000000000..ae13ea3823 Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png.import b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png.import new file mode 100644 index 0000000000..2e1fab4b17 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/shadow_math_25d_icon.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg b/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg new file mode 100644 index 0000000000..22bd96ec2d --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg @@ -0,0 +1 @@ + diff --git a/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg.import b/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg.import new file mode 100644 index 0000000000..3fd1336d9c --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/viewport_25d.svg.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png new file mode 100644 index 0000000000..e37e57502d Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png.import b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png.import new file mode 100644 index 0000000000..53087b1af0 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png new file mode 100644 index 0000000000..1e362220e2 Binary files /dev/null and b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png differ diff --git a/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png.import b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png.import new file mode 100644 index 0000000000..db9724c066 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/icons/y_sort_25d_icon.png.import @@ -0,0 +1,34 @@ +[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 +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/mono/2.5d/addons/node25d-cs/main_screen/.broken-cs-files/Viewport25D.cs b/mono/2.5d/addons/node25d-cs/main_screen/.broken-cs-files/Viewport25D.cs new file mode 100644 index 0000000000..f1ead376f7 --- /dev/null +++ b/mono/2.5d/addons/node25d-cs/main_screen/.broken-cs-files/Viewport25D.cs @@ -0,0 +1,230 @@ +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. + //yield(get_tree(), "idle_frame"); + //yield(get_tree(), "idle_frame"); + 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("Viewport2D"); + viewportOverlay = GetNode("ViewportOverlay"); + viewModeButtonGroup = GetParent().GetNode("TopBar").GetNode("ViewModeButtons").GetNode