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 解释器、依赖的模块、库文件等)打包成一个独立的可执行文件,方便在不同环境中运行…

凌风 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源解析技术全解析

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

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

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

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

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

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

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

重拾前端基础知识:JavaScript

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

【排序】详解选择排序

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

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

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

DML相关操作

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

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

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

C++命名空间

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

文物保护平台数据统计分析及预警-子系统专题分析

文物预防性监测与调控系统的监测统计分析子系统提供全面的文物状态及环境数据分析,为博物馆工作人员进行基于文物材质特性的专项保护提供相关科研辅助。主要的监测分析,包括各展厅文物统计分析、不同环境因素报表统计、以及监测调控设备统计分析等。 系统用户和文物管理人员可以…

从0开始入门智能知识库和星火大模型,打造AI客服。

介绍FastWiki FastWiki是一个高性能、基于最新技术栈的知识库系统,旨在为大规模信息检索和智能搜索提供解决方案。它采用微软Semantic Kernel进行深度学习和自然语言处理,在后端使用MasaFramework,前端采用MasaBlazor框架,实现了…

Swing程序设计(11)动作事件监听器,焦点事件监听器

文章目录 前言一、事件监听器是什么?二、详细展开 1.动作事件监听器2.焦点事件监听器总结 前言 如果你是坚持从Swing程序第一篇看到了这里,恭喜你,Swing程序设计简单地落下了帷幕,关于Swing程序更深的了解,可以自行学习…

MySQL性能优化-范式设计和反范式设计

范式化设计 范式化设计背景 范式是数据表设计的基本原则,又很容易被忽略。很多时候,当数据库运行了一段时间之后,我们才发现数据表设计得有问题。重新调整数据表的结构,就需要做数据迁移,还有可能影响程序的业务逻辑…

【Axure高保真原型】输入宽高控制图片尺寸

今天和大家分享输入图片宽高控制图片尺寸的原型模板,在输入框里输入图片的宽和高,图片会自动设置成对应数值的尺寸,包括了按比例或者自由设置两种方式,具体效果可以观看下方视频或者打开预览地址体验。 【原型效果】 【Axure高保…

数据库SQLite

1.简单创建一个数据库和删除一个数据库 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:orientation"vertical">&l…

wordpress外贸独立站

WordPress外贸电商主题 简洁实用的wordpress外贸电商主题&#xff0c;适合做外贸跨境的电商公司官网使用。 https://www.jianzhanpress.com/?p5025 华强北面3C数码WordPress外贸模板 电脑周边、3C数码产品行业的官方网站使用&#xff0c;用WordPress外贸模板快速搭建外贸网…