[Closed] floater vs dialog confusion
Hi,
recently i have started to make simple ui’s for my simple scripts. I was satisfied with rollout/createDialog. Until i have discovered floaters
What I like about floaters is that i can have more rollouts where each can be rolled up, you can scroll easily in the floater window and stuff like that.
Now I can’t figure out how to use floaters the similar way as i was using dialogs.
For example, this is from the script i’m working on:
try(destroyDialog TestScript)catch()
rollout TestScript "TestScript" width:300 height:587
(
-- UI definition
group "Bitmap:"
(
.
.
)
group "Global:"
(
.
.
)
on TestScript open do
(
--load settings from ini file
)
on TestScript close do
(
-- save settings on exit
)
-- functions, on button click handlers...
)
createDialog TestScript
I tried something like this with floater:
try(closeRolloutFloater TestScript)catch()
rollout MainSettings "Main settings"
(
-- UI definition
group "Bitmap:"
(
.
.
)
group "Global:"
(
.
.
)
on TestScript open do
(
--load settings from ini file
)
on TestScript close do
(
-- save settings on exit
)
-- functions, on button clicked handlers...
)
rollout ControlCurves "Control curves"
(
)
TestScript = newRolloutFloater "TestScript" 350 640
addRollout MainSettings TestScript
addRollout ControlCurves TestScript
This doesn’t seem to work. Obviously problem is in the “on TestScript open” handlers… how do I use on-open with floaters?
Thanks.
The handlers inside the first rollout should use the name of the rollout, not of the floater. A floater does not have event handlers. The first rollout of the floater can be used to store position data, and each rollout can have its own on open() and on close() event handlers to update settings and store the open state of the rollout.
Here is an example to play with.
You can also add an ON CLOSE() handler to store data when the floater is destroyed and its rollouts are being closed. But I prefer to store the data instantly, for example when a spinner is changed or the floater is moved.
(
global testRolloutFloater
local theIniFile = GetDir #plugcfg + "\ estRolloutFloater.ini"
rollout firstRollout "First Rollout"
(
spinner spn_someValue "Spinner"
on spn_someValue changed val do
(
--store the spinner's value
setIniSetting theIniFile "SomeValue" "Value" (val as string)
)
on firstRollout moved pos do
(
--only the first rollout in a floater will get this handler called
--when the floater is moved. Use to restore the floater's position.
setIniSetting theIniFile "Floater" "Position" (pos as string)
)
on firstRollout rolledUp val do
(
--val is true when open, but is used in rolledup: to close, thus invert!
setIniSetting theIniFile "FirstRollout" "Open" ((not val) as string)
)
on firstRollout open do
(
--update any UI controls based on the settings in the INI file.
--if nothing is saved, the result of getINIsetting is "" and (execute "") gives OK.
--Thus, if the result is OK, there was no value in the INI.
local theVal = execute (getIniSetting theIniFile "SomeValue" "Value")
if theVal != OK do spn_someValue.value = theVal
)
)
rollout secondRollout "Second Rollout"
(
checkbutton chk_someOption "Check Me!"
on chk_someOption changed val do
(
setIniSetting theIniFile "SomeOption" "Value" (val as string)
)
on secondRollout rolledUp val do
(
setIniSetting theIniFile "SecondRollout" "Open" ((not val) as string)
)
on secondRollout open do
(
local theVal = execute (getIniSetting theIniFile "SomeOption" "Value")
if theVal != OK do chk_someOption.state = theVal
)
)
try(closeRolloutFloater testRolloutFloater)catch()
local thePos = execute (getIniSetting theIniFile "Floater" "Position")
if thePos == OK do thePos = [100,100] --if no previous position found, use a default
testRolloutFloater = NewRolloutFloater "Test Floater" 200 120 thePos.x thePos.y
local theVal = execute (getIniSetting theIniFile "FirstRollout" "Open")
if theVal == OK do theVal = true --if no state found, roll it up!
addRollout firstRollout testRolloutFloater rolledup:theVal
local theVal = execute (getIniSetting theIniFile "SecondRollout" "Open")
if theVal == OK do theVal = true
addRollout secondRollout testRolloutFloater rolledup:theVal
)
That works, thanks Bobo!
Isn’t saving/loading settings on every ui interaction bad for hdd or something else? First I was doing it like that and than I thought it will be better to save it only once when the script is closed.
Also is there a better way how to handle ini loading like this:
CheckIfSettingExisted = (getINISetting testINI "Settings" "MinSize")
if CheckIfSettingExisted.count > 0 do SpinnMinSize.value = CheckIfSettingExisted as float
I was doing this because when the script is run the first time, or even multiple times and setting was not saved in the ini file, then getINIsetting returns “” and when i read it as float or integer i get 0/0.0 and that would load incorrect setting.
Edit:
I just noticed that in your sample script
if thePos == OK do thePos = [100,100]
does the trick.
Edit2: Hmm, seems like that’s not what i thought it is, or i don’t know how to use it correctly, will have to try again later.
The INI file handling is really fast and robust, so I haven’t seen any problems with updating values on the fly. Also, if the script or Max would crash, the last values will be safely stored…
The test for OK is, as I noted in the remarks inside the script, meant to catch non-existent values that have never been initialized in the INI file. Since getIniSetting() from a non-existing key always returns “” and (execute “”) always returns OK, I am checking to see if I have a valid value stored. If you know the class of the value you are expecting, you can check against that (if class theVal == Integer do… )
As usual, there are many ways to skin a cat, I am just showing what I have been using successfully for 10+ years…
heyho, i’m slightly running out of space in my UI so i thought why not scroll around a little bit
ok first i took an activeX tabControll and didn’t need to scroll but now i’m on my 64bit system and activeX doesn’t like me anymore.
well my problem is i only need to scroll a scecific area in the >dialog<.
much like the Material Editor with the possibility to Attach some controlls to the top and a floater below that or something like that. i allready tried some weird things but nothing really worked
You can either replace your ActiveX TabControl with the DotNet counterpart, or take a look at SubRollouts – a sub-rollout allows you to define an area inside the dialog or another rollout and populate with as many rollouts as you want, while leaving the rest of the UI non-scrolling.
oh didn’t know about them, thx
in the meantime i grown towards .net and it’s tabControl, but there comes another small prob for me.
i want to stay compatible to older and newer as well as 32 as 64bit versions, therefore i neet to implement the .net in ones later than 9SP1 and AX in older ones.
the selection is no problem, well basically it is because i want to do it in a rollout and not in an event handler.
either with an if statement or with a try i allways get the “– Syntax error: at try, expected <rollout clause>”…
and i don’t want to rewrite my complete UI to be generated dynamically, i’d just like to either create a AX or DotNet object.
do you know some way around this?
btw for anyone who’s curios how to load different files for different versions… i allmost :banghead:
(this one is noted before the rollout not in it )
----------------------------------------------
------------load HelpBrowser--------------
----------------------------------------------
try(
local MXSel=(filterString (((dotnetclass "System.Diagnostics.FileVersionInfo").GetVersionInfo (pathConfig.appendPath (pathConfig.GetDir #maxroot) "3dsmax.exe")).FileVersion) ".")
if (MXSel[4] as integer) < 100 then ( MXSel4=100 as string)else(MXSel4=MXSel[4])
)catch(
--catch if dotnet is not available (earlier than max9)
--Max 8 or earlier
try (FileIn "IN_Polypimp\\8\\help\\HelpBrowser.mse")
catch (
try (FileIn "IN_Polypimp\\8\\help\\HelpBrowser.ms")
catch(messagebox "error")
)
)
try(
--Max 9SP1 or later
if (( ( (MXSel[1]+MXSel[2] )+ MXSel[3] ) +MXSel4) as integer) >=910109 then (
try (FileIn "IN_Polypimp\\help\\HelpBrowser.mse")
catch (
try (FileIn "IN_Polypimp\\help\\HelpBrowser.ms" )
catch(messagebox "error #2")
)
)
--Max 9 or earlier
else (
try (FileIn "IN_Polypimp\\8\\help\\HelpBrowser.mse")
catch (
try (FileIn "IN_Polypimp\\help\\HelpBrowser.ms")
catch(messagebox "error #3")
)
)
)catch()
-----------------------------------------------------------------------
edit: oh man it’s rlly early here… and sumtimes i can be a dum*h!t… creating it in a variable before i create the rollout… duh:rolleyes:
edit2: it sounded so good in my head :surprised
The way I did it in Deadline submitter for Max and in Krakatoa was to split the source into a DN and AX versions. All the version-specific code would go into one piece, the general code into pieces around it. For example
someFile_01.ms
someFile_02_DN.ms –this contains the portion with DotNet
someFile_02_AX.ms –this contains the portion with ActiveX
someFile_03.ms
Then I would create a main .ms file for AX and DotNet with the content
–content of someFile_Main_AX.ms:
include “someFile_01.ms”
include “someFile_02_AX.ms”
include “someFile_03.ms”
–content of someFile_Main_DN.ms:
include “someFile_01.ms”
include “someFile_02_DN.ms”
include “someFile_03.ms”
And finally I would detect the MAX Version in a startup script and either load “somefile_Main_AX.ms” or “somefile_Main_DN.ms” depending on which type of controls I wanted.
This was, of course, a major PITA to maintain, so as of Deadline 3.0 and the next version of Krakatoa, Frantic is removing support for Max 8 and below. But it worked well…