386 lines
12 KiB
GDScript
386 lines
12 KiB
GDScript
extends Control
|
|
## 角色自定义界面
|
|
## 允许玩家自定义角色外观和个性
|
|
|
|
# 预加载必要的类
|
|
const CharacterDataClass = preload("res://scripts/CharacterData.gd")
|
|
|
|
# UI 元素
|
|
var container: VBoxContainer
|
|
var tabs: TabContainer
|
|
|
|
# 外观自定义
|
|
var appearance_container: VBoxContainer
|
|
var body_color_picker: ColorPicker
|
|
var head_color_picker: ColorPicker
|
|
var hair_color_picker: ColorPicker
|
|
var clothing_color_picker: ColorPicker
|
|
var randomize_appearance_button: Button
|
|
|
|
# 个性自定义
|
|
var personality_container: VBoxContainer
|
|
var trait_checkboxes: Dictionary = {}
|
|
var activity_option: OptionButton
|
|
var bio_text: TextEdit
|
|
|
|
# 预览
|
|
var preview_character: CharacterSprite
|
|
|
|
# 按钮
|
|
var save_button: Button
|
|
var cancel_button: Button
|
|
|
|
# 数据
|
|
var character_data: Dictionary = {}
|
|
|
|
# 信号
|
|
signal customization_saved(character_data: Dictionary)
|
|
signal customization_cancelled()
|
|
|
|
func _ready():
|
|
## 初始化自定义界面
|
|
_create_ui()
|
|
_setup_connections()
|
|
|
|
## 创建UI
|
|
func _create_ui():
|
|
## 创建自定义界面的所有UI元素
|
|
# 设置为全屏
|
|
anchor_right = 1.0
|
|
anchor_bottom = 1.0
|
|
|
|
# 添加半透明背景
|
|
var background = ColorRect.new()
|
|
background.color = Color(0, 0, 0, 0.7)
|
|
background.anchor_right = 1.0
|
|
background.anchor_bottom = 1.0
|
|
add_child(background)
|
|
|
|
# 主容器
|
|
container = VBoxContainer.new()
|
|
container.anchor_right = 1.0
|
|
container.anchor_bottom = 1.0
|
|
container.add_theme_constant_override("separation", 10)
|
|
add_child(container)
|
|
|
|
# 标题栏
|
|
var title_container = HBoxContainer.new()
|
|
container.add_child(title_container)
|
|
|
|
var title = Label.new()
|
|
title.text = "角色自定义"
|
|
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
title.add_theme_font_size_override("font_size", 24)
|
|
title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
title_container.add_child(title)
|
|
|
|
var close_button = Button.new()
|
|
close_button.text = "✕"
|
|
close_button.custom_minimum_size = Vector2(40, 40)
|
|
close_button.pressed.connect(_on_cancel_pressed)
|
|
title_container.add_child(close_button)
|
|
|
|
# 滚动容器
|
|
var scroll_container = ScrollContainer.new()
|
|
scroll_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
container.add_child(scroll_container)
|
|
|
|
# 标签页容器
|
|
tabs = TabContainer.new()
|
|
tabs.custom_minimum_size = Vector2(0, 500)
|
|
scroll_container.add_child(tabs)
|
|
|
|
# 创建外观标签页
|
|
_create_appearance_tab()
|
|
|
|
# 创建个性标签页
|
|
_create_personality_tab()
|
|
|
|
# 预览区域
|
|
_create_preview_area()
|
|
|
|
# 按钮区域
|
|
_create_button_area()
|
|
|
|
## 创建外观标签页
|
|
func _create_appearance_tab():
|
|
## 创建外观自定义标签页
|
|
appearance_container = VBoxContainer.new()
|
|
appearance_container.name = "外观"
|
|
tabs.add_child(appearance_container)
|
|
|
|
# 身体颜色
|
|
var body_section = _create_color_section("身体颜色", Color(0.29, 0.56, 0.89))
|
|
appearance_container.add_child(body_section.container)
|
|
body_color_picker = body_section.picker
|
|
|
|
# 头部颜色
|
|
var head_section = _create_color_section("头部颜色", Color(0.96, 0.90, 0.83))
|
|
appearance_container.add_child(head_section.container)
|
|
head_color_picker = head_section.picker
|
|
|
|
# 头发颜色
|
|
var hair_section = _create_color_section("头发颜色", Color(0.55, 0.27, 0.07))
|
|
appearance_container.add_child(hair_section.container)
|
|
hair_color_picker = hair_section.picker
|
|
|
|
# 服装颜色
|
|
var clothing_section = _create_color_section("服装颜色", Color(0.18, 0.55, 0.34))
|
|
appearance_container.add_child(clothing_section.container)
|
|
clothing_color_picker = clothing_section.picker
|
|
|
|
# 随机化按钮
|
|
randomize_appearance_button = Button.new()
|
|
randomize_appearance_button.text = "随机外观"
|
|
randomize_appearance_button.custom_minimum_size = Vector2(0, 40)
|
|
appearance_container.add_child(randomize_appearance_button)
|
|
|
|
## 创建颜色选择区域
|
|
func _create_color_section(label_text: String, default_color: Color) -> Dictionary:
|
|
## 创建颜色选择区域
|
|
var section_container = VBoxContainer.new()
|
|
|
|
var label = Label.new()
|
|
label.text = label_text
|
|
section_container.add_child(label)
|
|
|
|
var picker = ColorPicker.new()
|
|
picker.color = default_color
|
|
picker.custom_minimum_size = Vector2(300, 200)
|
|
picker.edit_alpha = false # 不需要透明度调节
|
|
section_container.add_child(picker)
|
|
|
|
return {
|
|
"container": section_container,
|
|
"picker": picker
|
|
}
|
|
|
|
## 创建个性标签页
|
|
func _create_personality_tab():
|
|
## 创建个性自定义标签页
|
|
personality_container = VBoxContainer.new()
|
|
personality_container.name = "个性"
|
|
tabs.add_child(personality_container)
|
|
|
|
# 个性特征
|
|
var traits_label = Label.new()
|
|
traits_label.text = "个性特征 (最多选择4个):"
|
|
personality_container.add_child(traits_label)
|
|
|
|
var traits_grid = GridContainer.new()
|
|
traits_grid.columns = 3
|
|
personality_container.add_child(traits_grid)
|
|
|
|
var personalization = preload("res://scripts/CharacterPersonalization.gd")
|
|
for trait_in in personalization.PERSONALITY_TRAITS:
|
|
var checkbox = CheckBox.new()
|
|
checkbox.text = trait_in
|
|
traits_grid.add_child(checkbox)
|
|
trait_checkboxes[trait_in] = checkbox
|
|
|
|
# 喜欢的活动
|
|
var activity_label = Label.new()
|
|
activity_label.text = "喜欢的活动:"
|
|
personality_container.add_child(activity_label)
|
|
|
|
activity_option = OptionButton.new()
|
|
for activity in personalization.ACTIVITIES:
|
|
activity_option.add_item(activity)
|
|
personality_container.add_child(activity_option)
|
|
|
|
# 个人简介
|
|
var bio_label = Label.new()
|
|
bio_label.text = "个人简介 (可选):"
|
|
personality_container.add_child(bio_label)
|
|
|
|
bio_text = TextEdit.new()
|
|
bio_text.custom_minimum_size = Vector2(0, 100)
|
|
bio_text.placeholder_text = "介绍一下你的角色..."
|
|
personality_container.add_child(bio_text)
|
|
|
|
## 创建预览区域
|
|
func _create_preview_area():
|
|
## 创建角色预览区域
|
|
var preview_label = Label.new()
|
|
preview_label.text = "预览:"
|
|
preview_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
container.add_child(preview_label)
|
|
|
|
var preview_container = CenterContainer.new()
|
|
preview_container.custom_minimum_size = Vector2(0, 100)
|
|
container.add_child(preview_container)
|
|
|
|
preview_character = CharacterSprite.new()
|
|
preview_container.add_child(preview_character)
|
|
|
|
## 创建按钮区域
|
|
func _create_button_area():
|
|
## 创建按钮区域
|
|
var button_container = HBoxContainer.new()
|
|
button_container.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
container.add_child(button_container)
|
|
|
|
save_button = Button.new()
|
|
save_button.text = "保存"
|
|
save_button.custom_minimum_size = Vector2(100, 40)
|
|
button_container.add_child(save_button)
|
|
|
|
var spacer = Control.new()
|
|
spacer.custom_minimum_size = Vector2(20, 0)
|
|
button_container.add_child(spacer)
|
|
|
|
cancel_button = Button.new()
|
|
cancel_button.text = "取消"
|
|
cancel_button.custom_minimum_size = Vector2(100, 40)
|
|
button_container.add_child(cancel_button)
|
|
|
|
## 设置连接
|
|
func _setup_connections():
|
|
## 设置信号连接
|
|
# 颜色选择器变化
|
|
body_color_picker.color_changed.connect(_on_appearance_changed)
|
|
head_color_picker.color_changed.connect(_on_appearance_changed)
|
|
hair_color_picker.color_changed.connect(_on_appearance_changed)
|
|
clothing_color_picker.color_changed.connect(_on_appearance_changed)
|
|
|
|
# 随机化按钮
|
|
randomize_appearance_button.pressed.connect(_on_randomize_appearance)
|
|
|
|
# 个性特征复选框
|
|
for checkbox in trait_checkboxes.values():
|
|
checkbox.toggled.connect(_on_trait_toggled)
|
|
|
|
# 按钮
|
|
save_button.pressed.connect(_on_save_pressed)
|
|
cancel_button.pressed.connect(_on_cancel_pressed)
|
|
|
|
## 加载角色数据
|
|
func load_character_data(data: Dictionary):
|
|
## 加载角色数据到界面
|
|
## @param data: 角色数据
|
|
character_data = data.duplicate(true)
|
|
|
|
# 加载外观数据
|
|
var appearance = data.get(CharacterDataClass.FIELD_APPEARANCE, {})
|
|
if appearance.has("body_color"):
|
|
body_color_picker.color = Color(appearance["body_color"])
|
|
if appearance.has("head_color"):
|
|
head_color_picker.color = Color(appearance["head_color"])
|
|
if appearance.has("hair_color"):
|
|
hair_color_picker.color = Color(appearance["hair_color"])
|
|
if appearance.has("clothing_color"):
|
|
clothing_color_picker.color = Color(appearance["clothing_color"])
|
|
|
|
# 加载个性数据
|
|
var personality = data.get(CharacterDataClass.FIELD_PERSONALITY, {})
|
|
var traits = personality.get("traits", [])
|
|
|
|
# 设置特征复选框
|
|
for trait_in in trait_checkboxes:
|
|
trait_checkboxes[trait_in].button_pressed = trait_in in traits
|
|
|
|
# 设置活动选项
|
|
var activity = personality.get("favorite_activity", "exploring")
|
|
var personalization = preload("res://scripts/CharacterPersonalization.gd")
|
|
var activity_index = personalization.ACTIVITIES.find(activity)
|
|
if activity_index >= 0:
|
|
activity_option.selected = activity_index
|
|
|
|
# 设置简介
|
|
bio_text.text = personality.get("bio", "")
|
|
|
|
# 更新预览
|
|
_update_preview()
|
|
|
|
## 外观变化回调
|
|
func _on_appearance_changed(_color: Color):
|
|
## 外观变化时更新预览
|
|
_update_preview()
|
|
|
|
## 随机化外观
|
|
func _on_randomize_appearance():
|
|
## 随机化角色外观
|
|
var personalization = preload("res://scripts/CharacterPersonalization.gd")
|
|
var random_appearance = personalization.generate_random_appearance()
|
|
|
|
body_color_picker.color = Color(random_appearance["body_color"])
|
|
head_color_picker.color = Color(random_appearance["head_color"])
|
|
hair_color_picker.color = Color(random_appearance["hair_color"])
|
|
clothing_color_picker.color = Color(random_appearance["clothing_color"])
|
|
|
|
_update_preview()
|
|
|
|
## 特征切换回调
|
|
func _on_trait_toggled(_pressed: bool):
|
|
## 特征复选框切换时检查数量限制
|
|
var selected_traits = []
|
|
for trait_in in trait_checkboxes:
|
|
if trait_checkboxes[trait_in].button_pressed:
|
|
selected_traits.append(trait_in)
|
|
|
|
# 限制最多4个特征
|
|
if selected_traits.size() > 4:
|
|
# 找到最后选中的并取消
|
|
for trait_in in trait_checkboxes:
|
|
if trait_checkboxes[trait_in].button_pressed and trait_in not in selected_traits.slice(0, 4):
|
|
trait_checkboxes[trait_in].button_pressed = false
|
|
break
|
|
|
|
## 保存按钮回调
|
|
func _on_save_pressed():
|
|
## 保存自定义设置
|
|
# 更新外观数据
|
|
var appearance = {
|
|
"sprite": "character_01",
|
|
"color": "#FFFFFF",
|
|
"body_color": body_color_picker.color.to_html(),
|
|
"head_color": head_color_picker.color.to_html(),
|
|
"hair_color": hair_color_picker.color.to_html(),
|
|
"clothing_color": clothing_color_picker.color.to_html()
|
|
}
|
|
CharacterDataClass.set_appearance(character_data, appearance)
|
|
|
|
# 更新个性数据
|
|
var selected_traits = []
|
|
for trait_in in trait_checkboxes:
|
|
if trait_checkboxes[trait_in].button_pressed:
|
|
selected_traits.append(trait_in)
|
|
|
|
var personality = {
|
|
"traits": selected_traits,
|
|
"bio": bio_text.text,
|
|
"favorite_activity": preload("res://scripts/CharacterPersonalization.gd").ACTIVITIES[activity_option.selected]
|
|
}
|
|
character_data[CharacterDataClass.FIELD_PERSONALITY] = personality
|
|
|
|
customization_saved.emit(character_data)
|
|
|
|
## 取消按钮回调
|
|
func _on_cancel_pressed():
|
|
## 取消自定义
|
|
customization_cancelled.emit()
|
|
|
|
## 处理输入事件
|
|
func _input(event):
|
|
## 处理ESC键关闭界面
|
|
if event is InputEventKey and event.pressed:
|
|
if event.keycode == KEY_ESCAPE:
|
|
_on_cancel_pressed()
|
|
get_viewport().set_input_as_handled()
|
|
|
|
## 更新预览
|
|
func _update_preview():
|
|
## 更新角色预览
|
|
if not preview_character:
|
|
return
|
|
|
|
var appearance = {
|
|
"body_color": body_color_picker.color.to_html(),
|
|
"head_color": head_color_picker.color.to_html(),
|
|
"hair_color": hair_color_picker.color.to_html(),
|
|
"clothing_color": clothing_color_picker.color.to_html()
|
|
}
|
|
|
|
var personalization = preload("res://scripts/CharacterPersonalization.gd")
|
|
personalization.apply_appearance_to_sprite(preview_character, appearance)
|