monkeystudio / scripts /studio /studio_main.gd
geter62's picture
Upload folder using huggingface_hub
84e8204 verified
Raw History Blame Contribute Delete
4.2 kB
extends Node3D
##
## StudioMain - root bootstrap for MonkeyStudio.
##
## Builds the runtime scene tree in code so the whole app is one auditable
## script rather than a fragile binary .tscn. Scene tree created:
##
## StudioMain (Node3D)
## β”œβ”€β”€ WorldEnvironment (mobile renderer settings)
## β”œβ”€β”€ Sun (DirectionalLight3D)
## β”œβ”€β”€ Camera3D (touch_camera.gd)
## β”œβ”€β”€ Geometry (Node3D) <- user-created meshes live here
## β”œβ”€β”€ Rig (Node3D) <- Skeleton3D lives here
## β”œβ”€β”€ Features (Node) <- lazily-instantiated feature modules
## └── UI (CanvasLayer)
## └── (built by studio_ui.gd)
##
const TouchCameraScript := preload("res://scripts/studio/touch_camera.gd")
const StudioUIScript := preload("res://scripts/studio/studio_ui.gd")
var camera: Camera3D
var geometry: Node3D
var rig: Node3D
var feature_host: Node
var ui: CanvasLayer
func _ready() -> void:
_build_environment()
_build_lighting()
_build_camera()
geometry = _make_node("Geometry")
rig = _make_node("Rig")
feature_host = Node.new()
feature_host.name = "Features"
add_child(feature_host)
FeatureRegistry.host = feature_host
_build_ui()
_spawn_starter_scene()
_connect_signals()
print("[StudioMain] ready. %d features available." % FeatureRegistry.feature_count())
func _build_environment() -> void:
var env := Environment.new()
env.background_mode = Environment.BG_COLOR
env.background_color = Color(0.08, 0.09, 0.11)
env.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
env.ambient_light_color = Color(0.35, 0.38, 0.45)
env.ambient_light_energy = 0.6
# Mobile-friendly tonemap + no heavy SSAO/GI by default.
env.tonemap_mode = Environment.TONE_MAPPER_FILMIC
env.ssao_enabled = false
env.glow_enabled = false
var we := WorldEnvironment.new()
we.name = "WorldEnvironment"
we.environment = env
add_child(we)
func _build_lighting() -> void:
var sun := DirectionalLight3D.new()
sun.name = "Sun"
sun.rotation_degrees = Vector3(-50, -40, 0)
sun.light_energy = 1.1
sun.shadow_enabled = true
# Lower shadow resolution on mobile to save bandwidth.
sun.directional_shadow_max_distance = 40.0
add_child(sun)
func _build_camera() -> void:
camera = TouchCameraScript.new()
camera.name = "Camera3D"
camera.fov = 60.0
camera.position = Vector3(4, 4, 8)
add_child(camera)
camera.focus = Vector3.ZERO
func _make_node(n: String) -> Node3D:
var node := Node3D.new()
node.name = n
add_child(node)
return node
func _build_ui() -> void:
ui = StudioUIScript.new()
ui.name = "UI"
add_child(ui)
## Spawn a cube so the app is immediately interactive on first launch.
func _spawn_starter_scene() -> void:
FeatureRegistry.activate("mesh.cube")
var gen: Node = feature_host.get_node_or_null("Feature_mesh.cube")
if gen != null and gen.has_method("spawn"):
var mesh: MeshInstance3D = gen.call("spawn", "cube", {"size": 1.5})
_ensure_collision(mesh)
StudioBus.object_selected.emit(mesh)
if camera != null:
camera.frame_aabb(mesh.mesh.get_aabb())
## Give a mesh a static trimesh collider so sculpting raycasts hit it.
func _ensure_collision(mi: MeshInstance3D) -> void:
if mi == null or mi.mesh == null:
return
var body := StaticBody3D.new()
body.name = mi.name + "_Body"
var shape := CollisionShape3D.new()
var trimesh := mi.mesh.create_trimesh_shape()
if trimesh != null:
shape.shape = trimesh
else:
# Fallback to a box for exotic primitives without trimesh support.
var box := BoxShape3D.new()
box.size = mi.mesh.get_aabb().size
shape.shape = box
body.add_child(shape)
mi.add_child(body)
func _connect_signals() -> void:
StudioBus.fps_throttled.connect(_on_fps_throttled)
MemoryManager.memory_warning.connect(_on_memory_warning)
func _on_fps_throttled(fps: int) -> void:
# Shed load: disable shadows first, then reduce the sim substep budget.
var sun := get_node_or_null("Sun") as DirectionalLight3D
if sun != null and sun.shadow_enabled:
sun.shadow_enabled = false
print("[Perf] shadows off at %d fps" % fps)
func _on_memory_warning(used_mb: float, budget_mb: float) -> void:
print("[Mem] warning: %.0f/%.0f MB" % [used_mb, budget_mb])