Forum Archive

I thought about spacing my questions, but... scene.present_modal_scene issues

WTFruit

I do feel bad, I don't want to be nagging but since there aren't 3rd-party resources for most of my questions, and I'm occasionally bumping into problems that I can't seem to figure out, I don't think I have anywhere else to go.

I'm trying to work out multiple-scene situations now. I thought the first possibility sounded very easy to implement: use present_modal_scene to display a scene on top of the original one. Unfortunately, even though everything looks right to me and I'm doing it exactly the same way as the example games (as far as I can tell), I'm getting an error.

Secondarily, I don't see an elegant way to move between scenes. Currently I have noticed that I can create another scene and run it whenever I want but it just puts it on top of the previous one, which is still running in the background and when I hit the "x", it takes me to the original scene. That doesn't seem like an ideal outcome.

So, the first problem. Here's my modal scene code:

import scene
import ui

class Scene1(scene.Scene):

   def __init__(self):
      pass

   def touch_began(self, touch):
      self.menu = Scene2()
      self.present_modal_scene(self.menu)


class Scene2(scene.Scene):

   def __init__(self):
      pass


scene.run(Scene1())

When I run that code it starts fine but when I tap to bring up the second scene, I get this error:

ValueError: max() arg is an empty sequence

I'm very stumped. I feel like it couldn't be a simpler thing but I've hit a wall.

The second problem (the general ability to switch between scenes), I don't even know where to begin with because I can't find any examples or info in the documentation.

Sorry for asking so many questions!

omz

I haven't run your code yet, but I think the problem is mostly that your __init__ methods are empty. That way, you're preventing the default initialization, which probably leads to weird errors down the line because variables that the scene expects to be there while running aren't initialized, etc.

You'd either have to call the base class's __init__ in your own initialization, or remove your __init__ methods entirely (it's often more convenient to use setup instead of __init__ for scenes).

WTFruit

@omz

Fair point that I never thought of, but I removed those without any change. Same error :/

omz

Ah, I just ran the code, and it turns out that there is also a bug in the scene module that makes present_modal_scene not work when the presenting scene has no content. The reason is that it's trying to set the z position (layer ordering) to the maximum of its children, but that fails when there are no children... You can work around this by just adding a dummy Node to the scene.

WTFruit

@omz

Hmmm interesting! I'll try that out shortly then. Any advice on multiple "main" scenes and how to more properly switch between them?

omz

@WTFruit You can set the self.view.scene attribute, though you'll have to call setup manually then. Here's a minimal example to illustrate:

import scene

class Scene1(scene.Scene):
    def setup(self):
        self.background_color = 'green'

    def touch_began(self, touch):
        next_scene = Scene2()
        self.view.scene = next_scene
        next_scene.setup()

class Scene2(scene.Scene):
    def setup(self):
        self.background_color = 'red'


scene.run(Scene1())

WTFruit

@omz (or anyone else reading this)

I finally got an implementation of the modal_scene working (took me long enough), it brings up the modal scene and everything. But it still gives me the same initial error at the moment that the modal scene is called. Is there anything I can do about that?

Thank you for the scene-change code by the way, it works like a charm. Although I was curious why this works:

self.menu = Scene2()
self.present_modal_scene(self.menu)

But not this:

self.present_modal_scene(Scene2())

I guess I'm misunderstanding the use of self.menu, I assumed it was basically a pointer, a stand-in for the other phrasing of the code (Scene2()).