+4 votes

Hi Everyone,

I am trying to create a custom control that can scroll its child controls, but I cannot find a base control (container, panel, etc) that will only show the parts of the child controls that are within the container's bounds, like the ScrollContainer does.
(I do not want to use the ScrollContainer)

I have tried the Container and Panel and others, but child controls are always fully visible, even if they are totally outside the parent.

How do you accomplish the clipping/masking behavior that the ScrollContainer does?

Thank you.

in Engine by (78 points)

3 Answers

+7 votes
Best answer

I just look at the github repo and find the scroll container and I think it's awesome you can mask every subnode of any 2d shape with this line of code

 func _draw():
     VisualServer.canvas_item_set_clip(get_canvas_item(),true)

just add a container or even a sprite then add this code for it and all of it's children will be cliped

by (576 points)
selected by
Thank you so much for helping me with this. I tried it, and it works!

Thats very useful, but the clipping only limits the appearance, input events can still hit the invisible buttons. Is there a way to also clip the input events ?

Nice! But it only clips to the bounding box of the canvas item.
Is there any way to clip the children to the actual shape of the parent? (which may be irregular, as taken from a texture image, for example)

The best thing I could think of to do that would be using a Light2D, settings its mode to "Mask" and setting its texture to that of the parent's shape. Then just make sure it culls the same layer that the children are on.

+1 vote

Control nodes have a checkbox for clipping the children nodes.

The name of the property is rect_clip_content.

by (22 points)

that's right.
the selected answer was for godot 1.x and 2.x
now we have rect_clip_content property with godot 3.x

That should be the accepted answer nowadays. In most cases there is no need to do the clipping manually in every draw call.

+1 vote

Originally found the solution in jabcross's answer above.

Adding a few more details for anyone else going down this rabbithole.


"Clip Content" is found here in the Inspector Dock :
Control -> Rect -> Clip Content

Clip Content Inspector Dock location

Rect is present in all nodes derived from Control
(which is derived from CanvasItem & Node)

Enabling clip content will make any portion of child nodes outside of the parent rect invisible.


This clip content setting can also be enabled in gdscript.

Add a script.gd to any Control derived node, and type

rect_clip_content = true

Hints for those starting out :

Do this in _ready(): and it will immediately take effect.
But unless you need to change this setting during gameplay, go ahead and just set it in the Inspector Dock. It's good to know how to do things in scripts, but prefer the Inspector when a setting will remain the same.

You do not need to type var, this variable is already present in your script as soon as you derive Control. The variable rect_clip_content is is a class property (aka class variable) that is present in any .gd script which derives Control or any of its descendants.

(If this is new information, it's good to know that when you type extends somenodename, you automatically have access in your .gd script to the extended node's methods & class properties. And also to all methods and properties from each node it inherits -> all the way up to the class Object.)


Word of caution : this clip rect setting only affects what is visible in the viewport.

Input events will still fire for any child nodes that are wholly or partially invisible due to the rect clipping of a parent node.

You need to do the following to clip input:

If you want to prevent hidden portions of nodes from triggering _input(event) calls or _gui_input(event) calls, add this function to the parent which is clipping content :

func _clips_input():
   return true

https://docs.godotengine.org/en/stable/classes/class_control.html#class-control-method-clips-input


I was recently making a picture viewer, and though parts were hidden they were still triggering input events when I thought nothing was under the cursor.

This page keeps coming up in my google searches for clipping,
so wanted to add some details.

Have a great day.

by (36 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.