feat: 审计差距②③背景/形态三件(T5-T8)——T5 屏底氛围层单点(backdrop_tile 0.14/vignette/beams/地图渐变 #4A3B2A→#3A2E22@40%;start/map/camp 三面旧满铺石纹退役,地图换层 tint 保 0.14 档)+T6 商店全屏页壳(page_shell 56px 通栏顶条+爬价规则行 set_visit_info〔shop_bp_visit_buys×shop_price_a 投喂三口〕+底注池源;bcard D1=232×352+图标槽 76/60)+T7 三选一同壳全屏(GP 汇总行+底部确认钮+免费注记)+T8 设置两列对齐(label 定宽 140/why 内联/返回 90 紧凑;减动效行核证=reduced_motion 单设置同驱 motion_scale+结算演播,demo 两行系同一设置不拆)——冒烟782/0+probe_gate --click全绿
This commit is contained in:
1 parent
58e8903a3c
commit
5e2fa8bb87
9 files changed
+231
-67
No files matched your search
@@ -153,6 +153,7 @@ func on_shop_buy(product_id: String) -> void:
|
||||
toast.show_toast("金币不足——买不起这件商品", "warn")
|
||||
return
|
||||
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
|
||||
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
|
||||
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost())
|
||||
_refresh_presentations.call()
|
||||
return
|
||||
@@ -174,6 +175,7 @@ func on_shop_refresh() -> void:
|
||||
toast.show_toast("金币不足——刷新失败", "warn")
|
||||
return
|
||||
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
|
||||
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
|
||||
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost())
|
||||
_refresh_presentations.call()
|
||||
|
||||
|
||||
@@ -521,9 +521,11 @@ func _on_runner_node(node: Dictionary, info: Dictionary) -> void:
|
||||
_open_modal(shop_overlay)
|
||||
if runner.is_shop_pool():
|
||||
shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp))
|
||||
shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行
|
||||
shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost()) # MC-1
|
||||
else:
|
||||
shop_overlay.open_shop(runner.shop_products(), int(runner.gp))
|
||||
shop_overlay.set_visit_info(-1, 1.0) # legacy 面无爬价行(off 对照承载)
|
||||
log_view.append_bb(Narrator.shop_line(int(runner.gp)))
|
||||
logger.log_node(node, info, runner.node_index)
|
||||
_refresh_presentations()
|
||||
|
||||
@@ -102,16 +102,13 @@ static func build_overlays(host: Control, db) -> Dictionary:
|
||||
static func build_start_overlay(host: Control, db = null) -> Dictionary:
|
||||
var overlay := overlay_bg(host, UiKit.BG_BRIGHT)
|
||||
overlay.theme = UiKit.tooltip_theme()
|
||||
# 石纹底噪底层(样张 v2 冻结批 T2——z 序=dim 之上/内容之下;缺位不挂即回退平色)
|
||||
var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
|
||||
if bd_tex != null:
|
||||
var bd := TextureRect.new()
|
||||
bd.texture = bd_tex
|
||||
bd.stretch_mode = TextureRect.STRETCH_TILE
|
||||
bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
bd.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
bd.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
# 石纹弱质感+斜光带+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.beams/.vignette 三层;
|
||||
# 旧满铺石纹不透退役。缺位不挂即回退平色)
|
||||
var bd := UiKit.backdrop_tile()
|
||||
if bd != null:
|
||||
overlay.add_child(bd)
|
||||
overlay.add_child(UiKit.beams_rect())
|
||||
overlay.add_child(UiKit.vignette_rect())
|
||||
# 双列骨架(M2):左=操作列 56% / 右=舞台+速览
|
||||
var cols := HBoxContainer.new()
|
||||
cols.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
|
||||
@@ -39,16 +39,12 @@ var _recent_list: Label # 最近冒险(逐行拼接 label——只读
|
||||
|
||||
func _init() -> void:
|
||||
var dim := UiKit.modal_dim(self, Color(0, 0, 0, 0.45)) # 方向稿=石纹底透出(浅 dim——石纹全屏底担当氛围)
|
||||
# 石纹底噪(样张 v2 冻结件——start overlay 同款;缺位不挂即回退平 dim)
|
||||
var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
|
||||
if bd_tex != null:
|
||||
var bd := TextureRect.new()
|
||||
bd.texture = bd_tex
|
||||
bd.stretch_mode = TextureRect.STRETCH_TILE
|
||||
bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
bd.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
bd.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
# 石纹弱质感+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.vignette;旧满铺石纹不透退役;
|
||||
# 缺位不挂即回退平 dim)
|
||||
var bd := UiKit.backdrop_tile()
|
||||
if bd != null:
|
||||
dim.add_child(bd)
|
||||
dim.add_child(UiKit.vignette_rect())
|
||||
|
||||
var root := MarginContainer.new()
|
||||
root.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
|
||||
@@ -20,6 +20,7 @@ var _continue_btn: Button # 继续钮(兑付反馈态唯一
|
||||
var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示;M7 升顶条图标钮)
|
||||
var _refresh_badge: Label # M7 余量角标(图标钮右上——demo ⑥ 同构)
|
||||
var _refresh_l: Label # 刷新余量读数(X 优先 + Y 冒险池)
|
||||
var _foot_hint: Label # T7 底注(demo .bonus-foot .hint——pick 态显隐)
|
||||
var _refresh_allowance := 0 # 组合根投喂余量(本视图零核心引用)
|
||||
var _selected := "" # 点选暂存(确认前可改选)
|
||||
var _header := "" # 停点头部文案(选择态保持显示)
|
||||
@@ -28,12 +29,12 @@ var _bcards: Array = [] # M7 bcard 引用列(select 高亮
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
# M7(UI 落码批):与商店同构(demo ⑥ 用户令两屏一致)——通栏顶条(标题+刷新图标钮/角标)+
|
||||
# 居中入账信息行 + bcard 三竖卡 + 底部唯一主钮「确认选择」;差异白名单=免费选择/✓章/无价签
|
||||
var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box
|
||||
var top := HBoxContainer.new()
|
||||
top.add_theme_constant_override("separation", 12)
|
||||
box.add_child(top)
|
||||
# T7(UI 设计对齐批 2026-10-06):全屏页形态(demo ⑥ #v-bonus——与商店 T6 同壳 page_shell,
|
||||
# 根底暗档)——56px 通栏顶条(标题+刷新图标钮/角标)+ 居中入账信息行(GP 汇总行承载)+
|
||||
# bcard 三竖卡(D1 232×352)+ 底部确认主钮与免费选择注记。差异白名单=免费选择/✓章/无价签。
|
||||
# 状态机不变:pick→[replace]→result。M7 同构裁决遗产保留。
|
||||
var page: Dictionary = UiKit.page_shell(self, false)
|
||||
var top: HBoxContainer = page.top_row
|
||||
top.add_child(UiKit.label("战利品三选一",UiKit.FS_TITLE, true, UiKit.WARM))
|
||||
var top_sp := Control.new()
|
||||
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
@@ -54,25 +55,34 @@ func _init() -> void:
|
||||
_refresh_l = UiKit.label("",UiKit.FS_CAPTION, false, UiKit.WARM_SOFT)
|
||||
_refresh_l.visible = false
|
||||
top.add_child(_refresh_l)
|
||||
var box: VBoxContainer = page.box
|
||||
_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT)
|
||||
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
box.add_child(_label)
|
||||
_choice_box = HBoxContainer.new()
|
||||
_choice_box.add_theme_constant_override("separation", 20)
|
||||
_choice_box.add_theme_constant_override("separation", 26) # demo .cards gap 26(T7 对齐)
|
||||
_choice_box.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
_choice_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
box.add_child(_choice_box)
|
||||
var foot := HBoxContainer.new()
|
||||
foot.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
foot.add_theme_constant_override("separation", 16)
|
||||
box.add_child(foot)
|
||||
_confirm_btn = UiKit.primary_button("确认选择")
|
||||
_confirm_btn.pressed.connect(_on_confirm_pressed)
|
||||
_confirm_btn.visible = false
|
||||
box.add_child(_confirm_btn)
|
||||
_replace_box = VBoxContainer.new()
|
||||
_replace_box.add_theme_constant_override("separation", 8)
|
||||
_replace_box.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
box.add_child(_replace_box)
|
||||
foot.add_child(_confirm_btn)
|
||||
_continue_btn = UiKit.button("继续")
|
||||
_continue_btn.pressed.connect(_emit_continue_pressed)
|
||||
_continue_btn.visible = false
|
||||
box.add_child(_continue_btn)
|
||||
foot.add_child(_continue_btn)
|
||||
_foot_hint = UiKit.label("免费选择 · 刷新不消耗 AP",UiKit.FS_HINT, false, UiKit.WARM_FAINT)
|
||||
foot.add_child(_foot_hint)
|
||||
_replace_box = VBoxContainer.new()
|
||||
_replace_box.add_theme_constant_override("separation", 8)
|
||||
_replace_box.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
_replace_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
box.add_child(_replace_box)
|
||||
visible = false
|
||||
|
||||
|
||||
@@ -105,6 +115,7 @@ func open_pick(header: String, cards: Array) -> void:
|
||||
_confirm_btn.visible = false
|
||||
_replace_box.visible = false
|
||||
_continue_btn.visible = false
|
||||
_foot_hint.visible = true # T7 底注=pick 态专属(replace/result 态让位)
|
||||
_refresh_btn.visible = false # 刷新余量随 set_refresh_info 投喂后现形(open 先归零防残留)
|
||||
_refresh_l.text = ""
|
||||
visible = true
|
||||
@@ -163,6 +174,7 @@ func show_result(text: String) -> void:
|
||||
_confirm_btn.visible = false
|
||||
_replace_box.visible = false
|
||||
_continue_btn.visible = true
|
||||
_foot_hint.visible = false
|
||||
visible = true
|
||||
|
||||
|
||||
@@ -184,6 +196,7 @@ func open_replace(items: Array, incoming_name: String, holding: int, slots: int)
|
||||
_confirm_btn.visible = false
|
||||
_replace_box.visible = true
|
||||
_continue_btn.visible = false
|
||||
_foot_hint.visible = false
|
||||
visible = true
|
||||
|
||||
|
||||
@@ -193,6 +206,7 @@ func close_pick() -> void:
|
||||
_replace_box.visible = false
|
||||
_continue_btn.visible = false
|
||||
_confirm_btn.visible = false
|
||||
_foot_hint.visible = false
|
||||
visible = false
|
||||
|
||||
|
||||
|
||||
@@ -72,21 +72,15 @@ func _init() -> void:
|
||||
# 节点图标贴图装载(样张 v1 冻结形制——load_tex 守卫,缺位回退现行字形)
|
||||
for t in TEX_NODE_ICONS:
|
||||
_node_icons[t] = UiKit.load_tex(TEX_NODE_ICONS[t])
|
||||
# 独立屏底(形态升格 2026-09-28——spec Layout:深底+石纹底噪铺满;底纹缺位回退纯色——load_tex 守卫)
|
||||
var base := ColorRect.new()
|
||||
base.color = UiKit.BG_ROOT
|
||||
base.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
# 独立屏底(形态升格 2026-09-28——spec Layout;UI 对齐批 T5 2026-10-06:demo #v-map 暖棕竖向
|
||||
# 渐变(#4A3B2A 0%→#3A2E22 40%)+石纹弱质感 0.14+暗角聚焦;旧满铺石纹不透退役;底纹缺位回退纯色)
|
||||
var base := UiKit.gradient_base(UiKit.BG_MAP_TOP, UiKit.BG_ROOT)
|
||||
add_child(base)
|
||||
var noise := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE)
|
||||
if noise != null:
|
||||
var tex := TextureRect.new()
|
||||
tex.texture = noise
|
||||
tex.stretch_mode = TextureRect.STRETCH_TILE
|
||||
tex.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
tex.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tex.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
var tex := UiKit.backdrop_tile()
|
||||
if tex != null:
|
||||
base.add_child(tex)
|
||||
_noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档)
|
||||
base.add_child(UiKit.vignette_rect())
|
||||
var center := CenterContainer.new()
|
||||
center.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
base.add_child(center)
|
||||
@@ -322,7 +316,8 @@ func _apply_level_tint(level_index: int) -> void:
|
||||
_tint_level = level_index
|
||||
var target: Color = BOARD_TINTS.get(level_index, Color(1, 1, 1))
|
||||
var tw := create_tween()
|
||||
tw.tween_property(_noise_rect, "modulate", target, UiKit.motion(0.45))
|
||||
tw.tween_property(_noise_rect, "modulate",
|
||||
Color(target.r, target.g, target.b, UiKit.BACKDROP_TILE_ALPHA), UiKit.motion(0.45)) # 0.14 弱质感档随 tint 保持(T5)
|
||||
|
||||
|
||||
# 状态栏刷新(命令式纪律——组合根打开本屏/兑付确认回执后重查;零推送信号订阅)
|
||||
|
||||
@@ -34,7 +34,9 @@ func retarget(store) -> void:
|
||||
func _build() -> void:
|
||||
# M4(UI 落码批):石板面板化(demo ③)+行牌化(标签+拨杆+状态字+后果说明行);
|
||||
# 设置项零增减(P-C6:只有主音量——demo 音效音量行系原型发明已撤);
|
||||
# 减动效与结算演出动画=同一设置(语义命名批合并),一行承载
|
||||
# 减动效与结算演出动画=同一设置(语义命名批合并),一行承载。
|
||||
# T8(UI 设计对齐批 2026-10-06):两列对齐(label 列定宽 140——demo .setrow label/控制两列)+
|
||||
# 后果说明内联随行(demo .why 同排)+返回钮紧凑化(demo .btn9 紧凑——原 216 宽砖)。
|
||||
var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_BRIGHT, Vector2(560, 0), 8, true,
|
||||
UiKit.panel_skinned(Vector4(20, 16, 20, 16)))
|
||||
var box: VBoxContainer = shell.box
|
||||
@@ -51,9 +53,12 @@ func _build() -> void:
|
||||
var vol_row := HBoxContainer.new()
|
||||
vol_row.add_theme_constant_override("separation", 14)
|
||||
box.add_child(vol_row)
|
||||
vol_row.add_child(UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL))
|
||||
var vol_lab := UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL)
|
||||
vol_lab.custom_minimum_size = Vector2(140, 0) # T8 label 列定宽(两列对齐)
|
||||
vol_row.add_child(vol_lab)
|
||||
_volume = UiKit.styled_slider(100.0, 0.0, 100.0)
|
||||
_volume.step = 1
|
||||
_volume.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
_volume.value_changed.connect(_on_volume_changed)
|
||||
vol_row.add_child(_volume)
|
||||
_volume_val = UiKit.label("100%",UiKit.FS_BODY, true, UiKit.INK_TITLE)
|
||||
@@ -64,33 +69,38 @@ func _build() -> void:
|
||||
var fs_row := HBoxContainer.new()
|
||||
fs_row.add_theme_constant_override("separation", 14)
|
||||
box.add_child(fs_row)
|
||||
fs_row.add_child(UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL))
|
||||
var fs_lab := UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL)
|
||||
fs_lab.custom_minimum_size = Vector2(140, 0) # T8 同上
|
||||
fs_row.add_child(fs_lab)
|
||||
_fs_btn = UiKit.switch_toggle(false)
|
||||
_fs_btn.toggled.connect(_on_fullscreen_toggled)
|
||||
fs_row.add_child(_fs_btn)
|
||||
_fs_st = UiKit.label("关",UiKit.FS_HINT, true, UiKit.INK_LABEL)
|
||||
fs_row.add_child(_fs_st)
|
||||
|
||||
# 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半)
|
||||
# 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半。
|
||||
# T8 核证:reduced_motion 单设置同驱 UiKit.motion_scale 与结算演播——demo「减动效」行与
|
||||
# 本行系同一设置,不另立行(拆两行=一设置双行重复,违语义命名批裁决)
|
||||
var motion_row := HBoxContainer.new()
|
||||
motion_row.add_theme_constant_override("separation", 14)
|
||||
box.add_child(motion_row)
|
||||
motion_row.add_child(UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL))
|
||||
var motion_lab := UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL)
|
||||
motion_lab.custom_minimum_size = Vector2(140, 0) # T8 同上
|
||||
motion_row.add_child(motion_lab)
|
||||
_motion_btn = UiKit.switch_toggle(true)
|
||||
_motion_btn.toggled.connect(_on_motion_toggled)
|
||||
motion_row.add_child(_motion_btn)
|
||||
_motion_st = UiKit.label("完整",UiKit.FS_HINT, true, UiKit.INK_LABEL)
|
||||
motion_row.add_child(_motion_st)
|
||||
var why := UiKit.label("快速 = 时长减半(运动敏感 / 演示用)",UiKit.FS_CAPTION, false, UiKit.INK_HINT)
|
||||
why.position.y = 0
|
||||
box.add_child(why)
|
||||
motion_row.add_child(why) # T8 内联随行(demo .why 同排;原独立行换排)
|
||||
|
||||
box.add_child(HSeparator.new())
|
||||
# 退出游戏已提级开始菜单(D1——设置面不再承载,用户裁决「退出只在一级菜单出现」)
|
||||
var close_row := HBoxContainer.new()
|
||||
close_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
box.add_child(close_row)
|
||||
var close_btn := UiKit.button("返回")
|
||||
var close_btn := UiKit.button("返回", 90.0) # T8 紧凑返回钮(demo 紧凑形;原 216 宽砖)
|
||||
close_btn.pressed.connect(_emit_closed)
|
||||
close_row.add_child(close_btn)
|
||||
|
||||
|
||||
@@ -20,21 +20,22 @@ const KIND_LABELS := {"attack": "攻击", "max_hp": "生命上限", "armor": "
|
||||
var _gp_label: Label
|
||||
var _refresh_btn: Button # M6 呈现位——MC-1 起由 set_refresh_display 投喂启用
|
||||
signal refresh_requested # MC-1:刷新意图(pool 面;组合根接 presenter.on_shop_refresh)
|
||||
var _visit_label: Label # T6 爬价规则行(demo .svisit——已购件数/现价倍数由 presenter 投喂)
|
||||
var _cards_box: VBoxContainer
|
||||
var _foot_hint: Label # T6 底注(demo .shop-foot .hint)
|
||||
var _card_rows: Array[Dictionary] = [] # [{product_id, price, bought, btn}]——refresh_state 就地重刷(零重建回流)
|
||||
var _shelf_rows: Array[Dictionary] = [] # [{kind_id, btn}]——pool 面卡片(买后整架重建=重抽反馈)
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
# M6(UI 落码批):pool 面卡面 bcard 三竖卡同构化(demo ⑤/2026-10-02 同构裁决呈现侧闭环)——
|
||||
# 库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 核心批投喂,占位禁用);
|
||||
# 爬价总览行不摆=已购次数无成文出口(随 MC-1 shop_draw 投影补)。legacy 面(open_shop)原样保留。
|
||||
var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box
|
||||
var top := HBoxContainer.new()
|
||||
top.add_theme_constant_override("separation", 12)
|
||||
box.add_child(top)
|
||||
var title := UiKit.label("商 店",UiKit.FS_TITLE, true, UiKit.WARM)
|
||||
top.add_child(title)
|
||||
# T6(UI 设计对齐批 2026-10-06):全屏页形态(demo ⑤ #v-shop——06 在册 D2 商店全屏化/D1 竖卡
|
||||
# 232×352 落地)——暖亮底+石纹弱质感+暗角(UiKit.page_shell)+56px 通栏顶条(标题+刷新图标钮/
|
||||
# 角标+GP 框)+ 爬价规则行 + bcard 三竖卡居中 + 底部离开钮与池源注记。
|
||||
# M6 遗产:库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 投喂)。
|
||||
# legacy 面(open_shop)行卡同壳呈现(shop=off 对照承载原样)。高内聚边界不变:纯视图 setter 面。
|
||||
var page: Dictionary = UiKit.page_shell(self, true)
|
||||
var top: HBoxContainer = page.top_row
|
||||
top.add_child(UiKit.label("商 店",UiKit.FS_TITLE, true, UiKit.WARM))
|
||||
var top_sp := Control.new()
|
||||
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
top.add_child(top_sp)
|
||||
@@ -56,15 +57,40 @@ func _init() -> void:
|
||||
top.add_child(gp_chip)
|
||||
_gp_label = UiKit.label("金币 0",UiKit.FS_BODY, true, UiKit.INK_ON_GOLD)
|
||||
gp_chip.add_child(_gp_label)
|
||||
var box: VBoxContainer = page.box
|
||||
_visit_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT)
|
||||
_visit_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
box.add_child(_visit_label)
|
||||
_cards_box = VBoxContainer.new()
|
||||
_cards_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
_cards_box.add_theme_constant_override("separation", 8)
|
||||
box.add_child(_cards_box)
|
||||
var foot := HBoxContainer.new()
|
||||
foot.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
foot.add_theme_constant_override("separation", 16)
|
||||
box.add_child(foot)
|
||||
var leave_btn := UiKit.button("离开商店")
|
||||
leave_btn.pressed.connect(_emit_leave_pressed)
|
||||
box.add_child(leave_btn)
|
||||
foot.add_child(leave_btn)
|
||||
_foot_hint = UiKit.label("货架与奖励三选一同一池 · 池空即空架关店",UiKit.FS_HINT, false, UiKit.WARM_FAINT)
|
||||
foot.add_child(_foot_hint)
|
||||
visible = false
|
||||
|
||||
|
||||
# 爬价规则行投喂(demo .svisit——buys<0 = legacy 面隐藏行;mult=pow(price_a, buys) 由 presenter 算)
|
||||
func set_visit_info(buys: int, price_a: float) -> void:
|
||||
if buys < 0:
|
||||
_visit_label.text = ""
|
||||
return
|
||||
var mult := pow(price_a, float(buys))
|
||||
_visit_label.text = "本次进店已购 %d 件 · 现价 %s | 买 1 件 → 三件全换新 · 全场涨价 ×%s" % [
|
||||
buys, _xnum(mult), _xnum(price_a)]
|
||||
|
||||
|
||||
func _xnum(v: float) -> String:
|
||||
return "×%d" % int(round(v)) if absf(v - roundf(v)) < 0.005 else "×%.2f" % v
|
||||
|
||||
|
||||
# 打开商店(products = runner.shop_products() 投影——[{product_id, display_name, attr, flat_value, price, purchased}])
|
||||
func open_shop(products: Array, gp: int) -> void:
|
||||
for child in _cards_box.get_children():
|
||||
@@ -137,7 +163,7 @@ func open_shelf(cards: Array, gp: int) -> void:
|
||||
_shelf_rows.clear()
|
||||
var row := HBoxContainer.new()
|
||||
row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
row.add_theme_constant_override("separation", 20)
|
||||
row.add_theme_constant_override("separation", 26) # demo .cards gap 26(T6 对齐)
|
||||
_cards_box.add_child(row)
|
||||
for c in cards:
|
||||
_shelf_rows.append(_build_shelf_card(row, c))
|
||||
|
||||
@@ -217,6 +217,85 @@ static func load_tex(path: String) -> Texture2D:
|
||||
return null
|
||||
|
||||
|
||||
# ── 屏底氛围层(UI 设计对齐批 T5 2026-10-06——demo .tilebg opacity .14/.vignette/.beams 对齐;
|
||||
# 旧「石纹全屏满铺不透」退役——demo 石纹只作弱质感,聚焦靠暗角)──
|
||||
const BACKDROP_TILE_ALPHA := 0.14 # demo .tilebg{opacity:.14}
|
||||
const BG_MAP_TOP := Color8(74, 59, 42) # 地图屏渐变顶 #4A3B2A(demo #v-map 180deg 0%;低点 40% = BG_ROOT #3A2E22)
|
||||
|
||||
|
||||
# 石纹弱质感全屏片(0.14;缺素材返回 null = 调用侧回退平色)
|
||||
static func backdrop_tile() -> TextureRect:
|
||||
var bd_tex := load_tex(TEX_BACKDROP_STONE)
|
||||
if bd_tex == null:
|
||||
return null
|
||||
var bd := TextureRect.new()
|
||||
bd.texture = bd_tex
|
||||
bd.stretch_mode = TextureRect.STRETCH_TILE
|
||||
bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
bd.modulate = Color(1, 1, 1, BACKDROP_TILE_ALPHA)
|
||||
bd.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
bd.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
return bd
|
||||
|
||||
|
||||
# 径向暗角(demo .vignette——ellipse 90%×80% at 50% 42%,透明 58% → 黑 0.30 满角)
|
||||
static func vignette_rect() -> TextureRect:
|
||||
var g := Gradient.new()
|
||||
g.offsets = PackedFloat32Array([0.0, 0.58, 1.0])
|
||||
g.colors = PackedColorArray([Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0.30)])
|
||||
var t := GradientTexture2D.new()
|
||||
t.gradient = g
|
||||
t.fill = GradientTexture2D.FILL_RADIAL
|
||||
t.fill_from = Vector2(0.5, 0.42)
|
||||
t.fill_to = Vector2(1.4, 0.42)
|
||||
t.width = 256
|
||||
t.height = 256
|
||||
var tr := TextureRect.new()
|
||||
tr.texture = t
|
||||
tr.stretch_mode = TextureRect.STRETCH_SCALE
|
||||
tr.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tr.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
return tr
|
||||
|
||||
|
||||
# 斜光带(demo #v-start .beams——repeating-linear-gradient 102deg,暖白 5% 窄带 240-340/560px;
|
||||
# 程序纹理循环带,确定性生成零随机)
|
||||
static func beams_rect() -> TextureRect:
|
||||
var img := Image.create(560, 560, false, Image.FORMAT_RGBA8)
|
||||
var ca := cos(0.2094) # 12°(102deg 带轴的垂直倾角)
|
||||
var sa := sin(0.2094)
|
||||
for y in 560:
|
||||
for x in 560:
|
||||
var d := fposmod(x * ca + y * sa, 560.0)
|
||||
if d >= 240.0 and d < 340.0:
|
||||
img.set_pixel(x, y, Color(1.0, 236.0 / 255.0, 200.0 / 255.0, 0.05))
|
||||
var tr := TextureRect.new()
|
||||
tr.texture = ImageTexture.create_from_image(img)
|
||||
tr.stretch_mode = TextureRect.STRETCH_TILE
|
||||
tr.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tr.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
return tr
|
||||
|
||||
|
||||
# 竖向渐变底(demo #v-map linear-gradient(180deg, top 0%, low 40%)——stop 后恒 low)
|
||||
static func gradient_base(top: Color, low: Color, stop := 0.4) -> TextureRect:
|
||||
var g := Gradient.new()
|
||||
g.offsets = PackedFloat32Array([0.0, stop])
|
||||
g.colors = PackedColorArray([top, low])
|
||||
var t := GradientTexture2D.new()
|
||||
t.gradient = g
|
||||
t.fill_from = Vector2(0.5, 0.0)
|
||||
t.fill_to = Vector2(0.5, 1.0)
|
||||
t.width = 64
|
||||
t.height = 256
|
||||
var tr := TextureRect.new()
|
||||
tr.texture = t
|
||||
tr.stretch_mode = TextureRect.STRETCH_SCALE
|
||||
tr.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
tr.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
return tr
|
||||
|
||||
|
||||
# CJK 随包字体(2026-09-27 用户拍板 Fusion Pixel OFL——CJK 覆盖+授权干净;命名遵 art-bible §8.3
|
||||
# 全小写 snake_case 域前缀)。守卫装载同 load_tex 纪律:缺位返回 null(引擎回退字体接手,不炸)。
|
||||
const FONT_UI := "res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf"
|
||||
@@ -307,6 +386,44 @@ static func modal_shell(parent: Control, dim_color: Color, min_size := Vector2.Z
|
||||
return {"dim": dim, "center": center, "panel": panel, "box": box}
|
||||
|
||||
|
||||
# ── 全屏页壳(UI 设计对齐批 T6/T7 2026-10-06——demo #v-shop/#v-bonus 全屏页形态落地:
|
||||
# 06 在册 D2 商店全屏化/D1 竖卡 232×352。暖底+石纹弱质感+暗角+56px 通栏顶条+内容列;
|
||||
# 商店=暖亮底、三选一=根底,两屏同构差异仅底色与顶条工具件)──
|
||||
const PAGE_TOP_H := 56.0
|
||||
|
||||
static func page_shell(host: Control, bright := true) -> Dictionary:
|
||||
var page := Control.new()
|
||||
page.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
host.add_child(page)
|
||||
var base := ColorRect.new()
|
||||
base.color = BG_BRIGHT if bright else BG_ROOT
|
||||
base.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
base.mouse_filter = Control.MOUSE_FILTER_STOP # 页底挡点击——模态语义由组合根输入锁兜底
|
||||
page.add_child(base)
|
||||
var tile := backdrop_tile()
|
||||
if tile != null:
|
||||
page.add_child(tile)
|
||||
page.add_child(vignette_rect())
|
||||
var top := PanelContainer.new()
|
||||
top.set_anchors_preset(Control.PRESET_TOP_WIDE)
|
||||
top.custom_minimum_size = Vector2(0, PAGE_TOP_H)
|
||||
top.add_theme_stylebox_override("panel",
|
||||
panel_flat(Color8(38, 29, 20), Color8(85, 72, 58), 0, 1, Vector4(26, 6, 26, 6)))
|
||||
page.add_child(top)
|
||||
var top_row := HBoxContainer.new()
|
||||
top_row.add_theme_constant_override("separation", 12)
|
||||
top.add_child(top_row)
|
||||
var box := VBoxContainer.new()
|
||||
box.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
box.offset_top = PAGE_TOP_H + 20
|
||||
box.offset_left = 26
|
||||
box.offset_right = -26
|
||||
box.offset_bottom = -22
|
||||
box.add_theme_constant_override("separation", 10)
|
||||
page.add_child(box)
|
||||
return {"page": page, "base": base, "top_row": top_row, "box": box}
|
||||
|
||||
|
||||
# 属性百分比合成(main._debug_hero_override 与调试浮窗生效值预览共用单点——两处同式实现收口)
|
||||
static func scaled(base: int, pct: int) -> int:
|
||||
return maxi(1, int(round(float(base) * (100.0 + float(pct)) / 100.0)))
|
||||
@@ -492,7 +609,7 @@ class BCard:
|
||||
_sb_normal = UiKit.panel_skinned(Vector4(12, 10, 12, 10)) if tex != null else UiKit.panel_flat(PANEL_DATA, PANEL_BORDER,RADIUS_OBJECT, 1, Vector4(12, 10, 12, 10)) # 回退=数据板单点(P7 乙后同值,字面量退役)
|
||||
_sb_sel = UiKit.panel_flat(PANEL_DATA, Color8(138, 90, 52), RADIUS_OBJECT, 2, Vector4(12, 10, 12, 10)) # 选中底=数据板单点(P7 乙后同值)
|
||||
add_theme_stylebox_override("panel", _sb_normal)
|
||||
custom_minimum_size = Vector2(216, 300)
|
||||
custom_minimum_size = Vector2(232, 352) # D1(UI 设计对齐批 T6 2026-10-06——demo .bcard 232×352;原 216×300)
|
||||
var box := VBoxContainer.new()
|
||||
box.add_theme_constant_override("separation", 8)
|
||||
add_child(box)
|
||||
@@ -503,16 +620,21 @@ class BCard:
|
||||
mark.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
mark.visible = false
|
||||
box.add_child(mark)
|
||||
# 图标槽(demo .ic 76×76 槽底+图标 60=20px 源 3 整数倍——P6 甲④ 2× 档升 3× 随 D1 对齐)
|
||||
var slot := PanelContainer.new()
|
||||
slot.add_theme_stylebox_override("panel", UiKit.panel_flat(SLOT_BACKDROP, PANEL_BORDER, 0, 1))
|
||||
slot.custom_minimum_size = Vector2(76, 76)
|
||||
slot.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
box.add_child(slot)
|
||||
icon_tr = TextureRect.new()
|
||||
var itex := UiKit.load_tex(icon_path)
|
||||
if itex != null:
|
||||
icon_tr.texture = itex
|
||||
icon_tr.custom_minimum_size = Vector2(40, 40) # P6 甲④(2026-10-06):20×20 源 2× 档(原 56=2.8× 违 §8.2)
|
||||
icon_tr.custom_minimum_size = Vector2(60, 60)
|
||||
icon_tr.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
icon_tr.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
icon_tr.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
|
||||
icon_tr.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
box.add_child(icon_tr)
|
||||
slot.add_child(icon_tr)
|
||||
name_l = UiKit.label(title,FS_SUB, true, INK_TITLE)
|
||||
name_l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
box.add_child(name_l)
|
||||
|
||||
Reference in new issue
Block a user