Download scripts/studio/studio_main.gd from geter62/monkeystudio: direct link, hf CLI and curl.
- Browser
- Download file 4.2 kB
-
https://huggingface.co/geter62/monkeystudio/resolve/main/scripts/studio/studio_main.gd
- Command line
-
hf download hf://geter62/monkeystudio/scripts/studio/studio_main.gd
-
curl -L -o studio_main.gd https://huggingface.co/geter62/monkeystudio/resolve/main/scripts/studio/studio_main.gd
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]) | |