Made game work
This commit is contained in:
@@ -1,285 +1,299 @@
|
||||
extends Spatial
|
||||
|
||||
onready var characters = [preload("res://characters/female_2018.escn"), preload("res://characters/male_2018.escn")]
|
||||
var body_mi: MeshInstance
|
||||
#var body_mesh: ArrayMesh
|
||||
#var orig_body_mesh: ArrayMesh
|
||||
var cloth_mis: Dictionary = {}
|
||||
#var cloth_meshes: Array = []
|
||||
#var cloth_orig_meshes: Array = []
|
||||
var clothes: Dictionary = {
|
||||
"dress": {
|
||||
"helper": ""
|
||||
},
|
||||
"panties": {
|
||||
"helper": ""
|
||||
},
|
||||
"pants": {
|
||||
"helper": "tights"
|
||||
},
|
||||
"suit": {
|
||||
"helper": "tights"
|
||||
},
|
||||
"bra": {
|
||||
"helper": ""
|
||||
},
|
||||
"top": {
|
||||
"helper": ""
|
||||
}
|
||||
}
|
||||
#var min_point: Vector3 = Vector3()
|
||||
#var max_point: Vector3 = Vector3()
|
||||
#var min_normal: Vector3 = Vector3()
|
||||
#var max_normal: Vector3 = Vector3()
|
||||
#var maps = {}
|
||||
#var vert_indices = {}
|
||||
var _vert_indices = {}
|
||||
#onready var characters = [preload("res://characters/female_2018.escn"), preload("res://characters/male_2018.escn")]
|
||||
#var body_mi: MeshInstance
|
||||
##var body_mesh: ArrayMesh
|
||||
##var orig_body_mesh: ArrayMesh
|
||||
#var cloth_mis: Dictionary = {}
|
||||
##var cloth_meshes: Array = []
|
||||
##var cloth_orig_meshes: Array = []
|
||||
#var clothes: Dictionary = {
|
||||
# "dress": {
|
||||
# "helper": ""
|
||||
# },
|
||||
# "panties": {
|
||||
# "helper": ""
|
||||
# },
|
||||
# "pants": {
|
||||
# "helper": "tights"
|
||||
# },
|
||||
# "suit": {
|
||||
# "helper": "tights"
|
||||
# },
|
||||
# "bra": {
|
||||
# "helper": ""
|
||||
# },
|
||||
# "top": {
|
||||
# "helper": ""
|
||||
# }
|
||||
#}
|
||||
##var min_point: Vector3 = Vector3()
|
||||
##var max_point: Vector3 = Vector3()
|
||||
##var min_normal: Vector3 = Vector3()
|
||||
##var max_normal: Vector3 = Vector3()
|
||||
##var maps = {}
|
||||
##var vert_indices = {}
|
||||
#var _vert_indices = {}
|
||||
var controls = {}
|
||||
var dna: DNA
|
||||
|
||||
var helper_names : = ["skirt"]
|
||||
|
||||
func get_mi(base: Node, mesh_name: String) -> MeshInstance:
|
||||
var queue = [base]
|
||||
var ret: MeshInstance
|
||||
while queue.size() > 0:
|
||||
var item = queue.pop_front()
|
||||
if item is MeshInstance && item.name == mesh_name && item.mesh:
|
||||
ret = item
|
||||
break
|
||||
for c in item.get_children():
|
||||
queue.push_back(c)
|
||||
return ret
|
||||
|
||||
func update_modifier(value: float, modifier: String):
|
||||
var start_time = OS.get_unix_time()
|
||||
var should_show : = false
|
||||
if body_mi.visible:
|
||||
body_mi.hide()
|
||||
should_show = true
|
||||
var val = value / 100.0
|
||||
val = clamp(val, 0.0, 1.0)
|
||||
dna.set_modifier_value(modifier, val)
|
||||
print(modifier, " ", val)
|
||||
body_mi.mesh = dna.modify_part("body")
|
||||
if should_show:
|
||||
body_mi.show()
|
||||
for k in cloth_mis.keys():
|
||||
if cloth_mis[k].visible:
|
||||
cloth_mis[k].hide()
|
||||
cloth_mis[k].mesh = dna.modify_part(k)
|
||||
cloth_mis[k].show()
|
||||
print("modifier_finished: ", OS.get_unix_time() - start_time)
|
||||
|
||||
func toggle_clothes(mi: MeshInstance, cloth_name: String):
|
||||
if !mi.visible:
|
||||
print("mod start")
|
||||
mi.mesh = dna.modify_part(cloth_name)
|
||||
print("mod end")
|
||||
mi.visible = !mi.visible
|
||||
|
||||
func find_mesh(base: Node, mesh_name: String) -> MeshInstance:
|
||||
assert(base)
|
||||
var queue = [base]
|
||||
var mi: MeshInstance
|
||||
while queue.size() > 0:
|
||||
var item = queue[0]
|
||||
assert(item)
|
||||
queue.pop_front()
|
||||
if item is MeshInstance && item.name == mesh_name:
|
||||
mi = item
|
||||
break
|
||||
for c in item.get_children():
|
||||
assert(c)
|
||||
queue.push_back(c)
|
||||
return mi
|
||||
#func modify_mesh(orig_mesh: ArrayMesh, mi: MeshInstance, v_indices: Dictionary):
|
||||
# var should_show : = false
|
||||
# if mi.visible:
|
||||
# mi.hide()
|
||||
# should_show = true
|
||||
# mi.mesh = null
|
||||
# for k in maps.keys():
|
||||
# maps[k].image.lock()
|
||||
# maps[k].image_normal.lock()
|
||||
# var surf : = 0
|
||||
# var mod_mesh = ArrayMesh.new()
|
||||
# var mrect: Rect2
|
||||
# for k in maps.keys():
|
||||
# if maps[k].value > 0.0001:
|
||||
# if mrect:
|
||||
# mrect = mrect.merge(maps[k].rect)
|
||||
# else:
|
||||
# mrect = maps[k].rect
|
||||
# for surface in range(orig_mesh.get_surface_count()):
|
||||
# var arrays: Array = orig_mesh.surface_get_arrays(surface)
|
||||
# var uv_index: int = ArrayMesh.ARRAY_TEX_UV
|
||||
# if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0:
|
||||
# uv_index = ArrayMesh.ARRAY_TEX_UV2
|
||||
# for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
|
||||
# var v: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][index]
|
||||
# var n: Vector3 = arrays[ArrayMesh.ARRAY_NORMAL][index]
|
||||
# var uv: Vector2 = arrays[uv_index][index]
|
||||
# if !mrect.has_point(uv):
|
||||
# continue
|
||||
# var diff : = Vector3()
|
||||
# var diffn : = Vector3()
|
||||
# for k in maps.keys():
|
||||
# if !maps[k].rect.has_point(uv) || abs(maps[k].value) < 0.0001:
|
||||
# continue
|
||||
# var pos: Vector2 = Vector2(uv.x * maps[k].width, uv.y * maps[k].height)
|
||||
# var offset: Color = maps[k].image.get_pixelv(pos)
|
||||
# var offsetn: Color = maps[k].image_normal.get_pixelv(pos)
|
||||
# var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b)
|
||||
# var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b)
|
||||
# for u in range(2):
|
||||
# diff[u] = range_lerp(pdiff[u], 0.0, 1.0, min_point[u], max_point[u]) * maps[k].value
|
||||
# diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, min_normal[u], max_normal[u]) * maps[k].value
|
||||
# if abs(diff[u]) < 0.0001:
|
||||
# diff[u] = 0
|
||||
# v -= diff
|
||||
# n -= diffn
|
||||
# arrays[ArrayMesh.ARRAY_VERTEX][index] = v
|
||||
# arrays[ArrayMesh.ARRAY_NORMAL][index] = n.normalized()
|
||||
# for v in v_indices.keys():
|
||||
# if v_indices[v].size() <= 1:
|
||||
# continue
|
||||
# var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][0]]
|
||||
# for idx in range(1, v_indices[v].size()):
|
||||
# vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][idx]], 0.5)
|
||||
# for idx in v_indices[v]:
|
||||
# arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx
|
||||
#var dna: DNA
|
||||
#
|
||||
# mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
# if orig_mesh.surface_get_material(surface):
|
||||
# mod_mesh.surface_set_material(surface, orig_mesh.surface_get_material(surface).duplicate(true))
|
||||
# surf += 1
|
||||
# for k in maps.keys():
|
||||
# maps[k].image.unlock()
|
||||
# maps[k].image_normal.unlock()
|
||||
# mi.mesh = mod_mesh
|
||||
#var helper_names : = ["skirt"]
|
||||
#
|
||||
#func get_mi(base: Node, mesh_name: String) -> MeshInstance:
|
||||
# var queue = [base]
|
||||
# var ret: MeshInstance
|
||||
# while queue.size() > 0:
|
||||
# var item = queue.pop_front()
|
||||
# if item is MeshInstance && item.name == mesh_name && item.mesh:
|
||||
# ret = item
|
||||
# break
|
||||
# for c in item.get_children():
|
||||
# queue.push_back(c)
|
||||
# return ret
|
||||
#
|
||||
#func update_modifier(value: float, modifier: String):
|
||||
# var start_time = OS.get_unix_time()
|
||||
# var should_show : = false
|
||||
# if body_mi.visible:
|
||||
# body_mi.hide()
|
||||
# should_show = true
|
||||
# var val = value / 100.0
|
||||
# val = clamp(val, 0.0, 1.0)
|
||||
# dna.set_modifier_value(modifier, val)
|
||||
# print(modifier, " ", val)
|
||||
# body_mi.mesh = dna.modify_part("body")
|
||||
# if should_show:
|
||||
# mi.show()
|
||||
# body_mi.show()
|
||||
# for k in cloth_mis.keys():
|
||||
# if cloth_mis[k].visible:
|
||||
# cloth_mis[k].hide()
|
||||
# cloth_mis[k].mesh = dna.modify_part(k)
|
||||
# cloth_mis[k].show()
|
||||
# print("modifier_finished: ", OS.get_unix_time() - start_time)
|
||||
#
|
||||
#func toggle_clothes(mi: MeshInstance, cloth_name: String):
|
||||
# if !mi.visible:
|
||||
# print("mod start")
|
||||
# mi.mesh = dna.modify_part(cloth_name)
|
||||
# print("mod end")
|
||||
# mi.visible = !mi.visible
|
||||
#
|
||||
#func find_mesh(base: Node, mesh_name: String) -> MeshInstance:
|
||||
# assert(base)
|
||||
# var queue = [base]
|
||||
# var mi: MeshInstance
|
||||
# while queue.size() > 0:
|
||||
# var item = queue[0]
|
||||
# assert(item)
|
||||
# queue.pop_front()
|
||||
# if item is MeshInstance && item.name == mesh_name:
|
||||
# mi = item
|
||||
# break
|
||||
# for c in item.get_children():
|
||||
# assert(c)
|
||||
# queue.push_back(c)
|
||||
# return mi
|
||||
##func modify_mesh(orig_mesh: ArrayMesh, mi: MeshInstance, v_indices: Dictionary):
|
||||
## var should_show : = false
|
||||
## if mi.visible:
|
||||
## mi.hide()
|
||||
## should_show = true
|
||||
## mi.mesh = null
|
||||
## for k in maps.keys():
|
||||
## maps[k].image.lock()
|
||||
## maps[k].image_normal.lock()
|
||||
## var surf : = 0
|
||||
## var mod_mesh = ArrayMesh.new()
|
||||
## var mrect: Rect2
|
||||
## for k in maps.keys():
|
||||
## if maps[k].value > 0.0001:
|
||||
## if mrect:
|
||||
## mrect = mrect.merge(maps[k].rect)
|
||||
## else:
|
||||
## mrect = maps[k].rect
|
||||
## for surface in range(orig_mesh.get_surface_count()):
|
||||
## var arrays: Array = orig_mesh.surface_get_arrays(surface)
|
||||
## var uv_index: int = ArrayMesh.ARRAY_TEX_UV
|
||||
## if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0:
|
||||
## uv_index = ArrayMesh.ARRAY_TEX_UV2
|
||||
## for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
|
||||
## var v: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][index]
|
||||
## var n: Vector3 = arrays[ArrayMesh.ARRAY_NORMAL][index]
|
||||
## var uv: Vector2 = arrays[uv_index][index]
|
||||
## if !mrect.has_point(uv):
|
||||
## continue
|
||||
## var diff : = Vector3()
|
||||
## var diffn : = Vector3()
|
||||
## for k in maps.keys():
|
||||
## if !maps[k].rect.has_point(uv) || abs(maps[k].value) < 0.0001:
|
||||
## continue
|
||||
## var pos: Vector2 = Vector2(uv.x * maps[k].width, uv.y * maps[k].height)
|
||||
## var offset: Color = maps[k].image.get_pixelv(pos)
|
||||
## var offsetn: Color = maps[k].image_normal.get_pixelv(pos)
|
||||
## var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b)
|
||||
## var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b)
|
||||
## for u in range(2):
|
||||
## diff[u] = range_lerp(pdiff[u], 0.0, 1.0, min_point[u], max_point[u]) * maps[k].value
|
||||
## diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, min_normal[u], max_normal[u]) * maps[k].value
|
||||
## if abs(diff[u]) < 0.0001:
|
||||
## diff[u] = 0
|
||||
## v -= diff
|
||||
## n -= diffn
|
||||
## arrays[ArrayMesh.ARRAY_VERTEX][index] = v
|
||||
## arrays[ArrayMesh.ARRAY_NORMAL][index] = n.normalized()
|
||||
## for v in v_indices.keys():
|
||||
## if v_indices[v].size() <= 1:
|
||||
## continue
|
||||
## var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][0]]
|
||||
## for idx in range(1, v_indices[v].size()):
|
||||
## vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][v_indices[v][idx]], 0.5)
|
||||
## for idx in v_indices[v]:
|
||||
## arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx
|
||||
##
|
||||
## mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
## if orig_mesh.surface_get_material(surface):
|
||||
## mod_mesh.surface_set_material(surface, orig_mesh.surface_get_material(surface).duplicate(true))
|
||||
## surf += 1
|
||||
## for k in maps.keys():
|
||||
## maps[k].image.unlock()
|
||||
## maps[k].image_normal.unlock()
|
||||
## mi.mesh = mod_mesh
|
||||
## if should_show:
|
||||
## mi.show()
|
||||
func update_slider(value: float, control: String, slider: HSlider):
|
||||
var modifier = ""
|
||||
if value >= 0:
|
||||
modifier = controls[control].plus
|
||||
if controls[control].has("minus"):
|
||||
dna.set_modifier_value(controls[control].minus, 0.0)
|
||||
else:
|
||||
value = -value
|
||||
modifier = controls[control].minus
|
||||
if controls[control].has("plus"):
|
||||
dna.set_modifier_value(controls[control].plus, 0.0)
|
||||
update_modifier(value, modifier)
|
||||
var ch: Node
|
||||
func rebuild_clothes_menu():
|
||||
# cloth_orig_meshes.clear()
|
||||
for c in $s/VBoxContainer/clothes.get_children():
|
||||
$s/VBoxContainer/clothes.remove_child(c)
|
||||
c.queue_free()
|
||||
$s/VBoxContainer/clothes.add_child(HSeparator.new())
|
||||
var clothes_label = Label.new()
|
||||
clothes_label.text = "Clothes"
|
||||
$s/VBoxContainer/clothes.add_child(clothes_label)
|
||||
for cloth in clothes.keys():
|
||||
var cloth_mi : = find_mesh(ch, cloth)
|
||||
if !cloth_mi:
|
||||
continue
|
||||
var cloth_button = Button.new()
|
||||
cloth_button.text = cloth_mi.name
|
||||
$s/VBoxContainer/clothes.add_child(cloth_button)
|
||||
cloth_button.connect("pressed", self, "toggle_clothes", [cloth_mi, cloth])
|
||||
func prepare_character(x: int) -> void:
|
||||
if ch != null:
|
||||
remove_child(ch)
|
||||
ch.queue_free()
|
||||
ch = characters[x].instance()
|
||||
add_child(ch)
|
||||
ch.rotation.y = PI
|
||||
rebuild_clothes_menu()
|
||||
body_mi = find_mesh(ch, "body")
|
||||
# body_mesh = body_mi.mesh.duplicate(true)
|
||||
# orig_body_mesh = body_mi.mesh.duplicate(true)
|
||||
_vert_indices = get_mi(ch, "body").get_meta("same_verts")
|
||||
var time = OS.get_unix_time()
|
||||
dna.add_body_mesh(body_mi.mesh, _vert_indices)
|
||||
var elapsed1 = OS.get_unix_time() - time
|
||||
# cloth_meshes.clear()
|
||||
cloth_mis.clear()
|
||||
print("body time: ", elapsed1)
|
||||
for cloth in clothes.keys():
|
||||
var cloth_mi : = find_mesh(ch, cloth)
|
||||
if !cloth_mi:
|
||||
continue
|
||||
time = OS.get_unix_time()
|
||||
dna.add_cloth_mesh(cloth, clothes[cloth].helper, cloth_mi.mesh)
|
||||
var elapsed2 = OS.get_unix_time() - time
|
||||
print("cloth time: ", elapsed2)
|
||||
cloth_mis[cloth] = cloth_mi
|
||||
# prepare_cloth(body_mi, cloth_mi)
|
||||
# cloth_meshes.push_back(cloth_mi.mesh)
|
||||
func button_female():
|
||||
prepare_character(0)
|
||||
func button_male():
|
||||
prepare_character(1)
|
||||
modifier = controls[control]
|
||||
characters.set_modifier_value(ch, modifier, value / 100.0)
|
||||
characters.call_deferred("update")
|
||||
# if controls[control].has("minus"):
|
||||
# dna.set_modifier_value(controls[control].minus, 0.0)
|
||||
# else:
|
||||
# value = -value
|
||||
# modifier = controls[control].minus
|
||||
# if controls[control].has("plus"):
|
||||
# dna.set_modifier_value(controls[control].plus, 0.0)
|
||||
# update_modifier(value, modifier)
|
||||
#var ch: Node
|
||||
#func rebuild_clothes_menu():
|
||||
## cloth_orig_meshes.clear()
|
||||
# for c in $s/VBoxContainer/clothes.get_children():
|
||||
# $s/VBoxContainer/clothes.remove_child(c)
|
||||
# c.queue_free()
|
||||
# $s/VBoxContainer/clothes.add_child(HSeparator.new())
|
||||
# var clothes_label = Label.new()
|
||||
# clothes_label.text = "Clothes"
|
||||
# $s/VBoxContainer/clothes.add_child(clothes_label)
|
||||
# for cloth in clothes.keys():
|
||||
# var cloth_mi : = find_mesh(ch, cloth)
|
||||
# if !cloth_mi:
|
||||
# continue
|
||||
# var cloth_button = Button.new()
|
||||
# cloth_button.text = cloth_mi.name
|
||||
# $s/VBoxContainer/clothes.add_child(cloth_button)
|
||||
# cloth_button.connect("pressed", self, "toggle_clothes", [cloth_mi, cloth])
|
||||
#func prepare_character(x: int) -> void:
|
||||
# if ch != null:
|
||||
# remove_child(ch)
|
||||
# ch.queue_free()
|
||||
# ch = characters[x].instance()
|
||||
# add_child(ch)
|
||||
# ch.rotation.y = PI
|
||||
# rebuild_clothes_menu()
|
||||
# body_mi = find_mesh(ch, "body")
|
||||
## body_mesh = body_mi.mesh.duplicate(true)
|
||||
## orig_body_mesh = body_mi.mesh.duplicate(true)
|
||||
# _vert_indices = get_mi(ch, "body").get_meta("same_verts")
|
||||
# var time = OS.get_unix_time()
|
||||
# dna.add_body_mesh(body_mi.mesh, _vert_indices)
|
||||
# var elapsed1 = OS.get_unix_time() - time
|
||||
## cloth_meshes.clear()
|
||||
# cloth_mis.clear()
|
||||
# print("body time: ", elapsed1)
|
||||
# for cloth in clothes.keys():
|
||||
# var cloth_mi : = find_mesh(ch, cloth)
|
||||
# if !cloth_mi:
|
||||
# continue
|
||||
# time = OS.get_unix_time()
|
||||
# dna.add_cloth_mesh(cloth, clothes[cloth].helper, cloth_mi.mesh)
|
||||
# var elapsed2 = OS.get_unix_time() - time
|
||||
# print("cloth time: ", elapsed2)
|
||||
# cloth_mis[cloth] = cloth_mi
|
||||
## prepare_cloth(body_mi, cloth_mi)
|
||||
## cloth_meshes.push_back(cloth_mi.mesh)
|
||||
#func button_female():
|
||||
# prepare_character(0)
|
||||
#func button_male():
|
||||
# prepare_character(1)
|
||||
var ch
|
||||
var mod_name_list
|
||||
func init_tail():
|
||||
ch = characters.spawn_character(0, Transform().rotated(Vector3(0, 1, 0), PI))
|
||||
mod_name_list = characters.get_modifier_list(ch)
|
||||
func _ready():
|
||||
dna = DNA.new("res://characters/common/config.bin")
|
||||
# var fd = File.new()
|
||||
# fd.open("res://characters/common/config.bin", File.READ)
|
||||
# min_point = fd.get_var()
|
||||
# max_point = fd.get_var()
|
||||
# min_normal = fd.get_var()
|
||||
# max_normal = fd.get_var()
|
||||
# maps = fd.get_var()
|
||||
# print(maps.keys())
|
||||
# vert_indices = fd.get_var()
|
||||
# fd.close()
|
||||
# print("min: ", min_point, " max: ", max_point)
|
||||
# for k in maps.keys():
|
||||
# print(k, ": ", maps[k].rect)
|
||||
|
||||
call_deferred("init_tail")
|
||||
# dna = DNA.new("res://characters/common/config.bin")
|
||||
## var fd = File.new()
|
||||
## fd.open("res://characters/common/config.bin", File.READ)
|
||||
## min_point = fd.get_var()
|
||||
## max_point = fd.get_var()
|
||||
## min_normal = fd.get_var()
|
||||
## max_normal = fd.get_var()
|
||||
## maps = fd.get_var()
|
||||
## print(maps.keys())
|
||||
## vert_indices = fd.get_var()
|
||||
## fd.close()
|
||||
## print("min: ", min_point, " max: ", max_point)
|
||||
## for k in maps.keys():
|
||||
## print(k, ": ", maps[k].rect)
|
||||
#
|
||||
var state : = 0
|
||||
func build_contols():
|
||||
for k in dna.get_modifier_list():
|
||||
if k.ends_with("_plus") && false:
|
||||
var cname = k.replace("_plus", "")
|
||||
if !controls.has(cname):
|
||||
controls[cname] = {}
|
||||
controls[cname].plus = k
|
||||
elif k.ends_with("_minus") && false:
|
||||
var cname = k.replace("_minus", "")
|
||||
if !controls.has(cname):
|
||||
controls[cname] = {}
|
||||
controls[cname].minus = k
|
||||
else:
|
||||
var cname = k
|
||||
controls[cname] = {}
|
||||
controls[cname].plus = k
|
||||
for k in mod_name_list:
|
||||
controls[k] = k
|
||||
# for k in dna.get_modifier_list():
|
||||
# if k.ends_with("_plus") && false:
|
||||
# var cname = k.replace("_plus", "")
|
||||
# if !controls.has(cname):
|
||||
# controls[cname] = {}
|
||||
# controls[cname].plus = k
|
||||
# elif k.ends_with("_minus") && false:
|
||||
# var cname = k.replace("_minus", "")
|
||||
# if !controls.has(cname):
|
||||
# controls[cname] = {}
|
||||
# controls[cname].minus = k
|
||||
# else:
|
||||
# var cname = k
|
||||
# controls[cname] = {}
|
||||
# controls[cname].plus = k
|
||||
for k in controls.keys():
|
||||
var ok = true
|
||||
for m in helper_names:
|
||||
if k.begins_with(m + "_"):
|
||||
ok = false
|
||||
break
|
||||
if !ok:
|
||||
continue
|
||||
# for m in helper_names:
|
||||
# if k.begins_with(m + "_"):
|
||||
# ok = false
|
||||
# break
|
||||
# if !ok:
|
||||
# continue
|
||||
var l = Label.new()
|
||||
l.text = k
|
||||
$s/VBoxContainer.add_child(l)
|
||||
var slider : = HSlider.new()
|
||||
slider.rect_min_size = Vector2(180, 30)
|
||||
print(controls[k])
|
||||
|
||||
if controls[k].has("minus") && controls[k].has("plus"):
|
||||
slider.min_value = -100
|
||||
slider.max_value = 100
|
||||
else:
|
||||
slider.min_value = 0
|
||||
slider.max_value = 100
|
||||
slider.min_value = -100
|
||||
slider.max_value = 100
|
||||
$s/VBoxContainer.add_child(slider)
|
||||
slider.connect("value_changed", self, "update_slider", [k, slider])
|
||||
slider.focus_mode = Control.FOCUS_CLICK
|
||||
# print(controls[k])
|
||||
#
|
||||
# if controls[k].has("minus") && controls[k].has("plus"):
|
||||
# slider.min_value = -100
|
||||
# slider.max_value = 100
|
||||
# else:
|
||||
# slider.min_value = 0
|
||||
# slider.max_value = 100
|
||||
# $s/VBoxContainer.add_child(slider)
|
||||
# slider.connect("value_changed", self, "update_slider", [k, slider])
|
||||
# slider.focus_mode = Control.FOCUS_CLICK
|
||||
if !world.next_scene:
|
||||
$s/VBoxContainer/ok.hide()
|
||||
else:
|
||||
@@ -291,11 +305,12 @@ func next_scene():
|
||||
func _process(delta):
|
||||
match(state):
|
||||
0:
|
||||
# find_same_verts()
|
||||
prepare_character(1)
|
||||
## find_same_verts()
|
||||
# prepare_character(1)
|
||||
state = 1
|
||||
1:
|
||||
# $Panel.hide()
|
||||
assert(body_mi.mesh)
|
||||
## $Panel.hide()
|
||||
# assert(body_mi.mesh)
|
||||
assert(ch)
|
||||
build_contols()
|
||||
state = 2
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://characters/customization/customize_player.gd" type="Script" id=1]
|
||||
[ext_resource path="res://characters/customization/cam.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="PlaneMesh" id=1]
|
||||
|
||||
[sub_resource type="BoxShape" id=2]
|
||||
extents = Vector3( 1, 0.1, 1 )
|
||||
|
||||
[node name="customize_player" type="Spatial"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
@@ -65,3 +68,9 @@ margin_right = 31.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
text = "OK"
|
||||
|
||||
[node name="StaticBody" type="StaticBody" parent="."]
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
|
||||
shape = SubResource( 2 )
|
||||
|
||||
@@ -176,156 +176,156 @@ func add_body_mesh(mesh: ArrayMesh, same_indices: Dictionary) -> Array:
|
||||
# maps[k].image.unlock()
|
||||
# maps[k].image_normal.unlock()
|
||||
# return mod_mesh
|
||||
func modify_part(part_name) -> ArrayMesh:
|
||||
# var mesh = meshes[part_name].orig_mesh
|
||||
# var indices = meshes[part_name].same_indices
|
||||
# return modify_mesh(mesh, indices)
|
||||
return _mod_part(part_name)
|
||||
func set_modifier_value(modifier: String, value: float):
|
||||
maps[modifier].value = value
|
||||
func get_mesh_modifier(m_name: String, arrays: Array) -> Array:
|
||||
maps[m_name].image.lock()
|
||||
maps[m_name].image_normal.lock()
|
||||
var indices = PoolIntArray()
|
||||
var mod_vertex = PoolVector3Array()
|
||||
var mod_normal = PoolVector3Array()
|
||||
var uv_index: int = ArrayMesh.ARRAY_TEX_UV
|
||||
if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0:
|
||||
uv_index = ArrayMesh.ARRAY_TEX_UV2
|
||||
var mrect: Rect2 = maps[m_name].rect
|
||||
var count = 0
|
||||
var max_count = arrays[ArrayMesh.ARRAY_VERTEX].size()
|
||||
var width: int = maps[m_name].width
|
||||
var height: int = maps[m_name].height
|
||||
indices.resize(max_count)
|
||||
mod_vertex.resize(max_count)
|
||||
mod_normal.resize(max_count)
|
||||
if uv_index != ArrayMesh.ARRAY_TEX_UV2:
|
||||
print("not on uv2")
|
||||
for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
|
||||
var uv: Vector2 = arrays[uv_index][index]
|
||||
if !mrect.has_point(uv):
|
||||
continue
|
||||
var diff: = Vector3()
|
||||
var diffn: = Vector3()
|
||||
var pos: Vector2 = Vector2(uv.x * width, uv.y * height)
|
||||
var offset: Color = maps[m_name].image.get_pixelv(pos)
|
||||
var offsetn: Color = maps[m_name].image_normal.get_pixelv(pos)
|
||||
var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b)
|
||||
var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b)
|
||||
for u in range(3):
|
||||
diff[u] = range_lerp(pdiff[u], 0.0, 1.0, maps[m_name].min_point[u], maps[m_name].min_point[u] + maps[m_name].point_scaler[u])
|
||||
diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, maps[m_name].min_normal[u], maps[m_name].min_normal[u] + maps[m_name].normal_scaler[u])
|
||||
if abs(diff[u]) < 0.0001:
|
||||
diff[u] = 0
|
||||
if diff.length() > 0.001:
|
||||
indices[count] = index
|
||||
mod_vertex[count] = diff
|
||||
mod_normal[count] = diffn
|
||||
count += 1
|
||||
indices.resize(count)
|
||||
mod_vertex.resize(count)
|
||||
mod_normal.resize(count)
|
||||
maps[m_name].image.unlock()
|
||||
maps[m_name].image_normal.unlock()
|
||||
return [indices, mod_vertex, mod_normal]
|
||||
func apply_modifier(mod: Array, arrays: Array, value: float, offset = 0.0):
|
||||
var value_: float = clamp(value, 0.0, 1.0)
|
||||
var indices: PoolIntArray = mod[0]
|
||||
var mod_vertex: PoolVector3Array = mod[1]
|
||||
var mod_normal: PoolVector3Array = mod[2]
|
||||
for count in range(indices.size()):
|
||||
var index: int = indices[count]
|
||||
var diff: Vector3 = mod_vertex[count]
|
||||
var diffn: Vector3 = mod_normal[count]
|
||||
var n = (arrays[ArrayMesh.ARRAY_NORMAL][index] - diffn).normalized() * offset
|
||||
arrays[ArrayMesh.ARRAY_VERTEX][index] -= diff * value_ - n
|
||||
# do not normalize now
|
||||
arrays[ArrayMesh.ARRAY_NORMAL][index] -= diffn * value_
|
||||
func _mod_part(part_name: String) -> ArrayMesh:
|
||||
print("modifying ", part_name)
|
||||
print("helper:", meshes[part_name].helper)
|
||||
var start_time = OS.get_unix_time()
|
||||
# var mesh: ArrayMesh = meshes[part_name].orig_mesh
|
||||
var mod_mesh: = ArrayMesh.new()
|
||||
var indices: Dictionary = meshes[part_name].same_indices
|
||||
var surface: int = 0
|
||||
if meshes[part_name].has("surface"):
|
||||
surface = meshes[part_name].surface
|
||||
# var arrays: Array = mesh.surface_get_arrays(surface)
|
||||
var arrays: Array = meshes[part_name].orig_arrays.duplicate()
|
||||
if part_name == "body":
|
||||
for mod in meshes[part_name].modifiers.keys():
|
||||
var mod_data = meshes[part_name].modifiers[mod]
|
||||
apply_modifier(mod_data, arrays, maps[mod].value)
|
||||
else:
|
||||
for mod in meshes[part_name].modifiers.keys():
|
||||
var mod_data = meshes[part_name].modifiers[mod]
|
||||
apply_modifier(mod_data, arrays, maps[mod].value, 0.0002)
|
||||
for v in indices.keys():
|
||||
if indices[v].size() <= 1:
|
||||
continue
|
||||
var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][indices[v][0]]
|
||||
for idx in range(1, indices[v].size()):
|
||||
vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][indices[v][idx]], 0.5)
|
||||
for idx in indices[v]:
|
||||
arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx
|
||||
mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
if meshes[part_name].material:
|
||||
mod_mesh.surface_set_material(surface, meshes[part_name].material.duplicate(true))
|
||||
# if mesh.surface_get_material(surface):
|
||||
# mod_mesh.surface_set_material(surface, mesh.surface_get_material(surface).duplicate(true))
|
||||
var elapsed = OS.get_unix_time() - start_time
|
||||
print("modified ", part_name, " ", elapsed)
|
||||
return mod_mesh
|
||||
#func modify_part(part_name) -> ArrayMesh:
|
||||
## var mesh = meshes[part_name].orig_mesh
|
||||
## var indices = meshes[part_name].same_indices
|
||||
## return modify_mesh(mesh, indices)
|
||||
# return _mod_part(part_name)
|
||||
#func set_modifier_value(modifier: String, value: float):
|
||||
# maps[modifier].value = value
|
||||
#func get_mesh_modifier(m_name: String, arrays: Array) -> Array:
|
||||
# maps[m_name].image.lock()
|
||||
# maps[m_name].image_normal.lock()
|
||||
# var indices = PoolIntArray()
|
||||
# var mod_vertex = PoolVector3Array()
|
||||
# var mod_normal = PoolVector3Array()
|
||||
# var uv_index: int = ArrayMesh.ARRAY_TEX_UV
|
||||
# if arrays[ArrayMesh.ARRAY_TEX_UV2] && arrays[ArrayMesh.ARRAY_TEX_UV2].size() > 0:
|
||||
# uv_index = ArrayMesh.ARRAY_TEX_UV2
|
||||
# var mrect: Rect2 = maps[m_name].rect
|
||||
# var count = 0
|
||||
# var max_count = arrays[ArrayMesh.ARRAY_VERTEX].size()
|
||||
# var width: int = maps[m_name].width
|
||||
# var height: int = maps[m_name].height
|
||||
# indices.resize(max_count)
|
||||
# mod_vertex.resize(max_count)
|
||||
# mod_normal.resize(max_count)
|
||||
# if uv_index != ArrayMesh.ARRAY_TEX_UV2:
|
||||
# print("not on uv2")
|
||||
# for index in range(arrays[ArrayMesh.ARRAY_VERTEX].size()):
|
||||
# var uv: Vector2 = arrays[uv_index][index]
|
||||
# if !mrect.has_point(uv):
|
||||
# continue
|
||||
# var diff: = Vector3()
|
||||
# var diffn: = Vector3()
|
||||
# var pos: Vector2 = Vector2(uv.x * width, uv.y * height)
|
||||
# var offset: Color = maps[m_name].image.get_pixelv(pos)
|
||||
# var offsetn: Color = maps[m_name].image_normal.get_pixelv(pos)
|
||||
# var pdiff: Vector3 = Vector3(offset.r, offset.g, offset.b)
|
||||
# var ndiff: Vector3 = Vector3(offsetn.r, offsetn.g, offsetn.b)
|
||||
# for u in range(3):
|
||||
# diff[u] = range_lerp(pdiff[u], 0.0, 1.0, maps[m_name].min_point[u], maps[m_name].min_point[u] + maps[m_name].point_scaler[u])
|
||||
# diffn[u] = range_lerp(ndiff[u], 0.0, 1.0, maps[m_name].min_normal[u], maps[m_name].min_normal[u] + maps[m_name].normal_scaler[u])
|
||||
# if abs(diff[u]) < 0.0001:
|
||||
# diff[u] = 0
|
||||
# if diff.length() > 0.001:
|
||||
# indices[count] = index
|
||||
# mod_vertex[count] = diff
|
||||
# mod_normal[count] = diffn
|
||||
# count += 1
|
||||
# indices.resize(count)
|
||||
# mod_vertex.resize(count)
|
||||
# mod_normal.resize(count)
|
||||
# maps[m_name].image.unlock()
|
||||
# maps[m_name].image_normal.unlock()
|
||||
# return [indices, mod_vertex, mod_normal]
|
||||
#func apply_modifier(mod: Array, arrays: Array, value: float, offset = 0.0):
|
||||
# var value_: float = clamp(value, 0.0, 1.0)
|
||||
# var indices: PoolIntArray = mod[0]
|
||||
# var mod_vertex: PoolVector3Array = mod[1]
|
||||
# var mod_normal: PoolVector3Array = mod[2]
|
||||
# for count in range(indices.size()):
|
||||
# var index: int = indices[count]
|
||||
# var diff: Vector3 = mod_vertex[count]
|
||||
# var diffn: Vector3 = mod_normal[count]
|
||||
# var n = (arrays[ArrayMesh.ARRAY_NORMAL][index] - diffn).normalized() * offset
|
||||
# arrays[ArrayMesh.ARRAY_VERTEX][index] -= diff * value_ - n
|
||||
# # do not normalize now
|
||||
# arrays[ArrayMesh.ARRAY_NORMAL][index] -= diffn * value_
|
||||
#func _mod_part(part_name: String) -> ArrayMesh:
|
||||
# print("modifying ", part_name)
|
||||
# print("helper:", meshes[part_name].helper)
|
||||
# var start_time = OS.get_unix_time()
|
||||
## var mesh: ArrayMesh = meshes[part_name].orig_mesh
|
||||
# var mod_mesh: = ArrayMesh.new()
|
||||
# var indices: Dictionary = meshes[part_name].same_indices
|
||||
# var surface: int = 0
|
||||
# if meshes[part_name].has("surface"):
|
||||
# surface = meshes[part_name].surface
|
||||
## var arrays: Array = mesh.surface_get_arrays(surface)
|
||||
# var arrays: Array = meshes[part_name].orig_arrays.duplicate()
|
||||
# if part_name == "body":
|
||||
# for mod in meshes[part_name].modifiers.keys():
|
||||
# var mod_data = meshes[part_name].modifiers[mod]
|
||||
# apply_modifier(mod_data, arrays, maps[mod].value)
|
||||
# else:
|
||||
# for mod in meshes[part_name].modifiers.keys():
|
||||
# var mod_data = meshes[part_name].modifiers[mod]
|
||||
# apply_modifier(mod_data, arrays, maps[mod].value, 0.0002)
|
||||
# for v in indices.keys():
|
||||
# if indices[v].size() <= 1:
|
||||
# continue
|
||||
# var vx: Vector3 = arrays[ArrayMesh.ARRAY_VERTEX][indices[v][0]]
|
||||
# for idx in range(1, indices[v].size()):
|
||||
# vx = vx.linear_interpolate(arrays[ArrayMesh.ARRAY_VERTEX][indices[v][idx]], 0.5)
|
||||
# for idx in indices[v]:
|
||||
# arrays[ArrayMesh.ARRAY_VERTEX][idx] = vx
|
||||
# mod_mesh.add_surface_from_arrays(ArrayMesh.PRIMITIVE_TRIANGLES, arrays)
|
||||
# if meshes[part_name].material:
|
||||
# mod_mesh.surface_set_material(surface, meshes[part_name].material.duplicate(true))
|
||||
## if mesh.surface_get_material(surface):
|
||||
## mod_mesh.surface_set_material(surface, mesh.surface_get_material(surface).duplicate(true))
|
||||
# var elapsed = OS.get_unix_time() - start_time
|
||||
# print("modified ", part_name, " ", elapsed)
|
||||
# return mod_mesh
|
||||
|
||||
func load_maps(path: String):
|
||||
maps = {}
|
||||
var fd: File = File.new()
|
||||
fd.open(path, File.READ)
|
||||
if !fd.is_open():
|
||||
print("Could not open " + path)
|
||||
print(fd.get_len())
|
||||
var count = fd.get_var()
|
||||
print(count)
|
||||
for c in range(count):
|
||||
var map_name = fd.get_var()
|
||||
map_name = map_name.replace("base:", "")
|
||||
var rect = fd.get_var()
|
||||
var map_min_point = fd.get_var()
|
||||
var point_scaler = fd.get_var()
|
||||
var map_min_normal = fd.get_var()
|
||||
var normal_scaler = fd.get_var()
|
||||
var map_width = fd.get_var()
|
||||
var map_height = fd.get_var()
|
||||
var data_size = fd.get_var()
|
||||
var data = fd.get_var()
|
||||
var map_normal_width = fd.get_var()
|
||||
var map_normal_height = fd.get_var()
|
||||
var normal_data_size = fd.get_var()
|
||||
var normal_data = fd.get_var()
|
||||
maps[map_name] = {}
|
||||
maps[map_name].rect = rect
|
||||
maps[map_name].min_point = map_min_point
|
||||
maps[map_name].point_scaler = point_scaler
|
||||
maps[map_name].min_normal = map_min_normal
|
||||
maps[map_name].normal_scaler = normal_scaler
|
||||
maps[map_name].width = map_width
|
||||
maps[map_name].height = map_height
|
||||
maps[map_name].normal_width = map_normal_width
|
||||
maps[map_name].normal_height = map_normal_height
|
||||
data = data.decompress(data_size, File.COMPRESSION_DEFLATE)
|
||||
maps[map_name].image = Image.new()
|
||||
maps[map_name].image.create_from_data(maps[map_name].width, maps[map_name].height, false, Image.FORMAT_RGB8, data)
|
||||
normal_data = normal_data.decompress(normal_data_size, File.COMPRESSION_DEFLATE)
|
||||
maps[map_name].image_normal = Image.new()
|
||||
maps[map_name].image_normal.create_from_data(maps[map_name].normal_width, maps[map_name].normal_height, false, Image.FORMAT_RGB8, normal_data)
|
||||
print(map_name, " ", map_width, " ", map_height, " ", data_size, " ", data.size(), " ", map_normal_width, " ", map_normal_height, " ", normal_data_size, " ", normal_data.size())
|
||||
maps[map_name].value = 0.0
|
||||
fd.close()
|
||||
#func load_maps(path: String):
|
||||
# maps = {}
|
||||
# var fd: File = File.new()
|
||||
# fd.open(path, File.READ)
|
||||
# if !fd.is_open():
|
||||
# print("Could not open " + path)
|
||||
# print(fd.get_len())
|
||||
# var count = fd.get_var()
|
||||
# print(count)
|
||||
# for c in range(count):
|
||||
# var map_name = fd.get_var()
|
||||
# map_name = map_name.replace("base:", "")
|
||||
# var rect = fd.get_var()
|
||||
# var map_min_point = fd.get_var()
|
||||
# var point_scaler = fd.get_var()
|
||||
# var map_min_normal = fd.get_var()
|
||||
# var normal_scaler = fd.get_var()
|
||||
# var map_width = fd.get_var()
|
||||
# var map_height = fd.get_var()
|
||||
# var data_size = fd.get_var()
|
||||
# var data = fd.get_var()
|
||||
# var map_normal_width = fd.get_var()
|
||||
# var map_normal_height = fd.get_var()
|
||||
# var normal_data_size = fd.get_var()
|
||||
# var normal_data = fd.get_var()
|
||||
# maps[map_name] = {}
|
||||
# maps[map_name].rect = rect
|
||||
# maps[map_name].min_point = map_min_point
|
||||
# maps[map_name].point_scaler = point_scaler
|
||||
# maps[map_name].min_normal = map_min_normal
|
||||
# maps[map_name].normal_scaler = normal_scaler
|
||||
# maps[map_name].width = map_width
|
||||
# maps[map_name].height = map_height
|
||||
# maps[map_name].normal_width = map_normal_width
|
||||
# maps[map_name].normal_height = map_normal_height
|
||||
# data = data.decompress(data_size, File.COMPRESSION_DEFLATE)
|
||||
# maps[map_name].image = Image.new()
|
||||
# maps[map_name].image.create_from_data(maps[map_name].width, maps[map_name].height, false, Image.FORMAT_RGB8, data)
|
||||
# normal_data = normal_data.decompress(normal_data_size, File.COMPRESSION_DEFLATE)
|
||||
# maps[map_name].image_normal = Image.new()
|
||||
# maps[map_name].image_normal.create_from_data(maps[map_name].normal_width, maps[map_name].normal_height, false, Image.FORMAT_RGB8, normal_data)
|
||||
# print(map_name, " ", map_width, " ", map_height, " ", data_size, " ", data.size(), " ", map_normal_width, " ", map_normal_height, " ", normal_data_size, " ", normal_data.size())
|
||||
# maps[map_name].value = 0.0
|
||||
# fd.close()
|
||||
|
||||
func _init(path: String):
|
||||
load_maps("res://characters/blendmaps.bin")
|
||||
#func _init(path: String):
|
||||
# load_maps("res://characters/blendmaps.bin")
|
||||
# var fd = File.new()
|
||||
# fd.open(path, File.READ)
|
||||
# min_point = fd.get_var()
|
||||
|
||||
@@ -81,8 +81,8 @@ script = ExtResource( 1 )
|
||||
[node name="female_2018" parent="female_2018" index="0"]
|
||||
bones/132/bound_children = [ NodePath("item_carry") ]
|
||||
|
||||
[node name="item_carry" type="BoneAttachment" parent="female_2018/female_2018" index="13"]
|
||||
transform = Transform( 0.816538, -0.555132, -0.158408, 0.505615, 0.555284, 0.660309, -0.278598, -0.619263, 0.734095, 0.174373, 0.783361, -0.0350451 )
|
||||
[node name="item_carry" type="BoneAttachment" parent="female_2018/female_2018" index="1"]
|
||||
transform = Transform( 0.816539, -0.555132, -0.158407, 0.505615, 0.555285, 0.660311, -0.2786, -0.619263, 0.734095, 0.174373, 0.783361, -0.035045 )
|
||||
bone_name = "wrist_R"
|
||||
|
||||
[node name="ball_carry" type="Spatial" parent="female_2018/female_2018/item_carry"]
|
||||
|
||||
@@ -77,8 +77,8 @@ script = ExtResource( 2 )
|
||||
[node name="male_g_2018" parent="male_2018" index="0"]
|
||||
bones/110/bound_children = [ NodePath("item_carry") ]
|
||||
|
||||
[node name="item_carry" type="BoneAttachment" parent="male_2018/male_g_2018" index="9"]
|
||||
transform = Transform( 0.579234, -0.742538, -0.336341, 0.736249, 0.299448, 0.606851, -0.349893, -0.59914, 0.720144, 0.334017, 1.00794, -0.175007 )
|
||||
[node name="item_carry" type="BoneAttachment" parent="male_2018/male_g_2018" index="1"]
|
||||
transform = Transform( 0.57822, -0.742842, -0.337411, 0.736408, 0.297145, 0.607789, -0.351231, -0.599909, 0.71885, 0.334138, 1.00818, -0.174576 )
|
||||
bone_name = "wrist_R"
|
||||
|
||||
[node name="ball_carry" type="Spatial" parent="male_2018/male_g_2018/item_carry"]
|
||||
|
||||
Reference in New Issue
Block a user