127 lines
3.1 KiB
GDScript
127 lines
3.1 KiB
GDScript
@tool
|
|
extends Node
|
|
|
|
@export_range(0.1, 10, 0.01) var height: float = 2.0
|
|
@export_range(0.1, 10, 0.01) var width: float = 1.0
|
|
## Player camera's NEAR clip distance
|
|
@export_range(0, 0.2, 0.001) var indent: float = 0.1
|
|
|
|
@export var portal: Portal
|
|
@export var portal_material: BaseMaterial3D
|
|
|
|
|
|
func _add_inspector_buttons() -> Array:
|
|
var buttons = []
|
|
|
|
buttons.push_back({
|
|
"name": "Generate Portal Mesh",
|
|
"pressed": generate_portal_mesh
|
|
})
|
|
buttons.push_back({
|
|
"name": "Remove Mesh",
|
|
"pressed": func(): portal.mesh = null
|
|
})
|
|
|
|
return buttons
|
|
|
|
func _get_configuration_warnings() -> PackedStringArray:
|
|
var warnings = []
|
|
|
|
if portal == null:
|
|
warnings.append("Assign a portal to generate the mesh for")
|
|
|
|
return warnings
|
|
|
|
func generate_portal_mesh() -> void:
|
|
if portal == null:
|
|
push_error("No portal")
|
|
return
|
|
|
|
if portal.mesh != null:
|
|
push_warning("The portal %s already has a mesh! Replacing." % portal.name)
|
|
portal.mesh = null
|
|
|
|
|
|
var mesh = ArrayMesh.new()
|
|
print("[PMM] Creating mesh")
|
|
|
|
var surface_array = []
|
|
surface_array.resize(Mesh.ARRAY_MAX)
|
|
|
|
var verts = PackedVector3Array()
|
|
var uvs = PackedVector2Array()
|
|
var normals = PackedVector3Array()
|
|
var indices = PackedInt32Array()
|
|
|
|
# Just to save some chars
|
|
var w = width / 2
|
|
var h = 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)
|
|
# 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)
|
|
|
|
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
|
|
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
|
|
|
|
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)
|
|
if portal_material:
|
|
mesh.surface_set_material(0, portal_material)
|
|
mesh.surface_set_name(0, "Portal Material")
|
|
portal.mesh = mesh
|
|
|
|
print("[PMM] Mesh assigned")
|