From e19733cfbea1a0032a0907ca4a595bda9a39d1a4 Mon Sep 17 00:00:00 2001 From: Tim Yuen Date: Thu, 14 Oct 2021 23:25:23 -0400 Subject: [PATCH 1/2] actually save bone transforms to config Former-commit-id: 1a058cc9fdce3cd710c13f602ff7272fa939cf99 --- utils/ConfigManager.gd | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/utils/ConfigManager.gd b/utils/ConfigManager.gd index d96ae53a..ed605d3c 100644 --- a/utils/ConfigManager.gd +++ b/utils/ConfigManager.gd @@ -479,8 +479,17 @@ func save_config(p_config: ConfigData = null) -> void: config = p_config.duplicate() else: # TODO this is gross - current_model_config.model_transform = AppManager.main.model_display_screen.model.transform - current_model_config.model_parent_transform = AppManager.main.model_display_screen.model_parent.transform + var model = AppManager.main.model_display_screen.model + var model_parent = AppManager.main.model_display_screen.model_parent + current_model_config.model_transform = model.transform + current_model_config.model_parent_transform = model_parent.transform + + for bone_index in model.skeleton.get_bone_count() - 1: + var bone_transform: Transform = model.skeleton.get_bone_pose(bone_index) + var bone_name: String = model.skeleton.get_bone_name(bone_index) + + current_model_config.bone_transforms[bone_name] = bone_transform + config = current_model_config.duplicate() var config_name = config.config_name From 484a4288f809160a4849212c9c6ea6eb2babf6f1 Mon Sep 17 00:00:00 2001 From: Tim Yuen Date: Mon, 25 Oct 2021 00:03:11 -0400 Subject: [PATCH 2/2] basic expression support, blink sensitivity, fix lighting not loading correctly, fix stop and starting face tracker not working Former-commit-id: eb72d60bbe4fab984f0f1f05c5ce9220443b56f9 --- .../alicia/AliciaSolid_vrm-0.51.vrm | Bin 7900182 -> 7917742 bytes entities/vrm/VRMModel.gd | 90 ++++++++++++------ project.godot | 12 +++ resources/gui/Tracking.gd | 28 ++++++ resources/gui/tracking.xml | 4 + screens/MainScreen.gd | 7 ++ screens/ModelDisplayScreen.gd | 16 +++- screens/gui/elements/DropDownElement.gd | 7 +- screens/gui/elements/InputElement.gd | 2 +- utils/AppManager.gd | 59 ++---------- utils/ConfigManager.gd | 32 ++++--- utils/OpenSeeGD.gd | 22 ++--- utils/SignalBroadcaster.gd | 10 ++ 13 files changed, 178 insertions(+), 111 deletions(-) diff --git a/assets/vrm-models/alicia/AliciaSolid_vrm-0.51.vrm b/assets/vrm-models/alicia/AliciaSolid_vrm-0.51.vrm index 3a884907771c766c4bfc88b521c8e8ab5be87694..34270ec8a4e1a8d6ebe3b06098eb2aad6fb97988 100644 GIT binary patch delta 518 zcmWmA%UX;9007W`X1WmdS5zoTl3S8uMxv&Mzm%ekJLTGh>86X>wz8Og+IoT6`MkzF zgI=U#abDo;?)^)Ye(xv3Ts|AcgCHoC3qfZxz7zflW2xfbbSAcU?`Kqu5hpAWKJ%J0Jz#H`c z-}hf$+=WihZ$sh5)!|4~AP`7DISd@%2am#6;b86GKR4GwqYN2sjIqWU?*kJ|G|6OB z4ExYWrkdtspO|ijnLahkY;(-@nR(`0;B#O2(pMH*X_qBIO#X1oOZ@p o=lt#u=Uwopzg+aUOD?OV diff --git a/entities/vrm/VRMModel.gd b/entities/vrm/VRMModel.gd index 6acd5549..cf0a1681 100644 --- a/entities/vrm/VRMModel.gd +++ b/entities/vrm/VRMModel.gd @@ -3,18 +3,18 @@ extends BasicModel var eco_mode: bool = false -var stored_offsets: ModelDisplayScreen.StoredOffsets +# var stored_offsets: ModelDisplayScreen.StoredOffsets var vrm_meta: Dictionary -var vrm_mappings: VRMMappings # TODO probably unused? +# var vrm_mappings: VRMMappings # TODO probably unused? var left_eye_id: int var right_eye_id: int var neck_bone_id: int var spine_bone_id: int -var mapped_meshes: Dictionary +# var mapped_meshes: Dictionary var facial_expressions var mouth_shapes @@ -22,7 +22,7 @@ var blinking var eye_movement # Blinking -var blink_threshold: float = 0.2 +var blink_threshold: float var eco_mode_is_blinking: bool = false class EyeClamps: @@ -64,18 +64,28 @@ var o := ExpressionData.new() var sorrow := ExpressionData.new() var u := ExpressionData.new() +# TODO stopgap +var last_expression: ExpressionData + ############################################################################### # Builtin functions # ############################################################################### func _ready() -> void: has_custom_update = true - translation_damp = 0.1 - rotation_damp = 0.01 - additional_bone_damp = 0.6 + # TODO this doesn't seem right, commented out for now + # translation_damp = 0.1 + # rotation_damp = 0.01 + # additional_bone_damp = 0.6 + + blink_threshold = AppManager.cm.current_model_config.blink_threshold + AppManager.sb.connect("blink_threshold", self, "_on_blink_threshold") + + # TODO stopgap + AppManager.sb.connect("blend_shapes", self, "_on_blend_shapes") # TODO this is gross - stored_offsets = get_parent().get_parent().stored_offsets + # stored_offsets = get_parent().get_parent().stored_offsets # Map expressions var anim_player: AnimationPlayer = find_node("anim") @@ -230,6 +240,30 @@ func _ready() -> void: # Connections # ############################################################################### +func _on_blink_threshold(value: float) -> void: + blink_threshold = value + +# TODO go back to this after refactoring expression mapping +func _on_blend_shapes(value: String) -> void: + var ed = get(value) + if not ed: + return + + if last_expression: + for idx in last_expression.morphs.size(): + _modify_blend_shape(last_expression.morphs[idx].mesh, last_expression.morphs[idx].morph, + last_expression.morphs[idx].values[0]) + + if ed == last_expression: + last_expression = null + return + + for idx in ed.morphs.size(): + _modify_blend_shape(ed.morphs[idx].mesh, ed.morphs[idx].morph, + ed.morphs[idx].values[1]) + + last_expression = ed + ############################################################################### # Private functions # ############################################################################### @@ -247,25 +281,30 @@ func scan_mapped_bones() -> void: if bone_name.to_lower() == "root": additional_bones_to_pose_names.erase(bone_name) -func set_expression_weight(expression_name: String, expression_weight: float) -> void: - for mesh_name in vrm_mappings[expression_name].get_meshes(): - for blend_name in vrm_mappings[expression_name].expression_data[mesh_name]: - _modify_blend_shape(mapped_meshes[mesh_name], blend_name, expression_weight) +# func set_expression_weight(expression_name: String, expression_weight: float) -> void: +# for mesh_name in vrm_mappings[expression_name].get_meshes(): +# for blend_name in vrm_mappings[expression_name].expression_data[mesh_name]: +# _modify_blend_shape(mapped_meshes[mesh_name], blend_name, expression_weight) func custom_update(data, interpolation_data) -> void: # NOTE: Eye mappings are intentionally reversed so that the model mirrors the data if not eco_mode: - # Left eye blinking - if data.left_eye_open >= blink_threshold: - _modify_blend_shape(blink_r.morphs[0].mesh, blink_r.morphs[0].morph, blink_r.morphs[0].values[1] - interpolation_data.interpolate(InterpolationData.InterpolationDataType.LEFT_EYE_BLINK, 1.0)) - else: - _modify_blend_shape(blink_r.morphs[0].mesh, blink_r.morphs[0].morph, blink_r.morphs[0].values[1]) - - # Right eye blinking - if data.right_eye_open >= blink_threshold: - _modify_blend_shape(blink_l.morphs[0].mesh, blink_l.morphs[0].morph, blink_l.morphs[0].values[1] - interpolation_data.interpolate(InterpolationData.InterpolationDataType.RIGHT_EYE_BLINK, 1.0)) + if (last_expression != joy and last_expression != sorrow): + # Left eye blinking + if data.left_eye_open >= blink_threshold: + _modify_blend_shape(blink_r.morphs[0].mesh, blink_r.morphs[0].morph, blink_r.morphs[0].values[1] - interpolation_data.interpolate(InterpolationData.InterpolationDataType.LEFT_EYE_BLINK, 1.0)) + else: + _modify_blend_shape(blink_r.morphs[0].mesh, blink_r.morphs[0].morph, blink_r.morphs[0].values[1]) + + # Right eye blinking + if data.right_eye_open >= blink_threshold: + _modify_blend_shape(blink_l.morphs[0].mesh, blink_l.morphs[0].morph, blink_l.morphs[0].values[1] - interpolation_data.interpolate(InterpolationData.InterpolationDataType.RIGHT_EYE_BLINK, 1.0)) + else: + _modify_blend_shape(blink_l.morphs[0].mesh, blink_l.morphs[0].morph, blink_l.morphs[0].values[1]) else: - _modify_blend_shape(blink_l.morphs[0].mesh, blink_l.morphs[0].morph, blink_l.morphs[0].values[1]) + # Unblink if the facial expression doesn't allow blinking + _modify_blend_shape(blink_r.morphs[0].mesh, blink_r.morphs[0].morph, blink_r.morphs[0].values[0]) + _modify_blend_shape(blink_l.morphs[0].mesh, blink_l.morphs[0].morph, blink_l.morphs[0].values[0]) # TODO eyes show weird behaviour when blinking # TODO make sure angle between eyes' x values are at least parallel @@ -302,13 +341,6 @@ func custom_update(data, interpolation_data) -> void: skeleton.set_bone_pose(right_eye_id, left_eye_transform) skeleton.set_bone_pose(left_eye_id, right_eye_transform) - # TODO Debug only - if Input.is_key_pressed(KEY_0): - print(left_eye_rotation) - - if Input.is_key_pressed(KEY_1): - print(str(self.eye_tracking_damp)) - # Mouth tracking _modify_blend_shape(a.morphs[0].mesh, a.morphs[0].morph, min(max(a.morphs[0].values[0], interpolation_data.interpolate(InterpolationData.InterpolationDataType.MOUTH_MOVEMENT, 2.0)), diff --git a/project.godot b/project.godot index afae6bb7..02447c86 100644 --- a/project.godot +++ b/project.godot @@ -45,6 +45,11 @@ _global_script_classes=[ { "path": "res://entities/physics/BasicPhysicsAttachment.gd" }, { "base": "Reference", +"class": "ConfigManager", +"language": "GDScript", +"path": "res://utils/ConfigManager.gd" +}, { +"base": "Reference", "class": "GOTH", "language": "GDScript", "path": "res://addons/goth/GOTH.gd" @@ -75,6 +80,11 @@ _global_script_classes=[ { "path": "res://screens/ModelDisplayScreen.gd" }, { "base": "Reference", +"class": "SignalBroadcaster", +"language": "GDScript", +"path": "res://utils/SignalBroadcaster.gd" +}, { +"base": "Reference", "class": "TranslationManager", "language": "GDScript", "path": "res://utils/TranslationManager.gd" @@ -102,12 +112,14 @@ _global_script_class_icons={ "BaseTest": "", "BasicModel": "", "BasicPhysicsAttachment": "", +"ConfigManager": "", "GOTH": "", "GOTHGui": "", "InterpolationData": "", "JSONUtil": "", "MainScreen": "", "ModelDisplayScreen": "", +"SignalBroadcaster": "", "TranslationManager": "", "VRMMappings": "", "VRMModel": "", diff --git a/resources/gui/Tracking.gd b/resources/gui/Tracking.gd index c830d771..932a44fd 100644 --- a/resources/gui/Tracking.gd +++ b/resources/gui/Tracking.gd @@ -1,10 +1,17 @@ extends Control +var camera_element +var blend_shape_element + func setup() -> void: pass func setup_cameras(element: Control) -> void: + camera_element = element + var popup_menu = element.menu_button.get_popup() + if not popup_menu.is_connected("index_pressed", self, "_on_camera_pressed"): + popup_menu.connect("index_pressed", self, "_on_camera_pressed") var result: Array = [] @@ -27,3 +34,24 @@ func setup_cameras(element: Control) -> void: for option in result: popup_menu.add_item(option) + +# TODO this is bad +func _on_camera_pressed(idx: int) -> void: + camera_element._handle_event([camera_element.event_name, camera_element.menu_button.get_popup().get_item_text(idx)[0]]) + +func setup_blend_shapes(element: Control) -> void: + blend_shape_element = element + + var popup_menu = element.menu_button.get_popup() + if not popup_menu.is_connected("index_pressed", self, "_on_blend_shape_pressed"): + popup_menu.connect("index_pressed", self, "_on_blend_shape_pressed") + + if not element.parent.model is VRMModel: + return + + for i in ["angry", "fun", "joy", "sorrow"]: + popup_menu.add_item(i) + +# TODO this is bad +func _on_blend_shape_pressed(idx: int) -> void: + blend_shape_element._handle_event([blend_shape_element.event_name, blend_shape_element.menu_button.get_popup().get_item_text(idx)]) diff --git a/resources/gui/tracking.xml b/resources/gui/tracking.xml index a870261c..0a6e6495 100644 --- a/resources/gui/tracking.xml +++ b/resources/gui/tracking.xml @@ -17,11 +17,15 @@