Ren'Py Changing the style of an element when a textbutton is hovered

Saint_RNG

Member
Game Developer
Apr 2, 2018
258
492
Hi guys,

I've come across a minor problem (non-blocking), I could very well continue with the current code but it's triggering me a bit. So after a few hours searching various forums, I haven't really managed to find a fully functional solution.



1. What do I want to achieve?

I want a button with text that, when clicked, displays a vbox with its content.
The button is accompanied by a small arrow to its right, which points to the right when the vbox is hidden and is also clickable (performs the same action as clicking on the text) . When the text OR the arrow get a click, it rotates the arrow 90° downwards (or reset to 0° if this is the 2nd click, to make the vbox and its contents disappear) .


You don't have permission to view the spoiler content. Log in or register now.

As you can see in the example, there are several buttons, each with its own child vbox and each independent of the other (when I click on one, only the child vbox of the clicked button is displayed).


2. What way did I choose to achieve this?

You don't have permission to view the spoiler content. Log in or register now.

So, as you can see, I opted for the solution with my text in the form of a textbutton and the arrow in the form of an imagebutton. The 2 do the same actions and..., well, it works perfectly.

So you're going to say, what's the problem then? :WaitWhat::WaitWhat::WaitWhat:

Well, the problem with this choice is that when my mouse cursor is over the textbutton, it triggers the hover style for the text, but not the hover style for the imagebutton... (and vice versa).


You don't have permission to view the spoiler content. Log in or register now.

So far there's nothing abnormal about it, it's normal behaviour given that it's two separate elements.

But unfortunately, that's not what I'm looking for - > when I move my mouse over one or the other, they should both have the same style.
That's where I'm struggling to find a solution.

Is there a way of triggering the other's hover style at the same time? Or change the idle style of the other element only when the first one is hovered?

You don't have permission to view the spoiler content. Log in or register now.

I don't think I've seen anything in the documentation ( ) that meets my needs.
Maybe the Function() one ? Like if hovered, "found the element with the id passed in parameter and apply the style passed in parameter"

I've also tried another way with a simple button containing a text element. And in a custom style, add the image in the form of a background.


You don't have permission to view the spoiler content. Log in or register now.

This solution solved the issue (the text and the arrow both reacted to the hover at the same time) but now it's impossible to move the arrow (stuck on the left of the text), I tried adding some left_padding or right_padding but without success. And then there's the problem of the transform to rotate the image, how do you just apply it to the background image?

I also thought of creating an imagebutton with the text directly integrated into the png, but the problems are :

  1. (Minor but a pain in the arse) Duplicate the image for each different text.
  2. How to manage just the rotation (with animation) of the arrow without affecting the text?

Am I looking too far when the solution is perhaps very simple? Am I approaching the solution in the wrong way?

Thanks in advance to those who will look into this little problem of mine. :geek:
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
The button is accompanied by a small arrow to its right, which points to the right when the vbox is hidden and is also clickable (performs the same action as clicking on the text) . When the text OR the arrow get a click, it rotates the arrow 90° downwards (or reset to 0° if this is the 2nd click, to make the vbox and its contents disappear) .
All you need is to tell Ren'Py what condition make the button be selected:

Python:
[...]
            imagebutton:
                yalign .6
                idle "codex/selector_idle.png"
                hover "codex/selector_hover.png"
                # <<<<
                # The images
                selected_idle "codex/selector_selected.png"
                selected_hover "codex/selector_selected_hover.png"
                # The condition
                selected "General" in codex_entry_p
                # >>>>
                # same action as the textbutton
                action [...]
side note: auto "codex/selector_%s.png" would have been better here.


All this being said, you absolutely don't need to rely on a textbutton/imagebutton couple for what you want to do. textbutton accept the style property, that is perfect for this ; it's how Ren'Py do the radio buttons in the default preference screen.
All it need it to define the style accordingly, relying on the to know what image to use for the background. You also need to use the style property for the text to not be put over the arrow, but that's all.

Python:
style arrowedButton is button:
    background "codex/selector_idle.png"
    hover_background "codex/selector_hover.png"
    selected_background "codex/selector_selected.png"
    selected_hover_background "codex/selector_selectedHover.png"
    right_padding 30   # Used an arbitrary value here, adjust accordingly to your arrow size.

style arrowedButton_text is button_text
Then all you need is a style "arrowedButton" to tell Ren'Py that your textbutton should follow that particular style.
 

Saint_RNG

Member
Game Developer
Apr 2, 2018
258
492
Thanks for the reply, perhaps the first part of my message was misleading (or I am confused ?). I don't have a problem with the selected state (by default selected_idle = idle and same for selected_hover with hover).
It's only for the hovered state (That's why I said it was a minor issue, because everything else works fine).

So in your first example, I'd have to use hovered instead of selected ? The few examples I've seen on other forums show that you can call actions using this, but what actions would it be in this case?


For the second part, like I said here:
I've also tried another way with a simple button containing a text element. And in a custom style, add the image in the form of a background.

Python:
style mycustomstyle is gui_button:
background "codex/selector_idle.png"
hover_background "codex/selector_hover.png"

# with the image manually rotated in photoshop (I didn't go this far because that wasn't the purpose of the test.).
selected_idle_background "codex/selector_selected_idle.png"
selected_hover_background "codex/selector_selected_hover.png"
This solution solved the issue (the text and the arrow both reacted to the hover at the same time) but now it's impossible to move the arrow (stuck on the left of the text), I tried adding some left_padding or right_padding but without success. And then there's the problem of the transform to rotate the image, how do you just apply it to the background image?
left_padding or right_padding don't seem to be working properly in my case.

Without padding and same with right_padding 30 or 50 or 250:
Capture5.PNG

With left_padding 50:
Capture6.PNG

I suppose it could be the size of my image (15px x 15px) that poses a problem?

And then there's also the problem of the transform. Now it also applies to the text:
Capture7.PNG

I don't yet have enough experience when it come to style (moving the arrow to the right of the text) and transform (apply the linear animation to the background only) unfortunately. :cry:
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
So in your first example, I'd have to use hovered instead of selected ?
In my first example, there's two lines for the selected image:
Python:
                selected_idle "codex/selector_selected.png"
                selected_hover "codex/selector_selected_hover.png"
and their names are relatively explicit. As explicit that is the list of style prefix I linked and shown in my second example:
Python:
    selected_background "codex/selector_selected.png"
    selected_hover_background "codex/selector_selectedHover.png"

The few examples I've seen on other forums show that you can call actions using this, but what actions would it be in this case?
None, because, as I implied, there's no need for a screen action... All what is needed to do what you want to achieve is the 5 lines style I gave.
Possibly with the addition of a sixth line, or with a variable for the image declaration, depending on the size of the background image and the position of the arrow.


left_padding or right_padding don't seem to be working properly in my case.
It's not a question of padding, it's a question of image size.
The solution being either to put the image in a displayable, or to use the style property. The first one also permit to have the arrow at the right of the text, what isn't possible with the second one.


And then there's also the problem of the transform. Now it also applies to the text:
Have you even read what I wrote ?

There's absolutely no need for a transform ! You just have an image with the arrow pointing to the right, and one with the arrow pointing to the bottom, using one or the other depending on the button state.

Why the hell people insist so often to complicate their life when they are using Ren'Py ?



I don't yet have enough experience when it come to [...]
It's absolutely not a question of experience, it's a question of logic.
I explicitly used different names for the files used as background, therefore it's obvious that their content is also different. Would you had accepted what I wrote, instead of being convinced that you need to use a transform and wonder how you can apply it when a button is hovered, it would have been even more obvious.
 

Saint_RNG

Member
Game Developer
Apr 2, 2018
258
492
Sorry for my confusion, in fact I had tested your second solution, but without applying the

Python:
selected "General" in codex_entry_p
you showed in your first example below the imagebutton, that's why it didn't work :whistle:

So yeah, now it shows the down arrow when the button is selected (and selected + hovered over), BUT it just makes the background image disappear and replaces it with the selected_background image, without that .1 second smooth 90° rotation effect I had with the transform. Is there another way of reproducing this effect?

Tested the Frame() displayable and Jesus that's a weird one for a first try...
So after playing a lot with the top, right, left and bottom values and added top and right padding, I finally got:
Capture8.PNG
That's almost it... the text has just been given a little trim. :LOL:
My first guess is that the text is "getting out" of the hbox ?

You don't have permission to view the spoiler content. Log in or register now.
 

Saint_RNG

Member
Game Developer
Apr 2, 2018
258
492
Tested the Frame() displayable and Jesus that's a weird one for a first try...
So after playing a lot with the top, right, left and bottom values and added top and right padding, I finally got:
Capture8.PNG
Capture8.PNG

That's almost it... the text has just been given a little trim. :LOL:
My first guess is that the text is "getting out" of the hbox ?
For this one, I managed to find a solution by changing the maximum size of my image:
From 15 x 15 to 50 x 50 (with the triangle still at 12 x 12).
By changing the padding a little, it works perfectly.
 
Last edited:
  • Like
Reactions: osanaiko