Skip to content
This repository has been archived by the owner on May 30, 2024. It is now read-only.

Commit

Permalink
Merge pull request #48 from you-win/config-improvements
Browse files Browse the repository at this point in the history
Config improvements

Former-commit-id: b4d2fe7
  • Loading branch information
you-win authored Oct 25, 2021
2 parents 6063988 + 484a428 commit b45b430
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 113 deletions.
Binary file modified assets/vrm-models/alicia/AliciaSolid_vrm-0.51.vrm
Binary file not shown.
90 changes: 61 additions & 29 deletions entities/vrm/VRMModel.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ 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
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:
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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 #
###############################################################################
Expand All @@ -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
Expand Down Expand Up @@ -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)),
Expand Down
12 changes: 12 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -102,12 +112,14 @@ _global_script_class_icons={
"BaseTest": "",
"BasicModel": "",
"BasicPhysicsAttachment": "",
"ConfigManager": "",
"GOTH": "",
"GOTHGui": "",
"InterpolationData": "",
"JSONUtil": "",
"MainScreen": "",
"ModelDisplayScreen": "",
"SignalBroadcaster": "",
"TranslationManager": "",
"VRMMappings": "",
"VRMModel": "",
Expand Down
28 changes: 28 additions & 0 deletions resources/gui/Tracking.gd
Original file line number Diff line number Diff line change
@@ -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 = []

Expand All @@ -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)])
4 changes: 4 additions & 0 deletions resources/gui/tracking.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
<label name="Misc."/>
<toggle name="Should Track Eye" data="should_track_eye" event="should_track_eye"/>
<input name="Gaze Strength" data="gaze_strength" event="gaze_strength" type="float"/>
<input name="Blink Threshold" data="blink_threshold" event="blink_threshold" type="float"/>
</left>
<right>
<label name="Tracking Options"/>
<drop_down name="Camera Select" data="camera_select" event="camera_select" setup="setup_cameras"/>
<input name="Tracker FPS" data="tracker_fps" event="tracker_fps" type="integer"/>
<button name="Start Tracker" event="start_tracker" label_updatable="true"/>
<!-- TODO this is bad, should refactor into a list -->
<label name="Blend Shapes"/>
<drop_down name="Blend Shapes" event="blend_shapes" setup="setup_blend_shapes"/>
</right>
</view>
7 changes: 7 additions & 0 deletions screens/MainScreen.gd
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ func _clean_load_model_display_screen(path: String) -> void:
model_display_screen = MODEL_SCREEN.instance()
model_display_screen.model_resource_path = path
add_child(model_display_screen)

# Set initial values from config
for key in AppManager.cm.current_model_config.main_light.keys():
main_light.get_child(0).set(key, AppManager.cm.current_model_config.main_light[key])

for key in AppManager.cm.current_model_config.world_environment.keys():
world_environment.set(key, AppManager.cm.current_model_config.world_environment[key])

###############################################################################
# Public functions #
Expand Down
16 changes: 15 additions & 1 deletion screens/ModelDisplayScreen.gd
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,23 @@ func _ready() -> void:

model_parent.call_deferred("add_child", model)

# Wait until the model is loaded else we get IK errors
yield(model, "ready")

# Set model initial values from config
model_initial_transform = AppManager.cm.current_model_config.model_transform
model_parent_initial_transform = AppManager.cm.current_model_config.model_parent_transform
model.transform = model_initial_transform
model_parent.transform = model_parent_initial_transform

for bone_index in model.skeleton.get_bone_count():
var bone_name: String = model.skeleton.get_bone_name(bone_index)
# Courtesy null check
if not AppManager.cm.current_model_config.bone_transforms.has(bone_name):
continue
var bone_transform: Transform = AppManager.cm.current_model_config.bone_transforms[bone_name]

model.skeleton.set_bone_pose(bone_index, bone_transform)

func _physics_process(_delta: float) -> void:
if not stored_offsets:
return
Expand Down Expand Up @@ -297,6 +306,11 @@ func _set_interpolation_rate(value: float) -> void:
###############################################################################

func load_external_model(file_path: String) -> Spatial:
var dir := Directory.new()
if not dir.file_exists(file_path):
AppManager.log_message("File path not found: %s\nLoading demo model" % file_path, true)
file_path = AppManager.cm.DEMO_MODEL_PATH

AppManager.log_message("Starting external loader.")
var loaded_model: Spatial
var vrm_meta: Dictionary
Expand Down
7 changes: 4 additions & 3 deletions screens/gui/elements/DropDownElement.gd
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ func _ready() -> void:

popup_menu = menu_button.get_popup()

popup_menu.connect("index_pressed", self, "_on_index_pressed")
# popup_menu.connect("index_pressed", self, "_on_index_pressed")

###############################################################################
# Connections #
###############################################################################

func _on_index_pressed(idx: int) -> void:
_handle_event([event_name, popup_menu.get_item_text(idx)[0]])
# TODO figure out how to do this better
# func _on_index_pressed(idx: int) -> void:
# _handle_event([event_name, popup_menu.get_item_text(idx)[0]])

###############################################################################
# Private functions #
Expand Down
2 changes: 1 addition & 1 deletion screens/gui/elements/InputElement.gd
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func _process(delta: float) -> void:
###############################################################################

func _on_text_entered(text: String) -> void:
_handle_event(text)
_emit_event(text)

func _on_text_changed(_text: String) -> void:
should_emit = true
Expand Down
Loading

0 comments on commit b45b430

Please sign in to comment.