[Solved] How to use ScreenVariableValue to pass a value back?

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
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

[Solved] How to use ScreenVariableValue to pass a value back?

#1 Post by Chekhov »

Perhaps I'm trying to do this in a way I shouldn't.

The core functionality of what I'm trying to build is the following:

1. You have a population of people
2. You can allocate that population to different jobs

I've decided to do this with bars that you can drag, while showing the number above it, as shown in the code below.

Code: Select all

allocation = Storage()
allocation.sawyer = 0
allocation.unassigned = 70

screen allocation():
    default temp_sawyer = allocation.sawyer
    frame:
        xpos 10 ypos 10
        xsize 200
        vbox:
            text "Unassigned: " + str(allocation.unassigned)
            bar value AnimatedValue(allocation.unassigned, colony.population) style "bar"
            text "Sawyer: " + str(temp_sawyer)
            bar value ScreenVariableValue("temp_sawyer", colony.population) style "bar"


A. How do I pass the value set back to allocation.sawyer?
B. Since the goal is to have multiple places to allocate people; how do I cause one to detract from another?

I suppose B might be a moderately difficult problem to solve, but perhaps it's been done before?
Last edited by Chekhov on Mon Apr 08, 2019 6:15 pm, edited 3 times in total.

User avatar
Matalla
Veteran
Posts: 202
Joined: Wed Mar 06, 2019 6:22 pm
Completed: Max Power and the Egyptian Beetle Case, The Candidate, The Last Hope, El cajón del viejo escritorio, Clementina y la luna roja, Caught in Orbit, Dirty Business Ep 0, Medianoche de nuevo, The Lost Smile
itch: matalla-interactive
Location: Spain
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#2 Post by Matalla »

I am no expert, so perhaps what I say have no much sense, but...

- Why do you use a default inside a screen? Shouldn't it be just a regular assignment ($ temp_sawyer = allocation.sawyer)

- Besides, if these 2 variables are indeed the same, why not use allocation.sawyer directly in the bar and get rid of the temp_sawyer? That way, the value should be updated automatically. Maybe using FieldValue instead of ScreenVariableValue? I'm not very sure about that, but there should be a type of bar value suited to that.
https://www.renpy.org/doc/html/screen_a ... bar-values
Comunidad Ren'Py en español (Discord)
Honest Critique

User avatar
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#3 Post by Chekhov »

Matalla wrote: Mon Apr 01, 2019 10:03 am - Besides, if these 2 variables are indeed the same, why not use allocation.sawyer directly in the bar and get rid of the temp_sawyer?
Because it throws an error saying that allocation.sawyer is not declared inside the screen.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#4 Post by trooper6 »

You have two different things with the same name. A storage object "allocation" and a screen "allocation"--don't have two different things with the same name.
You should be declaring your variables with default or define outside of blocks, so:

Code: Select all

default allocation = Storage()
You also shouldn't need those other two declarations if you pass those values in when you declare it. I can't give you an example because you didn't provide your Storage code.

You shouldn't need a Screen Variable...and it won't do what you want anyway. You should be able to use SetField on the storage object directly.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Matalla
Veteran
Posts: 202
Joined: Wed Mar 06, 2019 6:22 pm
Completed: Max Power and the Egyptian Beetle Case, The Candidate, The Last Hope, El cajón del viejo escritorio, Clementina y la luna roja, Caught in Orbit, Dirty Business Ep 0, Medianoche de nuevo, The Lost Smile
itch: matalla-interactive
Location: Spain
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#5 Post by Matalla »

Chekhov wrote: Mon Apr 01, 2019 10:37 am
Matalla wrote: Mon Apr 01, 2019 10:03 am - Besides, if these 2 variables are indeed the same, why not use allocation.sawyer directly in the bar and get rid of the temp_sawyer?
Because it throws an error saying that allocation.sawyer is not declared inside the screen.
I can understand that it'll do with a screen variable, have you tried with another type of bar value?
Comunidad Ren'Py en español (Discord)
Honest Critique

User avatar
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#6 Post by Chekhov »

Matalla wrote: Mon Apr 01, 2019 10:03 am Maybe using FieldValue instead of ScreenVariableValue?
Yes, this works perfectly, thank you.

Working results below for anyone who hits on this from a search:

Code: Select all

            text "Sawyer: " + str(allocation.sawyer)
            bar value FieldValue(allocation, "sawyer", colony.population, False, style = "bar")

User avatar
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#7 Post by Chekhov »

trooper6 wrote: Mon Apr 01, 2019 10:44 am You have two different things with the same name. A storage object "allocation" and a screen "allocation"--don't have two different things with the same name.
You should be declaring your variables with default or define outside of blocks, so:

Code: Select all

default allocation = Storage()
You also shouldn't need those other two declarations if you pass those values in when you declare it. I can't give you an example because you didn't provide your Storage code.

You shouldn't need a Screen Variable...and it won't do what you want anyway. You should be able to use SetField on the storage object directly.
Thanks, I hadn't noticed that I used the same name, as well as the other tips.

User avatar
Matalla
Veteran
Posts: 202
Joined: Wed Mar 06, 2019 6:22 pm
Completed: Max Power and the Egyptian Beetle Case, The Candidate, The Last Hope, El cajón del viejo escritorio, Clementina y la luna roja, Caught in Orbit, Dirty Business Ep 0, Medianoche de nuevo, The Lost Smile
itch: matalla-interactive
Location: Spain
Contact:

Re: [Solved] How to use ScreenVariableValue to pass a value back?

#8 Post by Matalla »

Well, if that works, adjusting the other bars and values shouldn't be too complicated with a conditional. Again, I'm no expert and will leave the code in more capable hands, but something with this kind of logic...

Code: Select all

if allocation.sawyer + allocation.whatever > colony.population:
	$ allocation.whatever = allocation.whatever - excess_population # where excess_population is the difference between population and jobs assigned
else:
	pass
Comunidad Ren'Py en español (Discord)
Honest Critique

User avatar
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#9 Post by Chekhov »

Right, I almost forgot about my second question.

Your solution would work, but I don't know how I can trigger it in real time, rather than once you click a button.

User avatar
Matalla
Veteran
Posts: 202
Joined: Wed Mar 06, 2019 6:22 pm
Completed: Max Power and the Egyptian Beetle Case, The Candidate, The Last Hope, El cajón del viejo escritorio, Clementina y la luna roja, Caught in Orbit, Dirty Business Ep 0, Medianoche de nuevo, The Lost Smile
itch: matalla-interactive
Location: Spain
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#10 Post by Matalla »

Chekhov wrote: Mon Apr 01, 2019 2:03 pm Right, I almost forgot about my second question.

Your solution would work, but I don't know how I can trigger it in real time, rather than once you click a button.
It will update in real time if you put the condition in the screen.

Again, this is clumsy, but it (mostly) works. Perhaps someone could give you a more elegant solution.

First add a hovered action to each bar to know what bar/value is being modified.

Code: Select all

bar value FieldValue(allocation, "sawyer", colony.population, False, style = "bar") hovered SetVariable("barchanged", "sawyer")
Then, add the condition (I guess it would work anywhere on the screen, but I checked it with this code at the end of the screen code)

Code: Select all

        if allocation.sawyer + allocation.whatever > colony.population:
            $ excess_population = allocation.sawyer + allocation.whatever - colony.population
            if barchanged == "sawyer":
                $ allocation.whatever = allocation.whatever - excess_population
            elif barchanged == "whatever":
                $ allocation.sawyer = allocation.sawyer - excess_population
        else:
            pass
Comunidad Ren'Py en español (Discord)
Honest Critique

User avatar
Chekhov
Regular
Posts: 113
Joined: Tue Jun 26, 2018 9:19 am
Projects: Pluton
Contact:

Re: How to use ScreenVariableValue to pass a value back?

#11 Post by Chekhov »

Matalla wrote: Mon Apr 01, 2019 3:32 pm
Chekhov wrote: Mon Apr 01, 2019 2:03 pm Right, I almost forgot about my second question.

Your solution would work, but I don't know how I can trigger it in real time, rather than once you click a button.
It will update in real time if you put the condition in the screen.

Again, this is clumsy, but it (mostly) works. Perhaps someone could give you a more elegant solution.

First add a hovered action to each bar to know what bar/value is being modified.

Code: Select all

bar value FieldValue(allocation, "sawyer", colony.population, False, style = "bar") hovered SetVariable("barchanged", "sawyer")
Then, add the condition (I guess it would work anywhere on the screen, but I checked it with this code at the end of the screen code)

Code: Select all

        if allocation.sawyer + allocation.whatever > colony.population:
            $ excess_population = allocation.sawyer + allocation.whatever - colony.population
            if barchanged == "sawyer":
                $ allocation.whatever = allocation.whatever - excess_population
            elif barchanged == "whatever":
                $ allocation.sawyer = allocation.sawyer - excess_population
        else:
            pass
I tried out the solution, but it was rather buggy; the bars updated somewhat unreliably.

On top of that, due to the high number of possible places of allocation locations, I ended up simplifying the code to prevent it from becoming a mess.

If anyone has use of this, quote this post and I'll copy & paste it.

Thanks for all the help!

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot]