@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 const UV_CHECKER_MATERIAL = preload("res://textures/uv-checker-material.tres") 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 # TODO: Shadow mesh maybe? Should a portal even cast a shadow? mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) mesh.surface_set_material(0, UV_CHECKER_MATERIAL) mesh.surface_set_name(0, "Portal Material") portal.mesh = mesh print("[PMM] Mesh assigned")