155 lines
4.8 KiB
GDScript
155 lines
4.8 KiB
GDScript
@tool
|
|
class_name DialogicFlexVector
|
|
extends Resource
|
|
## Represents a position or size in either absolute pixels or relative to a given parent size.[br][br]
|
|
## Allows mixing sizes, e.g. x could be absolute and y be relative.
|
|
## Make sure that whenever you are editing this value or retrieving it via [method as_pixels]
|
|
## or [method as_percent] the [member container_size] is up to date.
|
|
## Percentage is a float between 0.0 and 1.0, with 1.0 being 100% of the container_size dimension.
|
|
## Mainly used by PortraitContainer.
|
|
|
|
## The FlexVectors x_value.
|
|
@export var x_value := 0.0:
|
|
set(x):
|
|
x_value = x
|
|
emit_changed()
|
|
|
|
## The FlexVectors y_value.
|
|
@export var y_value := 0.0:
|
|
set(y):
|
|
y_value = y
|
|
emit_changed()
|
|
|
|
## If true, the [param x_value] is in percent (ranging from 0 to 1 as a multiplier of the parents x dimension).
|
|
@export var x_percent := true
|
|
## If true, the [param y_value] is in percent (ranging from 0 to 1 as a multiplier of the parents y dimension).
|
|
@export var y_percent := true
|
|
|
|
var container_size := Vector2()
|
|
|
|
|
|
## Returns the value in pixels. Make sure container_size is up to date.
|
|
func as_pixels() -> Vector2:
|
|
return Vector2(
|
|
x_value if not x_percent else x_value * container_size.x,
|
|
y_value if not y_percent else y_value * container_size.y
|
|
)
|
|
|
|
|
|
## Returns the value in percent. Make sure container_size is up to date.
|
|
func as_percent() -> Vector2:
|
|
return Vector2(
|
|
0 if container_size.x == 0 else x_value / container_size.x if not x_percent else x_value,
|
|
0 if container_size.y == 0 else y_value / container_size.y if not y_percent else y_value
|
|
)
|
|
|
|
|
|
## Adds the given vector, while keeping the current x_percent and y_percent states and converting the incoming values if necessary.
|
|
func add(flex_vector:DialogicFlexVector) -> void:
|
|
if x_percent == flex_vector.x_percent:
|
|
x_value += flex_vector.x_value
|
|
else:
|
|
if x_percent:
|
|
x_value += flex_vector.as_percent().x
|
|
else:
|
|
x_value += flex_vector.as_pixels().x
|
|
|
|
if y_percent == flex_vector.y_percent:
|
|
y_value += flex_vector.y_value
|
|
else:
|
|
if y_percent:
|
|
y_value += flex_vector.as_percent().y
|
|
else:
|
|
y_value += flex_vector.as_pixels().y
|
|
|
|
|
|
## Creates a new FlexVector from the given string. See [method overwrite_from_string]
|
|
static func from_string(input: String) -> DialogicFlexVector:
|
|
var vec := DialogicFlexVector.new()
|
|
vec.overwrite_from_string(input)
|
|
return vec
|
|
|
|
|
|
## Extracts information from an input string and applies it to this FlexVector.
|
|
## The string can be of format "x10 y20" or "x10px y0.2%".
|
|
## Just a single dimension can be supplied, leaving the other where it's at.
|
|
## If type isn't specified, percentag is assumed.
|
|
func overwrite_from_string(input:String) -> void:
|
|
var vector_regex := RegEx.create_from_string(r"(?<part>x|y)\s*(?<number>(-|\+)?(\d|\.|)*)(\s*(?<type>%|px))?")
|
|
for i in vector_regex.search_all(input):
|
|
var value := float(i.get_string(&'number'))
|
|
match i.get_string(&'part').to_lower().strip_edges():
|
|
"x":
|
|
x_value = value
|
|
match i.get_string(&'type'):
|
|
"px":
|
|
x_percent = false
|
|
"%", _:
|
|
x_percent = true
|
|
"y":
|
|
y_value = value
|
|
match i.get_string(&'type'):
|
|
"px":
|
|
y_percent = false
|
|
"%", _:
|
|
y_percent = true
|
|
|
|
|
|
|
|
## Creates a new FlexVector with the given parent_size and values from the [param vector] assumed to be in pixels.
|
|
static func from_vector(vector:Vector2, parent_size:=Vector2()) -> DialogicFlexVector:
|
|
var vec := DialogicFlexVector.new()
|
|
vec.container_size = parent_size
|
|
vec.x_value = vector.x
|
|
vec.x_percent = false
|
|
vec.y_value = vector.y
|
|
vec.y_percent = false
|
|
return vec
|
|
|
|
|
|
## Replaces the given values with the values from the [param vector] assumed to be in pixels, but keeping x_percent and y_percent state and converting if necessary.
|
|
func overwrite_from_vector(vector:Vector2) -> void:
|
|
zero()
|
|
add(from_vector(vector, container_size))
|
|
|
|
|
|
|
|
func copy() -> DialogicFlexVector:
|
|
var vec := DialogicFlexVector.new()
|
|
vec.x_value = x_value
|
|
vec.y_value = y_value
|
|
vec.x_percent = x_percent
|
|
vec.y_percent = y_percent
|
|
vec.container_size = container_size
|
|
return vec
|
|
|
|
|
|
## Sets both values to 0.
|
|
func zero() -> void:
|
|
x_value = 0
|
|
y_value = 0
|
|
|
|
|
|
## Converts a string representation of the FlexVector.
|
|
func _to_string() -> String:
|
|
return "x" + str(self.x_value) + ["px", "%"][int(self.x_percent)] + " y" + str(self.y_value) + ["px", "%"][int(self.y_percent)] + " "+str(get_instance_id())
|
|
|
|
|
|
## Applies x_percent and y_percent from the given [param flex_vec] to this one and converts the values.
|
|
## Make sure container_size is up to date before.
|
|
func make_similar(flex_vec: DialogicFlexVector) -> void:
|
|
if flex_vec.x_percent != x_percent:
|
|
if flex_vec.x_percent:
|
|
x_value = as_percent().x
|
|
x_percent = true
|
|
else:
|
|
x_value = as_pixels().x
|
|
x_percent = false
|
|
if flex_vec.y_percent != y_percent:
|
|
if flex_vec.y_percent:
|
|
y_value = as_percent().y
|
|
y_percent = true
|
|
else:
|
|
y_value = as_pixels().y
|
|
y_percent = false
|