You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
15 KiB
GDScript
342 lines
15 KiB
GDScript
@tool
|
|
extends Node3D
|
|
|
|
func get_resource_name(resource: Resource) -> String: return resource.resource_path.get_file().trim_suffix('.tres') #todo 性能
|
|
|
|
|
|
func snap_vector3(value: Vector3) -> Vector3: return Vector3(snap_float(value.x), snap_float(value.y), snap_float(value.z))
|
|
|
|
|
|
func snap_float(value: float) -> float: return floor(value/Setting.pixel_size) * Setting.pixel_size
|
|
|
|
|
|
func dir_angle(dir: Vector2) -> float:
|
|
dir.x = abs(dir.x)
|
|
return dir.angle_to(Vector2.RIGHT)
|
|
|
|
|
|
func angle_dir(angle: float) -> Vector2:
|
|
return Vector2.RIGHT.rotated(angle)
|
|
|
|
|
|
func vector_reduce(vector: Vector2, reduce: float) -> Vector2:
|
|
var length: float = vector.length()
|
|
if length == 0:
|
|
return vector
|
|
var new_len = max(length - reduce, 0)
|
|
var scale_rate = new_len / length
|
|
return vector * scale_rate
|
|
|
|
|
|
func get_level_grid_pos(pos: Vector3) -> Vector3i:
|
|
var grid_size: float = Setting.pixel_size* Setting.grid_pixel_size
|
|
var ret: Vector3i = Vector3i(get_div_scale(pos.x, grid_size), get_div_scale(pos.y, grid_size), get_div_scale(pos.z, grid_size))
|
|
return ret
|
|
|
|
|
|
func get_level_float_pos(pos: Vector3i) -> Vector3:
|
|
var grid_size: float = Setting.pixel_size* Setting.grid_pixel_size
|
|
return Vector3(pos.x*grid_size, pos.y*grid_size, pos.z*grid_size)
|
|
|
|
|
|
func get_level_id(pos: Vector3) -> Vector3i:
|
|
var ret: Vector3i = Vector3i(get_div_scale(pos.x, Setting.size_basic.x), get_div_scale(pos.y, Setting.size_basic.y), get_div_scale(pos.z, Setting.size_basic.z))
|
|
return ret
|
|
|
|
|
|
func get_div_scale(a: float, b: float) -> int:
|
|
#解决浮点数精度问题
|
|
var div: float = a / b
|
|
var is_positive: bool = div > 0
|
|
var decimal: float = abs(div - int(div))
|
|
if is_positive and decimal > 0.999:
|
|
div += 0.001
|
|
if not is_positive and decimal < 0.001:
|
|
div += 0.001
|
|
return floor(div)
|
|
|
|
|
|
func raycast_character(shape: Shape3D, origin: Vector3, dir: Vector2) -> Array[Character]:
|
|
var space_state: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
|
|
var query: PhysicsShapeQueryParameters3D = PhysicsShapeQueryParameters3D.new()
|
|
var angle: float = dir_angle(dir)
|
|
query.shape = shape
|
|
query.transform.origin = origin
|
|
query.transform.basis = query.transform.basis.rotated(Vector3.UP, angle)
|
|
var result: Array[Dictionary] = space_state.intersect_shape(query)
|
|
var result2: Array = result.map(func(v): return v["collider"]).filter(func(v): return v is Character)
|
|
var result3: Array[Character]
|
|
for node in result2:
|
|
result3.append(node as Character)
|
|
return result3
|
|
|
|
|
|
func clean_animation_lib():
|
|
#删除技能配置中没有的animation文件
|
|
#todo 非阻断 有空再说
|
|
pass
|
|
|
|
|
|
func refresh_animation_lib():
|
|
#刷新animation库 使其与animation文件同步
|
|
var animation_library_path: String = "res://resource/skill_animation_library/animation_library.tres"
|
|
var animation_library = load(animation_library_path)
|
|
|
|
var dir_path: String = "res://resource/skill_animation"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
for file in dir.get_files():
|
|
var path: String = dir_path + "/" + file
|
|
var res = load(path)
|
|
if res is Animation:
|
|
var animation: Animation = res as Animation
|
|
var animation_name: String = Util.get_resource_name(animation)
|
|
print("refresh_animation_lib: ", animation_name)
|
|
animation_library.add_animation(animation_name, animation)
|
|
animation_library.animation_added.emit(animation_name)
|
|
|
|
ResourceSaver.save(animation_library, animation_library_path)
|
|
|
|
|
|
func refresh_mesh_library(path_list: Array, from_editor_tool: bool = false):
|
|
print("refresh_mesh_library")
|
|
var default_shape_normal_full: Array[Variant] = [load("res://resource/mesh_library/default_shape_normal_full.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_normal_half: Array[Variant] = [load("res://resource/mesh_library/default_shape_normal_half.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_normal_stair1: Array[Variant] = [load("res://resource/mesh_library/default_shape_normal_stair1.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_normal_stair2: Array[Variant] = [load("res://resource/mesh_library/default_shape_normal_stair2.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_large_full: Array[Variant] = [load("res://resource/mesh_library/default_shape_large_full.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_large_half: Array[Variant] = [load("res://resource/mesh_library/default_shape_large_half.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_large_stair1: Array[Variant] = [load("res://resource/mesh_library/default_shape_large_stair1.tres") as Shape3D, Transform3D.IDENTITY]
|
|
var default_shape_large_stair2: Array[Variant] = [load("res://resource/mesh_library/default_shape_large_stair2.tres") as Shape3D, Transform3D.IDENTITY]
|
|
|
|
var mesh_library_main: MeshLibrary = load("res://resource/mesh_library/mesh_library_main.tres") as MeshLibrary
|
|
var mesh_library_sub: MeshLibrary = load("res://resource/mesh_library/mesh_library_sub.tres") as MeshLibrary
|
|
var mesh_library_deco1: MeshLibrary = load("res://resource/mesh_library/mesh_library_deco1.tres") as MeshLibrary
|
|
var mesh_library_deco2: MeshLibrary = load("res://resource/mesh_library/mesh_library_deco2.tres") as MeshLibrary
|
|
var mesh_library_chara: MeshLibrary = load("res://resource/mesh_library/mesh_library_chara.tres") as MeshLibrary
|
|
var mesh_library_main_id_list: Array[int] = []
|
|
var mesh_library_sub_id_list: Array[int] = []
|
|
var mesh_library_deco1_id_list: Array[int] = []
|
|
var mesh_library_deco2_id_list: Array[int] = []
|
|
var mesh_library_chara_id_list: Array[int] = []
|
|
|
|
var material_block_normal: Material = load("res://render/material/level_grid_block.tres") as Material
|
|
|
|
var reimport_files: Array[String] = []
|
|
for file_name_full in path_list:
|
|
var mesh_name = file_name_full.get_file().split('-')[0].trim_suffix('.vox')
|
|
print(file_name_full)
|
|
if not mesh_name.contains("_"):
|
|
continue
|
|
var name_prefix = mesh_name.split("_")[0]
|
|
|
|
var mesh_library: MeshLibrary
|
|
var mesh_library_id_list: Array[int]
|
|
var has_material: bool
|
|
var has_shape: bool
|
|
match name_prefix:
|
|
"main":
|
|
mesh_library = mesh_library_main; mesh_library_id_list=mesh_library_main_id_list; has_material = true; has_shape = true
|
|
"sub":
|
|
mesh_library = mesh_library_sub; mesh_library_id_list = mesh_library_sub_id_list; has_material = true; has_shape = true
|
|
"deco1":
|
|
mesh_library = mesh_library_deco1; mesh_library_id_list=mesh_library_deco1_id_list; has_material = true;
|
|
"deco2":
|
|
mesh_library = mesh_library_deco2; mesh_library_id_list=mesh_library_deco2_id_list; has_material = true;
|
|
"chara":
|
|
mesh_library = mesh_library_chara; mesh_library_id_list=mesh_library_chara_id_list
|
|
|
|
var mesh: Mesh = load(file_name_full) as Mesh
|
|
var mesh_id: int = mesh_library.find_item_by_name(mesh_name)
|
|
if mesh_id == -1:
|
|
mesh_id = mesh_library.get_last_unused_item_id()
|
|
mesh_library.create_item(mesh_id)
|
|
mesh_library_id_list.append(mesh_id)
|
|
mesh_library.set_item_name(mesh_id, mesh_name)
|
|
mesh_library.set_item_mesh(mesh_id, mesh)
|
|
|
|
if has_material:
|
|
var material: Material = mesh.surface_get_material(0) as Material
|
|
var material_set: Material = material_block_normal
|
|
if (mesh.get_surface_count() >0) and ((not material) or (material.get_path() != material_set.get_path())):
|
|
if from_editor_tool:
|
|
reimport_files.append(file_name_full)
|
|
else:
|
|
print("surface_set_material")
|
|
mesh.surface_set_material(0, material_block_normal)
|
|
ResourceSaver.save(mesh, file_name_full)
|
|
|
|
if has_shape:
|
|
var item_shapes: Array
|
|
var is_main = name_prefix == "main"
|
|
var name_subfix = mesh_name.split("_")[-1]
|
|
match name_subfix:
|
|
"full": item_shapes = default_shape_normal_full if not is_main else default_shape_large_full
|
|
"half": item_shapes = default_shape_normal_half if not is_main else default_shape_large_half
|
|
"stair1": item_shapes = default_shape_normal_stair1 if not is_main else default_shape_large_stair1
|
|
"stair2": item_shapes = default_shape_normal_stair2 if not is_main else default_shape_large_stair2
|
|
"auto": item_shapes = [mesh.create_convex_shape(), Transform3D.IDENTITY]
|
|
_: pass
|
|
if item_shapes:
|
|
mesh_library.set_item_shapes(mesh_id, item_shapes)
|
|
|
|
_save_mesh_library(mesh_library_main, mesh_library_main_id_list, from_editor_tool)
|
|
_save_mesh_library(mesh_library_sub, mesh_library_sub_id_list, from_editor_tool)
|
|
_save_mesh_library(mesh_library_deco1, mesh_library_deco1_id_list, from_editor_tool)
|
|
_save_mesh_library(mesh_library_deco2, mesh_library_deco2_id_list, from_editor_tool)
|
|
_save_mesh_library(mesh_library_chara, mesh_library_chara_id_list, from_editor_tool)
|
|
|
|
if from_editor_tool and reimport_files:
|
|
EditorInterface.get_resource_filesystem().reimport_files(reimport_files)
|
|
|
|
|
|
func _save_mesh_library(mesh_library: MeshLibrary, id_list: Array[int], from_editor_tool: bool):
|
|
if from_editor_tool:
|
|
var ids: PackedInt32Array = mesh_library.get_item_list()
|
|
for id in ids:
|
|
if not id in id_list:
|
|
mesh_library.remove_item(id)
|
|
|
|
var meshes: Array[Variant] = []
|
|
for id in id_list:
|
|
meshes.append(mesh_library.get_item_mesh(id))
|
|
var previews: Array[Texture2D] = EditorInterface.make_mesh_previews(meshes, 64)
|
|
for i in range(len(id_list)):
|
|
mesh_library.set_item_preview(id_list[i], previews[i])
|
|
ResourceSaver.save(mesh_library)
|
|
|
|
|
|
func refresh_all_animation_by_sprite_frames(sprite_frames: SpriteFrames):
|
|
var dir_path: String = "res://resource/skill_animation"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
var sprite_frames_name: String = sprite_frames.resource_path.get_file().split('-')[0]
|
|
for file in dir.get_files():
|
|
var path: String = dir_path + "/" + file
|
|
var res = load(path)
|
|
if not res is Animation:
|
|
continue
|
|
var animation: Animation = res as Animation
|
|
var sprite_frames_track: int = animation.find_track(NodePath("View:sprite_frames"), Animation.TYPE_VALUE)
|
|
if sprite_frames_track < 0:
|
|
continue
|
|
var sprite_frames_track_key_count: int = animation.track_get_key_count(sprite_frames_track)
|
|
if sprite_frames_track_key_count == 0:
|
|
continue
|
|
var sprite_frames_value: SpriteFrames = animation.track_get_key_value(sprite_frames_track, 0) as SpriteFrames
|
|
var target_sprite_frames_name: String = sprite_frames_value.resource_path.get_file().split('-')[0]
|
|
if sprite_frames_name != target_sprite_frames_name:
|
|
continue
|
|
var animation_track: int = animation.find_track(NodePath("View:animation"), Animation.TYPE_VALUE)
|
|
if animation_track < 0:
|
|
continue
|
|
var animation_track_key_count: int = animation.track_get_key_count(animation_track)
|
|
if animation_track_key_count == 0:
|
|
continue
|
|
var animation_value: String = animation.track_get_key_value(animation_track, 0) as String
|
|
refresh_animation_by_sprite_frames(path, sprite_frames, animation_value, animation)
|
|
Util.refresh_animation_lib()
|
|
|
|
|
|
func refresh_animation_by_sprite_frames(animation_path: String, sprite_frames: SpriteFrames, animation_name: String, animation: Animation) -> void:
|
|
if not sprite_frames.has_animation(animation_name):
|
|
print("动画不存在: ", animation_name)
|
|
return
|
|
var track_sprite_frames: int = animation.find_track(NodePath("View:sprite_frames"), Animation.TYPE_VALUE)
|
|
if track_sprite_frames < 0:
|
|
track_sprite_frames = animation.add_track(Animation.TYPE_VALUE)
|
|
animation.track_set_path(track_sprite_frames, "View:sprite_frames")
|
|
animation.track_insert_key(track_sprite_frames, 0, sprite_frames)
|
|
|
|
var track_animation: int = animation.find_track(NodePath("View:animation"), Animation.TYPE_VALUE)
|
|
if track_animation < 0:
|
|
track_animation = animation.add_track(Animation.TYPE_VALUE)
|
|
animation.track_set_path(track_animation, "View:animation")
|
|
animation.track_insert_key(track_animation, 0, animation_name)
|
|
|
|
var track_frame: int = animation.find_track(NodePath("View:frame"), Animation.TYPE_VALUE)
|
|
if track_frame >= 0:
|
|
animation.remove_track(track_frame)
|
|
track_frame = animation.add_track(Animation.TYPE_VALUE)
|
|
animation.track_set_path(track_frame, "View:frame")
|
|
var animation_speed: float = Setting.animation_frame_rate
|
|
var animation_frame_count: int = sprite_frames.get_frame_count(animation_name)
|
|
animation.length = animation_speed*animation_frame_count
|
|
for i in range(0, animation_frame_count):
|
|
var time = i * animation_speed
|
|
animation.track_insert_key(track_frame, time, i)
|
|
animation.value_track_set_update_mode(track_sprite_frames, Animation.UPDATE_DISCRETE)
|
|
animation.value_track_set_update_mode(track_animation, Animation.UPDATE_DISCRETE)
|
|
animation.value_track_set_update_mode(track_frame, Animation.UPDATE_DISCRETE)
|
|
print("refresh_animation: ", animation_name, "(", animation_frame_count, " frames)")
|
|
ResourceSaver.save(animation, animation_path)
|
|
|
|
|
|
func get_all_skill() -> Array[SkillCfg]:
|
|
var ret: Array[SkillCfg] = []
|
|
var dir_path: String = "res://config"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
for sub_dir_name: String in dir.get_directories():
|
|
if not sub_dir_name.begins_with("skill_"):
|
|
continue
|
|
var sub_dir_path: String = dir_path + "/" + sub_dir_name
|
|
var sub_dir: DirAccess = DirAccess.open(sub_dir_path)
|
|
for file: String in sub_dir.get_files():
|
|
var path: String = sub_dir_path + "/" + file
|
|
var res = load(path)
|
|
if res is SkillCfg:
|
|
ret.append(res)
|
|
return ret
|
|
|
|
|
|
func get_all_skill_player_weapon() -> Array[SkillWeaponCfg]:
|
|
var ret: Array[SkillWeaponCfg] = []
|
|
var dir_path: String = "res://config/skill_player_weapon"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
for file: String in dir.get_files():
|
|
var path: String = dir_path + "/" + file
|
|
var res = load(path)
|
|
if res is SkillWeaponCfg:
|
|
ret.append(res)
|
|
return ret
|
|
|
|
|
|
func get_all_skill_player_basic() -> Array[SkillWeaponCfg]:
|
|
var ret: Array[SkillWeaponCfg] = []
|
|
var dir_path: String = "res://config/skill_player_basic"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
for file: String in dir.get_files():
|
|
var path: String = dir_path + "/" + file
|
|
var res = load(path)
|
|
if res is SkillWeaponCfg:
|
|
ret.append(res)
|
|
return ret
|
|
|
|
|
|
func get_skill_player_weapon_by_weapon(weapon: WeaponCfg) -> Array[SkillWeaponCfg]:
|
|
var ret: Array[SkillWeaponCfg] = []
|
|
var dir_path: String = "res://config/skill_player_weapon"
|
|
var dir: DirAccess = DirAccess.open(dir_path)
|
|
for file: String in dir.get_files():
|
|
var path: String = dir_path + "/" + file
|
|
var res = load(path)
|
|
if res is SkillWeaponCfg:
|
|
if res.weapon == weapon:
|
|
ret.append(res)
|
|
return ret
|
|
|
|
|
|
func get_character_cfg_by_name(name: String) -> CharacterCfg:
|
|
var path_default: String = "res://config/character/%s.tres" % name
|
|
if ResourceLoader.exists(path_default):
|
|
var res = load(path_default)
|
|
if res is CharacterCfg:
|
|
return res
|
|
return null
|
|
|
|
|
|
func get_level_active_scene_by_name(name: String) -> PackedScene:
|
|
var path_default: String = "res://scene/level_active/%s.tscn" % name
|
|
if ResourceLoader.exists(path_default):
|
|
var res = load(path_default)
|
|
return res
|
|
return null
|