diff --git a/NOTES.md b/NOTES.md index fff00fa..218a1c3 100644 --- a/NOTES.md +++ b/NOTES.md @@ -50,7 +50,7 @@ Momentálně procedural mesh generuju helper nodem. Tohle je ideální kandidát - **Stíny** - shadow mesh tam můžu a nemusím plácnout (stejný jako hlavní). Další věc je že stíny by asi měly být na OFF a nebo DOUBLE_SIDED. Asi to nechám na uživateli.. to s meshem nesouvisí nutně. -### Texture portal mask +### Texture portal mask :x: Mám v plánu udělat texture masku pro tvarování protálů. S házením stínů to bude průser. V tomhle je přístup s _tvarem meshe_ lepší. Měl bych nakódit generování vícero tvarů...? @@ -59,3 +59,11 @@ Mám v plánu udělat texture masku pro tvarování protálů. S házením stín - Kdybys měl oblouk nahoře, tak nemůžeš jenom tak clipnout obdélníkový portál. Kdyby byl plochý, tak jo. Ale takhle bude ten okraj nahoře jakoby zabořený a nebude to pěkné (asi). Zvlášť v rožkách. :question: Tohle asi řeší tenký box s **culling- off** jak měl Sebastian ve svém Unity videu. Akorát to žere trochu renderingu.. ale v porovnání s X kamerama navíc je to asi fuk. + +> BoxMesh3D mi nefunguje na hned. Ugh, nejsem si jistý proč.. ale mám dojem že ten chlapík co vyrobil ty portály by to asi zkusil. Prohlubeň možná dává smysl. + +> Dal by se udělat celkem jednoduchý algoritmus co by generoval mesh "s prohlubní" pro jakýkoliv nákres zepředu. Obdélník je nejjednodušší, ale udělat oblouček by asi nebyl problém. +> +> **Custom Mesh subclassa?** + +- Custom mesh subclassa je trochu divná věc. Když to všechno nastaví jeden editorový Node tak to bude asi lepší. Custom mesh se mi přegenerovává při každém spuštění, ale já chci aby se prostě "zapekl" a uložil a nazdar bazar... diff --git a/addons/simple-portal-system/shaders/portal.gdshader b/addons/simple-portal-system/shaders/portal.gdshader index fdbf044..1936532 100644 --- a/addons/simple-portal-system/shaders/portal.gdshader +++ b/addons/simple-portal-system/shaders/portal.gdshader @@ -9,6 +9,7 @@ shader_type spatial; render_mode unshaded; + uniform float fade_out_distance_max = 10.0; uniform float fade_out_distance_min = 8.0; uniform vec4 fade_out_color = vec4(0.0); diff --git a/levels/level_cube_portals.tscn b/levels/level_cube_portals.tscn index ea2d3cb..78e373e 100644 --- a/levels/level_cube_portals.tscn +++ b/levels/level_cube_portals.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=15 format=4 uid="uid://d2d7xy8ash3kk"] +[gd_scene load_steps=18 format=4 uid="uid://d2d7xy8ash3kk"] [ext_resource type="PackedScene" uid="uid://b5x7fmpwck335" path="res://hud.tscn" id="1_ghyw7"] [ext_resource type="Material" uid="uid://bx6qeabdhq2s" path="res://addons/kenney_prototype_tools/materials/dark/material_01.tres" id="1_gpwe8"] [ext_resource type="Texture2D" uid="uid://cvxwlhcjdg7u7" path="res://textures/kloppenheim_06_puresky_2k.exr" id="1_i8fn5"] [ext_resource type="PackedScene" uid="uid://cgdlowfuuorvi" path="res://player.tscn" id="2_84t5d"] [ext_resource type="Script" uid="uid://d2bvvjsibau8c" path="res://addons/simple-portal-system/scripts/portal.gd" id="5_jfr1b"] +[ext_resource type="Script" uid="uid://s5kb624h26hs" path="res://models/portal_mesh.gd" id="6_gnq53"] [ext_resource type="Script" uid="uid://cili3lyodjqel" path="res://portal_environment_adapter.gd" id="6_jdap8"] [ext_resource type="PackedScene" uid="uid://d1dtxvwk86ple" path="res://procedural_mesh_maker.tscn" id="7_mq505"] @@ -42,18 +43,37 @@ _surfaces = [{ "vertex_data": PackedByteArray("AACAvwAAwD8AAAAAAACAPwAAwD8AAAAAAACAvwAAwL8AAAAAAACAPwAAwL8AAAAAZmZmvzMzsz/NzMy9ZmZmPzMzsz/NzMy9ZmZmvzMzs7/NzMy9ZmZmPzMzs7/NzMy9/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgA==") }] -[sub_resource type="ArrayMesh" id="ArrayMesh_gnq53"] +[sub_resource type="ArrayMesh" id="ArrayMesh_jhkhy"] _surfaces = [{ -"aabb": AABB(-1, -1.5, -0.1, 2, 3, 0.1), -"attribute_data": PackedByteArray("AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAgD/NzEw9iYgIPTMzcz+JiAg9zcxMPXd3dz8zM3M/d3d3Pw=="), +"aabb": AABB(-1, -1.5, -0.05, 2, 3, 0.05), +"attribute_data": PackedByteArray("AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAgD/NzMw8iYiIPJqZeT+JiIg8zczMPLy7ez+amXk/vLt7Pw=="), "format": 34359742487, "index_count": 30, "index_data": PackedByteArray("AAABAAQABAABAAUAAQADAAUABQADAAcAAwACAAcABwACAAYAAgAAAAYABgAAAAQABAAFAAYABgAFAAcA"), -"name": "Portal Material", "primitive": 3, "uv_scale": Vector4(0, 0, 0, 0), "vertex_count": 8, -"vertex_data": PackedByteArray("AACAvwAAwD8AAAAAAACAPwAAwD8AAAAAAACAvwAAwL8AAAAAAACAPwAAwL8AAAAAZmZmvzMzsz/NzMy9ZmZmPzMzsz/NzMy9ZmZmvzMzs7/NzMy9ZmZmPzMzs7/NzMy9/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgA==") +"vertex_data": PackedByteArray("AACAvwAAwD8AAAAAAACAPwAAwD8AAAAAAACAvwAAwL8AAAAAAACAPwAAwL8AAAAAMzNzv5qZuT/NzEy9MzNzP5qZuT/NzEy9MzNzv5qZub/NzEy9MzNzP5qZub/NzEy9/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgP9//3//fwCA/3//f/9/AID/f/9//38AgA==") +}] +script = ExtResource("6_gnq53") +height = 3.0 +width = 2.0 +indent = 0.05 +metadata/_custom_type_script = "uid://s5kb624h26hs" + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gnq53"] +albedo_color = Color(0, 0, 0, 1) + +[sub_resource type="ArrayMesh" id="ArrayMesh_gnq53"] +_surfaces = [{ +"aabb": AABB(-1.1, -1.6, -0.125, 2.2, 3.2, 0.25), +"attribute_data": PackedByteArray("F110PwSA1TwAAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAF110PwSA1TwAAIA/AAAAAI4uOj0EgNU8AAAAAAAAAAAAAIA/AACAPwAAgD8AAAAAF110PwBUeT8AAIA/AACAPxdddD8CAAA9F110PwBUeT8AAAAAAACAPwAAgD8AAIA/F110PwAAeD8AAIA/AACAPxdddD8EgNU8F110PwAAeD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/F110PwIAAD0AAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/F110PwIAAD0AAIA/AAAAAI4uOj0CAAA9ji46PQSA1TwAAIA/AAAAAAAAAAAAAAAAji46PQSA1TwAAAAAAAAAAI4uOj0AAHg/AAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/ji46PQBUeT8AAAAAAACAPxdddD8AVHk/AACAPwAAAAAAAAAAAAAAAAAAgD8AAIA/ji46PQBUeT8AAAAAAAAAAAAAAAAAAIA/ji46PQAAeD8AAAAAAACAPxdddD8AAHg/AACAPwAAAAAAAAAAAAAAAAAAgD8AAIA/ji46PQAAeD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/ji46PQIAAD0AAIA/AAAAAAAAAAAAAAAAji46PQIAAD0AAAAAAAAAAI4uOj0AVHk/AADAPgAAAAAAACA/AAAAAAAAID8AAIA/AAAAAAAAID8AAIA/AADAPgAAgD8AACA/AACAPwAAwD4AAAAAAAAgPwAAAAAAAMA+AAAgPwAAgD8AAMA+AACAPwAAwD4AAAAAAAAAAAAAID8AAIA/AADAPgAAgD8AACA/AAAgPwAAgD8AAMA+AACAPwAAwD4AAAAAAADAPgAAAAAAACA/AAAAAAAAID8AAIA/AACAPwAAwD4AAAAAAAAgPwAAAAAAAMA+"), +"format": 34359738391, +"material": SubResource("StandardMaterial3D_gnq53"), +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 96, +"vertex_data": PackedByteArray("AACAvwAgwr8AAAC+zcyMv83MzD8AAAC+zcyMv83MzL8AAAC+zcyMv83MzL8AAAA+zcyMv83MzL8AAAC+zcyMv83MzD8AAAC+AACAvwAgwr8AAAC+zcyMv83MzL8AAAC+AACAPwAgwr8AAAC+zcyMv83MzL8AAAA+zcyMP83MzL8AAAC+zcyMv83MzL8AAAC+AACAvwAgwr8AAAA+zcyMv83MzL8AAAA+AACAvwAAwD8AAAA+AACAvwAgwr8AAAA+zcyMP83MzL8AAAA+zcyMv83MzL8AAAA+AACAvwAAwD8AAAC+zcyMv83MzD8AAAC+AACAvwAgwr8AAAC+AACAvwAAwD8AAAC+zcyMP83MzD8AAAC+zcyMv83MzD8AAAC+zcyMv83MzD8AAAC+zcyMv83MzD8AAAA+zcyMv83MzL8AAAA+AACAvwAAwD8AAAA+zcyMv83MzL8AAAA+zcyMv83MzD8AAAA+zcyMv83MzD8AAAC+zcyMP83MzD8AAAA+zcyMv83MzD8AAAA+AACAvwAAwD8AAAA+zcyMv83MzD8AAAA+AACAPwAAwD8AAAA+AACAPwAgwr8AAAC+zcyMv83MzL8AAAC+zcyMP83MzL8AAAC+AACAPwAgwr8AAAC+zcyMP83MzL8AAAC+AACAPwAAwD8AAAC+zcyMv83MzL8AAAA+zcyMP83MzL8AAAA+zcyMP83MzL8AAAC+AACAPwAgwr8AAAA+zcyMP83MzL8AAAA+AACAvwAgwr8AAAA+zcyMP83MzL8AAAA+zcyMP83MzD8AAAA+zcyMP83MzL8AAAC+AACAPwAgwr8AAAA+zcyMP83MzD8AAAA+zcyMP83MzL8AAAA+AACAPwAAwD8AAAC+zcyMP83MzD8AAAC+AACAvwAAwD8AAAC+zcyMP83MzD8AAAC+zcyMP83MzD8AAAA+zcyMv83MzD8AAAC+AACAPwAAwD8AAAC+zcyMP83MzL8AAAC+zcyMP83MzD8AAAC+zcyMP83MzD8AAAA+zcyMP83MzD8AAAC+zcyMP83MzL8AAAC+AACAPwAAwD8AAAA+zcyMv83MzD8AAAA+zcyMP83MzD8AAAA+AACAPwAAwD8AAAA+zcyMP83MzD8AAAA+AACAPwAgwr8AAAA+AACAvwAgwr8AAAA+AACAvwAgwr8AAAC+AACAPwAgwr8AAAC+AACAvwAAwD8AAAA+AACAvwAgwr8AAAC+AACAvwAgwr8AAAA+AACAvwAgwr8AAAC+AACAvwAAwD8AAAA+AACAvwAAwD8AAAC+AACAvwAAwD8AAAC+AACAvwAAwD8AAAA+AACAPwAAwD8AAAA+AACAPwAAwD8AAAC+AACAPwAgwr8AAAA+AACAPwAgwr8AAAC+AACAPwAgwr8AAAC+AACAPwAgwr8AAAA+AACAvwAgwr8AAAA+AACAPwAAwD8AAAA+AACAPwAAwD8AAAC+AACAvwAAwD8AAAC+AACAPwAgwr8AAAA+AACAPwAAwD8AAAC+AACAPwAAwD8AAAA+/////wAA/z//////AAD/P/////8AAP8/AAD/f/9//n8AAP9//3/+fwAA/3//f/5//////wAA/z//////AAD/P/////8AAP8//38AAP//AAD/fwAA//8AAP9/AAD//wAA/3//fwAA/z//f/9/AAD/P/9//38AAP8//3//fwAA/z//f/9/AAD/P/9//38AAP8//////wAA/z//////AAD/P/////8AAP8//////wAA/z//////AAD/P/////8AAP8/AAD/f/9//n8AAP9//3/+fwAA/3//f/5//3//fwAA/z//f/9/AAD/P/9//38AAP8//3//////AAD/f/////8AAP9//////wAA/3//fwAA/z//f/9/AAD/P/9//38AAP8//////wAA/z//////AAD/P/////8AAP8//////wAA/z//////AAD/P/////8AAP8//38AAP//AAD/fwAA//8AAP9/AAD//wAA/3//fwAA/z//f/9/AAD/P/9//38AAP8/////f/9//n////9//3/+f////3//f/5//3//fwAA/z//f/9/AAD/P/9//38AAP8//////wAA/z//////AAD/P/////8AAP8//3//////AAD/f/////8AAP9//////wAA/////wAA/z//////AAD/P/////8AAP8/////f/9//n////9//3/+f////3//f/5//3//fwAA/z//f/9/AAD/P/9//38AAP8//3//fwAA/z//f/9/AAD/P/9//38AAP8//3//////////f/////////9/////////////f/9/AID///9//38AgP///3//fwCA////f/9/AID///9//38AgP///3//fwCA/38AAP//////fwAA//////9/AAD/////AAD/f/9/AIAAAP9//38AgAAA/3//fwCA/3//////////f/////////9//////////38AAP//////fwAA//////9/AAD/////AAD/f/9/AIAAAP9//38AgAAA/3//fwCA") }] [node name="level_cube_portals" type="Node3D"] @@ -98,7 +118,7 @@ text = "Portal A" [node name="Portal B" type="MeshInstance3D" parent="." node_paths=PackedStringArray("exit_portal")] transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 1, 6) -mesh = SubResource("ArrayMesh_gnq53") +mesh = SubResource("ArrayMesh_jhkhy") script = ExtResource("5_jfr1b") destroy_disabled_viewport = false fade_out_distance_max = 100.0 @@ -119,3 +139,24 @@ base = NodePath("../WorldEnvironment") height = 3.0 width = 2.0 portal = NodePath("../Portal B") + +[node name="Outer" type="CSGBox3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 6) +visible = false +size = Vector3(2.2, 3.2, 0.25) + +[node name="CSGCombiner3D" type="CSGCombiner3D" parent="Outer"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) +operation = 2 + +[node name="Inner" type="CSGBox3D" parent="Outer/CSGCombiner3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.991699, 0) +size = Vector3(2, 3.0166, 1) + +[node name="Frame" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 6) +mesh = SubResource("ArrayMesh_gnq53") + +[node name="Frame2" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, -6) +mesh = SubResource("ArrayMesh_gnq53") diff --git a/menu.gd b/menu.gd index 6eff30f..6ca0bee 100644 --- a/menu.gd +++ b/menu.gd @@ -1,19 +1,19 @@ extends Control -const LEVEL_5_ROOMS = preload("res://levels/level_5rooms.tscn") -const LEVEL_3_ROOMS = preload("res://levels/level_3_rooms.tscn") -const LEVEL_PLATFORMER = preload("res://levels/level_platformer.tscn") -const LEVEL_SEMAPHORE_LIGHTS = preload("res://levels/level_semaphore_lights.tscn") -const LEVEL_CUBE_PORTALS = preload("res://levels/level_cube_portals.tscn") +const LEVEL_5_ROOMS: PackedScene = preload("res://levels/level_5rooms.tscn") +const LEVEL_3_ROOMS: PackedScene = preload("res://levels/level_3_rooms.tscn") +const LEVEL_PLATFORMER: PackedScene = preload("res://levels/level_platformer.tscn") +const LEVEL_SEMAPHORE_LIGHTS: PackedScene = preload("res://levels/level_semaphore_lights.tscn") +const LEVEL_CUBE_PORTALS: PackedScene = preload("res://levels/level_cube_portals.tscn") @onready var items_container: VBoxContainer = $CenterContainer/ItemsContainer -var levels = { +var levels: Dictionary = { "Semaphore": LEVEL_3_ROOMS, "Semaphore - Lights Demo": LEVEL_SEMAPHORE_LIGHTS, "5 rooms": LEVEL_5_ROOMS, "Platform": LEVEL_PLATFORMER, - "Cube portals": LEVEL_CUBE_PORTALS + "Recurisve portals - WIP": LEVEL_CUBE_PORTALS } func _ready() -> void: diff --git a/models/portal_mesh.gd b/models/portal_mesh.gd new file mode 100644 index 0000000..c04f763 --- /dev/null +++ b/models/portal_mesh.gd @@ -0,0 +1,105 @@ +@tool +extends ArrayMesh +class_name PortalMesh + +@export_range(0.1, 10, 0.01) var height: float = 2.0: + set(new_val): + height = new_val + generate_portal_mesh() + +@export_range(0.1, 10, 0.01) var width: float = 1.0: + set(new_val): + width = new_val + generate_portal_mesh() + +## Player camera's NEAR clip distance +@export_range(0, 0.2, 0.001) var indent: float = 0.1: + set(new_val): + indent = new_val + generate_portal_mesh() + +func _init() -> void: + if Engine.is_editor_hint(): + generate_portal_mesh() + +func generate_portal_mesh() -> void: + print("[PortalMesh] Creating mesh") + var _start_time = Time.get_ticks_usec() + clear_surfaces() # Reset + + var surface_array: Array = [] + surface_array.resize(Mesh.ARRAY_MAX) + + var verts: PackedVector3Array = PackedVector3Array() + var uvs: PackedVector2Array = PackedVector2Array() + var normals: PackedVector3Array = PackedVector3Array() + var indices: PackedInt32Array = PackedInt32Array() + + # Just to save some chars + var w: float = width / 2 + var h: float = height / 2 + + + # Outside rect + var TOP_LEFT: Vector3 = Vector3(-w, h, 0) + var TOP_RIGHT: Vector3 = Vector3(w, h, 0) + var BOTTOM_LEFT: Vector3 = Vector3(-w, -h, 0) + var BOTTOM_RIGHT: Vector3 = Vector3(w, -h, 0) + # Inside rect, indented + var INDENT_TL: Vector3 = TOP_LEFT + Vector3(indent, -indent, -indent) + var INDENT_TR: Vector3 = TOP_RIGHT + Vector3(-indent, -indent, -indent) + var INDENT_BL: Vector3 = BOTTOM_LEFT + Vector3(indent, indent, -indent) + var INDENT_BR: Vector3 = BOTTOM_RIGHT + Vector3(-indent, indent, -indent) + + verts.append_array([ + TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, + INDENT_TL, INDENT_TR, INDENT_BL, INDENT_BR + ]) + + var ix: float = indent / width + var iy: float = indent / height + uvs.append_array([ + Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), # Outside UVs + Vector2(ix, iy), Vector2(1-ix, iy), Vector2(ix, 1-iy), Vector2(1-ix, 1-iy) # Indented UVs + ]) + + # We are going for a flat-surface look here. Portals should be unshaded anyways. + normals.append_array([ + Vector3.BACK, Vector3.BACK, Vector3.BACK, Vector3.BACK, + Vector3.BACK, Vector3.BACK, Vector3.BACK, Vector3.BACK + ]) + + # 0 ----------- 1 + # | \ / | + # | 4-------5 | + # | | | | + # | | | | + # | 6-------7 | + # | / \ | + # 2 ----------- 3 + + # Triangles are clockwise! + + indices.append_array([ + 0, 1, 4, + 4, 1, 5, # Top section done + 1, 3, 5, + 5, 3, 7, # right section done + 3, 2, 7, + 7, 2, 6, # bottom section done + 2, 0, 6, + 6, 0, 4, # left section done + + 4, 5, 6, + 6, 5, 7, # middle sectiondone + ]) + + surface_array[Mesh.ARRAY_VERTEX] = verts + surface_array[Mesh.ARRAY_TEX_UV] = uvs + surface_array[Mesh.ARRAY_NORMAL] = normals + surface_array[Mesh.ARRAY_INDEX] = indices + + add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) + + print("[PortalMesh] Done in %f ms" % [(Time.get_ticks_usec() - _start_time) / 1000.0]) + diff --git a/models/portal_mesh.gd.uid b/models/portal_mesh.gd.uid new file mode 100644 index 0000000..6bd7c3e --- /dev/null +++ b/models/portal_mesh.gd.uid @@ -0,0 +1 @@ +uid://s5kb624h26hs diff --git a/procedural_mesh_maker.gd b/procedural_mesh_maker.gd index 8cf9cba..823ae41 100644 --- a/procedural_mesh_maker.gd +++ b/procedural_mesh_maker.gd @@ -11,7 +11,7 @@ extends Node func _add_inspector_buttons() -> Array: - var buttons = [] + var buttons: Array = [] buttons.push_back({ "name": "Generate Portal Mesh", @@ -25,7 +25,7 @@ func _add_inspector_buttons() -> Array: return buttons func _get_configuration_warnings() -> PackedStringArray: - var warnings = [] + var warnings: Array = [] if portal == null: warnings.append("Assign a portal to generate the mesh for") @@ -45,37 +45,37 @@ func generate_portal_mesh() -> void: var mesh = ArrayMesh.new() print("[PMM] Creating mesh") - var surface_array = [] + var surface_array: Array = [] surface_array.resize(Mesh.ARRAY_MAX) - var verts = PackedVector3Array() - var uvs = PackedVector2Array() - var normals = PackedVector3Array() - var indices = PackedInt32Array() + var verts: PackedVector3Array = PackedVector3Array() + var uvs: PackedVector2Array = PackedVector2Array() + var normals: PackedVector3Array = PackedVector3Array() + var indices: PackedInt32Array = PackedInt32Array() # Just to save some chars - var w = width / 2 - var h = height / 2 + var w: float = width / 2 + var h: float = height / 2 # Outside rect - var TOP_LEFT = Vector3(-w, h, 0) - var TOP_RIGHT = Vector3(w, h, 0) - var BOTTOM_LEFT = Vector3(-w, -h, 0) - var BOTTOM_RIGHT = Vector3(w, -h, 0) + var TOP_LEFT: Vector3 = Vector3(-w, h, 0) + var TOP_RIGHT: Vector3 = Vector3(w, h, 0) + var BOTTOM_LEFT: Vector3 = Vector3(-w, -h, 0) + var BOTTOM_RIGHT: Vector3 = Vector3(w, -h, 0) # Inside rect, indented - var INDENT_TL = TOP_LEFT + Vector3(indent, -indent, -indent) - var INDENT_TR = TOP_RIGHT + Vector3(-indent, -indent, -indent) - var INDENT_BL = BOTTOM_LEFT + Vector3(indent, indent, -indent) - var INDENT_BR = BOTTOM_RIGHT + Vector3(-indent, indent, -indent) + var INDENT_TL: Vector3 = TOP_LEFT + Vector3(indent, -indent, -indent) + var INDENT_TR: Vector3 = TOP_RIGHT + Vector3(-indent, -indent, -indent) + var INDENT_BL: Vector3 = BOTTOM_LEFT + Vector3(indent, indent, -indent) + var INDENT_BR: Vector3 = BOTTOM_RIGHT + Vector3(-indent, indent, -indent) verts.append_array([ TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, INDENT_TL, INDENT_TR, INDENT_BL, INDENT_BR ]) - var ix = indent / width - var iy = indent / height + var ix: float = indent / width + var iy: float = indent / height uvs.append_array([ Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), # Outside UVs Vector2(ix, iy), Vector2(1-ix, iy), Vector2(ix, 1-iy), Vector2(1-ix, 1-iy) # Indented UVs