【Godot4.3】自定义圆角容器

news/2025/2/25 17:29:10

概述

Godot控件想要完全实现现代UI风格,需要进行大量的自定义组件设计。本篇就依托于笔者自己对现代UI设计中的圆角面板元素模仿来制作圆角容器组件。

圆角容器

圆角元素在现代的扁平UI设计中非常常见,在Godot中可以通过改进PanelContainer来或者自定义容器来实现圆角面板效果。

  • 我初期想基于PanelContainer写一个容器类,但是发现比较绕
  • 于是还是直接基于Container类型写了一个自定义容器
  • 初期我偏向于直接用绘图函数绘制StyleBox
  • 但是当遇到渐变和图片时,绘制StyleBox的方式将无法获得圆角
  • 所以最后不得不采用绘图函数draw_colored_polygon,并且自己计算圆角矩形顶点集合以及计算每个点的UV坐标,从而实现一种类似矢量遮罩的效果。

最终实现效果

基础效果

RadiusPanelContainer

容器的自定义参数如下:

基本参数

实现如下功能:

  • 快速获得带圆角的纯色、图片背景(包括渐变等)的容器
  • 可以设定统一的描边颜色、宽度,以及圆角大小
  • 可以设定子元素的内边距
  • 可以设定容器的不透明度

注意: 需要搭配常见容器使用,第一个子元素也是唯一被正确显示的第一级子元素,需要是一个容器类型。


第一级第一个子元素需要为<a class=容器类型" width="300" />

完整代码

# ==========================================================
# RadiusPanelContainer
# 类型:自定义容器
# 概述:现代化UI系列,实现基础的圆角面板元素
# 巽星石
# 创建时间20251313:45:32
# 最后修改时间:20251317:54:39
# ==========================================================
@tool
class_name  RadiusPanelContainer extends Container

# =============================== 参数 ===============================

@export var padding:=10: ## 内边距
	set(val):
		padding = val
		queue_redraw()

@export_range(0.0,1.0,0.1) var opacity=1.0: ## 透明度
	set(val):
		opacity = val
		if val:
			self_modulate = Color(1.0,1.0,1.0,val)
		queue_redraw()

@export_group("background")
@export var bg_color:=Color.WHITE: ## 背景颜色
	set(val):
		bg_color = val
		queue_redraw()

@export var bg_texture:Texture2D: ## 背景图片
	set(val):
		bg_texture = val
		queue_redraw()

@export_group("border")
@export var border_color:=Color.WHITE: ## 边框颜色
	set(val):
		border_color = val
		queue_redraw()


@export var border_radius:=5: ## 圆角半径
	set(val):
		border_radius = val
		queue_redraw()


@export var border_width:=0:## 边线宽度
	set(val):
		border_width = val
		queue_redraw()


# =============================== 虚函数 ===============================
func _init() -> void:
	clip_contents = true

func _draw() -> void:
	var rect = get_rect() * get_transform()
	var pots = round_rect(rect,border_radius,border_width/2.0)
	# 绘制背景
	if bg_texture:
		var uvs:PackedVector2Array
		for pot in pots: # 计算UV坐标
			uvs.append(pot/rect.size)
		# 绘制圆角矩形
		draw_colored_polygon(pots,bg_color,uvs,bg_texture)
	else:
		draw_polygon(pots,[bg_color])
	# 绘制边线
	draw_polyline(pots,border_color,border_width)
	# 重排子元素
	queue_sort()

func _notification(what: int) -> void:
	var rect = get_rect() * get_transform()
	rect.position += Vector2.ONE * padding
	rect.size -= Vector2.ONE * padding * 2
	match what:
		NOTIFICATION_SORT_CHILDREN:
			if get_child_count()>0:
				fit_child_in_rect(get_children()[0],rect)

# =============================== 自定义函数 ===============================
# 求圆弧点集
func arc(c:Vector2,r:float,start_angle:float,end_angle:float,steps:=10) -> PackedVector2Array:
	var arr:PackedVector2Array
	var v1 = Vector2.RIGHT * r
	var ang = deg_to_rad(end_angle - start_angle)/float(steps)
	for i in range(steps+1):
		arr.append(v1.rotated(ang * float(i) + deg_to_rad(start_angle)) + c)
	return arr

# 获取圆角矩形
func round_rect(rect:Rect2,r:float,offset:float) -> PackedVector2Array:
	var arr:PackedVector2Array
	var pots:PackedVector2Array = get_rect2_points(rect) # 矩形顶点
	var vec = Vector2.ONE * (r + offset)  # 圆角偏移向量
	arr.append_array(arc(pots[0] + vec,r,180,270))
	arr.append_array(arc(pots[1] + Transform2D.FLIP_X * vec,r,270,360))
	arr.append_array(arc(pots[2] + vec * -1,r,0,90))
	arr.append_array(arc(pots[3] + Transform2D.FLIP_Y * vec,r,90,180))
	arr.append(pots[0] + vec - Vector2(r,0))
	return arr

# 获取Rect对应的点集合
func get_rect2_points(rect:Rect2) -> PackedVector2Array:
	var arr:PackedVector2Array
	var pos = rect.position
	var end = rect.end
	var w = rect.size.x
	arr.append(pos)
	arr.append(pos + Vector2.RIGHT * w)
	arr.append(end)
	arr.append(end - Vector2.RIGHT * w)
	return arr

提示

  • 这只是个基础版本,后续改进,敬请期待

http://www.niftyadmin.cn/n/5865766.html

相关文章

【IEEE出版,往届会后3个月EI检索 | 西华大学主办 | 中英文期刊、SCI期刊推荐】第四届能源、电力与电气国际学术会议(ICEPET 2025)

第四届能源、电力与电气国际学术会议&#xff08;ICEPET 2025&#xff09;由西华大学主办&#xff0c;西华大学能源与动力工程学院、西华大学电气与电子信息学院、西华大学航空航天学院、流体及动力机械教育部重点实验室、流体机械及工程四川省重点实验室、四川省水电能源动力装…

2025年02月24日Github流行趋势

项目名称&#xff1a;mastra 项目地址url&#xff1a;https://github.com/mastra-ai/mastra 项目语言&#xff1a;TypeScript 历史star数&#xff1a;5735 今日star数&#xff1a;1140 项目维护者&#xff1a;adeleke5140, abhiaiyer91, TheIsrael1, adeniyii, Joshuafolorunsh…

冒泡排序:简单又易于实现的排序算法

大家好&#xff0c;今天我们来聊聊 冒泡排序&#xff08;Bubble Sort&#xff09;算法。听名字是不是很简单&#xff0c;感觉就像是水面上泡泡一样&#xff1f;没错&#xff0c;冒泡排序的名字来源于这种排序过程中&#xff0c;较大的元素像气泡一样逐步“冒泡”到数组的顶端。…

第4章 4.4 EF Core数据库迁移 Add-Migration UpDate-Database

4.4.1 数据库迁移原理 总结一下就是&#xff1a; 1. 数据库迁移命令的执行&#xff0c;其实就是生成在数据库执行的脚本代码&#xff08;两个文件&#xff1a;数字_迁移名.cs 数字_迁移名.Designer.cs&#xff09;&#xff0c;用于对数据库进行定义和修饰。 2. 数据库迁移…

java23种设计模式-原型模式

原型模式&#xff08;Prototype Pattern&#xff09;学习笔记 &#x1f31f; 定义 原型模式属于创建型设计模式&#xff0c;通过复制现有对象&#xff08;原型&#xff09;来创建新对象&#xff0c;避免重复进行初始化操作。该模式的核心是实现对象的克隆能力。 &#x1f3af…

基于深度学习的SSD口罩识别项目完整资料版(视频教程+课件+源码+数据)

基于深度学习的SSD口罩识别项目完整资料版&#xff0c;包含视频教程、PPT课件和源码. 01 项目介绍.mp4 02 SSD算法原理回顾.mp4 03 数据集收集.mp4 04 自定义数据集.mp4 05 生成anchors.mp4 06 展示anchors.mp4 07 计算iou值.mp4 08 计算target.mp4 09 定义模型.mp4 10 模型训练…

【开关电源】汽车前端电源保护电路设计

前言&#xff1a; 汽车电池端子在启动或者保养过程中被反接&#xff0c;如果对这些故障不能及时处理&#xff0c;就可能导致ECU或供电设备被损坏&#xff1b;此外在供电过程中电压也存在不稳定的情况。在EMC测试中ISO16750和ISO7637也会有负电压的情况。 肖特基二极管和 P 沟道…

抖音营销创新策略与案例分析:以奈雪的茶为例及开源AI智能名片2+1链动模式S2B2C商城小程序的启示

摘要&#xff1a;随着互联网技术的快速发展&#xff0c;社交媒体平台已成为品牌推广和市场营销的重要阵地。抖音作为短视频领域的佼佼者&#xff0c;凭借其庞大的用户基础和强大的算法推荐机制&#xff0c;为众多品牌提供了广阔的营销空间。本文以奈雪的茶在抖音的6周年营销活动…