PDA

View Full Version : Renaming a label


Teriander
04-10-2008, 11:21 PM
I've been researching this, but I can't find the answer. I feel like this is crazy simple but...
How do I use a varible to rename a label? This is what I think should do it, but it doesn't.
(this code is inside a button)

rollout SetUpStatus "Setup Status"
(
label lblIRStatus align:#center
lblIRStatus.text = "test"
)
createDialog SetupStatus 200 300

I recieve the error message:
--Syntax error:at., expected name
-- In line: lblIRStatus.t

how do I dynamically add text to a label?

labbejason
04-11-2008, 12:04 AM
Hey Reggie, you can't just setup a variable like that in the rollout itself. You can however, change it in an event. In this case, when the dialog opens:

(
rollout SetUpStatus "Setup Status"
(
label lblIRStatus align:#center

on SetupStatus open do
(
lblIRStatus.text = "test"
)
)
createDialog SetupStatus 200 300
)

Teriander
04-11-2008, 12:09 AM
Labbejason,

Thanks again for your help. I had learned this was going to be difficult for what Im trying to achieve, so I've switched to using a "edittext" box instead. What Im trying to create is a Status box that will popup when a button is pressed, this box will list the name of cameras that have been sent for rendering. Right now everything works except getting variables to read in the textbox... After making changes this is what I have so for:

rollout SetUpStatus "Setup Status"
(
edittext txtIRStatus align:#center fieldwidth:190 height:350 readonly:true align:#center
on txtIRStatus changed do
(
txtIRStatus.text = "Test"
)
)
createDialog SetupStatus 200 360

"Test" will be replaced with a variable CameraName that calls the name of cameras elsewhere in the code. But first I want to get "Test" to display correctly in the rollout :(

labbejason
04-11-2008, 12:57 AM
So if you want to display the cameras you are going to send to rendering, may I suggest using a listBox instead? Unlike editText, you'll be able to display multiple cameras very neatly and easily. Here's an example:

(
rollout getCamDialog "Get Cameras"
(
group "Camera List"
(
listBox camList "" items:#() readOnly:true
)
button getCam "Get Cameras from Scene" width:190 height:15

on getCam pressed do
(
myCams = for o in cameras where (superClassOf o) == camera collect o.name
camList.items = myCams
)
)
createDialog getCamDialog 200 195
)

Teriander
04-11-2008, 01:08 AM
Jason,

Thanks for posting! I sent you a private message. Let me know if you have any suggtions based off what Im trying to achieve. I will work with the listbox and see what I can achieve!

labbejason
04-11-2008, 01:14 AM
LOL I sent you another private message as you wrote this :P. Let's keep it on here so everybody else can pitch in their 2 cents.

I just recommended that since it was only one camera being done at a time, to just stick with something simple like messageBox.

Teriander
04-11-2008, 01:35 AM
Is it possible to update a messagebox that is has already been created? If the scene has 20 cameras to render, I wouldn't want 20 popup boxes filling the user's screen :(

It looks like the messageBox can't be updated :( and the user has to click "OK" to start the next camera. The reminder will go away :(

labbejason
04-11-2008, 01:49 AM
So does your tool do a batch render where it does multiple cameras all at once? Or does the user render a from a camera one at a time? If it's one at a time, I don't see what's the problem with a messageBox.
You already got a couple of options thrown at you, maybe you should give a step by step walkthrough of how you want it to work.

Teriander
04-11-2008, 02:04 AM
Sure, I'll explain in better detail :)

Right now my main rollout has 2 buttons and a dropdown list of all the cameras.
Button 1. Is for setting up Irradience Map automatically.
Button 2. Is for setting up File Save Output location automatically.
Both Buttons create the path name based on the camera's name that is already selected.

Now, all of this is working great, but Im trying to add a second Rollout that popups when either Button 1 or 2 is pressed. The second rollout will only have text information that says what camera has been sent (saved output or irradience map). This will help prevent the mistake of sending the same camera twice. With a scene of 20 cameras, you may forget if you sent "EntranceCam02" Irradience Map or not.

With a messageBox that requires you to close the box to continue using max, closing the box defeats the purpose of having a reminder on your scene :) Im thinking a listbox or edittext box like you suggested at first may be the best solution.

I hope this is easier to understand. let me know if you have any questions, thanks!!

(to answer your question, its not a batch, its one at a time)

labbejason
04-11-2008, 02:13 AM
Ah gotcha, thanks for the explanation. An editText would work fine. It should be the exact same concept as my first example with the label. You could use a listBox too, but that's something you would use for multiple objects. It really doesn't matter though, as either one will do exactly what you need it to do.

And just for fun, if they accidently do send a camera twice, make 100 messageBox come up to say 'Camera already sent!' That'll teach them to mess with you! :)

Teriander
04-11-2008, 02:25 AM
I like your 100 Messages idea :) Only problem is they will hate me if it crashes their scene :)

Question, Im going the edittext route, what is the best "on" command to use so my textbox updates? The script I have is working with no errors, but it doesn't update the change I make to the .text variable... Here is what I have in my button:

rollout SetUpStatus "Setup Status"
(
edittext txtIRStatus text:"Setup Status:" align:#center fieldwidth:190 height:350 readonly:true align:#center

on txtIRStatus changed do
(
txtIRStatus.text = "Test"
)
)
createDialog SetupStatus 200 360

Shouldn't "Setup Status:" get replaced with "Test" ??

Bobo
04-11-2008, 02:56 AM
I like your 100 Messages idea :) Only problem is they will hate me if it crashes their scene :)

Question, Im going the edittext route, what is the best "on" command to use so my textbox updates? The script I have is working with no errors, but it doesn't update the change I make to the .text variable... Here is what I have in my button:

rollout SetUpStatus "Setup Status"
(
edittext txtIRStatus text:"Setup Status:" align:#center fieldwidth:190 height:350 readonly:true align:#center

on txtIRStatus changed do
(
txtIRStatus.text = "Test"
)
)
createDialog SetupStatus 200 360

Shouldn't "Setup Status:" get replaced with "Test" ??

First of all, the handler is never called because you set the field as "readOnly" (thus, it cannot be typed in). If you set the readOnly:false, you will get an error message that the argument count is wrong.

The handler of an edittext control requires one argument after the "changed" and before the "do" which will contain the new text. MAXScript will send the one argument to the function defined by the handler, but since you defined the handler without any arguments, you will get the "expected 0, got 1" error.

This handler is called once per keystroke, while on yourTextControl Entered txt do() will be called when the text field loses focus (on Enter, Tab or mouse click outside of it).

rollout SetUpStatus "Setup Status"
(
edittext txtIRStatus text:"Setup Status:" align:#center fieldwidth:190 height:350 readonly:false align:#center
on txtIRStatus changed txt do
(
txtIRStatus.text = "Test"
)
)
createDialog SetupStatus 200 360
If you type in the field, the word Test will appear instead.


If you want to display text in the field that comes from another source and avoid typing in from the user, you have two choices:

1. Keep the readOnly:true and remove the event handler (as it does not work). Instead, write a user function you can call with a string that will append to the text in the field and display the result.

rollout SetUpStatus "Setup Status"
(
local infoString = "Setup Status:"
local theCounter = 0
button btn_pressMe "Press Me!"
edittext txtIRStatus text:infoString align:#center fieldwidth:190 height:350 readonly:true align:#center
fn updateInfo txt =
(
infoString += "\r\n" + txt
txtIRStatus.text = InfoString
)
on btn_pressMe pressed do
(
theCounter += 1
updateInfo ("The button was pressed " + theCounter as string + (if theCounter == 1 then " time" else " times"))
)
)
createDialog SetupStatus 200 360

2. Remove the readOnly or set it to false and use the event handler to override the entered text with the actual info text you want on each keypress. THis way, the user will TRY but never succeed to enter anything. See 1. for the way to display data.

rollout SetUpStatus "Setup Status"
(
local infoString = "Setup Status:"
local theCounter = 0
button btn_pressMe "Press Me!"
edittext txtIRStatus text:infoString align:#center fieldwidth:190 height:350 readonly:false align:#center
fn updateInfo txt =
(
infoString += "\r\n" + txt
txtIRStatus.text = InfoString
)
on txtIRStatus changed txt do txtIRStatus.text = InfoString
on btn_pressMe pressed do
(
theCounter += 1
updateInfo ("The button was pressed " + theCounter as string + (if theCounter == 1 then " time" else " times"))
)
)
createDialog SetupStatus 200 360

The cool thing about this approach is that the user can still select text from the box and COPY it from there to paste into some text file or whatever...


I personally prefer using a ListBox for this kind of info because it can scroll down automatically. Obviously, you could do the same with the edittext above by prepending instead of appending the string:

fn updateInfo txt =
(
infoString = txt + "\r\n" + infoString
txtIRStatus.text = InfoString
)

This will cause the latest line to be on top of the list and the old stuff will scroll off.

Here is how I would have done it:

rollout SetUpStatus "Setup Status"
(
local theCounter = 0
button btn_pressMe "Press Me!"
listbox lbx_Info items:#("Setup Status:") width:195 align:#center height:24
fn updateInfo txt =
(
lbx_Info.items = append lbx_Info.items txt
lbx_Info.selection = lbx_Info.items.count
)
on btn_pressMe pressed do
(
theCounter += 1
updateInfo ("The button was pressed " + theCounter as string + (if theCounter == 1 then " time" else " times"))
)
)
createDialog SetupStatus 200 360

Teriander
04-11-2008, 03:36 AM
Bobo, it's working great with your code. I copied the code from the last example you provided and it runs with no problem... You are truely amazing! I will try to modify this code to work with reading from my main rollout and list the camera's name when a button on my main rollout is pressed...

Thanks again!! :thumbsup:

Teriander
04-11-2008, 04:48 AM
Im getting closer to getting it working correctly, Everything is working except for one minor problem now...

When the user presses the button on the Main Rollout a SECOND time, it does not update the popup rollout with text. It does work when the popup rollout is opened for the first time, but clicking the button again on the Main Rollout will not update my popup rollout, what is wrong with my code?

rollout SetUpStatus "Setup Status"
(
local theCounter = 0
listbox lbx_Info items:#("Setup Status:") width:295 align:#center height:24
fn updateInfo txt =
(
lbx_Info.items = append lbx_Info.items txt
lbx_Info.selection = lbx_Info.items.count
)
on SetUpStatus open do
(
theCounter += 1
selectedCam = viewport.getCamera()
cameraN = selectedCam.name
updateInfo ("'" + cameraN + "'" + " was setup for Irradience Map.")
)
on MainRollout.butStart pressed do
(
updateInfo ("'" + cameraN + "'" + " was setup for Irradience Map.")
)
)
createDialog SetupStatus 300 360

Bobo
04-11-2008, 05:53 AM
You cannot have a handler from the Main rollout placed in the second rollout.
All event handling is performed in the rollout where the handled controls are defined.
So if the butStart button is in the Main rollout, that's where the handler should be.

Let's start from the beginning.

Always put ALL your code in a local scope defined by outer brackets.
Then you can pre-declare the variable SetUpStatus that will be used later for the second rollout, which will make it visible to the first rollout EVEN BEFORE the second rollout has been defined.

Thus, when the handler is executed in the Main rollout, it will be able to call functions in the second rollout.

Here is an example where both rollouts are defined as local in the scope of the script and displayed in a single rollout floater which is global in order to be able to be closed when the script is being run again.

(--start local scope
global theCamScriptFloater --this will be the floater containing the two rollouts
local SetUpStatus --pre-declare the second rollout so the first one can "see" it
rollout MainRollout "Main Rollout"
(
button butStart "START!"
on butStart pressed do
(
selectedCam = viewport.getCamera()
if isValidNode selectedCam then
SetUpStatus.updateInfo ("'" + selectedCam.name + "'" + " was setup for Irradience Map.")
else
SetUpStatus.updateInfo ("Viewport is NOT a Camera!")
)
)

rollout SetUpStatus "Setup Status"
(
listbox lbx_Info items:#("Setup Status:") width:295 align:#center height:24
fn updateInfo txt =
(
lbx_Info.items = append lbx_Info.items txt
lbx_Info.selection = lbx_Info.items.count
)
)
try(closeRolloutFloater theCamScriptFloater)catch() --try to close the floater if already open
theCamScriptFloater = newRolloutFloater "Camera Demo" 320 600 --create a new floater
addRollout mainRollout theCamScriptFloater --add the main rollout to the floater
addRollout SetUpStatus theCamScriptFloater --add the second rollout to the floater
)--end script


And here is the same with two "independent" dialogs:

(--start local scope
global CameraUtility_MainRollout
global CameraUtility_SetUpStatus
try(destroyDialog CameraUtility_MainRollout)catch()
try(destroyDialog CameraUtility_SetUpStatus)catch()

rollout CameraUtility_MainRollout "Main Rollout"
(
button butStart "START!"
on butStart pressed do
(
selectedCam = viewport.getCamera()
if isValidNode selectedCam then
CameraUtility_SetUpStatus.updateInfo ("'" + selectedCam.name + "'" + " was setup for Irradience Map.")
else
CameraUtility_SetUpStatus.updateInfo ("Viewport is NOT a Camera!")
)
on CameraUtility_MainRollout moved pos do
SetDialogPos CameraUtility_SetUpStatus (pos+[0,225])
)
rollout CameraUtility_SetUpStatus "Setup Status"
(
listbox lbx_Info items:#("Setup Status:") width:295 align:#center height:24
fn updateInfo txt =
(
lbx_Info.items = append lbx_Info.items txt
lbx_Info.selection = lbx_Info.items.count
)
)

createDialog CameraUtility_MainRollout 200 200 100 100
createDialog CameraUtility_SetUpStatus 300 340 100 325
)--end script

As you will notice, thanks to the ON MOVED handler in the main dialog, the second dialog "sticks" to the first one when you move it, but you can move the second one independently.

These are, of course, just simple examples that do nothing but create dummy UIs.
You can turn either of them into a button on a toolbar by adding a MacroScript definition outside of the outside ( ) brackets, like

MacroScript CameraTool category:"Teriander Tools"
(
... --your code here
)

Teriander
04-11-2008, 06:04 AM
Bobo, Thanks for the reply on this! Im anxious to test this tomorrow morning! It looks like it should work well. Both methods.. Evertime I read your script I learn a new method, or property that I never knew existed. Thanks for your support :)

Teriander
04-11-2008, 07:14 PM
Bobo,

I've tried both of your scripts, and they both work VERY well. You structured the examples so they are easily able to be modified. Thank you very much!!

Teriander

CGTalk Moderation
04-11-2008, 07:14 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.