add code step 1
This commit is contained in:
parent
e4fb9933ad
commit
ac51d3031d
1
icon.svg
Normal file
1
icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
After Width: | Height: | Size: 994 B |
64
log/logger/logs/v-demo-1.json
Normal file
64
log/logger/logs/v-demo-1.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"event_date": "12/22/2024",
|
||||
"item_id": "876528753689",
|
||||
"log_content": "* 完成动画导入功能:\n * 自动检测目录下文件,帧排序后,导入到: res://config/animation/player_sprite_frames.tres \n * 文件名 mapping 到动画 animation 名称\n * 取第一帧作动画\n * 镜像动画\n * 网格化检阅",
|
||||
"tags": [
|
||||
"2@code",
|
||||
"3@art_tool",
|
||||
"2@animation"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
},
|
||||
{
|
||||
"event_date": "12/20/2024",
|
||||
"item_id": "2546254798879",
|
||||
"log_content": "* 游戏时间戳\n * 全局游戏时长记录\n * 当前存档时间状态:章节进度,游戏时长等\n* 场景管理器:发送消息浮窗\n* 事件系统:\n * 数据格式(四要素):\n * 时间(chapter_section,时间戳,周目状态等)\n * 地点(场景id,坐标)\n * 实体(实体id,状态)\n * 实体动作(action_id)\n * 流程:发送事件流程,消费事件流程\n* 存档:\n * 保存全局配置(如游戏总时长,周目数)\n * 分存档保存当前存档状态:时间、场景、实体\n* 组装实体:\n * 规格配置:进行中\n * 素材填充:进行中",
|
||||
"tags": [
|
||||
"2@code",
|
||||
"2@design"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
},
|
||||
{
|
||||
"event_date": "12/19/2024",
|
||||
"item_id": "52643524662456",
|
||||
"log_content": "* 角色移动状态机功能:静止/行走/奔跑/躺卧移动/上下爬行\n * 允许锁定移动/锁定奔跑,躺卧移动与上下爬行互斥\n* 规格化调整:\n * UI 规格化:物品HUD,对话浮窗\n * 场景规格化:层次背景,角色\n* 镜头 Marker :随玩家移动方向轻微偏移,优化视野细节",
|
||||
"tags": [
|
||||
"2@design",
|
||||
"2@code",
|
||||
"2@animation"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
},
|
||||
{
|
||||
"event_date": "12/18/2024",
|
||||
"item_id": "5423765786358",
|
||||
"log_content": "确定资源类型,围绕规格化的资源\n基本工作流设计\n完善 HUD 功能",
|
||||
"tags": [
|
||||
"2@ui",
|
||||
"2@design"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
},
|
||||
{
|
||||
"event_date": "12/17/2024",
|
||||
"item_id": "11242354",
|
||||
"log_content": "加入基础的游戏背景、角色行走功能",
|
||||
"tags": [
|
||||
"2@code"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
},
|
||||
{
|
||||
"event_date": "12/16/2024",
|
||||
"item_id": "17343458739570",
|
||||
"log_content": "新建项目等",
|
||||
"tags": [
|
||||
"2@design"
|
||||
],
|
||||
"update_date": "12/22/2024"
|
||||
}
|
||||
]
|
||||
}
|
140
log/logger/project_log_panel.gd
Normal file
140
log/logger/project_log_panel.gd
Normal file
@ -0,0 +1,140 @@
|
||||
extends CanvasLayer
|
||||
|
||||
class_name ProjectLogPanel
|
||||
|
||||
enum TAG_TYPE{VERSION=0,FIX=1,FEATURE=2,TOOL=3}
|
||||
|
||||
const TAG_TYPE_COLOR_DICT = {
|
||||
TAG_TYPE.VERSION: Color.SKY_BLUE,
|
||||
TAG_TYPE.FIX: Color.RED,
|
||||
TAG_TYPE.FEATURE: Color.AQUAMARINE,
|
||||
TAG_TYPE.TOOL: Color.ORCHID
|
||||
}
|
||||
|
||||
const TAG_DICT = {
|
||||
TAG_TYPE.VERSION:["demo","0.1","1.0"],
|
||||
TAG_TYPE.FIX:["bugfix","uxfix"],
|
||||
TAG_TYPE.FEATURE:["code","design","ui","audio","art","animation"],
|
||||
TAG_TYPE.TOOL:["art_tool","log_tool","manage_tool"],
|
||||
}
|
||||
|
||||
#const LOG_CONFIG_KEY_prefix = "log_panel_json_"
|
||||
const LOG_DATA_DIR = "res://log/logger/logs/"
|
||||
var log_files = []
|
||||
var current_log_file
|
||||
|
||||
const IMAGE_DIR = ""
|
||||
|
||||
@onready var add_btn := %Add
|
||||
@onready var save_btn := %Save
|
||||
@onready var archives_btn := %Archives as MenuButton
|
||||
@onready var archives_label := %ArchiveLabel as Label
|
||||
@onready var log_items_container = %LogItemsContainer
|
||||
|
||||
const LOG_ITEM_GROUP = "log_item"
|
||||
const LOG_ITEM_GROUP_MENBER = "log_item[{0}]"
|
||||
|
||||
var log_item_scene = preload("res://log/logger/project_log_panel_item.tscn")
|
||||
|
||||
var data = {"items":[]} as Dictionary
|
||||
|
||||
func _ready():
|
||||
add_btn.pressed.connect(_on_add)
|
||||
save_btn.pressed.connect(save_logs)
|
||||
archives_btn.get_popup().id_pressed.connect(_on_archive_switch)
|
||||
_load_archives()
|
||||
_on_archive_switch(log_files.find("v-demo-mountwuwang.json"))
|
||||
# var quat = Quaternion.from_euler(Vector3(deg_to_rad(10),0,deg_to_rad(10)))
|
||||
# print(quat)
|
||||
# quat = quat.normalized()
|
||||
# print(quat)
|
||||
# quat = Quaternion(Vector3(1,0,0),deg_to_rad(10)) * Quaternion(Vector3(0,0,1),deg_to_rad(10))
|
||||
# print(quat)
|
||||
# quat = quat.normalized()
|
||||
# print(quat)
|
||||
|
||||
func _load_archives():
|
||||
log_files = DirAccess.get_files_at(LOG_DATA_DIR) as PackedStringArray
|
||||
if log_files.size() == 0:
|
||||
printerr("_load_archives no file exists:",LOG_DATA_DIR)
|
||||
for i in range(0,log_files.size()):
|
||||
archives_btn.get_popup().add_item(log_files[i],i)
|
||||
_on_archive_switch(0)
|
||||
|
||||
func _load_logs():
|
||||
var path = _get_curr_path()
|
||||
if !FileAccess.file_exists(path):
|
||||
printerr("_load_logs no file exists:",path)
|
||||
return
|
||||
var json = ResourceLoader.load(path,"",ResourceLoader.CACHE_MODE_IGNORE)
|
||||
#print("load data=",json.data)
|
||||
print("loaded data")
|
||||
data = json.data
|
||||
if !data.has("items"):
|
||||
data["items"] = []
|
||||
_refresh_items()
|
||||
|
||||
func _get_curr_path():
|
||||
return LOG_DATA_DIR + current_log_file
|
||||
|
||||
func _refresh_items():
|
||||
var items = data["items"] as Array
|
||||
get_tree().call_group(LOG_ITEM_GROUP, "queue_free")
|
||||
for i in range(items.size()):
|
||||
var item_instance = log_item_scene.instantiate() as Control
|
||||
item_instance.add_to_group(LOG_ITEM_GROUP)
|
||||
item_instance.add_to_group(LOG_ITEM_GROUP_MENBER.format([]))
|
||||
item_instance.update.connect(_on_log_item_update.bind(i))
|
||||
#item_instance.save.connect(_on_log_item_save.bind(i))
|
||||
item_instance.remove.connect(_on_log_item_remove.bind(i))
|
||||
log_items_container.add_child(item_instance)
|
||||
if items[i] is Dictionary:
|
||||
item_instance.load_item(items[i])
|
||||
elif items[i] is String:
|
||||
var item_dict = JSON.parse_string(items[i])
|
||||
item_instance.load_item(item_dict)
|
||||
else :
|
||||
push_error("unknow type items[",i,"]=",items[i])
|
||||
|
||||
func save_logs():
|
||||
var path = _get_curr_path()
|
||||
if !FileAccess.file_exists(path):
|
||||
printerr("save_logs no file exists:",path)
|
||||
return
|
||||
#print("save logs data=", data)
|
||||
print("saved logs")
|
||||
var file := FileAccess.open(path, FileAccess.WRITE_READ) as FileAccess
|
||||
file.store_string(JSON.stringify(data, "\t"))
|
||||
file.close()
|
||||
|
||||
func _on_log_item_update(item:LogItem.ItemData, index:int):
|
||||
var json = item.to_json_dict()
|
||||
print("_on_log_item_update item=", json)
|
||||
data["items"][index] = json
|
||||
|
||||
func _on_log_item_save(item:LogItem.ItemData, index:int):
|
||||
var json = item.to_json_dict()
|
||||
print("_on_log_item_save item=", json)
|
||||
data["items"][index] = json
|
||||
save_logs()
|
||||
|
||||
func _on_log_item_remove(index:int):
|
||||
(data["items"] as Array).remove_at(index)
|
||||
save_logs()
|
||||
# reset index for each item
|
||||
_refresh_items()
|
||||
|
||||
func _on_add():
|
||||
(data["items"] as Array).push_front({})
|
||||
save_logs()
|
||||
# reset index for each item
|
||||
_refresh_items()
|
||||
|
||||
func _on_archive_switch(id:int):
|
||||
current_log_file = log_files[id]
|
||||
archives_label.text = log_files[id]
|
||||
_load_logs()
|
||||
|
||||
func _unhandled_input(event):
|
||||
if event.is_action("save"):
|
||||
save_logs()
|
119
log/logger/project_log_panel.tscn
Normal file
119
log/logger/project_log_panel.tscn
Normal file
@ -0,0 +1,119 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://b3n06jtdpqy5y"]
|
||||
|
||||
[ext_resource type="Script" path="res://log/logger/project_log_panel.gd" id="1_2rhk7"]
|
||||
[ext_resource type="PackedScene" uid="uid://bdy4u3e7rmo7f" path="res://ui/button/sound_button.tscn" id="2_71u5c"]
|
||||
[ext_resource type="PackedScene" uid="uid://dhvo15vyxpkja" path="res://log/logger/project_log_panel_item.tscn" id="4_1yhgi"]
|
||||
|
||||
[node name="ProjectLogPanel" type="CanvasLayer"]
|
||||
script = ExtResource("1_2rhk7")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/margin_left = 8
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 6
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 6
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
alignment = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 6
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 6
|
||||
|
||||
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_colors/font_color = Color(0.670588, 0.952941, 0.972549, 1)
|
||||
theme_override_colors/font_shadow_color = Color(0.180392, 0.180392, 0.180392, 1)
|
||||
theme_override_colors/font_outline_color = Color(0.0156863, 0.258824, 0.341176, 1)
|
||||
theme_override_constants/shadow_offset_x = 2
|
||||
theme_override_constants/shadow_offset_y = 2
|
||||
theme_override_constants/outline_size = 4
|
||||
theme_override_constants/shadow_outline_size = 12
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Project Log"
|
||||
|
||||
[node name="Add" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer" instance=ExtResource("2_71u5c")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 4
|
||||
text = "Add"
|
||||
script = null
|
||||
|
||||
[node name="Save" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer" instance=ExtResource("2_71u5c")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 4
|
||||
text = "Save"
|
||||
script = null
|
||||
|
||||
[node name="Archives" type="MenuButton" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
text = "Archives"
|
||||
flat = false
|
||||
|
||||
[node name="ArchiveLabel" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/margin_left = 8
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer/MarginContainer2/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/margin_left = 4
|
||||
theme_override_constants/margin_top = 4
|
||||
theme_override_constants/margin_right = 8
|
||||
theme_override_constants/margin_bottom = 4
|
||||
|
||||
[node name="LogItemsContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer2/ScrollContainer/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
alignment = 1
|
||||
|
||||
[node name="LogItem" parent="MarginContainer/VBoxContainer/MarginContainer2/ScrollContainer/MarginContainer/LogItemsContainer" instance=ExtResource("4_1yhgi")]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LogItem2" parent="MarginContainer/VBoxContainer/MarginContainer2/ScrollContainer/MarginContainer/LogItemsContainer" instance=ExtResource("4_1yhgi")]
|
||||
visible = false
|
||||
layout_mode = 2
|
198
log/logger/project_log_panel_item.gd
Normal file
198
log/logger/project_log_panel_item.gd
Normal file
@ -0,0 +1,198 @@
|
||||
extends HBoxContainer
|
||||
|
||||
class_name LogItem
|
||||
|
||||
#signal save(data:ItemData)
|
||||
signal update(data: ItemData)
|
||||
signal remove
|
||||
|
||||
const TAG_BTN_GROUP_PREFIX = "tag_btn"
|
||||
|
||||
@onready var log_content := %LogContent as TextEdit
|
||||
@onready var event_date := %EventDate as Label
|
||||
#@onready var update_date := %LogUpdateDate as Label
|
||||
@onready var tags_container := %TagsContainer as GridContainer
|
||||
@onready var add_tag_btn := %AddTag as MenuButton
|
||||
@onready var reload_btn = %Reload
|
||||
@onready var save_btn = %Save
|
||||
@onready var delete_btn = %Delete
|
||||
|
||||
var original_data := ItemData.new()
|
||||
var data: ItemData = original_data
|
||||
|
||||
|
||||
class ItemData:
|
||||
var item_id := _generate_random_id()
|
||||
var log_content := "":
|
||||
set(new_val):
|
||||
if new_val != log_content:
|
||||
update_date = _get_current_time()
|
||||
log_content = new_val
|
||||
var tags := []:
|
||||
set(new_val):
|
||||
update_date = _get_current_time()
|
||||
tags = new_val
|
||||
var event_date := _get_current_time()
|
||||
var update_date := _get_current_time()
|
||||
|
||||
func _generate_random_id() -> String:
|
||||
# float time
|
||||
var timestamp := Time.get_unix_time_from_system()
|
||||
return str(int(timestamp * 10000 + randi_range(0, 10000)))
|
||||
|
||||
func _get_current_time() -> String:
|
||||
# Returns the current date as a dictionary of keys: year, month, day, and weekday.
|
||||
var dict = Time.get_date_dict_from_system()
|
||||
return str(dict["month"]) + "/" + str(dict["day"]) + "/" + str(dict["year"])
|
||||
|
||||
func duplicate() -> ItemData:
|
||||
var item := ItemData.new()
|
||||
item.item_id = item_id
|
||||
item.log_content = log_content
|
||||
item.tags = tags.duplicate()
|
||||
item.event_date = event_date
|
||||
item.update_date = update_date
|
||||
return item
|
||||
|
||||
func to_json_dict() -> Dictionary:
|
||||
# JSON.stringify(self) doesn't work
|
||||
return {
|
||||
"item_id": item_id,
|
||||
"log_content": log_content,
|
||||
"tags": tags,
|
||||
"event_date": event_date,
|
||||
"update_date": update_date,
|
||||
}
|
||||
|
||||
static func parse(data: Dictionary) -> ItemData:
|
||||
var item := ItemData.new()
|
||||
if data.has("item_id"):
|
||||
item.item_id = data["item_id"]
|
||||
if data.has("tags"):
|
||||
item.tags = data["tags"]
|
||||
if data.has("log_content"):
|
||||
item.log_content = data["log_content"]
|
||||
if data.has("event_date"):
|
||||
item.event_date = data["event_date"]
|
||||
if data.has("update_date"):
|
||||
item.update_date = data["update_date"]
|
||||
return item
|
||||
|
||||
|
||||
# {id:{"btn":btn,"key":key,"name":name,"id":id}}
|
||||
static var tag_btns = {}
|
||||
static var tag_key_to_id_map = {}
|
||||
|
||||
static var tag_shadow_color = Color.html("1b1b1b")
|
||||
static var tag_shadow_outline_size = 1
|
||||
|
||||
|
||||
# id->key
|
||||
var current_tags = {}
|
||||
|
||||
func _ready():
|
||||
_load_tag_popup()
|
||||
reload_btn.pressed.connect(_on_reload_pressed)
|
||||
#save_btn.pressed.connect(_save_item)
|
||||
delete_btn.pressed.connect(_remove_signal)
|
||||
log_content.text_changed.connect(_on_log_content_changed)
|
||||
call_deferred("_update_signal")
|
||||
#load_item(original_data)
|
||||
|
||||
|
||||
static func _static_init():
|
||||
var tag_id := 0
|
||||
for tag_type in ProjectLogPanel.TAG_TYPE.values():
|
||||
var tag_color = ProjectLogPanel.TAG_TYPE_COLOR_DICT[tag_type]
|
||||
for tag in ProjectLogPanel.TAG_DICT[tag_type]:
|
||||
var tag_btn = Button.new() as Button
|
||||
tag_btn.add_theme_color_override("font_color", tag_color)
|
||||
tag_btn.add_theme_color_override("font_shadow_color", tag_shadow_color)
|
||||
tag_btn.add_theme_constant_override("shadow_outline_size", tag_shadow_outline_size)
|
||||
tag_btn.text = tag
|
||||
var tag_key = _get_tag_key(tag_type, tag)
|
||||
tag_btns[tag_id] = {"btn": tag_btn, "id": tag_id, "name": tag, "key": tag_key}
|
||||
tag_key_to_id_map[tag_key] = tag_id
|
||||
tag_id += 1
|
||||
|
||||
|
||||
static func _get_tag_key(tag_type: ProjectLogPanel.TAG_TYPE, tag: String):
|
||||
return str(tag_type) + "@" + tag
|
||||
|
||||
|
||||
func _load_tag_popup():
|
||||
var popup = add_tag_btn.get_popup() as PopupMenu
|
||||
for btn_dict in tag_btns.values():
|
||||
popup.add_item(btn_dict["name"], btn_dict["id"])
|
||||
popup.id_pressed.connect(_on_popup_menu_pressed)
|
||||
|
||||
|
||||
func _reload_tag_btns():
|
||||
var btn_group = TAG_BTN_GROUP_PREFIX + data.item_id
|
||||
get_tree().call_group(btn_group, "queue_free")
|
||||
current_tags.clear()
|
||||
for tag_key in data["tags"]:
|
||||
if !tag_key_to_id_map.has(tag_key):
|
||||
push_error("tag_key has been removed!! tag_key=", tag_key)
|
||||
continue
|
||||
var tag_id = tag_key_to_id_map[tag_key]
|
||||
current_tags[tag_id] = tag_key
|
||||
var btn = (tag_btns[tag_id]["btn"] as Button).duplicate()
|
||||
btn.pressed.connect(_on_tag_btn_pressed.bind(btn, tag_id))
|
||||
btn.add_to_group(btn_group)
|
||||
tags_container.add_child(btn)
|
||||
|
||||
|
||||
func load_item(new_data: Dictionary):
|
||||
if new_data.keys().size() != 0:
|
||||
original_data = ItemData.parse(new_data)
|
||||
_reload_original_data()
|
||||
|
||||
|
||||
func _reload_original_data():
|
||||
data = original_data.duplicate()
|
||||
#print("_load_item_data data=", data)
|
||||
log_content.text = data.log_content
|
||||
event_date.text = data.event_date
|
||||
#update_date.text = data["update_date"]
|
||||
_reload_tag_btns()
|
||||
|
||||
|
||||
func _on_popup_menu_pressed(id: int):
|
||||
#{"btn":btn,"key":key,"name":name,"id":id}
|
||||
if !current_tags.has(id):
|
||||
current_tags[id] = tag_btns[id]["key"]
|
||||
data.tags = current_tags.values()
|
||||
_update_signal()
|
||||
#_save_item()
|
||||
_reload_tag_btns()
|
||||
|
||||
|
||||
func _on_log_content_changed():
|
||||
data["log_content"] = log_content.text
|
||||
_update_signal()
|
||||
|
||||
|
||||
func _on_tag_btn_pressed(btn: Control, id: int):
|
||||
current_tags.erase(id)
|
||||
btn.queue_free()
|
||||
data.tags = current_tags.values()
|
||||
_update_signal()
|
||||
#_save_item()
|
||||
|
||||
|
||||
#func _save_item():
|
||||
#save.emit(data)
|
||||
|
||||
|
||||
func _update_signal():
|
||||
update.emit(data)
|
||||
|
||||
|
||||
func _remove_signal():
|
||||
remove.emit()
|
||||
|
||||
|
||||
func _on_reload_pressed():
|
||||
_reload_original_data()
|
||||
_update_signal()
|
86
log/logger/project_log_panel_item.tscn
Normal file
86
log/logger/project_log_panel_item.tscn
Normal file
@ -0,0 +1,86 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dhvo15vyxpkja"]
|
||||
|
||||
[ext_resource type="Script" path="res://log/logger/project_log_panel_item.gd" id="1_gn7ev"]
|
||||
[ext_resource type="PackedScene" uid="uid://bdy4u3e7rmo7f" path="res://ui/button/sound_button.tscn" id="2_wb6pu"]
|
||||
|
||||
[node name="LogItem" type="HBoxContainer"]
|
||||
anchors_preset = 14
|
||||
anchor_top = 0.5
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 0.5
|
||||
offset_top = -4.0
|
||||
offset_bottom = 4.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_gn7ev")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="LogContent" type="TextEdit" parent="MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "123"
|
||||
wrap_mode = 1
|
||||
scroll_fit_content_height = true
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TagsContainer" type="GridContainer" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
columns = 2
|
||||
|
||||
[node name="AddTag" type="MenuButton" parent="HBoxContainer/TagsContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Tags"
|
||||
|
||||
[node name="VBoxContainer2" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="EventDate" type="Label" parent="VBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.929412, 0.929412, 0.929412, 1)
|
||||
theme_override_colors/font_shadow_color = Color(0.105882, 0.105882, 0.105882, 1)
|
||||
theme_override_constants/shadow_offset_x = 1
|
||||
theme_override_constants/shadow_offset_y = 1
|
||||
theme_override_constants/shadow_outline_size = 4
|
||||
text = "01/01/24"
|
||||
|
||||
[node name="LogUpdateDate" type="Label" parent="VBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "01/01/24"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Reload" parent="VBoxContainer2/HBoxContainer" instance=ExtResource("2_wb6pu")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
text = "Reload"
|
||||
script = null
|
||||
|
||||
[node name="Save" parent="VBoxContainer2/HBoxContainer" instance=ExtResource("2_wb6pu")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
text = "Save"
|
||||
script = null
|
||||
|
||||
[node name="Delete" parent="VBoxContainer2/HBoxContainer" instance=ExtResource("2_wb6pu")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
text = "Delete"
|
||||
script = null
|
125
manager/archive_manager/archive_manager.gd
Normal file
125
manager/archive_manager/archive_manager.gd
Normal file
@ -0,0 +1,125 @@
|
||||
extends Node
|
||||
|
||||
@export var user_archive_root_dir := "user://archive/" # must end with "/"
|
||||
@export var save_dir_prefix := "save"
|
||||
|
||||
var accessible := false
|
||||
var archives: Array[int] # archive id list in ascending order
|
||||
|
||||
var managers = {
|
||||
"TimeManager": TimeManager,
|
||||
"EntityManager": EntityManager,
|
||||
"SceneManager": SceneManager,
|
||||
"InputManager": InputManager,
|
||||
# "ArchiveManager" : ArchiveManager, #self
|
||||
# "AudioManager" : AudioManager,
|
||||
# "EventManager" : EventManager,
|
||||
# "CameraManager" : CameraManager,
|
||||
# "DialogManager" : DialogManager,
|
||||
# "CgManager": CgManager,
|
||||
}
|
||||
|
||||
var autosave_timer := Timer.new()
|
||||
|
||||
func _ready() -> void:
|
||||
accessible = _check_archive_dirs()
|
||||
if !accessible:
|
||||
return
|
||||
# _open_log_file()
|
||||
add_child(autosave_timer)
|
||||
autosave_timer.wait_time = GlobalConfigManager.config.auto_save_seconds
|
||||
autosave_timer.one_shot = false
|
||||
autosave_timer.timeout.connect(_try_auto_save)
|
||||
autosave_timer.stop()
|
||||
GlobalConfigManager.config.current_selected_save_changed.connect(_check_autosave_options)
|
||||
GlobalConfigManager.config.auto_save_seconds_changed.connect(_check_autosave_options)
|
||||
load_all()
|
||||
SceneManager.pop_notification("预加载完成")
|
||||
|
||||
|
||||
|
||||
func _check_autosave_options():
|
||||
if (
|
||||
GlobalConfigManager.config.auto_save_seconds > 5
|
||||
and GlobalConfigManager.config.current_selected_save >= 0
|
||||
):
|
||||
autosave_timer.start()
|
||||
else:
|
||||
autosave_timer.stop()
|
||||
|
||||
|
||||
func _try_auto_save():
|
||||
if (
|
||||
GlobalConfigManager.config.auto_save_seconds > 5
|
||||
and GlobalConfigManager.config.current_selected_save >= 0
|
||||
):
|
||||
save_all()
|
||||
SceneManager.pop_notification("自动保存成功")
|
||||
|
||||
|
||||
func _check_archive_dirs() -> bool:
|
||||
# Check if the archive directory is accessible
|
||||
if !DirAccess.dir_exists_absolute(user_archive_root_dir):
|
||||
DirAccess.make_dir_recursive_absolute(user_archive_root_dir)
|
||||
print("Create archive directory:", user_archive_root_dir)
|
||||
var archive_dir_access = DirAccess.open(user_archive_root_dir)
|
||||
if !archive_dir_access:
|
||||
printerr("Archive directory is not accessible")
|
||||
# TODO pop up a dialog to inform the user
|
||||
return false
|
||||
var files = archive_dir_access.get_files()
|
||||
# get archive number
|
||||
for file in files:
|
||||
if file.begins_with(save_dir_prefix):
|
||||
var id_str = file.substr(save_dir_prefix.length())
|
||||
var id = int(id_str)
|
||||
archives.append(id)
|
||||
archives.sort()
|
||||
return true
|
||||
|
||||
|
||||
func save_all() -> void:
|
||||
# save config
|
||||
var config = GlobalConfigManager.config
|
||||
var path = user_archive_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
|
||||
ResourceSaver.save(config, path)
|
||||
if not accessible or GlobalConfigManager.config.current_selected_save == -1:
|
||||
return
|
||||
# Save all managers by the current selected save
|
||||
for manager in managers:
|
||||
# .tres
|
||||
var res = managers[manager].get_data_res()
|
||||
if !res:
|
||||
continue
|
||||
# save to file
|
||||
path = (
|
||||
user_archive_root_dir
|
||||
+ str(config.current_selected_save)
|
||||
+ "/"
|
||||
+ manager
|
||||
+ GlobalConfig.RES_FILE_FORMAT
|
||||
)
|
||||
ResourceSaver.save(res, path)
|
||||
|
||||
|
||||
func load_all() -> void:
|
||||
_check_archive_dirs()
|
||||
# load config
|
||||
var path = user_archive_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
|
||||
var config
|
||||
if FileAccess.file_exists(path):
|
||||
config = ResourceLoader.load(path)
|
||||
GlobalConfigManager.load_data_res(config)
|
||||
else:
|
||||
config = GlobalConfigManager.config
|
||||
# save config
|
||||
ResourceSaver.save(config, path)
|
||||
if not accessible or config.current_selected_save == -1:
|
||||
return
|
||||
# Load managers by the current selected save
|
||||
path = user_archive_root_dir + save_dir_prefix + str(config.current_selected_save) + "/"
|
||||
for manager in managers:
|
||||
var manager_path = path + manager + GlobalConfig.RES_FILE_FORMAT
|
||||
if FileAccess.file_exists(manager_path):
|
||||
var res = ResourceLoader.load(manager_path)
|
||||
managers[manager].load_data_res(res)
|
1
manager/assemble/asset_metadata.gd
Normal file
1
manager/assemble/asset_metadata.gd
Normal file
@ -0,0 +1 @@
|
||||
class_name AssetMetadata extends Resource
|
11
manager/assemble/dialog/dialog_manager.gd
Normal file
11
manager/assemble/dialog/dialog_manager.gd
Normal file
@ -0,0 +1,11 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
11
manager/assemble/entity/entity.gd
Normal file
11
manager/assemble/entity/entity.gd
Normal file
@ -0,0 +1,11 @@
|
||||
class_name AssetMetadata extends Resource
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
18
manager/assemble/entity/entity_manager.gd
Normal file
18
manager/assemble/entity/entity_manager.gd
Normal file
@ -0,0 +1,18 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
func get_data_res() -> Resource:
|
||||
return null
|
||||
|
||||
|
||||
func load_data_res(data: Resource) -> void:
|
||||
pass
|
15
manager/assemble/scene/scene_manager.gd
Normal file
15
manager/assemble/scene/scene_manager.gd
Normal file
@ -0,0 +1,15 @@
|
||||
extends Node
|
||||
|
||||
func pop_notification(msg: String, number := 1) -> void:
|
||||
var notification_node = get_node_or_null("/root/Main/UILayer/Notification")
|
||||
if notification_node:
|
||||
notification_node.show_notification(msg, number)
|
||||
else:
|
||||
printerr("Notification node not found")
|
||||
|
||||
func get_data_res() -> Resource:
|
||||
return null
|
||||
|
||||
|
||||
func load_data_res(data: Resource) -> void:
|
||||
pass
|
11
manager/audio_manager/audio_manager.gd
Normal file
11
manager/audio_manager/audio_manager.gd
Normal file
@ -0,0 +1,11 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
11
manager/camera_manager/camera_manager.gd
Normal file
11
manager/camera_manager/camera_manager.gd
Normal file
@ -0,0 +1,11 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
11
manager/cg_manager/cg_manager.gd
Normal file
11
manager/cg_manager/cg_manager.gd
Normal file
@ -0,0 +1,11 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
34
manager/config_manager/global_config.gd
Normal file
34
manager/config_manager/global_config.gd
Normal file
@ -0,0 +1,34 @@
|
||||
class_name GlobalConfig extends Resource
|
||||
|
||||
# .res would be binary encoded, .tres is text encoded
|
||||
const RES_FILE_FORMAT = ".tres"
|
||||
|
||||
const CONFIG_FILE_NAME = "config"
|
||||
|
||||
const DEBUG = true
|
||||
#const DEBUG = false
|
||||
|
||||
const CANVAS_LAYER_VIGNETTE = 1000
|
||||
const CANVAS_LAYER_PROP_INSPECTOR = 100
|
||||
const CANVAS_LAYER_UI = 99
|
||||
const CANVAS_LAYER_FG = 50
|
||||
const CANVAS_LAYER_BG = -100
|
||||
|
||||
const COLOR_BOARDER = Color.BLACK
|
||||
|
||||
const _ART_RESOURCE_BASE_DIR = "res://asset/art/"
|
||||
|
||||
signal current_selected_save_changed
|
||||
signal auto_save_seconds_changed
|
||||
|
||||
# 注意:编辑与新增属性时,需要同时编辑 GlobalConfigManager.gd 中的 load_data_res 方法
|
||||
@export var game_total_seconds := 0 # 游戏总时长
|
||||
@export var game_rounds := 1 # 当前周目数
|
||||
@export var current_selected_save := -1: # 当前选定存档 id, -1 means no save selected
|
||||
set(val):
|
||||
current_selected_save = val
|
||||
current_selected_save_changed.emit()
|
||||
@export var auto_save_seconds := 60:
|
||||
set(val):
|
||||
auto_save_seconds = val
|
||||
auto_save_seconds_changed.emit()
|
15
manager/config_manager/global_config_manager.gd
Normal file
15
manager/config_manager/global_config_manager.gd
Normal file
@ -0,0 +1,15 @@
|
||||
extends Node
|
||||
|
||||
var config = GlobalConfig.new()
|
||||
|
||||
|
||||
func get_data_res() -> Resource:
|
||||
return config
|
||||
|
||||
|
||||
func load_data_res(data: Resource) -> void:
|
||||
var new_config = data as GlobalConfig
|
||||
config.game_total_seconds = new_config.game_total_seconds
|
||||
config.game_rounds = new_config.game_rounds
|
||||
config.current_selected_save = new_config.current_selected_save
|
||||
config.auto_save_seconds = new_config.auto_save_seconds
|
31
manager/event_manager/event_manager.gd
Normal file
31
manager/event_manager/event_manager.gd
Normal file
@ -0,0 +1,31 @@
|
||||
extends Node
|
||||
|
||||
# 事件注册表
|
||||
# { entity: [MatcherConsumer] }
|
||||
var _event_registry: Dictionary = {}
|
||||
|
||||
class MatcherConsumer extends RefCounted:
|
||||
var _matcher: GameEventMatcher
|
||||
var _consumer: Callable
|
||||
|
||||
func _init(matcher: GameEventMatcher, consumer: Callable) -> void:
|
||||
self._matcher = matcher
|
||||
self._consumer = consumer
|
||||
|
||||
# 注册事件
|
||||
func register_event_matcher(event_matcher: GameEventMatcher, consumer: Callable) -> void:
|
||||
if !event_matcher.entity:
|
||||
return
|
||||
var matcher_consumer = MatcherConsumer.new(event_matcher, consumer)
|
||||
if event_matcher.entity not in _event_registry:
|
||||
_event_registry[event_matcher.entity] = []
|
||||
_event_registry[event_matcher.entity].append(matcher_consumer)
|
||||
|
||||
# 触发事件
|
||||
func trigger_event(event: GameEvent) -> void:
|
||||
if event.entity not in _event_registry:
|
||||
return
|
||||
for matcher_consumer in _event_registry[event.entity]:
|
||||
# matcher_consumer = matcher_consumer as MatcherConsumer
|
||||
if matcher_consumer._matcher.match(event):
|
||||
matcher_consumer._consumer.call(event)
|
19
manager/event_manager/game_event.gd
Normal file
19
manager/event_manager/game_event.gd
Normal file
@ -0,0 +1,19 @@
|
||||
class_name GameEvent extends Resource
|
||||
|
||||
# * 事件&剧情管理器: player / release / debug 事件,触发者:玩家/系统(系统触发意味着进入 CG)
|
||||
# * 事件定义:「通变之谓事」
|
||||
# * 事件发送机制:玩家进行特定操作后,发送事件进度(开始(注意到),尝试&进度,完成:成功or失败)
|
||||
# * 发送内容
|
||||
# * 时间点:玩家现实时间(系统时间),游戏时长(时间戳),章节剧情时间点(事件编号)
|
||||
# * 地点:场景编号,位置坐标
|
||||
# * 实体:道具/NPC/部署点
|
||||
# * 激发器类型:地图区域(手动部署) / 玩家特定操作(自动发送)/ 实体信号(监听玩家特定操作/状态变化)
|
||||
# * 事件订阅机制:订阅开始/进度/成功/失败,触发特定响应
|
||||
# * 消费器能力:执行 CG(锁定/无锁定,剧本/特效) / 执行实体变化脚本(赠送/消耗/状态变化)
|
||||
# * 保存与加载
|
||||
@export var event_id: int
|
||||
@export var packed_time: PackedTime
|
||||
@export var scene: String
|
||||
@export var scene_position: Vector2
|
||||
@export var entity: String
|
||||
@export var entity_action: String
|
43
manager/event_manager/game_event_matcher.gd
Normal file
43
manager/event_manager/game_event_matcher.gd
Normal file
@ -0,0 +1,43 @@
|
||||
class_name GameEventMatcher extends Resource
|
||||
|
||||
# match event under certain conditions
|
||||
|
||||
# can't be empty
|
||||
@export var entity: String
|
||||
# empty means any action
|
||||
@export var entity_actions: Array[String]
|
||||
# empty means any scene
|
||||
@export var scenes: Array[String]
|
||||
# regex matcher, "[chapter]_[section]", * means any
|
||||
# e.g. 3_* means any section in chapter 3
|
||||
# empty means any chapter_section
|
||||
@export var chapter_section: Array[String]
|
||||
|
||||
# check if the event matches the conditions
|
||||
func match(event: GameEvent) -> bool:
|
||||
if !entity or entity != event.entity:
|
||||
return false
|
||||
if entity_actions.size() > 0 and !entity_actions.has(event.entity_action):
|
||||
return false
|
||||
if scenes.size() > 0 and !scenes.has(event.scene):
|
||||
return false
|
||||
if chapter_section.size() > 0:
|
||||
var chapter := str(event.packed_time.chapter)
|
||||
var section := str(event.packed_time.section)
|
||||
var matched := false
|
||||
for chapter_section_matcher in chapter_section:
|
||||
# regex match
|
||||
var parts = chapter_section_matcher.split("_")
|
||||
if parts.size() != 2:
|
||||
continue
|
||||
var chapter_matcher = parts[0]
|
||||
var section_matcher = parts[1]
|
||||
if chapter_matcher == "*" or chapter_matcher == chapter:
|
||||
matched = true
|
||||
break
|
||||
if section_matcher == "*" or section_matcher == section:
|
||||
matched = true
|
||||
break
|
||||
if !matched:
|
||||
return false
|
||||
return true
|
19
manager/input/input_manager.gd
Normal file
19
manager/input/input_manager.gd
Normal file
@ -0,0 +1,19 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func get_data_res() -> Resource:
|
||||
return null
|
||||
|
||||
|
||||
func load_data_res(data: Resource) -> void:
|
||||
pass
|
12
manager/time_manager/packed_time.gd
Normal file
12
manager/time_manager/packed_time.gd
Normal file
@ -0,0 +1,12 @@
|
||||
class_name PackedTime extends Resource
|
||||
|
||||
# 系统时间,游戏时长,章节时间点
|
||||
|
||||
@export var game_archive_id := 0
|
||||
@export var game_rounds := 0
|
||||
@export var timestamp := "2024-12-20 08:00:00" #system
|
||||
@export var game_seconds_all := 0 #game seconds since current archive start
|
||||
@export var game_seconds_current := 0 #game seconds since last chapter
|
||||
@export var chapter := 0 #chapter id
|
||||
@export var section := 0 #section id
|
||||
|
63
manager/time_manager/time_manager.gd
Normal file
63
manager/time_manager/time_manager.gd
Normal file
@ -0,0 +1,63 @@
|
||||
extends Node
|
||||
|
||||
@export var current_chapter := 0
|
||||
@export var current_section := 0
|
||||
@export var game_seconds_all := 0
|
||||
@export var game_seconds_current := 0
|
||||
|
||||
var timer: Timer
|
||||
|
||||
func _ready() -> void:
|
||||
timer = Timer.new()
|
||||
timer.wait_time = 1
|
||||
timer.one_shot = false
|
||||
timer.timeout.connect(_on_timer_timeout)
|
||||
add_child(timer)
|
||||
timer.start()
|
||||
|
||||
|
||||
func _on_timer_timeout():
|
||||
game_seconds_all += 1
|
||||
game_seconds_current += 1
|
||||
GlobalConfigManager.config.game_total_seconds += 1
|
||||
|
||||
|
||||
func pack_current_time():
|
||||
var packed_time = PackedTime.new()
|
||||
packed_time.time = Time.get_datetime_string_from_system(false, true)
|
||||
packed_time.chapter = current_chapter
|
||||
packed_time.section = current_section
|
||||
packed_time.game_archive_id = ArchiveManager.current_archive_id
|
||||
packed_time.game_seconds_all = game_seconds_all
|
||||
packed_time.game_seconds_current = game_seconds_current
|
||||
|
||||
|
||||
# for log use
|
||||
func get_concise_timemark() -> String:
|
||||
var hour := game_seconds_current / 3600 as int
|
||||
var minute := (game_seconds_current % 3600) / 60 as int
|
||||
var second := game_seconds_current % 60
|
||||
return (
|
||||
"r"
|
||||
+ str(ArchiveManager.current_archive_id)
|
||||
+ "_c"
|
||||
+ str(current_chapter)
|
||||
+ "_s"
|
||||
+ str(current_section)
|
||||
+ " "
|
||||
+ str(hour)
|
||||
+ ":"
|
||||
+ str(minute)
|
||||
+ ":"
|
||||
+ str(second)
|
||||
)
|
||||
|
||||
func get_data_res() -> Resource:
|
||||
return pack_current_time()
|
||||
|
||||
func load_data_res(data: Resource) -> void:
|
||||
var packed_time = data as PackedTime
|
||||
game_seconds_all = packed_time.game_seconds_all
|
||||
game_seconds_current = packed_time.game_seconds_current
|
||||
current_chapter = packed_time.chapter
|
||||
current_section = packed_time.section
|
114
project.godot
Normal file
114
project.godot
Normal file
@ -0,0 +1,114 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[addons]
|
||||
|
||||
resources_spreadsheet_view/array_color_tint=100.0
|
||||
resources_spreadsheet_view/color_rows=true
|
||||
resources_spreadsheet_view/array_min_width=128.0
|
||||
resources_spreadsheet_view/resource_preview_size=32.0
|
||||
resources_spreadsheet_view/clip_headers=false
|
||||
resources_spreadsheet_view/dupe_arrays=true
|
||||
resources_spreadsheet_view/context_menu_on_leftclick=false
|
||||
|
||||
[application]
|
||||
|
||||
config/name="xiandie"
|
||||
run/main_scene="res://scene/main.tscn"
|
||||
config/features=PackedStringArray("4.3", "Mobile")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[audio]
|
||||
|
||||
buses/default_bus_layout="res://config/default_bus_layout.tres"
|
||||
|
||||
[autoload]
|
||||
|
||||
DebugMenu="*res://addons/debug_menu/debug_menu.tscn"
|
||||
GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd"
|
||||
TimeManager="*res://manager/time_manager/time_manager.gd"
|
||||
EntityManager="*res://manager/assemble/entity/entity_manager.gd"
|
||||
SceneManager="*res://manager/assemble/scene/scene_manager.gd"
|
||||
AudioManager="*res://manager/audio_manager/audio_manager.gd"
|
||||
EventManager="*res://manager/event_manager/event_manager.gd"
|
||||
DialogManager="*res://manager/assemble/dialog/dialog_manager.gd"
|
||||
CameraManager="*res://manager/camera_manager/camera_manager.gd"
|
||||
CgManager="*res://manager/cg_manager/cg_manager.gd"
|
||||
InputManager="*res://manager/input/input_manager.gd"
|
||||
ArchiveManager="*res://manager/archive_manager/archive_manager.gd"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=564
|
||||
window/size/viewport_height=317
|
||||
window/size/window_width_override=1692
|
||||
window/size/window_height_override=951
|
||||
window/stretch/mode="canvas_items"
|
||||
window/stretch/scale_mode="integer"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/debug_menu/plugin.cfg", "res://addons/project-statistics/plugin.cfg")
|
||||
|
||||
[gui]
|
||||
|
||||
theme/custom="res://config/default_theme.tres"
|
||||
theme/custom_font="res://asset/font/zpix-commercial-one-grand.ttf"
|
||||
|
||||
[input]
|
||||
|
||||
save={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
up={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
down={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
run={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
jump={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
textures/canvas_textures/default_texture_filter=0
|
||||
renderer/rendering_method="mobile"
|
||||
|
||||
[statistics]
|
||||
|
||||
force_include=PackedStringArray()
|
6
scene/camera/camera_focus_marker.gd
Normal file
6
scene/camera/camera_focus_marker.gd
Normal file
@ -0,0 +1,6 @@
|
||||
extends Marker2D
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
6
scene/camera/camera_focus_marker.tscn
Normal file
6
scene/camera/camera_focus_marker.tscn
Normal file
@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cqkeegrcdjyg4"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/camera/camera_focus_marker.gd" id="1_7t4e6"]
|
||||
|
||||
[node name="CameraFocusMarker" type="Marker2D"]
|
||||
script = ExtResource("1_7t4e6")
|
9
scene/camera/main_camera.gd
Normal file
9
scene/camera/main_camera.gd
Normal file
@ -0,0 +1,9 @@
|
||||
extends Camera2D
|
||||
|
||||
class_name MainCamera
|
||||
|
||||
func _ready() -> void:
|
||||
enabled = true
|
||||
#position_smoothing_enabled = false
|
||||
position_smoothing_speed = 10
|
||||
position_smoothing_enabled = true
|
6
scene/camera/main_camera.tscn
Normal file
6
scene/camera/main_camera.tscn
Normal file
@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://ogyvstscr0kx"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/camera/main_camera.gd" id="1_pwiuw"]
|
||||
|
||||
[node name="MainCamera" type="Camera2D"]
|
||||
script = ExtResource("1_pwiuw")
|
1
scene/dialog/dialog_container.gd
Normal file
1
scene/dialog/dialog_container.gd
Normal file
@ -0,0 +1 @@
|
||||
extends Control
|
44
scene/dialog/dialog_container.tscn
Normal file
44
scene/dialog/dialog_container.tscn
Normal file
@ -0,0 +1,44 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dmkt1roqc4he7"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/dialog/dialog_container.gd" id="1_s1ka3"]
|
||||
[ext_resource type="Theme" uid="uid://j42sexotwnvk" path="res://config/default_theme.tres" id="2_q6yks"]
|
||||
|
||||
[node name="DialogContainer" type="MarginContainer"]
|
||||
anchors_preset = 12
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_top = -86.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
size_flags_vertical = 8
|
||||
theme_override_constants/margin_left = 32
|
||||
theme_override_constants/margin_top = 16
|
||||
theme_override_constants/margin_right = 32
|
||||
theme_override_constants/margin_bottom = 42
|
||||
script = ExtResource("1_s1ka3")
|
||||
|
||||
[node name="DialogPanelContainer" type="PanelContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DialogMarginContainer" type="MarginContainer" parent="DialogPanelContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("2_q6yks")
|
||||
theme_type_variation = &"dialog_container"
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 8
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 8
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="DialogPanelContainer/DialogMarginContainer"]
|
||||
custom_minimum_size = Vector2(460, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
mouse_filter = 2
|
||||
text = "Dialog: test
|
||||
2
|
||||
3
|
||||
4
|
||||
5"
|
||||
fit_content = true
|
8
scene/ground/boarder_frame.gd
Normal file
8
scene/ground/boarder_frame.gd
Normal file
@ -0,0 +1,8 @@
|
||||
extends Control
|
||||
|
||||
@onready var color_top := %ColorRectTop as ColorRect
|
||||
@onready var color_bottom := %ColorRectBottom as ColorRect
|
||||
|
||||
func _ready() -> void:
|
||||
color_top.color = GlobalConfig.COLOR_BOARDER
|
||||
color_bottom.color = GlobalConfig.COLOR_BOARDER
|
41
scene/ground/boarder_frame.tscn
Normal file
41
scene/ground/boarder_frame.tscn
Normal file
@ -0,0 +1,41 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://o4a2eluydtep"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/ground/boarder_frame.gd" id="1_50vde"]
|
||||
|
||||
[node name="BoarderFrame" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_50vde")
|
||||
|
||||
[node name="ColorRectTop" type="ColorRect" parent="."]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(564, 38.5)
|
||||
layout_mode = 1
|
||||
anchors_preset = 5
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
offset_left = -282.0
|
||||
offset_right = 282.0
|
||||
offset_bottom = 40.0
|
||||
grow_horizontal = 2
|
||||
color = Color(0.372549, 0.0156863, 0.0156863, 1)
|
||||
|
||||
[node name="ColorRectBottom" type="ColorRect" parent="."]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(564, 38.5)
|
||||
layout_mode = 1
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -282.0
|
||||
offset_top = -38.5
|
||||
offset_right = 282.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
color = Color(0.372549, 0.0156863, 0.0156863, 1)
|
12
scene/ground/parallax_background.gd
Normal file
12
scene/ground/parallax_background.gd
Normal file
@ -0,0 +1,12 @@
|
||||
extends ParallaxBackground
|
||||
|
||||
#
|
||||
## Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _physics_process(delta: float) -> void:
|
||||
#var x = Input.get_axis("left", "right")
|
||||
#var y = Input.get_axis("up", "down")
|
||||
#camera.position.x += delta * x * 1000
|
||||
#camera.position.y += delta * y * 1000
|
||||
|
||||
func _ready() -> void:
|
||||
layer = GlobalConfig.CANVAS_LAYER_BG
|
15
scene/ground/parallax_background.tscn
Normal file
15
scene/ground/parallax_background.tscn
Normal file
@ -0,0 +1,15 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://d0mnndg67dru1"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/ground/parallax_background.gd" id="1_w8735"]
|
||||
[ext_resource type="Texture2D" uid="uid://dukm6cix2kghn" path="res://asset/art/第一章/场景五(1012外间现实版)/1012外间.png" id="2_6t5qy"]
|
||||
|
||||
[node name="ParallaxBackground" type="ParallaxBackground"]
|
||||
scroll_base_offset = Vector2(-250, -200)
|
||||
script = ExtResource("1_w8735")
|
||||
|
||||
[node name="ParallaxLayer" type="ParallaxLayer" parent="."]
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="ParallaxLayer"]
|
||||
scale = Vector2(1.33649, 1.32083)
|
||||
texture = ExtResource("2_6t5qy")
|
||||
centered = false
|
5
scene/ground/parallax_foreground.gd
Normal file
5
scene/ground/parallax_foreground.gd
Normal file
@ -0,0 +1,5 @@
|
||||
extends ParallaxBackground
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
layer = GlobalConfig.CANVAS_LAYER_FG
|
21
scene/ground/parallax_foreground.tscn
Normal file
21
scene/ground/parallax_foreground.tscn
Normal file
@ -0,0 +1,21 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://02lmmldikfar"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/ground/parallax_foreground.gd" id="1_32n5c"]
|
||||
[ext_resource type="Texture2D" uid="uid://c0l7pkwvbrgey" path="res://asset/art/第一章/场景五(1012外间现实版)/前景.png" id="3_4g2yq"]
|
||||
[ext_resource type="PackedScene" uid="uid://o4a2eluydtep" path="res://scene/ground/boarder_frame.tscn" id="4_18dtv"]
|
||||
|
||||
[node name="ParallaxForeground" type="ParallaxBackground"]
|
||||
scroll_base_offset = Vector2(-250, -200)
|
||||
script = ExtResource("1_32n5c")
|
||||
|
||||
[node name="ParallaxLayer2" type="ParallaxLayer" parent="."]
|
||||
motion_scale = Vector2(1.1, 1.1)
|
||||
motion_mirroring = Vector2(2000, 1300)
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="ParallaxLayer2"]
|
||||
position = Vector2(2, 73)
|
||||
scale = Vector2(1.33886, 1.05)
|
||||
texture = ExtResource("3_4g2yq")
|
||||
centered = false
|
||||
|
||||
[node name="ShadedFrame" parent="." instance=ExtResource("4_18dtv")]
|
1
scene/hud/prop_hud.gd
Normal file
1
scene/hud/prop_hud.gd
Normal file
@ -0,0 +1 @@
|
||||
extends Control
|
85
scene/hud/prop_hud.tscn
Normal file
85
scene/hud/prop_hud.tscn
Normal file
@ -0,0 +1,85 @@
|
||||
[gd_scene load_steps=12 format=3 uid="uid://dc778gsjfr3ky"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/hud/prop_hud.gd" id="1_bbv0a"]
|
||||
[ext_resource type="Texture2D" uid="uid://chyumeohdhwnh" path="res://asset/art/ui/道具快捷栏/normal_left.png" id="2_bjc2b"]
|
||||
[ext_resource type="Texture2D" uid="uid://cvepj6u80c5wv" path="res://asset/art/ui/道具快捷栏/pressed_left.png" id="3_fca7p"]
|
||||
[ext_resource type="Script" path="res://ui/button/sound_texture_button.gd" id="3_xijdf"]
|
||||
[ext_resource type="Texture2D" uid="uid://bospbmb0gr2sb" path="res://asset/art/ui/道具快捷栏/Prop.png" id="5_6tt77"]
|
||||
[ext_resource type="Script" path="res://config/audio/audio_stream_collection.gd" id="5_wmvnw"]
|
||||
[ext_resource type="Resource" uid="uid://cor5ec6ogq3fe" path="res://config/audio/casino/card_slide.tres" id="6_32vbt"]
|
||||
[ext_resource type="Texture2D" uid="uid://optvgar5g2c" path="res://asset/art/道具/第一章/绳子物品.png" id="8_kpmil"]
|
||||
[ext_resource type="Texture2D" uid="uid://bgsbwhy1c2jna" path="res://asset/art/ui/道具快捷栏/hand.png" id="9_0crjo"]
|
||||
[ext_resource type="Texture2D" uid="uid://boqpr7i2a5uan" path="res://asset/art/ui/道具快捷栏/normal_right.png" id="10_vkaik"]
|
||||
[ext_resource type="Texture2D" uid="uid://daj2n408y2vfp" path="res://asset/art/ui/道具快捷栏/pressed_right.png" id="11_a512b"]
|
||||
|
||||
[node name="PropHUD" type="HBoxContainer"]
|
||||
offset_left = 10.0
|
||||
offset_top = 4.0
|
||||
offset_right = 98.0
|
||||
offset_bottom = 36.0
|
||||
scale = Vector2(0.3, 0.3)
|
||||
script = ExtResource("1_bbv0a")
|
||||
|
||||
[node name="LeftMargin" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 8
|
||||
|
||||
[node name="LeftButton" type="TextureButton" parent="LeftMargin"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource("2_bjc2b")
|
||||
texture_pressed = ExtResource("3_fca7p")
|
||||
stretch_mode = 5
|
||||
script = ExtResource("3_xijdf")
|
||||
|
||||
[node name="HudPanel" type="TextureButton" parent="."]
|
||||
custom_minimum_size = Vector2(32, 32)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource("5_6tt77")
|
||||
stretch_mode = 5
|
||||
script = ExtResource("3_xijdf")
|
||||
audio_collections = Array[ExtResource("5_wmvnw")]([ExtResource("6_32vbt")])
|
||||
|
||||
[node name="Prop" type="TextureRect" parent="HudPanel"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -73.0
|
||||
offset_top = -41.0
|
||||
offset_right = 73.0
|
||||
offset_bottom = 41.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
texture = ExtResource("8_kpmil")
|
||||
|
||||
[node name="Mark" type="TextureRect" parent="HudPanel"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -14.0
|
||||
offset_top = -15.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
texture = ExtResource("9_0crjo")
|
||||
|
||||
[node name="RightMargin" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_right = 8
|
||||
|
||||
[node name="RightButton" type="TextureButton" parent="RightMargin"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
texture_normal = ExtResource("10_vkaik")
|
||||
texture_pressed = ExtResource("11_a512b")
|
||||
stretch_mode = 5
|
||||
script = ExtResource("3_xijdf")
|
16
scene/hud/prop_hud_item_2d.tscn
Normal file
16
scene/hud/prop_hud_item_2d.tscn
Normal file
@ -0,0 +1,16 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dpgmgc5qf0apc"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_5nh3u"]
|
||||
script/source = "extends StaticBody2D
|
||||
|
||||
func _ready() -> void:
|
||||
pass"
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_gyjm3"]
|
||||
size = Vector2(38, 38)
|
||||
|
||||
[node name="PropHudItem2D" type="StaticBody2D"]
|
||||
script = SubResource("GDScript_5nh3u")
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("RectangleShape2D_gyjm3")
|
4
scene/main.gd
Normal file
4
scene/main.gd
Normal file
@ -0,0 +1,4 @@
|
||||
extends Node2D
|
||||
|
||||
func _ready() -> void:
|
||||
$UILayer.layer = GlobalConfig.CANVAS_LAYER_VIGNETTE
|
48
scene/main.tscn
Normal file
48
scene/main.tscn
Normal file
@ -0,0 +1,48 @@
|
||||
[gd_scene load_steps=12 format=3 uid="uid://dygvcmykn02n8"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://d0mnndg67dru1" path="res://scene/ground/parallax_background.tscn" id="1_f7g4d"]
|
||||
[ext_resource type="Script" path="res://scene/main.gd" id="1_pks84"]
|
||||
[ext_resource type="PackedScene" uid="uid://3gk1gxwanw24" path="res://ui/vignette/vignette_shading.tscn" id="2_d1re1"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmkt1roqc4he7" path="res://scene/dialog/dialog_container.tscn" id="3_prpss"]
|
||||
[ext_resource type="PackedScene" uid="uid://dc778gsjfr3ky" path="res://scene/hud/prop_hud.tscn" id="4_t7gb2"]
|
||||
[ext_resource type="PackedScene" uid="uid://5g07x6q7wwr1" path="res://scene/notification/notification.tscn" id="5_3gg5t"]
|
||||
[ext_resource type="PackedScene" uid="uid://cekhj65axie0p" path="res://scene/popup/prop_inspector_2d.tscn" id="5_ux0rw"]
|
||||
[ext_resource type="PackedScene" uid="uid://cjhw5ecygrqty" path="res://scene/player/player_2d.tscn" id="6_6geb0"]
|
||||
[ext_resource type="PackedScene" uid="uid://cqkeegrcdjyg4" path="res://scene/camera/camera_focus_marker.tscn" id="7_n7qcv"]
|
||||
[ext_resource type="PackedScene" uid="uid://ogyvstscr0kx" path="res://scene/camera/main_camera.tscn" id="8_nj084"]
|
||||
[ext_resource type="PackedScene" uid="uid://02lmmldikfar" path="res://scene/ground/parallax_foreground.tscn" id="11_anxqu"]
|
||||
|
||||
[node name="Main" type="Node2D"]
|
||||
script = ExtResource("1_pks84")
|
||||
|
||||
[node name="ParallaxBackground" parent="." instance=ExtResource("1_f7g4d")]
|
||||
|
||||
[node name="UILayer" type="CanvasLayer" parent="."]
|
||||
layer = 5
|
||||
|
||||
[node name="HUD2D" parent="UILayer" instance=ExtResource("4_t7gb2")]
|
||||
scale = Vector2(0.24, 0.24)
|
||||
mouse_filter = 0
|
||||
|
||||
[node name="DialogLayer" parent="UILayer" instance=ExtResource("3_prpss")]
|
||||
offset_top = -134.0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Notification" parent="UILayer" instance=ExtResource("5_3gg5t")]
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="VignetteShading" parent="." instance=ExtResource("2_d1re1")]
|
||||
|
||||
[node name="PropInspector2D" parent="." instance=ExtResource("5_ux0rw")]
|
||||
|
||||
[node name="Player2D" parent="." instance=ExtResource("6_6geb0")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="CameraFocusMarker" parent="Player2D" instance=ExtResource("7_n7qcv")]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="MainCamera" parent="Player2D/CameraFocusMarker" instance=ExtResource("8_nj084")]
|
||||
unique_name_in_owner = true
|
||||
position = Vector2(1, 0)
|
||||
|
||||
[node name="ParallaxForeground" parent="." instance=ExtResource("11_anxqu")]
|
6
scene/notification/notification.gd
Normal file
6
scene/notification/notification.gd
Normal file
@ -0,0 +1,6 @@
|
||||
extends Control
|
||||
|
||||
|
||||
func show_notification(msg, number):
|
||||
#TODO: Implement this method
|
||||
print("show_notification:", msg, number)
|
12
scene/notification/notification.tscn
Normal file
12
scene/notification/notification.tscn
Normal file
@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://5g07x6q7wwr1"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/notification/notification.gd" id="1_j0g80"]
|
||||
|
||||
[node name="Notification" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_j0g80")
|
166
scene/player/player_2d.gd
Normal file
166
scene/player/player_2d.gd
Normal file
@ -0,0 +1,166 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
class_name MainPlayer
|
||||
|
||||
enum MOVEMENT_STATUS {
|
||||
IDLE,
|
||||
WALKING,
|
||||
RUNNING,
|
||||
LAYING_STAY,
|
||||
LAYING_MOVING,
|
||||
CLIMBING_STAY,
|
||||
CLIMBING,
|
||||
}
|
||||
|
||||
@export var action_locked := false:
|
||||
set(val):
|
||||
action_locked = val
|
||||
_process_action_lock()
|
||||
@export var current_status : MOVEMENT_STATUS
|
||||
@export var facing_direction := Vector2(1.0, -1.0)
|
||||
@export var is_laying := false:
|
||||
set(val):
|
||||
is_laying = val
|
||||
# reset the facing direction wether the player is laying or not.
|
||||
_reset_face_direction()
|
||||
if is_laying:
|
||||
is_climbing = false
|
||||
@export var is_climbing := false:
|
||||
set(val):
|
||||
is_climbing = val
|
||||
# reset the facing direction wether the player is climbing or not.
|
||||
_reset_face_direction()
|
||||
if is_climbing:
|
||||
is_laying = false
|
||||
@export var running_locked := false
|
||||
@export var speed_walking := 300.0
|
||||
@export var speed_runnig := 500.0
|
||||
@export var speed_laying := 150.0
|
||||
@export var speed_climbing := 170.0
|
||||
#const JUMP_VELOCITY = -400.0
|
||||
|
||||
@onready var camera = %MainCamera as Camera2D
|
||||
@onready var sprite = %AnimatedSprite2D as AnimatedSprite2D
|
||||
|
||||
func _ready() -> void:
|
||||
_reset_face_direction()
|
||||
|
||||
func _reset_face_direction() -> void:
|
||||
facing_direction = Vector2(1, -1)
|
||||
|
||||
func _process_action_lock() -> void:
|
||||
# reset status to idle or stay
|
||||
if action_locked:
|
||||
if current_status == MOVEMENT_STATUS.WALKING or current_status == MOVEMENT_STATUS.RUNNING:
|
||||
current_status = MOVEMENT_STATUS.IDLE
|
||||
elif current_status == MOVEMENT_STATUS.LAYING_MOVING:
|
||||
current_status = MOVEMENT_STATUS.LAYING_STAY
|
||||
elif current_status == MOVEMENT_STATUS.CLIMBING:
|
||||
current_status = MOVEMENT_STATUS.CLIMBING_STAY
|
||||
_play_animation()
|
||||
|
||||
# return whether the player status or facing direction has changed.
|
||||
func _check_status(direction) -> bool:
|
||||
var tmp_status = current_status
|
||||
var new_facing_direction := facing_direction
|
||||
if is_laying:
|
||||
if direction.x:
|
||||
new_facing_direction.x = direction.x
|
||||
tmp_status = MOVEMENT_STATUS.LAYING_MOVING
|
||||
else:
|
||||
tmp_status = MOVEMENT_STATUS.LAYING_STAY
|
||||
elif is_climbing:
|
||||
if direction.y:
|
||||
new_facing_direction.y = direction.y
|
||||
tmp_status = MOVEMENT_STATUS.CLIMBING
|
||||
else:
|
||||
tmp_status = MOVEMENT_STATUS.CLIMBING_STAY
|
||||
else:
|
||||
if direction.x:
|
||||
new_facing_direction.x = direction.x
|
||||
tmp_status = MOVEMENT_STATUS.WALKING
|
||||
if !running_locked and Input.is_action_pressed("run"):
|
||||
tmp_status = MOVEMENT_STATUS.RUNNING
|
||||
else:
|
||||
tmp_status = MOVEMENT_STATUS.IDLE
|
||||
if new_facing_direction != facing_direction or tmp_status != current_status:
|
||||
facing_direction = new_facing_direction
|
||||
current_status = tmp_status
|
||||
return true
|
||||
return false
|
||||
|
||||
func _play_animation() -> void:
|
||||
match current_status:
|
||||
MOVEMENT_STATUS.IDLE:
|
||||
if facing_direction.x > 0.0:
|
||||
sprite.play(&"idle_r")
|
||||
else:
|
||||
sprite.play(&"idle_l")
|
||||
MOVEMENT_STATUS.WALKING:
|
||||
if facing_direction.x > 0.0:
|
||||
sprite.play(&"walking_r")
|
||||
else:
|
||||
sprite.play(&"walking_l")
|
||||
MOVEMENT_STATUS.RUNNING:
|
||||
if facing_direction.x > 0.0:
|
||||
sprite.play(&"running_r")
|
||||
else:
|
||||
sprite.play(&"running_l")
|
||||
MOVEMENT_STATUS.LAYING_STAY:
|
||||
if facing_direction.x > 0.0:
|
||||
sprite.play(&"laying_stay_r")
|
||||
else:
|
||||
sprite.play(&"laying_stay_l")
|
||||
MOVEMENT_STATUS.LAYING_MOVING:
|
||||
if facing_direction.x > 0.0:
|
||||
sprite.play(&"laying_moving_r")
|
||||
else:
|
||||
sprite.play(&"laying_moving_l")
|
||||
MOVEMENT_STATUS.CLIMBING_STAY:
|
||||
sprite.play(&"climbing_stay")
|
||||
MOVEMENT_STATUS.CLIMBING:
|
||||
if facing_direction.y > 0.0:
|
||||
sprite.play(&"climbing_down")
|
||||
else:
|
||||
sprite.play(&"climbing_up")
|
||||
|
||||
func _get_speed(direction: Vector2) -> Vector2:
|
||||
match current_status:
|
||||
MOVEMENT_STATUS.WALKING:
|
||||
return Vector2(speed_walking * direction.x, 0.0)
|
||||
MOVEMENT_STATUS.RUNNING:
|
||||
return Vector2(speed_runnig * direction.x, 0.0)
|
||||
MOVEMENT_STATUS.LAYING_MOVING:
|
||||
return Vector2(speed_laying * direction.x, 0.0)
|
||||
MOVEMENT_STATUS.CLIMBING:
|
||||
return Vector2(0, speed_climbing * direction.y)
|
||||
return Vector2(0, 0)
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if action_locked:
|
||||
velocity = Vector2.ZERO
|
||||
return
|
||||
|
||||
# Add the gravity.
|
||||
#if not is_on_floor():
|
||||
#velocity += get_gravity() * delta
|
||||
#if Input.is_action_just_pressed("jump") and is_on_floor():
|
||||
#velocity.y = JUMP_VELOCITY
|
||||
var x_direction := Input.get_axis("left", "right")
|
||||
var y_direction := Input.get_axis("up", "down")
|
||||
var direction := Vector2(x_direction, y_direction)
|
||||
if _check_status(direction):
|
||||
_play_animation()
|
||||
var speed := _get_speed(direction) as Vector2
|
||||
velocity.x = move_toward(velocity.x, speed.x, 300.0)
|
||||
velocity.y = move_toward(velocity.y, speed.y, 300.0)
|
||||
move_and_slide()
|
||||
_tweak_camera_marker()
|
||||
|
||||
# drag the camera marker against the player movement
|
||||
# so there will be a better vision in front of the player.
|
||||
func _tweak_camera_marker():
|
||||
var marker = get_node("./CameraFocusMarker") as Node2D
|
||||
if marker:
|
||||
marker.position.x = facing_direction.x * abs(velocity.x) * 0.11
|
||||
marker.position.y = facing_direction.y * abs(velocity.y) * 0.11
|
34
scene/player/player_2d.tscn
Normal file
34
scene/player/player_2d.tscn
Normal file
@ -0,0 +1,34 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cjhw5ecygrqty"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/player/player_2d.gd" id="1_3a78y"]
|
||||
[ext_resource type="SpriteFrames" uid="uid://c43gyexokirl4" path="res://config/animation/player_sprite_frames.tres" id="1_23i43"]
|
||||
[ext_resource type="Texture2D" uid="uid://t526pexw4ng4" path="res://asset/art/neutral_point_light.webp" id="3_scilj"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_fno82"]
|
||||
size = Vector2(105, 238.5)
|
||||
|
||||
[node name="Player2D" type="CharacterBody2D"]
|
||||
script = ExtResource("1_3a78y")
|
||||
current_status = null
|
||||
facing_direction = null
|
||||
running_locked = null
|
||||
speed_walking = null
|
||||
speed_runnig = null
|
||||
speed_laying = null
|
||||
speed_climbing = null
|
||||
|
||||
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
sprite_frames = ExtResource("1_23i43")
|
||||
animation = &"idle_r"
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2(-1, -1)
|
||||
shape = SubResource("RectangleShape2D_fno82")
|
||||
|
||||
[node name="PointLight2D" type="PointLight2D" parent="."]
|
||||
position = Vector2(2, -175)
|
||||
scale = Vector2(0.810547, 0.849609)
|
||||
energy = 0.4
|
||||
texture = ExtResource("3_scilj")
|
||||
height = 50.0
|
12
scene/popup/prop_inspector_2d.gd
Normal file
12
scene/popup/prop_inspector_2d.gd
Normal file
@ -0,0 +1,12 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var panel := %Panel
|
||||
|
||||
@export var shown := false:
|
||||
set(val):
|
||||
shown = val
|
||||
panel.visible = val
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
layer = GlobalConfig.CANVAS_LAYER_PROP_INSPECTOR
|
15
scene/popup/prop_inspector_2d.tscn
Normal file
15
scene/popup/prop_inspector_2d.tscn
Normal file
@ -0,0 +1,15 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cekhj65axie0p"]
|
||||
|
||||
[ext_resource type="Script" path="res://scene/popup/prop_inspector_2d.gd" id="1_p4yxb"]
|
||||
|
||||
[node name="PropInspector2D" type="CanvasLayer"]
|
||||
script = ExtResource("1_p4yxb")
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
9
scene/settings/settings.tscn
Normal file
9
scene/settings/settings.tscn
Normal file
@ -0,0 +1,9 @@
|
||||
[gd_scene format=3 uid="uid://beok2r6fgburn"]
|
||||
|
||||
[node name="Settings" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
19
ui/button/sound_button.gd
Normal file
19
ui/button/sound_button.gd
Normal file
@ -0,0 +1,19 @@
|
||||
extends Button
|
||||
|
||||
class_name SoundButton
|
||||
|
||||
@export var audio_collections: Array[AudioStreamCollection]
|
||||
|
||||
func _ready():
|
||||
if !audio_collections:
|
||||
audio_collections.append(preload("res://config/audio/ui/ui_click.tres"))
|
||||
#print("sound button loaded default ui_click.tres")
|
||||
|
||||
if audio_collections:
|
||||
#print("sound button load audio_collections into audio_player")
|
||||
var audio_player := RandomAudioStreamPlayer.new()
|
||||
audio_player.audio_collections = audio_collections
|
||||
pressed.connect(audio_player.play_random)
|
||||
add_child(audio_player)
|
||||
else:
|
||||
printerr("sound button has no audio_collections! ignore initialization of audio_player")
|
8
ui/button/sound_button.tscn
Normal file
8
ui/button/sound_button.tscn
Normal file
@ -0,0 +1,8 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bdy4u3e7rmo7f"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/button/sound_button.gd" id="1_vn1us"]
|
||||
|
||||
[node name="SoundButton" type="Button"]
|
||||
offset_right = 8.0
|
||||
offset_bottom = 8.0
|
||||
script = ExtResource("1_vn1us")
|
28
ui/button/sound_texture_button.gd
Normal file
28
ui/button/sound_texture_button.gd
Normal file
@ -0,0 +1,28 @@
|
||||
extends TextureButton
|
||||
|
||||
class_name SoundTextureButton
|
||||
|
||||
@export var audio_collections: Array[AudioStreamCollection]
|
||||
|
||||
func _ready():
|
||||
if !audio_collections:
|
||||
audio_collections.append(preload("res://config/audio/ui/ui_click.tres"))
|
||||
#print("sound button loaded default ui_click.tres")
|
||||
|
||||
if audio_collections:
|
||||
#print("sound button load audio_collections into audio_player")
|
||||
var audio_player := RandomAudioStreamPlayer.new()
|
||||
audio_player.audio_collections = audio_collections
|
||||
button_down.connect(audio_player.play_random)
|
||||
add_child(audio_player)
|
||||
else:
|
||||
printerr("sound button has no audio_collections! ignore initialization of audio_player")
|
||||
#button_down.connect(_on_press_down)
|
||||
#button_up.connect(_on_press_up)
|
||||
|
||||
|
||||
#func _on_press_down():
|
||||
#InputUtil.set_cursor_hand_patting()
|
||||
#
|
||||
#func _on_press_up():
|
||||
#InputUtil.set_cursor_hand_rest()
|
8
ui/button/sound_texture_button.tscn
Normal file
8
ui/button/sound_texture_button.tscn
Normal file
@ -0,0 +1,8 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cef5mgr1hgpmr"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/button/sound_texture_button.gd" id="1_k7j4d"]
|
||||
|
||||
[node name="SoundButton" type="TextureButton"]
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
script = ExtResource("1_k7j4d")
|
100
ui/hud/Inventory.tscn
Executable file
100
ui/hud/Inventory.tscn
Executable file
@ -0,0 +1,100 @@
|
||||
[gd_scene load_steps=14 format=3 uid="uid://cmyxinb0ickva"]
|
||||
|
||||
[ext_resource type="Script" path="res://UI/Inventory.gd" id="1_gbar7"]
|
||||
[ext_resource type="Texture2D" uid="uid://2jc6qio7tmuk" path="res://assets/HUD/背包按键/道具快捷栏/zz.png" id="2_c4gqh"]
|
||||
[ext_resource type="Texture2D" uid="uid://dr1fvkrmtynb6" path="res://assets/HUD/背包按键/道具快捷栏/az.png" id="3_ftsid"]
|
||||
[ext_resource type="Texture2D" uid="uid://b3pfdsyj0dcdb" path="res://assets/HUD/背包按键/道具快捷栏/wz.png" id="4_rn4wj"]
|
||||
[ext_resource type="Texture2D" uid="uid://ykv7o43dtjn0" path="res://assets/HUD/背包按键/道具快捷栏/k.png" id="5_o2bgy"]
|
||||
[ext_resource type="Texture2D" uid="uid://bgjt0y7vs5ix0" path="res://assets/HUD/背包按键/道具快捷栏/s.png" id="6_abx1s"]
|
||||
[ext_resource type="Texture2D" uid="uid://ukdbwrvd8qdq" path="res://assets/HUD/背包按键/道具快捷栏/zy.png" id="7_n66je"]
|
||||
[ext_resource type="Texture2D" uid="uid://sv8u083cpov6" path="res://assets/HUD/背包按键/道具快捷栏/ay.png" id="8_iym7w"]
|
||||
[ext_resource type="Texture2D" uid="uid://dva4vpj5uo8td" path="res://assets/HUD/背包按键/道具快捷栏/wy.png" id="9_aoirx"]
|
||||
[ext_resource type="FontFile" uid="uid://dehtmf0lanaf3" path="res://assets/HUD/字体/方正楷体简体.TTF" id="10_8p7i8"]
|
||||
|
||||
[sub_resource type="FontFile" id="FontFile_5oap5"]
|
||||
subpixel_positioning = 0
|
||||
msdf_pixel_range = 14
|
||||
msdf_size = 128
|
||||
cache/0/16/0/ascent = 0.0
|
||||
cache/0/16/0/descent = 0.0
|
||||
cache/0/16/0/underline_position = 0.0
|
||||
cache/0/16/0/underline_thickness = 0.0
|
||||
cache/0/16/0/scale = 1.0
|
||||
cache/0/16/0/kerning_overrides/16/0 = Vector2(0, 0)
|
||||
|
||||
[sub_resource type="Theme" id="Theme_bioai"]
|
||||
default_base_scale = 0.98
|
||||
default_font = SubResource("FontFile_5oap5")
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jk1w7"]
|
||||
size = Vector2(83.6779, 34.3683)
|
||||
|
||||
[node name="Inventory" type="VBoxContainer"]
|
||||
offset_left = 10.0
|
||||
offset_top = 7.0
|
||||
offset_right = 277.0
|
||||
offset_bottom = 184.0
|
||||
scale = Vector2(0.18, 0.18)
|
||||
theme_override_constants/separation = 5
|
||||
script = ExtResource("1_gbar7")
|
||||
|
||||
[node name="ItemBar" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Prev" type="TextureButton" parent="ItemBar"]
|
||||
custom_minimum_size = Vector2(60, 0)
|
||||
layout_mode = 2
|
||||
theme = SubResource("Theme_bioai")
|
||||
texture_normal = ExtResource("2_c4gqh")
|
||||
texture_pressed = ExtResource("3_ftsid")
|
||||
texture_disabled = ExtResource("4_rn4wj")
|
||||
stretch_mode = 3
|
||||
|
||||
[node name="Use" type="TextureButton" parent="ItemBar"]
|
||||
layout_mode = 2
|
||||
texture_normal = ExtResource("5_o2bgy")
|
||||
|
||||
[node name="Prop" type="Sprite2D" parent="ItemBar/Use"]
|
||||
z_index = 1
|
||||
position = Vector2(72, 72)
|
||||
|
||||
[node name="Hand" type="Sprite2D" parent="ItemBar/Use"]
|
||||
z_index = 1
|
||||
position = Vector2(110, 102)
|
||||
texture = ExtResource("6_abx1s")
|
||||
|
||||
[node name="Next" type="TextureButton" parent="ItemBar"]
|
||||
custom_minimum_size = Vector2(60, 0)
|
||||
layout_mode = 2
|
||||
texture_normal = ExtResource("7_n66je")
|
||||
texture_pressed = ExtResource("8_iym7w")
|
||||
texture_disabled = ExtResource("9_aoirx")
|
||||
stretch_mode = 3
|
||||
|
||||
[node name="Area2D" type="Area2D" parent="ItemBar"]
|
||||
visible = false
|
||||
position = Vector2(-200, -99.9999)
|
||||
scale = Vector2(3.60011, 5.23739)
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ItemBar/Area2D"]
|
||||
position = Vector2(91.4901, 32.4589)
|
||||
scale = Vector2(1, 0.999999)
|
||||
shape = SubResource("RectangleShape2D_jk1w7")
|
||||
one_way_collision_margin = 0.0
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("10_8p7i8")
|
||||
theme_override_font_sizes/font_size = 35
|
||||
text = "道具的描述"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Timer" type="Timer" parent="Label"]
|
||||
wait_time = 1.5
|
||||
one_shot = true
|
||||
|
||||
[connection signal="pressed" from="ItemBar/Prev" to="." method="_on_prev_pressed"]
|
||||
[connection signal="pressed" from="ItemBar/Use" to="." method="_on_use_pressed"]
|
||||
[connection signal="pressed" from="ItemBar/Next" to="." method="_on_next_pressed"]
|
||||
[connection signal="timeout" from="Label/Timer" to="." method="_on_timer_timeout"]
|
11
ui/hud/hud.tscn
Normal file
11
ui/hud/hud.tscn
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bs63fypttsiop"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cmyxinb0ickva" path="res://ui/hud/Inventory.tscn" id="1_tam4l"]
|
||||
|
||||
[node name="HUD" type="CanvasLayer"]
|
||||
layer = 99
|
||||
|
||||
[node name="Inventory" parent="." instance=ExtResource("1_tam4l")]
|
||||
offset_top = 4.0
|
||||
offset_bottom = 193.0
|
||||
script = null
|
112
ui/hud/inventory.gd
Executable file
112
ui/hud/inventory.gd
Executable file
@ -0,0 +1,112 @@
|
||||
#背包实现
|
||||
extends VBoxContainer
|
||||
|
||||
var _hand_outro: Tween
|
||||
var _label_outro: Tween
|
||||
#@onready var item_bar = $ItemBar
|
||||
@onready var prev = $ItemBar/Prev
|
||||
@onready var prop = $ItemBar/Use/Prop
|
||||
@onready var hand = $ItemBar/Use/Hand
|
||||
@onready var next = $ItemBar/Next
|
||||
@onready var label = $Label
|
||||
@onready var timer = $Label/Timer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
#SceneManager.inventory.add_item(preload("res://items/1014_yaoshi.tres"))
|
||||
#SceneManager.inventory.add_item(preload("res://items/3014_yaoshi.tres"))
|
||||
hand.hide()
|
||||
hand.modulate.a = 0.0
|
||||
label.hide()
|
||||
label.modulate.a = 0.0
|
||||
|
||||
SceneManager.inventory.changed.connect(_update_ui)
|
||||
_update_ui(true)
|
||||
|
||||
|
||||
#设置在屏幕中点击任意位置,互动手图案消失
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("click") and SceneManager.inventory.active_item:
|
||||
SceneManager.inventory.set_deferred("active_item", true)
|
||||
|
||||
_hand_outro = create_tween()
|
||||
_hand_outro.set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE).set_parallel()
|
||||
_hand_outro.tween_property(hand, "scale", Vector2.ONE * 0.5, 0.15) #Vector2.ONE * 0.5 设置手缩放的大小.0.15表示消失的速度
|
||||
_hand_outro.tween_property(hand, "modulate:a", 0.0, 0.15)
|
||||
_hand_outro.chain().tween_callback(hand.hide)
|
||||
|
||||
|
||||
|
||||
func _update_ui(is_init = false): #is_inte = false 让背包物品在最开始出现时没有动画效果
|
||||
var count = SceneManager.inventory.get_item_count()
|
||||
prev.disabled = count < 2
|
||||
next.disabled = count < 2
|
||||
visible = count > 0
|
||||
|
||||
var item = SceneManager.inventory.get_current_item()
|
||||
if not item:
|
||||
return
|
||||
else:
|
||||
label.text = item.description
|
||||
prop.texture = item.prop_texture
|
||||
#item_bar.modulate.a = 1
|
||||
#print("prop")
|
||||
|
||||
#添加背包物品在左右滑动时的弹出动画效果
|
||||
|
||||
if is_init:
|
||||
return
|
||||
|
||||
var tween := create_tween()
|
||||
tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
||||
tween.tween_property(prop, "scale", Vector2.ONE, 0.15).from(Vector2.ZERO)
|
||||
|
||||
_show_label()
|
||||
|
||||
func _show_label() -> void:
|
||||
if _label_outro and _label_outro.is_valid():
|
||||
_label_outro.kill()
|
||||
_label_outro = null
|
||||
label.show()
|
||||
var tween = create_tween()
|
||||
tween.set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE)
|
||||
tween.tween_property(label,"modulate:a",1.0,0.2)
|
||||
tween.tween_callback(timer.start)
|
||||
|
||||
|
||||
|
||||
func _on_prev_pressed() -> void:
|
||||
SoundManager.play_sfx("interact")
|
||||
SceneManager.inventory.select_prev()
|
||||
print("prev1")
|
||||
|
||||
func _on_next_pressed() -> void:
|
||||
SoundManager.play_sfx("interact")
|
||||
SceneManager.inventory.select_next()
|
||||
print("next2")
|
||||
|
||||
@onready var use = $ItemBar/Use
|
||||
|
||||
|
||||
func _on_use_pressed() -> void:
|
||||
if use.button_mask == MOUSE_BUTTON_MASK_LEFT:
|
||||
SceneManager.inventory.active_item = SceneManager.inventory.get_current_item()
|
||||
print("use3")
|
||||
|
||||
if _hand_outro and _hand_outro.is_valid():
|
||||
_hand_outro.kill()
|
||||
_hand_outro = null
|
||||
hand.show()
|
||||
var tween = create_tween()
|
||||
tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK).set_parallel()
|
||||
tween.tween_property(hand, "scale", Vector2.ONE, 0.15).from(Vector2.ZERO)
|
||||
tween.tween_property(hand, "modulate:a", 1.0, 0.15)
|
||||
|
||||
_show_label()
|
||||
|
||||
|
||||
func _on_timer_timeout():
|
||||
_label_outro = create_tween()
|
||||
_label_outro.set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE)
|
||||
_label_outro.tween_property(label,"modulate:a",0.0,0.2)
|
||||
_label_outro.chain().tween_callback(label.hide)
|
10
ui/settings.tscn
Normal file
10
ui/settings.tscn
Normal file
@ -0,0 +1,10 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c5wtakm14h7cy"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://db8rd4nwl6pve" path="res://asset/art/ui/ui_settings.skt/Layer~2.png" id="1_sl0gr"]
|
||||
|
||||
[sub_resource type="AtlasTexture" id="AtlasTexture_jngmd"]
|
||||
atlas = ExtResource("1_sl0gr")
|
||||
region = Rect2(254, 362, 994, 1314)
|
||||
|
||||
[node name="Settings" type="Sprite2D"]
|
||||
texture = SubResource("AtlasTexture_jngmd")
|
14
ui/vignette/vignette_shading.gd
Normal file
14
ui/vignette/vignette_shading.gd
Normal file
@ -0,0 +1,14 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@export var rgb := Color8(0x3f,0x26,0x31):
|
||||
set(new_val):
|
||||
rgb = new_val
|
||||
%ColorRect.material.set("shader_parameter/vignette_rgb", new_val)
|
||||
|
||||
@export_range(0, 5) var intensity := 0.3:
|
||||
set(new_val):
|
||||
intensity = new_val
|
||||
%ColorRect.material.set("shader_parameter/vignette_intensity", new_val)
|
||||
|
||||
func _ready() -> void:
|
||||
layer = GlobalConfig.CANVAS_LAYER_VIGNETTE
|
23
ui/vignette/vignette_shading.tscn
Normal file
23
ui/vignette/vignette_shading.tscn
Normal file
@ -0,0 +1,23 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://3gk1gxwanw24"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/vignette/vignette_shading.gd" id="1_6w7er"]
|
||||
[ext_resource type="Shader" path="res://asset/shader/vignette.gdshader" id="1_akp6k"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_pabt5"]
|
||||
shader = ExtResource("1_akp6k")
|
||||
shader_parameter/vignette_intensity = 0.4
|
||||
shader_parameter/vignette_rgb = Color(0.247059, 0.14902, 0.192157, 1)
|
||||
|
||||
[node name="VignetteShading" type="CanvasLayer"]
|
||||
layer = 100
|
||||
script = ExtResource("1_6w7er")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
unique_name_in_owner = true
|
||||
material = SubResource("ShaderMaterial_pabt5")
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
17
util/resource_utils.gd
Normal file
17
util/resource_utils.gd
Normal file
@ -0,0 +1,17 @@
|
||||
extends Object
|
||||
class_name ResourceUtils
|
||||
|
||||
# # remove editor's cache
|
||||
# func remove_editor_cache(resource: Resource) -> void:
|
||||
# if Engine.is_editor_hint():
|
||||
# (resource)
|
||||
|
||||
|
||||
static func remove_editor_cache(name: String) -> void:
|
||||
pass
|
||||
# var dir = DirAccess.open("res://.godot/editor")
|
||||
# for file in dir.get_files():
|
||||
# if file.get_basename().begins_with(name):
|
||||
# DirAccess.remove_absolute("res://.godot/editor/" + file)
|
||||
# print("Removed editor cache: ", file)
|
||||
# break
|
Loading…
Reference in New Issue
Block a user