Ignore set scale in children

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By supaiku
:warning: Old Version Published before Godot 3 was released.

Hi,

is it possible for children of a node to ignore the scale change if the parent is scaled?

The behavior right now is, if set_scale is called on a node, all it’s children are also scaled. But I have some labels as part of the children that I don’t want to scale, because scaling (dynamic) fonts looks uaf.

:bust_in_silhouette: Reply From: splite

Technically no, becouse every node get parents transformation matrix, modify it by self position, rotation and scale and send it to own children, so scale is global when it come to node drawing. No one know what was the last scale added, you have only theirs sum.

Practically you have three options:

I will talk about 2D, but it is basically the same in 3D, only with one more parameter. Please note that GUI controls are 2D.

Manual option:
Just count it by hand. If you scale something (2,2), scale child nodes by (0.5,0.5) If you have just few nodes, its fastest way. Formula is trivial: 1/scale If you scale 25times on x and 0.5 times on y, reverting scale is x:1/25; y:1/0.5 => x:0,04; y:2

Reset matrix option:
This will not reset only parents scale but all scaling inherited.

see Matrices and transforms tutorial.

Have to go to work, i will try to return and add some example. Basically you want to modify matrix3x2 for 2D and matrix 3x3 for 3D at specific position to reset scaling. Not sure how to do it in Godot…

Scripted option:

func _ready():
    var scale = get_parent().get_scale()
    self.set_scale(Vector2(1/scale.x, 1/scale.y)) #2D
    #self.set_scale(Vector3(1/scale.x, 1/scale.y, 1/scale.z)) #3D

scripted recursive options:

Same as before, so i am not counting it as option, but with recursive walk to root (so its global scale reset as in matrix option)

func _ready():
    var scale = sum_scaleables(get_parent(), new Vector2(0,0)) #or Vector3 for 3D
    self.set_scale(Vector2(1/scale.x, 1/scale.y)) #2D

func sum_scaleables(parent, scaletmp):
    if(parent.has_method("get_scale")):
        scaletmp += parent.parent.get_scale()
    if parent.get_parent() == null
        return scaletmp
    return sum_scalabes(parent.get_parent(), scaletmp)

This, is the correct answer. It’s quite frustrating though, especially if you’re working with nested scenes.

dynamite-ready | 2017-12-27 17:15

:bust_in_silhouette: Reply From: volzhs

Make your scene tree in different way.

- Root
    - NodeA
        - Label
        - NodeB (other visual stuff)  <= scale this

Or, you can override set_scale function in NodeA

func set_scale(value):
    get_node("NodeB").set_scale(value)