当前位置: 首页 > news >正文

Godot自定义控件样式语法解析

前言

本篇原始文章写于2023年8月7日,存储在我的语雀文档中。但是语雀分享有诸多不便,为了让更多Godoter更轻松的搜到和看到,就转过来了。
这个项目我上传了Github,后续会贴上链接。

概述

Godot控件体系存在的问题之一就是样式无法用纯文本形式简洁而清晰的定义,一切都要靠主题编辑器或检视器面板那一套手动的东西。4.x提供了一些样式属性和方法,但仍然算不上简洁。

在样式定义方面,前端的CSS样式表可谓是最佳实践之一。

如果能够以类似CSS一样的纯文本形式解析和控制Godot的控件样式,那么样式定义就能更轻松。

基于这样的想法,笔者尝试建立了一个类CSS样式的样式书写和解析机制。让使用者可以基于一个简单的导出变量,用纯文本的方式定义控件的样式。

样式解析函数库

ConfigFile提供了一个名叫parse() 的方法,可以将符合ConfigFile风格和书写规则的字符串直接解析到ConfigFile实例。进而可以使用其提供的方法便捷的遍历节、键和值。

基于此我创建了一个名为Sty的静态函数库。
下面是初期的一个效果,已经可以解析按钮多个状态下的一些简单样式。

# ========================================================
# 名称:Sty
# 类型:静态函数库
# 简介:用于解析和应用控件样式
# 作者:巽星石
# Godot版本:4.1.1-stable (official)
# 创建时间:2023-08-07 23:11:57
# 最后修改时间:2023-08-07 23:11:57
# ========================================================
class_name Sty# 样式解析
static func parse_style(ctl:Control,style_str:String):var cfg = ConfigFile.new()var err = cfg.parse(style_str.replace(":","=\"").replace(";","\""))if err == OK: # 解析成功for section in cfg.get_sections():for key in cfg.get_section_keys(section):var val = cfg.get_value(section,key)match key:"font_size":pass"color":match section:"normal":ctl.add_theme_color_override("font_color",Color(val))"hover","pressed","disabled","focus":ctl.add_theme_color_override("font_%s_color" % section,Color(val))"bg_color":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)stylebox.bg_color = Color(val)"radius":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.corner_radius_top_left = int(vals[0])stylebox.corner_radius_top_right = int(vals[1])stylebox.corner_radius_bottom_left = int(vals[2])stylebox.corner_radius_bottom_right = int(vals[3])"border_width":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.border_width_left = int(vals[0])stylebox.border_width_top = int(vals[1])stylebox.border_width_right = int(vals[2])stylebox.border_width_bottom = int(vals[3])"border_color":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)stylebox.border_color = Color(val)"padding":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.content_margin_left = int(vals[0])stylebox.content_margin_top = int(vals[1])stylebox.content_margin_right = int(vals[2])stylebox.content_margin_bottom = int(vals[3])"margin":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.expand_margin_left = int(vals[0])stylebox.expand_margin_top = int(vals[1])stylebox.expand_margin_right = int(vals[2])stylebox.expand_margin_bottom = int(vals[3])"shadow_color":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)stylebox.shadow_color = Color(val)"shadow_size":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)stylebox.shadow_size = int(val)"shadow_offset":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.shadow_offset = Vector2(float(vals[0]),float(vals[1]))"skew":match section:"normal","hover","pressed","disabled","focus":var stylebox:StyleBoxFlat = get_stylebox(ctl,section)var vals = val.split(",")stylebox.skew = Vector2(float(vals[0]),float(vals[1]))# 获取控件对应名称的样式盒
static func get_stylebox(ctl:Control,name:String) -> StyleBoxFlat:var stylebox:StyleBoxFlatif ctl.has_theme_stylebox_override(name):stylebox = ctl.get_theme_stylebox(name)else:stylebox= StyleBoxFlat.new()ctl.add_theme_stylebox_override(name, stylebox)return stylebox

实际使用

为普通节点添加style属性

我们创建一个UI场景,添加一个Button
在这里插入图片描述

Button添加如下代码:

@tool
extends Button@export_multiline var style:String = "":set(val):style = valSty.parse_style(self,val)

接着我们在检视器面板的style变量中,定义如下的样式:

[normal]
font_size :64;
color:#FF4400;
bg_color:yellow;
radius:55,5,56,45;
skew:0.1,0;
border_width:5,2,5,2;
border_color:#444;
[disable]
color:#00FF00;
[hover]
color:#00FF00;
bg_color:#ccc;
radius:55,5,5,45;

关于语法

因为我是以Button控件为模板进行初期的样式语法测试,所以以Button为例的话,我们可以看到一个按钮的样式其实是可以分为几个状态的:正常(normal),禁用(disable),鼠标经过(hover),按下(pressed),获得焦点(focus)。

所以我采用了状态优先,属性名称简化和重用的设计,并且采用了Godot的ConfigFile格式。

将按钮的不同状态作为配置文件的section,但是为了简化书写,让其更像是CSS风格,所以采用了冒号和封号,而不是等号来设定键值对。在解析时冒号和封号会被替换。

然后对应的按钮样式被定义为如下图:
在这里插入图片描述

因为加了@tool关键字,所以在normal状态中定义的样式都会被实时的显示在编辑器中,而其他的诸如hover等需要在运行后查看。

相关文章:

  • Java数据类型(八种基本数据类型 + 四种引用类型)、数据类型转换
  • 机器学习:模型评估和模型保存
  • 【软考】设计模式之访问者模式
  • Redis的主从搭建
  • Linux笔记--GCC
  • 全新2.0版本极其抽象的门(Spring Security)
  • Unity RectTransform·屏幕坐标转换
  • 【研发日记】Matlab/Simulink技能解锁(三)——在Stateflow编辑窗口Debug
  • 2024目前三种有效加速国内Github
  • 算法修炼-动态规划之路径问题(1)
  • 代码随想录算法训练营第四十六天 139.单词拆分、多重背包(了解)、 背包总结
  • 类与对象的实践----日期相关函数的实现
  • 【硬件相关】IB网/以太网基础介绍及部署实践
  • cartographer ceres后端优化
  • 13. Springboot集成Protobuf
  • 【个人向】《HTTP图解》阅后小结
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Angular Elements 及其运作原理
  • CentOS从零开始部署Nodejs项目
  • Java新版本的开发已正式进入轨道,版本号18.3
  • Next.js之基础概念(二)
  • Puppeteer:浏览器控制器
  • rabbitmq延迟消息示例
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • 大主子表关联的性能优化方法
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 你不可错过的前端面试题(一)
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 我是如何设计 Upload 上传组件的
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #LLM入门|Prompt#3.3_存储_Memory
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (30)数组元素和与数字和的绝对差
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (三)模仿学习-Action数据的模仿
  • (十)T检验-第一部分
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)德国人的记事本
  • .cfg\.dat\.mak(持续补充)
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET Core 中插件式开发实现
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • @angular/cli项目构建--Dynamic.Form
  • @Resource和@Autowired的区别
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [AIGC] Java 和 Kotlin 的区别
  • [Android] Amazon 的 android 音视频开发文档