Since i’m not really good with HWNDs and UIAccessor etc. i would take another route.
When you load a preset, there are not too many values that get changed.
I think it’s Color, Intensity, Dimming, Distribution file, maybe a few more.
Now these values are exposed to maxscript. So just setting up a few presets and then assigning them with maxscript should be easy to do.
This way you also don’t have to select them.
quick & dirty example:
fn loadpreset mylight myvalues =
(
for x in myvalues do
(
try (setProperty mylight x[1] x[2])
catch()
)
)
preset1 = #( \
#("intensity", 80), \
#("kelvin", 2500), \
#("intensityType", 1)\
)
preset2 = #( \
#("intensity", 80), \
#("kelvin", 5000), \
#("intensityType", 3)\
)
for mylight in selection do loadpreset mylight preset1
Since i am by no means an expert i’d also like to ask the professionals here.
Is this a good/bad approach?
Heilandzack: the preset is specifically the color, and when working with photometric lights the preset selected from the dropdown overrides any other color values you may want to apply. I.e. in the listener:
$.color -- check light color value
(color 415.968 224.624 79.6526) -- result for a photometric light set to Halogen
$.color = (color 255 255 0) -- set a new light color value
(color 255 255 0) -- returns entered value
$.color -- check light color value again
(color 415.968 224.624 79.6526) -- no change
Yeah you’re right, i just checked. Another option would be to switch to Kelvin Temperature and set that. But i understand that that is propably not what you’re looking for…
Are you sure it’s not updated? Maybe it’s too intense to distinguish colors?
What colors are we talking about? Rendertime or ui?
global ComboBoxOpsAssembly
fn CreateComboBoxOpsAssembly =
(
source = ""
source += "using System;
"
source += "using System.Text;
"
source += "using System.Runtime.InteropServices;
"
source += "public class ComboBoxOps
"
source += "{
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int SendMessage(IntPtr window, int message, int wParam, IntPtr lParam);
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int SendMessage(IntPtr window, int message, int wParam, int lParam);
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
"
source += " public const int CB_GETCOUNT = 0x0146;
"
source += " public const int CB_GETCURSEL = 0x0147;
"
source += " public const int CB_GETLBTEXT = 0x0148;
"
source += " public const int CB_GETLBTEXTLEN = 0x0149;
"
source += " public const int CB_FINDSTRING = 0x014C;
"
source += " public const int CB_SELECTSTRING = 0x014D;
"
source += " public const int CB_SETCURSEL = 0x014E;
"
source += " [DllImport(\"user32.dll\", CharSet = CharSet.Auto)]
"
source += " static extern int SendMessage(Int32 hWnd, int msg, int wParam, [Out] StringBuilder param);
"
source += " public static string GetText(Int32 hWnd, int msg, int wParam, int length)
"
source += " {
"
source += " StringBuilder sb = new StringBuilder(length + 1);
"
source += " SendMessage(hWnd, msg, wParam, sb);
"
source += " return sb.ToString();
"
source += " }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add("System.dll");
compilerParams.GenerateInMemory = true
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
ComboBoxOpsAssembly = compilerResults.CompiledAssembly
ComboBoxOpsAssembly.CreateInstance "ComboBoxOps"
)
global ComboBoxOps = CreateComboBoxOpsAssembly()
h = windows.getchildhwnd #max "Command Panel"
c = windows.getchildhwnd h[1] "Color"
c = uiaccessor.getnextwindow c[1]
c = uiaccessor.getnextwindow c
combobox_hwnd = uiaccessor.getnextwindow c
ComboBoxOps.SendMessage (dotNetObject "system.intptr" combobox_hwnd) ComboBoxOps.CB_SETCURSEL 5 0
I’m talking about both. The value is not updating beyond the UI selection. Also, if you click off of the selected light and directly back onto it after running the code, you will see that the UI selection has reverted.
BTW… set/get color preset is accessible via SDK
lslights.h ->>
PresetLightColor LightscapeLight::GetColorPreset();
LightscapeLight::SetColorPreset(PresetLightColor id);
Yeah, I saw that. No way to access from Maxscript though…
For current purposes, I’m guessing that CB_SETITEMDATA is what I need to get in there? Or…?
no… it’s not enough. as i said you have somehow to confirm changing the value.
i don’t have time now to play with the idea, but i guess you have to send CBN_SELCHANGE or CBN_SELENDOK message (or both) to its parent control.
here is what I would try first:
http://stackoverflow.com/questions/23136283/winapi-simulating-item-selection-in-combobox
Anyone else want to take a crack at it? I feel like I’m chasing my tail here.
i did it!
global ComboBoxOpsAssembly
fn CreateComboBoxOpsAssembly =
(
source = ""
source += "using System;
"
source += "using System.Text;
"
source += "using System.Runtime.InteropServices;
"
source += "public class ComboBoxOps
"
source += "{
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int SendMessage(IntPtr window, int message, int wParam, IntPtr lParam);
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
"
source += " public const int CB_GETCOUNT = 0x0146;
"
source += " public const int CB_GETCURSEL = 0x0147;
"
source += " public const int CB_GETLBTEXT = 0x0148;
"
source += " public const int CB_GETLBTEXTLEN = 0x0149;
"
source += " public const int CB_FINDSTRING = 0x014C;
"
source += " public const int CB_SELECTSTRING = 0x014D;
"
source += " public const int CB_SETCURSEL = 0x014E;
"
source += " [DllImport(\"user32.dll\")]
"
source += " static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [Out] StringBuilder param);
"
source += " public static string GetText(IntPtr hWnd, int msg, int wParam, int length)
"
source += " {
"
source += " StringBuilder sb = new StringBuilder(length + 1);
"
source += " SendMessage(hWnd, msg, wParam, sb);
"
source += " return sb.ToString();
"
source += " }
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern int PostMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
"
source += " [DllImport(\"user32.dll\")]
"
source += " static extern int GetDlgCtrlID(IntPtr hwndCtl);
"
source += " [DllImport(\"user32.dll\")]
"
source += " public static extern IntPtr GetParent(IntPtr hWnd);
"
source += " public static int MAKEWPARAM(int low, int high)
"
source += " {
"
source += " return ((high << 16) | (low & 0xffff));
"
source += " }
"
source += " public const int WM_COMMAND = 0x111;
"
source += " public const int CBN_SELENDOK = 9;
"
source += " public const int CBN_SELCHANGE = 1;
"
source += " public void ConfirmSelChange(IntPtr hWnd)
"
source += " {
"
source += " PostMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), CBN_SELENDOK), (int)hWnd);
"
source += " PostMessage(GetParent(hWnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWnd), CBN_SELCHANGE), (int)hWnd);
"
source += " }
"
source += " public int SetCurrentSel(IntPtr hWnd, int index)
"
source += " {
"
source += " SendMessage(hWnd, CB_SETCURSEL, index, IntPtr.Zero);
"
source += " ConfirmSelChange(hWnd);
"
source += " return SendMessage(hWnd, CB_GETCURSEL, 0, IntPtr.Zero);
"
source += " }
"
source += "}
"
csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
compilerParams.ReferencedAssemblies.Add("System.dll");
compilerParams.GenerateInMemory = true
compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
ComboBoxOpsAssembly = compilerResults.CompiledAssembly
ComboBoxOpsAssembly.CreateInstance "ComboBoxOps"
)
global ComboBoxOps = CreateComboBoxOpsAssembly()
/*
hwnd = dotnetobject "System.IntPtr" <hwnd of presets combo box>
ComboBoxOps.SetCurrentSel hwnd 5
*/
(but it took one hour of my life)
Goddamn, Denis. If I could knock something like that together in an hour I would be… well, a more proficient coder than I am now
Seriously though, you’re the man. If there’s ever anything I can do for you, don’t hesitate to ask me!
Okay, thought I was done with this, but if it’s going to do what I want I need it to work in this context, and I’m having some trouble with it.
-- (after loading ComboBoxOpsAssembly)
ca = attributes "ca" (
parameters params rollout:RO (
lt type:#node
preset type:#integer ui:spn_preset
)
rollout RO "" (
local s, holder
spinner spn_preset range:[0,21,2] type:#integer
on RO open do (
s = (refs.dependentNodes (custAttributes.getOwner this))[1]
holder = s.modifiers["ca"]
)
on spn_preset changed val do (
clearListener()
/*
-- Not working...
select lt
maxC = windows.getChildrenHWND #max
hWnd = for i = 1 to maxC.count where maxC[i][5] == "Intensity/Color/Attenuation" do (exit with maxC[i+5][1])
ComboBoxOps.SetCurrentSel hWnd val
select s
*/
-- Store script as a string
str = ""
str += "select $" + lt.name + "
"
str += "maxC = windows.getChildrenHWND #max
"
str += "hWnd = for i = 1 to maxC.count where maxC[i][5] == \"Intensity/Color/Attenuation\" do (exit with maxC[i+5][1])
"
str += "ComboBoxOps.SetCurrentSel hWnd " + val as string + "
"
str += "select s
"
format str -- select and run listener output to demonstrate that the resulting script works
execute str -- execute the string and see that nothing happens from inside the handler
)
)
)
-- Create scene
---------------
delete objects
teapot segments:8
plane length:100 width:100
s = geoSphere()
s.pos = [0, 0, 100]
tgt = targetObject()
lt = Target_Light target:tgt intensity:15000
lt.pos = [100, -100, 100]
holder = emptyModifier name:"holder"
custAttributes.add holder ca #unique
holder.lt = lt
addModifier s holder
select s