scale and rotate

This commit is contained in:
Face
2025-08-10 14:52:35 +03:00
parent 6fdf422f7e
commit 0e069bd438
7 changed files with 422 additions and 2 deletions

View File

@@ -182,6 +182,8 @@ static func setup_panel_hover_support(panel: PanelContainer, normal_styles: Dict
# Store references for the hover handlers
panel.set_meta("normal_stylebox", normal_stylebox)
panel.set_meta("hover_stylebox", hover_stylebox)
panel.set_meta("normal_styles", normal_styles.duplicate(true))
panel.set_meta("hover_styles", merged_hover_styles.duplicate(true))
# Connect mouse events
panel.mouse_entered.connect(_on_panel_mouse_entered.bind(panel))
@@ -191,11 +193,28 @@ static func _on_panel_mouse_entered(panel: PanelContainer):
if panel.has_meta("hover_stylebox"):
var hover_stylebox = panel.get_meta("hover_stylebox")
panel.add_theme_stylebox_override("panel", hover_stylebox)
if panel.has_meta("hover_styles"):
var hover_styles = panel.get_meta("hover_styles")
var transform_target = find_transform_target_for_panel(panel)
StyleManager.apply_transform_properties_direct(transform_target, hover_styles)
static func _on_panel_mouse_exited(panel: PanelContainer):
if panel.has_meta("normal_stylebox"):
var normal_stylebox = panel.get_meta("normal_stylebox")
panel.add_theme_stylebox_override("panel", normal_stylebox)
if panel.has_meta("normal_styles"):
var normal_styles = panel.get_meta("normal_styles")
var transform_target = find_transform_target_for_panel(panel)
StyleManager.apply_transform_properties_direct(transform_target, normal_styles)
static func find_transform_target_for_panel(panel: PanelContainer) -> Control:
var parent = panel.get_parent()
if parent and parent is FlexContainer:
return parent
return panel
static func needs_background_wrapper(styles: Dictionary) -> bool:
return styles.has("background-color") or styles.has("border-radius") or styles.has("padding") or styles.has("padding-top") or styles.has("padding-right") or styles.has("padding-bottom") or styles.has("padding-left") or styles.has("border-width") or styles.has("border-top-width") or styles.has("border-right-width") or styles.has("border-bottom-width") or styles.has("border-left-width") or styles.has("border-color") or styles.has("border-style") or styles.has("border-top-color") or styles.has("border-right-color") or styles.has("border-bottom-color") or styles.has("border-left-color")

View File

@@ -0,0 +1,158 @@
class_name TransformUtils
extends RefCounted
# Utility functions for parsing CSS transform values (scale and rotation)
# Parse scale values - returns a Vector2 with x and y scale factors
static func parse_scale(val: String) -> Vector2:
if val == null or val.is_empty():
return Vector2.ONE
# Named scale values
var named = {
"0": Vector2.ZERO,
"50": Vector2(0.5, 0.5),
"75": Vector2(0.75, 0.75),
"90": Vector2(0.9, 0.9),
"95": Vector2(0.95, 0.95),
"100": Vector2.ONE,
"105": Vector2(1.05, 1.05),
"110": Vector2(1.1, 1.1),
"125": Vector2(1.25, 1.25),
"150": Vector2(1.5, 1.5),
"200": Vector2(2.0, 2.0)
}
if named.has(val):
return named[val]
# Direct numeric value (treat as percentage: 100 = 1.0, 50 = 0.5, etc.)
if val.is_valid_int():
var scale_factor = float(val) / 100.0
return Vector2(scale_factor, scale_factor)
# Direct decimal value
if val.is_valid_float():
var scale_factor = float(val)
return Vector2(scale_factor, scale_factor)
return Vector2.ONE
# Parse rotation values - returns rotation in radians
static func parse_rotation(val: String) -> float:
if val == null or val.is_empty():
return 0.0
# Named rotation values (in degrees, converted to radians)
var named = {
"0": 0.0,
"1": deg_to_rad(1.0),
"2": deg_to_rad(2.0),
"3": deg_to_rad(3.0),
"6": deg_to_rad(6.0),
"12": deg_to_rad(12.0),
"45": deg_to_rad(45.0),
"90": deg_to_rad(90.0),
"180": deg_to_rad(180.0),
"270": deg_to_rad(270.0)
}
if named.has(val):
return named[val]
# Handle explicit unit specifications
if val.ends_with("deg"):
var degrees = float(val.replace("deg", ""))
return deg_to_rad(degrees)
elif val.ends_with("rad"):
return float(val.replace("rad", ""))
elif val.ends_with("turn"):
var turns = float(val.replace("turn", ""))
return turns * 2.0 * PI
# Direct numeric value - assume degrees
if val.is_valid_float():
return deg_to_rad(float(val))
return 0.0
# Parse arbitrary value from brackets like [1.7] or [45deg] or [3.5rad]
static func parse_bracket_value(bracket_content: String, value_type: String):
if bracket_content.is_empty():
return null
match value_type:
"scale":
return parse_scale(bracket_content)
"rotation":
return parse_rotation(bracket_content)
_:
return null
# Extract bracket content for transform utilities
static func extract_bracket_content(string: String, start_idx: int) -> String:
var open_idx = string.find("[", start_idx)
if open_idx == -1:
return ""
var close_idx = string.find("]", open_idx)
if close_idx == -1:
return ""
return string.substr(open_idx + 1, close_idx - open_idx - 1)
# Parse scale utility and return the appropriate property name and value
static func parse_scale_utility(utility_name: String) -> Dictionary:
var result = {}
if utility_name.begins_with("scale-x-"):
var val = utility_name.substr(8) # after "scale-x-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var scale_vec = parse_scale(val)
result["scale-x"] = scale_vec.x
return result
elif utility_name.begins_with("scale-y-"):
var val = utility_name.substr(8) # after "scale-y-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var scale_vec = parse_scale(val)
result["scale-y"] = scale_vec.y
return result
elif utility_name.begins_with("scale-"):
var val = utility_name.substr(6) # after "scale-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var scale_vec = parse_scale(val)
result["scale-x"] = scale_vec.x
result["scale-y"] = scale_vec.y
return result
return result
# Parse rotation utility and return the appropriate property name and value
static func parse_rotation_utility(utility_name: String) -> Dictionary:
var result = {}
if utility_name.begins_with("rotate-x-"):
var val = utility_name.substr(9) # after "rotate-x-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var rotation = parse_rotation(val)
result["rotate-x"] = rotation
return result
elif utility_name.begins_with("rotate-y-"):
var val = utility_name.substr(9) # after "rotate-y-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var rotation = parse_rotation(val)
result["rotate-y"] = rotation
return result
elif utility_name.begins_with("rotate-"):
var val = utility_name.substr(7) # after "rotate-"
if val.begins_with("[") and val.ends_with("]"):
val = val.substr(1, val.length() - 2)
var rotation = parse_rotation(val)
result["rotate-z"] = rotation # Default rotation is around Z-axis
return result
return result

View File

@@ -0,0 +1 @@
uid://m8sb57jskjyp

View File

@@ -41,6 +41,10 @@ static func init_patterns():
"^opacity-\\[.*\\]$", # custom opacity values
"^z-\\[.*\\]$", # custom z-index values
"^cursor-[a-zA-Z-]+$", # cursor types
"^scale-(x-|y-)?\\d+$", # scale utilities like scale-100, scale-x-75, scale-y-150
"^scale-(x-|y-)?\\[.*\\]$", # custom scale values like scale-[1.5], scale-x-[2.0]
"^rotate-(x-|y-)?\\d+$", # rotation utilities like rotate-45, rotate-x-90, rotate-y-180
"^rotate-(x-|y-)?\\[.*\\]$", # custom rotation values like rotate-[45deg], rotate-x-[90deg], rotate-y-[3.5rad]
"^(hover|active):", # pseudo classes
]
for pattern in utility_patterns: