Besides (hopefully) helping with code cleanliness, this also allows us to store extra per-player or per-model information.main
parent
fdfdfc0634
commit
b0fdfe0e41
2 changed files with 107 additions and 71 deletions
@ -0,0 +1,71 @@ |
||||
class_name SyncController |
||||
extends Node |
||||
|
||||
var module: copyMultiplayer |
||||
var model_controller: ModelController |
||||
var peer_id: int |
||||
|
||||
var nickname: String # FIXME: Not assigned or used. |
||||
var model_name: String |
||||
var model: Node |
||||
var skeleton: Skeleton3D |
||||
|
||||
# Allows us to use the "apply_animations" function to apply blendshapes to a model. |
||||
static var _functions_blendshapes: Script = load("res://Mods/MediaPipe/MediaPipeController_BlendShapes.gd") |
||||
|
||||
func _ready() -> void: |
||||
module = get_parent().get_parent() |
||||
model_controller = get_parent() |
||||
peer_id = model_controller.name.to_int() |
||||
|
||||
## Attempts to change the model of this player. |
||||
func change_model(filename: String) -> void: |
||||
if not filename.is_valid_filename(): |
||||
module.print_log("ERROR: '%s' is not a valid file name!" % filename) |
||||
return |
||||
var full_path := module.cache.path_join(filename) |
||||
if not FileAccess.file_exists(full_path): |
||||
module.print_log("Player %d wanted to switch to '%s', but it doesn't exist, skipping" % [ peer_id, filename ]) |
||||
return |
||||
if not model_controller.load_vrm(full_path): |
||||
module.print_log("ERROR: Model '%s' could not be loaded!" % filename) |
||||
return |
||||
module.print_log("Player %d switched to '%s'" % [ peer_id, filename ]) |
||||
model_name = filename |
||||
model = model_controller.get_node_or_null("Model") |
||||
skeleton = model_controller._get_model_skeleton() |
||||
|
||||
func sync_model_animation( |
||||
model_transform: Transform3D, |
||||
shape_dict: Dictionary, # Dictionary[String, float] |
||||
bone_poses: Dictionary, # Dictionary[String, Transform3D] |
||||
) -> void: |
||||
if (not model) or (not skeleton): return |
||||
model.transform = model_transform |
||||
_functions_blendshapes.apply_animations(model, shape_dict) |
||||
for bone_name in bone_poses: |
||||
var pose: Transform3D = bone_poses[bone_name] |
||||
var idx := skeleton.find_bone(bone_name) |
||||
if idx != -1: skeleton.set_bone_pose(idx, pose) |
||||
|
||||
@warning_ignore("shadowed_variable") |
||||
static func send_model_animation(module: copyMultiplayer) -> void: |
||||
# Check if there's other players we're connected to. |
||||
if module.multiplayer.get_peers().size() == 0: return |
||||
|
||||
var model := module.get_model() |
||||
var skeleton := module.get_skeleton() |
||||
var media_pipe = module.get_node("../MediaPipeController") |
||||
if (not model) or (not skeleton) or (not media_pipe): return |
||||
|
||||
var shape_dict = media_pipe.blend_shape_last_values |
||||
|
||||
var bone_poses = {} |
||||
for bone_name in module.tracked_bones: |
||||
var bone_idx = skeleton.find_bone(bone_name) |
||||
if bone_idx == -1: continue |
||||
var bone_pose = skeleton.get_bone_pose(bone_idx) |
||||
bone_poses[bone_name] = bone_pose |
||||
|
||||
# FIXME: This sends way more information than necessary, but works as a proof-of-concept! |
||||
module.sync_model_animation.rpc(model.transform, shape_dict, bone_poses) |
Loading…
Reference in new issue