feat(skin): add skin system + Miku character skin
Skin System: - PlayerSkin resource class (model_path, color_tint, etc.) - SkinManager with default skins: Default, Red Team, Forest, Miku - HumanoidModel.apply_skin() supports both GLB model replacement and procedural color tinting - Procedural meshes auto-hide when GLB model is loaded Miku Skin: - 43-part procedural model generated in Blender (headless) - Twin tails, headphones, thigh-high socks, idol outfit - Teal/cyan color scheme with red accents - Exported to assets/characters/skins/miku.glb - Applied to player 1 in test level builder Pipeline: - Blender 5.0.1 + MCP addon installed - Bridge script for socket-based Blender control - docs/3D_ASSET_PIPELINE.md documents full workflow
This commit is contained in:
@@ -163,6 +163,49 @@ func _ready() -> void:
|
||||
calf_r.cast_shadow = shadow_setting
|
||||
calf_r_pivot.add_child(calf_r)
|
||||
|
||||
## Skin System
|
||||
var current_skin: PlayerSkin
|
||||
var skin_model: Node3D
|
||||
|
||||
func apply_skin(skin: PlayerSkin) -> void:
|
||||
current_skin = skin
|
||||
if skin.model_path != "" and skin.model_path != null:
|
||||
var loaded = load(skin.model_path)
|
||||
if loaded:
|
||||
_set_procedural_visible(false)
|
||||
if skin_model:
|
||||
skin_model.queue_free()
|
||||
skin_model = null
|
||||
skin_model = loaded.instantiate()
|
||||
if skin_model:
|
||||
skin_model.name = "SkinModel"
|
||||
add_child(skin_model)
|
||||
print("HumanoidModel: applied skin '%s'" % skin.skin_name)
|
||||
return
|
||||
_set_procedural_visible(true)
|
||||
if skin_model:
|
||||
skin_model.queue_free()
|
||||
skin_model = null
|
||||
_apply_color(skin.color_tint)
|
||||
|
||||
func _set_procedural_visible(visible: bool) -> void:
|
||||
for part in [torso, head, upper_arm_l, lower_arm_l, upper_arm_r, lower_arm_r, thigh_l, calf_l, thigh_r, calf_r]:
|
||||
if part:
|
||||
part.visible = visible
|
||||
|
||||
func _apply_color(col: Color) -> void:
|
||||
var mat = StandardMaterial3D.new()
|
||||
mat.albedo_color = col
|
||||
mat.roughness = 0.8
|
||||
for part in [torso, upper_arm_l, lower_arm_l, upper_arm_r, lower_arm_r, thigh_l, calf_l, thigh_r, calf_r]:
|
||||
if part and part.mesh:
|
||||
part.mesh.material = mat
|
||||
if head and head.mesh:
|
||||
var hmat = StandardMaterial3D.new()
|
||||
hmat.albedo_color = Color(0.95, 0.85, 0.78)
|
||||
hmat.roughness = 0.8
|
||||
head.mesh.material = hmat
|
||||
|
||||
func update_state(state: String, speed: float, is_crouching: bool = false) -> void:
|
||||
current_state = state
|
||||
movement_speed = speed
|
||||
|
||||
Reference in New Issue
Block a user