"Cross-breeding" labels and callables

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
herenvardo
Veteran
Posts: 359
Joined: Sat Feb 25, 2006 11:09 am
Location: Sant Cugat del Vallès (Barcelona, Spain)
Contact:

"Cross-breeding" labels and callables

#1 Post by herenvardo » Tue Nov 15, 2011 8:13 pm

It's been over three years since I last tortured the Ren'py engine, so I had to go for something big :twisted: !

Actually, what I'm looking for is not that big, and it is in fact a 180º turn from what I used to do back in 2008: rather than building huge python blocks, I'm looking for ways to do as much as possible within Ren'py code and rely as little as possible on python (ideally doing only class and utility function definitions, aside from single-line, $-prefixed computations).

The problem is that some of my classes' instances are meant to be callable, and calling them would do some non-trivial stuff, sometimes including multiple interactions.
To handle multiple interactions, the only sane choice is to do things from Ren'py code. I am aware of that. So ok, no problem, implementing the whole thing in Ren'py code would be as easy as implementing it in python.
Well, there is one problem: for the object to be "called" properly, I have to define things on its __call__ method.

I know this is theoretically plausible: in all likelihood, Ren'py implements the "call a ren'py label" as a function, so at the very least it should be possible to hack my class so it's __call__ actually "points" to that function.
But I know that messing with Ren'py's internal stuff is, in the best case, completely inadvisable. Yet, before I start looking for workarounds (I have already have some ideas in mind), I'd rather try to find an actual solution.

Thus, here is the question: is there a sane way to plug a label as the __call__ method for a class?
I have failed to meet my deadlines so many times I'm not announcing my projects anymore. Whatever I'm working on, it'll be released when it is ready :P

User avatar
PyTom
Ren'Py Creator
Posts: 15875
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: "Cross-breeding" labels and callables

#2 Post by PyTom » Wed Nov 16, 2011 10:53 am

There's a couple of ways you can do this. If it's okay to terminate the function, and the _entire python block it's in_, you can use renpy.call. The following code works (the output goes to the console):

Code: Select all

python:
    print "This line will be printed."
    renpy.call("my_label")
    print "This line won't be printed."
Otherwise, you have to use renpy.call_in_new_context, which works, but you can't save while you're in a new context.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
"Silly and fun things are important." - Elon Musk
Software > Drama • https://www.patreon.com/renpytom

User avatar
herenvardo
Veteran
Posts: 359
Joined: Sat Feb 25, 2006 11:09 am
Location: Sant Cugat del Vallès (Barcelona, Spain)
Contact:

Re: "Cross-breeding" labels and callables

#3 Post by herenvardo » Wed Nov 16, 2011 12:36 pm

PyTom wrote:If it's okay to terminate the function, and the _entire python block it's in_
I hope it'd be ok, but I'd need to confirm what "terminate the function" exactly means.

Let's say I have these scattered around my scripts:

Code: Select all

python: # This would most probably be within an init:
    class MyCallableClass:
        def __call__(self):
            renpy.call("my_label_implementing_stuff")
        # there will also be an __init__ and some interesting stuff, but not relevant now

Code: Select all

$ myCallableObject = MyCallableClass()

Code: Select all

label my_label_implementing_stuff:
    # Here I'll go nuts with all my UI-related code
    return
And now to the critical part:

Code: Select all

$ myCallableObject()
# Will the flow return here after running through the label?
If the answer to that last comment is "yes", everything will be fine :D

On a side note: will renpy.call() allow me to pass some arguments to the label? I'm hoping it emulates the good old call statement, and last time I tried (which was years ago :? ) that statement allowed passing arguments. That would be great, but I can still work around it if there is no other choice.
I guess returning values is quite out of the question, but fortunately I don't need them.

Thanks for your answers!
I have failed to meet my deadlines so many times I'm not announcing my projects anymore. Whatever I'm working on, it'll be released when it is ready :P

User avatar
PyTom
Ren'Py Creator
Posts: 15875
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: "Cross-breeding" labels and callables

#4 Post by PyTom » Wed Nov 16, 2011 12:41 pm

The answer is yes on both accounts.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
"Silly and fun things are important." - Elon Musk
Software > Drama • https://www.patreon.com/renpytom

Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot]