Custom user interface
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.
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.
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
Yeah, I slipped the new demo back to 5.6.2, since I want people to have a stable version of 5.6 to work with.
Of course, the sooner I can see the backgrounds, the better.
Of course, the sooner I can see the backgrounds, the better.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Ok, I'm having troubles with the "hovered" and "unhovered" parameters of buttons. What I'm trying to do :
Have a bunch of buttons generated from a list and placed on screen (OK).
Have these buttons clickable and return a unique result for each of them (their ID)... (OK).
Have the interface react to hovering each of them and display a unique text for each of them (NOT OK ^^;...).
The concrete example of what I'm trying to do is : a map, locations on the map (imagebutton) that you can either click (=goto) or just hover (displays name of location or detailed infos).
The main problem is that you define "hovered=somefunction". Except that function has no way to know which button called it. I wish something like "hovered=somefunction(ID)" would be possible but it's not. I could also have "somefunction()" get its caller afterwards... something like "self.ID", but self isn't not accessible and I'm pretty sure I can't set ID anyway :/...
I know you mentioned DynamicDisplayable but it only changes styles, not text.
Any idea ? :/
Have a bunch of buttons generated from a list and placed on screen (OK).
Have these buttons clickable and return a unique result for each of them (their ID)... (OK).
Have the interface react to hovering each of them and display a unique text for each of them (NOT OK ^^;...).
The concrete example of what I'm trying to do is : a map, locations on the map (imagebutton) that you can either click (=goto) or just hover (displays name of location or detailed infos).
The main problem is that you define "hovered=somefunction". Except that function has no way to know which button called it. I wish something like "hovered=somefunction(ID)" would be possible but it's not. I could also have "somefunction()" get its caller afterwards... something like "self.ID", but self isn't not accessible and I'm pretty sure I can't set ID anyway :/...
I know you mentioned DynamicDisplayable but it only changes styles, not text.
Any idea ? :/
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
Well, DynamicDisplayables can change Displayables as well as styles. So I'm not sure what you mean by that.
Ren'Py does not need to support passing default data to functions... this is Python, not C++. There are a couple of ways you can get default data to functions that need it.
The first is to use bound methods. In Python, when one takes a reference to a method on an object, a callable is created that remembers both the object and the method. So one can do (in straight python):
And it will print out 42.
Another way is to create a new function, with default values for some of its parameters. This is the way I'd recommend solving your problem:
I suggest doing this inside a python hide, to prevent the newly-created functions (the different variants of hovered) from leaking into the main namespace, and preventing loading and saving. It's not necessary in this case, but it can't hurt.
You can also do this using closures, which accomplish roughly the same thing without as much typing. (But with a larger dose of magic.)
Ren'Py does not need to support passing default data to functions... this is Python, not C++. There are a couple of ways you can get default data to functions that need it.
The first is to use bound methods. In Python, when one takes a reference to a method on an object, a callable is created that remembers both the object and the method. So one can do (in straight python):
Code: Select all
class Foo(object):
def __init__(self, a):
self.a = a
def bar(self):
print self.a
o = Foo(42)
bound_method = o.bar
# ....
bound_method()
Another way is to create a new function, with default values for some of its parameters. This is the way I'd recommend solving your problem:
Code: Select all
label splashscreen:
python hide:
store.hovered_text = ""
def mybutton(text, hovered_text, clicked):
def hovered(hovered_text=hovered_text):
if store.hovered_text == hovered_text:
return
store.hovered_text = hovered_text
renpy.restart_interaction()
return None
ui.textbutton(text, hovered=hovered, clicked=clicked)
ui.vbox()
ui.hbox()
mybutton("Foo", "You're hovering the foo button.", ui.returns(1))
mybutton("Bar", "You're hovering the bar button.", ui.returns(2))
mybutton("Baz", "You're hovering the baz button.", ui.returns(3))
ui.close()
ui.add(DynamicDisplayable("Text(store.hovered_text)"))
ui.close()
ui.interact()
You can also do this using closures, which accomplish roughly the same thing without as much typing. (But with a larger dose of magic.)
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
Yeah, python is big on it's first-class functions and bound methods. So you use things like closures, bound methods, and default arguments quite a bit, where in a language like C you need a way of supplying data (traditionally, a void *) to the callback function.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Still quite confusing ^.^...
Ok, I tried and am facing a problem already (*sigh*)... See, I defined a "displayMap" function in some "map.rpy" file. This is the one looping through available locations and displaying them.
According to your tip, it now tries to call this "mybutton"-type function to generate the hoverable buttons.
Last thing : I'd call displayMap from quite anywhere in the game.
Problem : mybutton should be in a python hide block... displayMap should too, then... and could still access the location list with "store.locations"... but now, I can't call displayMap since it's defined and then destroyed (at least I suppose that's the concept of python hide ?) without having been used once.
So uh... can anything declared in python hide block be called from "outside"? ô_o...
I can see a possible workaround : define a label in my game (displaymap) that would contain all this python hide block (definitions and use of functions)... then call it from anywhere in the game.
It means the whole thing will be generated on the fly, executed, and sent back to the abysses, right ?
EDIT : The workaround works but this means that I'll have to copy paste my hover functions a *lot* :/... I'm still eager for a cleaner solution ^^;
And an additional question : can imagebutton accept Displayable instead of just filenames ? *thinking of animated, hoverable imagebuttons >.>...*
Ok, I tried and am facing a problem already (*sigh*)... See, I defined a "displayMap" function in some "map.rpy" file. This is the one looping through available locations and displaying them.
According to your tip, it now tries to call this "mybutton"-type function to generate the hoverable buttons.
Last thing : I'd call displayMap from quite anywhere in the game.
Problem : mybutton should be in a python hide block... displayMap should too, then... and could still access the location list with "store.locations"... but now, I can't call displayMap since it's defined and then destroyed (at least I suppose that's the concept of python hide ?) without having been used once.
So uh... can anything declared in python hide block be called from "outside"? ô_o...
I can see a possible workaround : define a label in my game (displaymap) that would contain all this python hide block (definitions and use of functions)... then call it from anywhere in the game.
It means the whole thing will be generated on the fly, executed, and sent back to the abysses, right ?
EDIT : The workaround works but this means that I'll have to copy paste my hover functions a *lot* :/... I'm still eager for a cleaner solution ^^;
And an additional question : can imagebutton accept Displayable instead of just filenames ? *thinking of animated, hoverable imagebuttons >.>...*
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
There's no need to use python hide inside an init block. It's only during game execution (when things defined or changed will be saved) that it matters.
The answer is no on ui.imagebutton, but there's no good reason for that. It's just that it currently restricts its inputs to images. I'll fix that in 5.6.2.
In the meantime, you can fake it.
The idea is to make a generic button with two displayables as backgrounds, and then put a null inside it so it becomes the appropriate size.
The answer is no on ui.imagebutton, but there's no good reason for that. It's just that it currently restricts its inputs to images. I'll fix that in 5.6.2.
In the meantime, you can fake it.
Code: Select all
ui.button(background=anim1, hover_background=anim2, clicked=click_func)
ui.null(100, 200)
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Only at execution ? Coooool~ X3... Well all these functions will clearly be created on init... except... *thinks*... this means mybutton() doesn't need to be in a hide, but... mybutton creates functions when called... so... if mybutton is called at runtime... are the created functions added to store ? :/
I also read something about local/global variables. Putting "i=1" in a function, for example, means i becomes a new local variable, even if "i" already exists in the global scope. Can it be used in our case to select what should be local and what shouldn't ?
ui.imagebutton : Okay, good ^.^. It was strange that they were the only ones not allowing animation . And ohh, ui.null accepts size ? XD... So many hidden features ^^;. I'll really have to fill the wiki once I get the hang of all these .
Thanks again for your help. I know you didn't mean Ren'Py to be used for RPGs (that's not what I'm doing though) but there really is lots of possibilities for such things. And it's not even that hard to make it seems. There's just one thing I see as impossible : realtime action. But anything with a windowed interface seems ok.
I also read something about local/global variables. Putting "i=1" in a function, for example, means i becomes a new local variable, even if "i" already exists in the global scope. Can it be used in our case to select what should be local and what shouldn't ?
ui.imagebutton : Okay, good ^.^. It was strange that they were the only ones not allowing animation . And ohh, ui.null accepts size ? XD... So many hidden features ^^;. I'll really have to fill the wiki once I get the hang of all these .
Thanks again for your help. I know you didn't mean Ren'Py to be used for RPGs (that's not what I'm doing though) but there really is lots of possibilities for such things. And it's not even that hard to make it seems. There's just one thing I see as impossible : realtime action. But anything with a windowed interface seems ok.
Just a side note before the main dish : "ui.null(100,200)" doesn't work. ui.null doesn't accept any argument.
Now to the main problem :
See the renpy.transition ? It makes Renpy crash with this :
when I click on one of the three image buttons. Sometimes it's immediate... sometimes not... Very weird.
Now to the main problem :
Code: Select all
label mmenu:
scene mainmenu with Dissolve(0.2)
show ttMainmenu at MoveEase((0.5,0.0), (0.5,0.1), 0.5, mode="out", xanchor="center", yanchor="center")
$ renpy.transition(dissolve) # randomly crashes ren'py when clicking on either imagebutton
$ ui.hbox(spacing=20, xpos=0.5, ypos=0.5, xanchor="center", yanchor="center")
$ ui.imagebutton("bAssign.png", "bAssign_sel.png", clicked=ui.jumps("assign"))
$ ui.imagebutton("bBrew.png", "bBrew_sel.png", clicked=ui.jumps("brew"))
$ ui.imagebutton("bStatus.png", "bStatus_sel.png", clicked=ui.jumps("status"))
$ ui.close()
$ ui.frame(xpos=0.5, xanchor="center", ypos=0.75, style="banner", xmaximum=400)
$ ui.text("Please choose an activity...", style="banner")
$ ui.frame(xpos=0.7, ypos=0.90)
$ ui.textbutton("Sortir...", clicked=ui.jumps("intro"))
$ ui.interact()
#
when I click on one of the three image buttons. Sometimes it's immediate... sometimes not... Very weird.
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
Hm... does the crash happen when you get rid of the MoveEase? There's a slightly different (and slower) codepath that is used when Dissolve has to deal with a changing screen. But it shouldn't crash.
Any debugging information created would be appreciated... check the Event Log for details.
Any debugging information created would be appreciated... check the Event Log for details.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
- PyTom
- Ren'Py Creator
- Posts: 16088
- 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:
Um... the event log is a windows thing. I'm not sure where it is... could someone help out.
Also, if you could send me a test case, I could try to debug it.
Also, if you could send me a test case, I could try to debug it.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Who is online
Users browsing this forum: haitai