This repository has no description
5.5 kB
165 lines
1# SPDX-License-Identifier: MIT
2# SPDX-FileCopyrightText: 2023 MizunagiKB <mizukb@live.jp>
3extends Node2D
4
5
6const DEFAULT_ASSET: String = "res://addons/gd_cubism/example/res/live2d/mao_pro_jp/runtime/mao_pro.model3.json"
7
8const CONVEX_MESH_SRC: Array[String] = [
9 "ArtMesh121",
10 "ArtMesh122",
11 "ArtMesh135",
12 "ArtMesh146",
13 "ArtMesh147",
14 "ArtMesh231",
15 "ArtMesh278"
16]
17var order_window_position: bool = false
18var mouse_button_pressed: bool = false
19var window_position: Vector2i
20var mouse_position: Vector2
21
22var enable_transparent: bool = false
23var ary_character_expression: Array
24var ary_character_motion: Array
25
26
27# ---------------------------------------------------------------------- ported
28# I have ported the code for check_cross and convex_hull to GDScript.
29# * https://tjkendev.github.io/procon-library/
30# * https://tjkendev.github.io/procon-library/cpp/geometry/graham_scan.html
31
32func check_cross(ary_check: Array, vtx: Vector2) -> bool:
33 var va: Vector2 = ary_check[ary_check.size() - 2]
34 var vb: Vector2 = ary_check[ary_check.size() - 1]
35
36 return (((vb.x - va.x) * (vtx.y - va.y)) - ((vb.y - va.y) * (vtx.x - va.x))) > 0
37
38
39func convex_hull(ary_vertex: Array[Vector2]) -> Array:
40 ary_vertex.sort()
41
42 var ary_result: Array
43 var n: int = ary_vertex.size()
44
45 for vtx in ary_vertex:
46 while ary_result.size() > 1 and check_cross(ary_result, vtx):
47 ary_result.pop_back()
48 ary_result.push_back(vtx)
49
50 var t: int = ary_result.size()
51
52 var i: int = n - 2
53 while i >= 0:
54 var vtx: Vector2 = ary_vertex[i]
55 while ary_result.size() > t and check_cross(ary_result, vtx):
56 ary_result.pop_back()
57 ary_result.push_back(vtx)
58
59 i -= 1
60
61 ary_result.pop_back()
62
63 return ary_result
64
65# ---------------------------------------------------------------------- ported
66
67
68func recalc_model_position(model: GDCubismUserModel):
69 if model.assets == "":
70 return
71
72 var canvas_info: Dictionary = model.get_canvas_info()
73
74 if canvas_info.is_empty() != true:
75 var vct_viewport_size = Vector2(get_viewport_rect().size)
76 var scale: float = vct_viewport_size.y / max(canvas_info.size_in_pixels.x, canvas_info.size_in_pixels.y)
77 model.position = vct_viewport_size / 2.0
78 model.scale = Vector2(scale, scale)
79
80
81func _ready():
82 if $GDCubismUserModel.assets == "":
83 $GDCubismUserModel.assets = DEFAULT_ASSET
84
85 recalc_model_position($GDCubismUserModel)
86
87 ary_character_expression = $GDCubismUserModel.get_expressions()
88
89 var dict_motion = $GDCubismUserModel.get_motions()
90 for group in dict_motion.keys():
91 for no in range(dict_motion[group]):
92 ary_character_motion.append({"group": group, "no": no})
93
94
95func _process(delta):
96 if order_window_position == true:
97 DisplayServer.window_set_position(Vector2i(window_position))
98 order_window_position = false
99
100 var dict_mesh = $GDCubismUserModel.get_meshes()
101 var ary: PackedVector2Array
102
103 for name in CONVEX_MESH_SRC:
104 ary += dict_mesh[name].get_mesh().surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
105
106 var ary_polygon = convex_hull(ary)
107
108 if ary_polygon.size() > 2:
109 var region: PackedVector2Array
110 var adjust: Vector2 = get_viewport_rect().size
111
112 for v in ary_polygon:
113 v *= $GDCubismUserModel.scale
114 v += $GDCubismUserModel.position
115 region.append(v)
116
117 $Polygon2D.polygon = PackedVector2Array(region)
118
119
120func _input(event):
121 if event is InputEventKey:
122 if event.is_pressed() == true:
123
124 if event.keycode == KEY_ESCAPE:
125 get_tree().quit()
126
127 if event.keycode == KEY_SPACE:
128 var motion = ary_character_motion[randi_range(0, ary_character_motion.size() - 1)]
129 $GDCubismUserModel.start_motion_loop(
130 motion.group,
131 motion.no,
132 GDCubismUserModel.PRIORITY_FORCE,
133 true,
134 true
135 )
136 if event.keycode == KEY_TAB:
137 if enable_transparent == true:
138 enable_transparent = false
139 DisplayServer.window_set_mouse_passthrough([])
140 else:
141 enable_transparent = true
142 DisplayServer.window_set_mouse_passthrough($Polygon2D.polygon)
143 get_tree().root.transparent_bg = enable_transparent
144 DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_TRANSPARENT, enable_transparent, 0)
145 DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_ALWAYS_ON_TOP, true, 0)
146
147 if event.keycode >= KEY_0 and event.keycode <= KEY_9:
148 var index: int = event.keycode - KEY_0
149 if index < ary_character_expression.size():
150 $GDCubismUserModel.start_expression(
151 ary_character_expression[index]
152 )
153
154 if event is InputEventMouseButton:
155 if event.pressed == true:
156 window_position = DisplayServer.window_get_position()
157 mouse_position = get_viewport().get_mouse_position()
158 else:
159 get_viewport().warp_mouse(mouse_position)
160 mouse_button_pressed = event.pressed
161
162 if event is InputEventMouseMotion:
163 if mouse_button_pressed == true:
164 order_window_position = true
165 window_position += Vector2i(event.relative)