Download scripts/core/feature_registry.gd from geter62/monkeystudio: direct link, hf CLI and curl.
- Browser
- Download file 4.91 kB
-
https://huggingface.co/geter62/monkeystudio/resolve/main/scripts/core/feature_registry.gd
- Command line
-
hf download hf://geter62/monkeystudio/scripts/core/feature_registry.gd
-
curl -L -o feature_registry.gd https://huggingface.co/geter62/monkeystudio/resolve/main/scripts/core/feature_registry.gd
4.91 kB
| extends Node | |
| ## | |
| ## FeatureRegistry - catalog of every tool/feature and its RAM budget. | |
| ## | |
| ## This is what makes "100+ features that never OOM" possible: features are | |
| ## *descriptions*, not live objects. A feature is only instantiated when the | |
| ## user actually opens it, and torn down when they close it. The registry maps | |
| ## each feature id -> {name, module, cost_mb, loaded}. | |
| ## | |
| ## Modules are GDScript files under res://scripts/modules/. Each module is a | |
| ## Node that implements `_activate(host)` and `_deactivate()`. | |
| ## | |
| signal feature_activated(id: String) | |
| signal feature_deactivated(id: String) | |
| signal feature_failed(id: String, reason: String) | |
| ## id -> { name, module_path, cost_mb, node, active } | |
| var _features: Dictionary = {} | |
| ## Currently instantiated feature nodes, keyed by id. | |
| var _live: Dictionary = {} | |
| ## Parent node that hosts active feature modules. | |
| var host: Node = null | |
| func _ready() -> void: | |
| register_all() | |
| ## --- Public API ------------------------------------------------------------- | |
| ## Instantiate and activate a feature. Safe to call twice (no-op if active). | |
| func activate(id: String) -> bool: | |
| if not _features.has(id): | |
| feature_failed.emit(id, "unknown feature") | |
| return false | |
| if _live.has(id): | |
| feature_activated.emit(id) | |
| return true | |
| var f: Dictionary = _features[id] | |
| # Reserve memory *before* instantiating so eviction can happen first. | |
| MemoryManager.register(id, f["module_path"], float(f["cost_mb"])) | |
| var script: Resource = MemoryManager.acquire(id) | |
| if script == null or host == null: | |
| feature_failed.emit(id, "load failed or no host") | |
| MemoryManager.release(id) | |
| return false | |
| var node: Node = (script as GDScript).new() | |
| node.name = "Feature_" + id | |
| host.add_child(node) | |
| if node.has_method("_activate"): | |
| node.call("_activate", host) | |
| _live[id] = node | |
| feature_activated.emit(id) | |
| return true | |
| ## Deactivate and destroy a feature, returning its RAM to the pool. | |
| func deactivate(id: String) -> void: | |
| if not _live.has(id): | |
| return | |
| var node: Node = _live[id] | |
| if node.has_method("_deactivate"): | |
| node.call("_deactivate") | |
| node.queue_free() | |
| _live.erase(id) | |
| MemoryManager.release(id) | |
| # If nothing else references the module, drop the loaded script now. | |
| MemoryManager.purge(id) | |
| feature_deactivated.emit(id) | |
| func is_active(id: String) -> bool: | |
| return _live.has(id) | |
| func list_features() -> Array: | |
| var ids := _features.keys() | |
| ids.sort() | |
| return ids | |
| func feature_count() -> int: | |
| return _features.size() | |
| func get_info(id: String) -> Dictionary: | |
| return _features.get(id, {}) | |
| ## --- Registration ----------------------------------------------------------- | |
| func _reg(id: String, name: String, module_path: String, cost_mb: float) -> void: | |
| _features[id] = { | |
| "name": name, | |
| "module_path": module_path, | |
| "cost_mb": cost_mb, | |
| "active": false, | |
| } | |
| ## The full feature catalog. Costs are conservative RAM estimates in MB and are | |
| ## the numbers MemoryManager uses for eviction decisions. | |
| func register_all() -> void: | |
| # --- Mesh generation (Features 1-20) --- | |
| _reg("mesh.cube", "Cube Primitive", "res://scripts/modules/mesh_gen.gd", 0.5) | |
| _reg("mesh.sphere", "UV Sphere", "res://scripts/modules/mesh_gen.gd", 1.0) | |
| _reg("mesh.cylinder","Cylinder", "res://scripts/modules/mesh_gen.gd", 0.5) | |
| _reg("mesh.plane", "Plane", "res://scripts/modules/mesh_gen.gd", 0.2) | |
| _reg("mesh.suzanne", "Monkey Head", "res://scripts/modules/mesh_gen.gd", 2.0) | |
| _reg("mesh.torus", "Torus", "res://scripts/modules/mesh_gen.gd", 1.5) | |
| _reg("mesh.ico", "Icosphere", "res://scripts/modules/mesh_gen.gd", 1.0) | |
| _reg("mesh.text", "Text Mesh", "res://scripts/modules/mesh_gen.gd", 1.0) | |
| # --- Sculpting (Features 21-40) --- | |
| _reg("sculpt.draw", "Draw Brush", "res://scripts/modules/sculpt.gd", 4.0) | |
| _reg("sculpt.grab", "Grab Brush", "res://scripts/modules/sculpt.gd", 4.0) | |
| _reg("sculpt.pinch", "Pinch Brush", "res://scripts/modules/sculpt.gd", 4.0) | |
| _reg("sculpt.smooth", "Smooth Brush", "res://scripts/modules/sculpt.gd", 4.0) | |
| _reg("sculpt.flatten", "Flatten Brush", "res://scripts/modules/sculpt.gd", 4.0) | |
| # --- Rigging (Features 41-60) --- | |
| _reg("rig.skeleton", "Armature Editor", "res://scripts/modules/rigging.gd", 8.0) | |
| _reg("rig.weight", "Weight Paint", "res://scripts/modules/rigging.gd", 6.0) | |
| # --- Simulation (Features 61-80) --- | |
| _reg("sim.cloth", "Cloth Sim", "res://scripts/modules/simulation.gd", 12.0) | |
| _reg("sim.hair", "Hair Sim", "res://scripts/modules/simulation.gd", 10.0) | |
| _reg("sim.wind", "Wind Field", "res://scripts/modules/simulation.gd", 2.0) | |
| # --- Animation (Features 81-100) --- | |
| _reg("anim.timeline", "Timeline", "res://scripts/modules/timeline.gd", 3.0) | |
| _reg("anim.keyframe", "Keyframe Tool","res://scripts/modules/timeline.gd", 3.0) | |
| print("[FeatureRegistry] %d features registered" % _features.size()) | |