mcpField
G
godot-ui-theming

godot-ui-theming

github.com/thedivergentai设计与 UI907618 次安装2 周前更新
代码仓库

关于 godot-ui-theming

面向 Godot UI 开发者的主题设计指南,涵盖 Theme、StyleBox、字体与覆盖机制,并提供运行时切换和无障碍样式模式。

主要功能

  1. 01Theme 资源与样式管理
  2. 02运行时主题切换和回退
  3. 03StyleBox 安全修改与隔离
  4. 04主题类型变体样式
  5. 05缩放、RTL 与焦点提示

适用场景

  1. 01在游戏中切换深色、浅色或高对比主题
  2. 02为单个控件调整颜色而不修改共享样式
  3. 03构建适配 DPI 和分辨率的界面
  4. 04支持 RTL 布局和控制器焦点提示

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-dev-agentic-skills --skill godot-ui-theming

安装后在 Claude Code 中输入/godot-ui-theming确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
migration-notes.md
theme-authoring-recipes.md
scripts/
crisp_ui_scaler.gd
custom_chart_drawing.gd
danger_button_assignment.gd
dynamic_stylebox_color.gd
focus_prompt_icon_swapper.gd
global_theme_manager.gd
memory_safe_custom_drawing.gd
procedural_theme_safe.gd
pulsating_ui_theme.gd
rtl_theme_mirroring.gd
theme_isolation.gd
theme_swapper.gd
ui_scale_manager.gd

详细介绍

UI 主题

主题资源、StyleBox 样式、字体管理和覆盖系统共同定义一致的 UI 视觉标识。

可用脚本

global_theme_manager.gd

专业的主题管理器,支持动态切换、主题变体和回退处理。

ui_scale_manager.gd

运行时主题切换以及 DPI/分辨率缩放管理。

theme_swapper.gd

使用级联主题根节点传播实现动态深色/浅色模式。

danger_button_assignment.gd

专业运用 theme_type_variation 实现语义化 UI 样式,无需重复创建场景。

dynamic_stylebox_color.gd

安全地在运行时修改 StyleBox。展示用于隔离覆盖的关键 duplicate() 模式。

procedural_theme_safe.gd

使用 NOTIFICATION_THEME_CHANGED 为生成的 UI 元素可靠地设置主题。

custom_chart_drawing.gd

在自定义 _draw() 逻辑中读取活动主题属性(颜色、字体)的模式。

theme_isolation.gd

通过隔离节点与父主题的关联并引用项目默认设置,确保 HUD 风格一致。

pulsating_ui_theme.gd

使用 Tweens 为 UI 样式添加动画。复制后直接对 StyleBox 属性进行操作。

crisp_ui_scaler.gd

使用 content_scale_factor 实现高质量、分辨率无关的缩放,以保持字体清晰。

memory_safe_custom_drawing.gd

通过在类级别缓存 RenderingServer 所需的资源,修复“样式框消失”错误。

rtl_theme_mirroring.gd

支持双向(RTL/LTR)UI。根据布局方向动态切换主题变体。

focus_prompt_icon_swapper.gd

切换控制器/键盘提示图标组 + 焦点高亮面板。无障碍提示界面必备。

UI 主题设计中绝对不要做的事

  • 绝对不要在 _ready() 中为大量节点创建 StyleBox — 实例化 100 次 StyleBoxFlat.new() 会创建 100 个独立对象。使用 Theme 资源共享样式。
  • 绝对不要忘记主题继承 — 如果子级有自己的主题,父级主题就会被忽略。在根节点应用主题,并使用 theme_type_variation 进行特定覆盖。
  • 绝对不要在 StyleBox 中硬编码颜色 — 使用 theme.get_color(),确保调色板只有一个可信来源。
  • 绝对不要使用 add_theme_override 设置全局样式 — 这种做法很脆弱。在 Theme 资源中定义样式,让它们自动应用到整个项目。
  • 绝对不要在 _draw() 或 _process() 期间修改主题资源 — 频繁重新计算布局会严重降低性能。
  • 绝对不要在没有备用方案的情况下将 StyleBoxEmpty 赋给焦点样式 — 这会在不易察觉的情况下破坏手柄/键盘导航 [1]。始终提供可见的替代效果(例如缩放变化)。
  • 绝对不要使用标准的 set() 设置主题属性 — 调用 node.set("font_color", red) 会失败。必须使用专用的 add_theme_color_override() API [3]。
  • 绝对不要使用 expand_margin_* 扩大可点击区域 — 它只会扩大视觉边界。使用 StyleBox 上的 content_margin_*,或调整 Control 的大小,确保输入有效 [5]。
  • 绝对不要在 _draw() 中将 StyleBox 定义为局部变量 — 在 RenderingServer 完成绘制前,它们就会被垃圾回收 [7]。请将其存储在类级别。
  • 绝对不要仅为修改一种颜色而复制场景/主题 — 使用 theme_type_variation,在同一个 Theme 中创建轻量派生样式(例如 "DangerButton")[8]。
  • 绝对不要在 StyleBoxFlat 上省略 corner_radius_all — 它是统一设置圆角的简写;所有角都相同时,应优先使用它,而不是分别设置四个圆角字段。
  • 绝对不要混淆 Theme 项与 Control 覆盖项 — add_theme_*_override 只会覆盖该节点上的 Theme 资源项;拥有自身 theme 的子级 Control 仍会阻断父级级联。切换根节点时,使用 remove_theme_*_override 清除覆盖项,不要让陈旧的覆盖项与新 Theme 冲突。

决策树 — 主题归属

目标选择备注/脚本
整个应用的外观Project Settings → GUI → Theme在 Theme 编辑器中创作 — 此处不介绍逐节点 StyleBox 教程
某个 Control 与众不同在该节点上使用 add_theme_*_override仅限本地;绝不用作全局样式
按钮/面板子类型theme_type_variation参见 danger_button_assignment.gd
运行时调整颜色且不修改共享 Themestylebox.duplicate(),然后进行覆盖参见 dynamic_stylebox_color.gd

字体与 StyleBox:通过 Theme 编辑器/Project Theme 进行编辑。运行时辅助脚本:global_theme_manager.gd、theme_swapper.gd、procedural_theme_safe.gd。

专家级主题设计模式

1. 共享调色板(静态模式)

维护一个唯一可信的 UI 颜色来源,让 Theme 编辑器和 GDScript 都能访问。

  • Theme 设置:在 .theme 文件中创建名为 Palette 的自定义类型,并添加 Color 项(例如 primary、danger、accent)。
  • 静态访问:使用 SharedPalette 类,其中包含 static func get_primary() -> Color,从 ThemeDB.get_project_theme() 获取颜色。这样可确保 UI 脚本与视觉主题始终保持一致。
2. 主题类型变体

对于“Danger”或“Ghost”等样式变体,不要重复创建按钮场景或 StyleBox。

  • 实现:在 Theme 编辑器中创建一个新的类型变体。将其基础类型设为 Button。
  • 继承:变体会继承基础类型的所有属性。只需覆盖不同的属性(例如,将 DangerButton 的 font_color 设为红色)。
  • 使用:通过代码 node.theme_type_variation = &"DangerButton" 或 Inspector 下拉菜单进行指定。

强制要求:阅读 danger_button_assignment.gd——不要为颜色变体复制 Button 场景。

3. 运行时 StyleBox 颜色(先复制)

当需要在运行时为单个 Control 着色时,修改前先复制 StyleBox——共享的 Theme StyleBox 必须保持不可变。

强制要求:阅读 dynamic_stylebox_color.gd——绝不要原地修改 Theme StyleBox。

4. 运行时切换主题(无障碍)

为整个游戏高效切换浅色、深色或高对比度视觉样式。

  • 级联更新:为根 Control 节点指定新的 Theme 资源。Godot 会将其传播给所有后代节点。
  • 无障碍:使用 NOTIFICATION_THEME_CHANGED 更新不支持自动主题设置的元素(例如自定义 _draw() 逻辑或 RichText 效果)。
  • 高对比度:为低视力用户提供无障碍体验时,确保高对比度主题使用纯黑/纯白,并采用更粗的焦点轮廓。

强制要求:阅读 theme_swapper.gd——在主题根节点切换;不要遍历每个 Control 并逐一指定主题。

5. RTL / LTR 主题镜像

双向布局在切换方向时需要镜像 StyleBox / 类型变体组——仅手动翻转锚点并不足够。

强制要求:阅读 rtl_theme_mirroring.gd——根据布局方向切换主题变体;不要将 LTR 边距硬编码。

6. 主题化资源加载(季节性变体)

Godot Theme 不仅支持颜色和字体,还可以存储纹理。

  • 设置:将 UI 图标定义为独立 Theme 资源中的 Icon 项(例如 halloween.theme、christmas.theme)。
  • 切换:切换根主题资源后,新图标纹理会立即级联应用到所有按钮和面板,无需手动编写逻辑。
7. UI 焦点管理器(动态控制器图标)

标准焦点样式是静态的。为改善无障碍体验,应根据设备切换提示图标,并将高亮面板补间至 get_global_rect()。

强制要求:阅读 focus_prompt_icon_swapper.gd——不要将手柄图标路径粘贴到 Control 脚本中。

与上文的运行时切换主题(无障碍)以及用于高对比度根节点的 theme_swapper.gd 配合使用。

8. 资源依赖审计(减少绘制调用)

确保 UI 纹理经过优化,以提升渲染性能。

  • 图集打包:使用 AtlasTexture 从单张大型图集中裁剪小型 UI 元素。这可以减少 VRAM 状态切换并尽量减少绘制调用 [14]。
  • 压缩策略:
    • 2D/像素艺术:使用无损压缩,避免出现模糊伪影 [15]。
    • UI 背景:对大型插图使用有损或 Basis Universal,以节省磁盘空间,同时不增加 VRAM 使用量 [15]。
  • 审计:使用 ResourceLoader.get_dependencies(scene_path),确保没有未压缩的原始资源(例如 .png)泄漏到最终导出中 [19]。

深入配方(按需查阅)

大模型无知规则:如果通用 Agent 在阅读前不会知道某项内容,就将它放在这里或 scripts/ 中——绝不要删除,只能移动。

主题参考资料
StyleBox / 字体设置theme-authoring-recipes.md

参考

渐进式披露:仅在研究特定 API 时打开官方文档链接; 将工作路由到相关领域时再加载相关技能——不要预先加载整个技能体系。

官方文档
  • GUI 换肤 — Theme 资源、StyleBox,以及层叠式皮肤所有权。
  • 使用 Theme 编辑器 — 创建 Theme 资源,无需手动编辑每个 Control 覆盖项。
  • Theme 类型变体 — 为按钮/面板子类型创建变体,无需复制整个 Theme。
  • 使用字体 — 使用 DynamicFont/字体大小主题设置提升 UI 可读性。
  • 自定义 GUI 控件 — 使用主题化的 _draw() 时,需要查找主题项的场景。
  • 尺寸与锚点 — 可适应主题缩放和 DPI 变化的布局。
  • Theme — 运行时获取/设置颜色、常量、图标和 StyleBox。
  • ThemeDB — 项目默认 Theme 和回退解析。
  • Control — 主题覆盖项和 NOTIFICATION_THEME_CHANGED。
  • StyleBox — 大多数 Theme 皮肤使用的面板/按钮装饰。
  • AtlasTexture — 将 UI 图标打包,以减少绘制调用开销。
  • Input — 自定义光标和由手柄驱动的提示图标切换。
相关技能
前置条件
补充技能
下游 / 消费者
主模块
  • godot-master — UI 主题设置的库路由器和镜像模块入口。

评论

支持 Markdown