Ren'Py Ren'Py Scaling defined images

onionbros

Rodion Raskolnikov
Game Developer
Feb 1, 2019
64
159
Hello comrades,

I have a bit of in interesting issue here. I am trying to show characters (as imagebuttons) in different locations with adaptive scaling. Meaning that for example, if you're in a small room the character is larger (closer), while outdoors they are smaller. I am trying to write general code for this so it works for any character. This is already in a nested loop, so I'll cut that out since I don't think it is relevant to my question:

imagebutton:
yalign 1.0
idle im.Scale(z.name + "_" + y.EM_Active, SubLocations[SubLocationID].scale*default_scale_x, SubLocations[SubLocationID].scale*default_scale_y)
hover z.name + "_" + y.EM_Active
action Jump(z.name + "_Passive")

The exact positioning and scaling according to the location is defined in the SubLocations class, which is used here to calculate the width and height scaling needed in im.Scale.
The image meant to be shown is already defined as a Ren'Py image. For example: John_Wifebeater would be an image of character "John" (z.name) in his outfit "Wifebeater" (y.EM_Active), defined as image John_Wifebeater = "/path/...." in another file.

The hover option works, but obviously doesn't show the required scaling. Is it possible to use im.Scale with already defined images? Above code gives this error:

"IOError couldn't find file 'John_Wifebeater'.

So I guess it doesn't recognize that there is an image defined with this name...

Any help is appreciated :)
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
I can't speak to the scaling issues directly, but I may be able to shed some light on the "[...] couldn't find file".

RenPy has two ways (mainly) of accessing images.

Either you name the image explicitly ... hover "john_wifebeater.png"
Or you use a ... hover john_wifebeater

Displayables are usually images. Something like:

image john_wifebeater = "john_wifebeater.jpg"

Generally, people don't code all the image statements, as RenPy automatically creates a displayable for each image it find in the /game/images/ folder and subfolders during the game startup.
What usually gets people into trouble though, is that RenPy auto-creates all displayables with lowercase names; regardless of operating system. (It's following the that all variables should be lowercase). By far the easiest solution is to have all your image filenames be lowercase too, to avoid confusion. But people tend to only learn that after they get on the wrong side of RenPy's lowercase behavior.

All of which doesn't stop you manually creating your own image statement with mixed case naming.

image John_Wifebeater = "john_wifebeater.webp"

... but you're probably creating problems for yourself by doing that.

My guess is that you'd solve your problem by coding:

hover z.name + "_" + y.EM_Active + ".png" Or something similar.

I'm presuming that the concatenation of those strings results in a string, rather than a displayable. So the file extension is probably all that's required.
Although if it is using the displayable name instead, it might need a adding in there some-how instead.

I will however highlight that you can use image manipulation with hover statements.
A while ago, I coded something to allow the player to pick between languages. It included code like this:

Python:
            imagebutton:
                idle im.MatrixColor("gui/language_english.png", im.matrix.contrast(0.4))
                hover "gui/language_english.png"
                action Language(None)

I see no reason why that couldn't be modified to use something like im.Scale() instead.
 
  • Like
Reactions: onionbros

onionbros

Rodion Raskolnikov
Game Developer
Feb 1, 2019
64
159
Hello grandmaster, you've already helped me with several issues in the past via other people's questions. So let me say thanks more directly. My main issue here is using a displayable directly within an image manipulation, I don't think the uppercase is the issue . In your example, if you used a pre-defined displayable, let's say:

Python:
image language_english = "gui/language_english.png"

            imagebutton:

                idle im.MatrixColor(language_english, im.matrix.contrast(0.4))

                hover "gui/language_english.png"

                action Language(None)
You will probably get the same error as me, that you cannot find the file "language_english". Do you think there is a way around this or am I doing something wrong?

It doesn't really make sense to me how it finds the image in the hover statement below, but not in the idle statement (despite the image displayable being the same thing):

Python:
idle im.Scale(z.name.lower() + " " + y.EM_Active.lower(), SubLocations[SubLocationID].scale*default_scale_x, SubLocations[SubLocationID].scale*default_scale_y)  #uses images and scaling defined in images.rpy
hover z.name.lower() + " " + y.EM_Active.lower()
I know that im.Scale works within a hover statement, I was using it before I changed the file input to this more complicated form.

Best,
onion
 
Last edited:

dikau

Member
Dec 16, 2019
315
274
I think Image Manipulator (im.<>) only works with images (literal) and other Image Manipulator.
Use Image() it's an image manipulator...... ....I think (I might be wrong, lol), like this:
Code:
define <your_defined_image_name> = Image("images/what/ever/image.png")
and then you can use it on im.Scale(<your_defined_image_name>) (note: Again .... I might be wrong and never tested this method)


or You could use Transform() for defined images:
Code:
idle Transform( "<image or defined image>", xzoom=xx, yzoom=yy)
also you can just use zoom, instead xzoom and yzoom
 
Last edited:

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
Hello grandmaster

Oh, I'm definitely not.
I've just got time on my hands and enough of memory to remember all the stuff I failed to get working the first time around.
As will be self-evident here in a second, I can help think things through... but sometimes, I'm completely wrong.

My main issue here is using a displayable directly within an image manipulation, I don't think the uppercase is the issue . In your example, if you used a pre-defined displayable, let's say:

image language_english = "gui/language_english.png"

Yeah. I just tried the same thing... and I'm completely wrong about the whole displayable aspect. They're usually interchangeable... except... you know... here.

The says "image" and I assumed that including displayable too.
So yeah, the lowercase aspect is not an issue here either.

The documentation for the blur the lines in my head by describing them as "An image manipulator is a displayable that takes an image or image manipulator". Though that's likely a lack of imagination on my part when they use "image" and "displayable" in the same sentence.

Overall, if the image can't be a displayable... and instead a full path image name... then the "add .png" idea from my original post might be an option.

Something like:

Python:
imagebutton:
    yalign 1.0
    idle im.Scale(z.name + "_" + y.EM_Active + ".png", SubLocations[SubLocationID].scale*default_scale_x, SubLocations[SubLocationID].scale*default_scale_y)
    hover z.name + "_" + y.EM_Active + ".png"
    action Jump(z.name + "_Passive")

Where you are effectively replacing "John_Wifebeater" with "John_Wifebeater.png" in places where the documentation specifically says "image" rather than "displayable". If you have those images in a sub folder, you may need to include that too.

As with my first reply, this is me hoping I'm making the correct leap of faith. Although I did test my own code with this adaptation...

Python:
default word_lang = "gui/language"
default word_en   = "english"

# [...]

            imagebutton:
                idle im.MatrixColor(word_lang + "_" + word_en + ".png", im.matrix.contrast(0.4))
                hover word_lang + "_" + word_en + ".png"
                action Language(None)

Which I hope is similar enough to what you are doing, as to be close enough to get it to work.
 

dikau

Member
Dec 16, 2019
315
274
Looking at the documentation page, there isn't im.Scale anymore... only im.FactorScale.

and here's a snippet from the page:
With the few exceptions listed below, the use of image manipulators is historic. A number of image manipulators that had been documented in the past should no longer be used, as they suffer from inherent problems. ...
 

onionbros

Rodion Raskolnikov
Game Developer
Feb 1, 2019
64
159
Hello to both of you,

The .png solution also does not work, it just tells me that it can't find john_wifebeater.png. Besides I don't want it to look for the original file in the first place since the defined displayable already has some changes to it (character height is scaled for each character manually in the definition).

im.FactorScale also does not work, I see no difference between im.Scale and im.FactorScale for this usage...

Lastly, and this is the good news :), using zoom works perfectly. I don't need to rename or define anything else! It doesn't make sense to me, since it looks very similar to im.Scale, but I don't need to understand everything :D

Full code is:


Python:
$ default_scale = 0.8     #needed to correct from old scaling procedure

    if IsWeekend == False:
        hbox:
            xalign SubLocations[SubLocationID].x
            yalign SubLocations[SubLocationID].y
            yoffset -100
            for z in Portfolio:
                if z.IsActive:
                    for y in GirlRoutines:
                        if y.girl_id == z.number:
                            #Early Morning
                            if calendar.DayTimeValue == 0 and Location == y.loc_early_morning:
                                imagebutton:
                                    yalign 1.0
                                    idle Transform(z.name.lower() + " " + y.EM_Active.lower(), zoom=SubLocations[SubLocationID].scale*default_scale)
                                    hover Transform(z.name.lower() + " " + y.EM_Active.lower(), zoom=SubLocations[SubLocationID].scale*default_scale)
                                    action Jump(z.name + "_Passive")
Thank you both!
Best,
onion
 
Last edited:
  • Like
Reactions: 79flavors

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,285
Python:
image language_english = "gui/language_english.png"
            imagebutton:
                idle im.MatrixColor(language_english, im.matrix.contrast(0.4))
                hover "gui/language_english.png"
                action Language(None)
You will probably get the same error as me, that you cannot find the file "language_english".
You are defining a string, not a displayable. You should have used default, not image.

And it is the issue you had. Images are not stored in the default store, and therefore will always make Ren'Py complain that it don't find them when you used them where they aren't expected.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
You are defining a string, not a displayable. You should have used default, not image.

Yeah. That one is on me.

I'd originally offered a suggestion using displayables, without realizing that it wouldn't work in that circumstance.
That code snippet was just part of the fallout of my misunderstanding.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,369
15,285
Yeah. That one is on me.

I'd originally offered a suggestion using displayables, without realizing that it wouldn't work in that circumstance.
That code snippet was just part of the fallout of my misunderstanding.
It happen, don't worry.

Few times ago I wrote around 100 lines of Python before realizing that they don't need a semi-colon...