0 votes

I have a Camera2D scene that operates my camera size and travel limits for different scenes. Within this scene is a simple child node called "Limits" (just acts like a folder) and inside this are two Position2D children called "TopLeftLimit" and "BottomRightLimit." These limits control the outer reaches of where the camera can travel in any given scene, and show as crosshairs in the editor but not in-game (I believe this is always the case for Position2D's but may be wrong). This is great to work with as all you have to do is move two crosshairs with your mouse in the editor to desired locations and boom, the camera is bound to stay between them.

Editor Screenshot: https://imgur.com/gallery/2enh9bY

However, I may have some times that I don't want a limit on my camera's outer bounds, say, maybe during development/debugging, and I would like to be able to turn these limits off, physically in-game (removing camera travel limits) as well as visually in the editor (hiding the crosshairs). I successfully did this for the physical, in-game portion with an export boolean checkbox called "Camera Limits Active" which sets the Limits child node (and therefore its children, the TopLeft and BottomRight limits) to be removed if said checkbox is unchecked (false), but for the life of me, I can't get these stupid crosshairs to hide unless I manually go into the editor and click the little eyeballs next to them or uncheck the "visible" checkbox on both of them in the Inspector. I want my one custom export variable checkbox to do this automatically so that there is a visual indication within the editor that my camera limits are off, thru code.

What am I doing wrong? Is this possible?

The following code is attached to the Camera2D scene on the parent, Camera2D node.

# Extensions
extends Camera2D


# Constants
export(bool) var cameraLimitsActive = true


# Variables
onready var limits = $Limits
onready var topLeftLimit = $Limits/TopLeftLimit
onready var bottomRightLimit = $Limits/BottomRightLimit


# Functions
func _ready():
    if cameraLimitsActive:
        topLeftLimit.visible = true
        bottomRightLimit.visible = true
        limit_top = topLeftLimit.position.y
        limit_left = topLeftLimit.position.x
        limit_bottom = bottomRightLimit.position.y
        limit_right = bottomRightLimit.position.x
    else:
        remove_child(limits)
        topLeftLimit.visible = false
        bottomRightLimit.visible = false
Godot version 3.4.4.stable
in Engine by (38 points)
edited by

1 Answer

0 votes

why not have 'limits' node be the node that can turn on-off visible (such as Node2D)
then

cameraLimitsActive = $Limits.visible

instead.

so you can toggle both visible and cameraLimit by only 'limits' node's eyeball via editor

by (133 points)

Where in the script do I put this? I've tried a few things but this isn't working, unfortunately. I tried:

export(bool) var cameraLimitsActive = $Limits.visible

with if cameraLimitsActive = true, cameraLimitsActive = true, else, cameraLimitsActive = false

I've also tried just keeping the export var as I had it and changing the solutions in the if statement to if true, $Limits.visible = true, else, false, bypassing my limits variable just in case that had something weird going on...

Maybe it's because I have the if statement in the _ready() function? I'm not sure where else I could put the if statement. I want it to update in real-time in the editor even when the game is not running.

change export to onready to make it get $Limits.visible when it run

# Constants
onready var cameraLimitsActive = $Limits.visible


# Variables
onready var limits = $Limits
onready var topLeftLimit = $Limits/TopLeftLimit
onready var bottomRightLimit = $Limits/BottomRightLimit


# Functions
func _ready():
    if cameraLimitsActive:
        limit_top = topLeftLimit.position.y
        limit_left = topLeftLimit.position.x
        limit_bottom = bottomRightLimit.position.y
        limit_right = bottomRightLimit.position.x
   else:
        remove_child(limits)

but if you really want your script to run in the editor, Godot has this
https://docs.godotengine.org/en/stable/tutorials/plugins/running_code_in_the_editor.html
I didn't try it yet but it should be the thing you want

Yeah neither of those things worked either :/

Unfortunately, I do need cameraLimitsActive to be an export variable so I can easily change it from the Inspector in the editor. Just making it an onready var would get rid of all functionality here. I tried:

export(bool) onready var cameraLimitsActive = true

which ran the game but for some reason the "onready" part kept the physical, in-game limits from being turned off. Setting it equal to $Limits.visible returned "Invalid get index 'visible' (on base: 'null instance')."

I tried the tool thing too, like this:

# Extensions
tool
extends Camera2D


# Variables
export(bool) var cameraLimitsActive = true

onready var limits = $Limits
onready var topLeftLimit = $Limits/TopLeftLimit
onready var bottomRightLimit = $Limits/BottomRightLimit


# Functions
func _ready():
    if Engine.editor_hint:
        if cameraLimitsActive
            limits.visible = true
        else:
            limits.visible = false
    if not Engine.editor_hint:
        if cameraLimitsActive:
            limit_top = topLeftLimit.position.y
            limit_left = topLeftLimit.position.x
            limit_bottom = bottomRightLimit.position.y
            limit_right = bottomRightLimit.position.x
        else:
            remove_child(limits)

where again, having cameraLimitsActive equal to $Limits.visible returned "Invalid get index 'visible' (on base: 'null instance')." I tried this as a process(delta): function as well, no difference.

I got rid of the tool functionality via ctrl+Z and brought my code back to:

# Extensions
extends Camera2D


# Variables
export(bool) var cameraLimitsActive = true

onready var limits = $Limits
onready var topLeftLimit = $Limits/TopLeftLimit
onready var bottomRightLimit = $Limits/BottomRightLimit


# Functions
func _ready():
    if cameraLimitsActive:
        limits.visible = true
        limit_top = topLeftLimit.position.y
        limit_left = topLeftLimit.position.x
        limit_bottom = bottomRightLimit.position.y
        limit_right = bottomRightLimit.position.x
    else:
        remove_child(limits)
        limits.visible = false

just to get us back on the same page.

At first, this Tool thing destroyed my Camera2D in my World (yes, even after removing it from my code), but I fixed that by deleting the Camera2D and adding a new one, then reassigning it to my RemoteTransform2D that connects it to my character (but that's a whole different convo).

_ready() function isn't triggered automatically when you update value
use setget instead

# Extensions
tool
extends Camera2D


# Variables
export(bool) var cameraLimitsActive = true  setget onLimitsChange

onready var limits = $Limits
onready var topLeftLimit = $Limits/TopLeftLimit
onready var bottomRightLimit = $Limits/BottomRightLimit


func onLimitsChange(val):
    cameraLimitsActive = val
    if cameraLimitsActive:
        limits.visible = true
        limit_top = topLeftLimit.position.y
        limit_left = topLeftLimit.position.x
        limit_bottom = bottomRightLimit.position.y
        limit_right = bottomRightLimit.position.x
    else :
        limits.visible = false
        limit_top = -10000000
        limit_left = -10000000
        limit_bottom = 10000000
        limit_right = 10000000

Closer...this does work for turning off the crosshairs, but breaks the camera completely (have to do that reassigning trick again). I think I might just give up. This isn't worth the effort. The gameplay functionality is there at least.

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 Frequently asked questions and 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 [email protected] with your username.