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等需要在运行后查看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/721715.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【pyinstaller打包记录】Windows系统打包exe后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件(可执行程序)的工具。它能够将 Python 代码和其相关的依赖项(包括 Python 解释器、依赖的模块、库文件等)打包成一个独立的可执行文件,方便在不同环境中运行…

SQL索引优化

自己学习日志 索引优化 为搜索字段、排序字段、select查询列,创建合适的索引,不过要考虑数据的业务厂家:查询多还是增删多 尽量建立组合索引并注意组合索引的创建顺序,按照顺序组织查询条件,尽量将筛选颗粒度大的条件…

凌风 TEMU工具箱 抢仓 库存销售数据利润计算 选品监控采集上品 一网打尽

凌风TEMU工具箱介绍 一、安装教程1、下载方式2、环境准备3、安装步骤3.1、插件安装3.2、客户端安装 4、启动软件 二、使用教程一:登录注册激活方法2.1 注册登录2.2 激活方式 (激活码激活)2.3 绑定店铺 二:使用方法:功能…

Android Gradle开发与应用 (四) : Gradle构建与生命周期

1. 前言 前几篇文章,我们对Gradle中的基本知识,包括Gradle项目结构、Gradle Wrapper、GradleUserHome、Groovy基础语法、Groovy语法概念、Groovy闭包等知识点,这篇文章我们接着来介绍Gradle构建过程中的知识点。 2. Project : Gradle中构建…

揭秘大气颗粒物与VOCs:PMF源解析技术全解析

在现今日益严峻的环境问题中,大气颗粒物和臭氧污染尤为突出,它们不仅深刻影响着全球气候和生态环境,更对人体健康构成了严重威胁。为了有效应对这一挑战,我们首先需要深入了解颗粒物和臭氧的来源,特别是臭氧的前体物之…

遥测终端助力城市内涝积水监测,守护城市生命线!

近年来,随着全球气候的变化和城市化进程的加速,强降雨事件频发,导致城市内涝问题日益严重。道路低洼处、下穿式立交桥和隧道在强降雨时常常产生大量积水,给人们的出行带来极大不便,严重时甚至威胁人民的生命安全和造成…

Unity 学习笔记索引

Unity安装与简单设置 Unity 常用操作与素材网站 Unity 脚本-生命周期常用函数 Unity 预制体与变体 Unity 使用脚本获取组件,代码生成预制体 Unity 向量计算、欧拉角与四元数转换、输出文本、告警、错误、修改时间、定时器、路径、 Unity 切换场景-(同步与…

JVM运行时数据区——方法区

文章目录 1、栈、堆、方法区的交互关系2、方法区的理解2.1、方法区的官方描述2.2、方法区的基本理解2.3、JDK中方法区的变化 3、设置方法区大小与OOM3.1、设置方法区内存的大小3.2、方法区内存溢出 4、方法区的内部结构4.1、类型信息、域信息和方法信息介绍4.1.1、类型信息4.1.…

Spring Cloud原理详解

Spring Cloud 是基于 Spring Boot 的微服务架构开发工具包,旨在帮助开发人员快速构建分布式系统中的一些常见模式,例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、领导选举、分布式会话和集群状态。Spring Cloud 是 Spring 生态系…

用户和用户组管理及密码管理

用户: useradd 新建用户 useradd 用户名称 useradd -g 组名称 用户名称 userdel 删除用户 passwd 修改用户密码 usermod 修改用户属性 usermod [选项] 用户名 chage 修改用户属性 chage [选项…

动手学深度学习—循环神经网络RNN详解

循环神经网络 循环神经网络的步骤: 处理数据 将数据按照批量大小和时间步数进行处理,最后得到迭代器,即每一个迭代的大小是批量大小时间步数,迭代次数根据整个数据的大小决定,最后得出处理的数据(参照第三…

极狐GitLab Runner 添加 极狐GitLab 域名 host

本文作者 徐晓伟 自定义 GitLab 域名解析 查看极狐 GitLab runner 日志 查看极狐 GitLab Runner Pod 名称 [rootanolis-7-9 ~]# kubectl -n gitlab-test get pod | grep gitlab-runner my-gitlab-gitlab-runner-6fb4bf7468-nmnkp 0/1 Running 29 (62s ago…

【嵌入式——QT】QDockWidget

QDockWidget提供了dock widget的概念,也称为工具面板或实用窗口。Dock窗口是放置在QMainWindow中围绕中心窗口组件的Dock窗口组件区域中的次要窗口,QDockWidget是可以在QMainWindow窗口停靠,或在桌面最上层浮动的界面组件。 停靠窗口可以被移…

重拾前端基础知识:JavaScript

重拾前端基础知识:JavaScript 前言使用JavaScript输出语法运算符条件语句循环数据类型字符串数字数组对象日期函数 数学正则表达式异常处理类集合模块JSON闭包异步调试DOM(文档对象模型)事件事件监听器表单 BOM(浏览器对象模型&am…

【排序】详解选择排序

一、思想 选择排序的原理与思想非常直观和简单,它通过不断地选择未排序部分的最小(或最大)元素,并将其放到已排序部分的末尾来实现排序。 具体来说,选择排序的过程可以分解为以下几个步骤: 寻找最小&…

三步骤找到用户真正痛点 提高需求分析质量

用户痛点对于需求分析具有至关重要的作用,这直接关系着需求分析结果是否真正满足用户需求,关系着最终研发的产品是否能够满足市场的需求,是否能够在竞争激烈的市场中脱颖而出。因此找到用户真正痛点至关重要。 1、什么是痛点 痛点是消费者心理…

DML相关操作

DML 是数据操作语言,用来对数据库中表的数据记录进行增删改操作 添加数据(insert)修改数据(update)删除数据(delete) DML-添加数据 1.给指定字段添加数据 insert into 表名(字段…

关于用强化学习进行股市预测的新思路(2)

据上次新模型开始正式使用以来,发现了几个问题。 1. 因为是一个转债对应一个模型,导致每次预测结果很少。 2. 预测出来的结果,大部分还是受大盘影响。不过大部分最终还是会回本盈利,时间长短的问题。 3. 需要经常更新模型&#x…

各中间件性能、优缺点对比

参考资料: Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

C++命名空间

在C/C中,变量,函数和和类这些名称都存在于全局作用域中,可能会导致很多冲突,使用命名空间的目的是对标识符的名称进行本地化,避免命名冲突或名字污染,namespace关键字就是解决这种问题的。如下程序并无问题…