-
Spinners dinamicos
Hola. Llevo un ratio intentando hacer un script y me he quedado estancado, quizá tenga la solución justo delante y no la vea de ahí mi mensaje. A ver si me podéis ayudar, aunque sea conceptualmente.
Estoy tratando de controlar mediante spinner las subdivisiones del sampling de una serie de luces Vray. Para ello recorro las luces que tengo seleccionadas y género dinámicamente tantos spinner como luces tenga en selección. A su vez al value de cada spinner le asigno el valor actual del parámetro de subdivisiones que tiene cada luz Vray. El problema lo tengo a la hora del feedback, porque cuando modifico los valores con los spinner sólo me afecta a la última luz seleccionada y encima todos los spiners afectan a la última luz que haya seleccionado, mientras que al resto de luces no.
El esquema sería (para 2 luces, e).
Primero selecciono las 2 luces con lo que mi selección actual sería.
Vraylight00, vraylight01.
Ahora género mis spinner:
Spin_1 con su valor.
Spin_2 con su valor.
Cuando modifico ambos spinner sólo se me afectada la luz vraylight01 por ser la última luz en la pila o array de selección.
Mi duda es: ¿cómo puedo hacer que un handler sepa que spinner estoy afectando? Y así poder modificar el parámetro de la luz correspondiente.
Aquí pongo el código de esta sección:
For obj in sel_actual do.
Mat_sel = append mat_sel obj.
) - Del for.
Samp = utcreator sampling sampling height:400.
Samp, begin().
Colocamos justo encima el nombre de subdivisiones.
Local nomlabel = (label_) as name.
Samp, addcontrol #label nomlabel nombre subdivisiones paramstroffset:[95,0] width:300 height:15).
Espacio.
Local nomlabel = (espacio_) as name.
Samp, addcontrol #label nomlabel - Paramstroffset:[90,-5] width:300 height:15).
Bucle que genera los spinner necesarios en función de las luces seleccionadas.
For I = 1 todo mat_sel, count do.
Variables de control de parámetros de los spiners.
Nomspin = (spin_+ (i as string)) as name.
Nomluz = (mat_sel[i].name + : ) as name.
Valspin =(mat_sel[i].subdivisiones) as string.
Nomobj = mat_sel[i].
Samp, addcontrol #spinner nomspin nomluz paramstr type:#integer range:[0,100, + valspin + ] fieldwidth:40 align:#center)\.
Samp, addhandler nomspin #changed valspin filter:on.
Codestrnomobj.subdivisiones= valspin)\.
) - Del for.
Samp, end().
Addsubrollout vrayluces.child sampling. Muchas gracias por anticipado.
-
El problema es que estás usando la misma variable valspin para todos los handlers, y todos están ejecutando el mismo código codestr que modifica la propiedad subdivisiones de la variable nomobj. En cada iteración del bucle, nomobj se sobrescribe con la luz actual (mat_sel[i]), por lo que al final del bucle, nomobj siempre apunta a la última luz. Todos los handlers creados hacen referencia a esta misma variable final, no a la luz que les correspondía en su iteración.
La solución es capturar el valor específico de cada luz en el momento de crear el handler, de modo que cada uno opere sobre su propio objeto. Debes crear un closure o una estructura que almacene la referencia correcta. En MAXScript, una forma común es definir una función dentro del bucle que tenga su propio contexto.
Reestructura el bucle de creación de spinners y handlers de esta manera:
For i = 1 to mat_sel.count do
(
local nomspin = ("spin_" + (i as string)) as name
local nomluz = (mat_sel[i].name + ": ") as string
local valspin_inicial = mat_sel[i].subdivisiones
local obj_actual = mat_sel[i]
samp.addControl #spinner nomspin nomluz paramStr type:#integer range:[0,100,valspin_inicial] fieldwidth:40 align:#center
on nomspin changed val do
(
obj_actual.subdivisiones = val
)
)
Observa que el handler on changed val do se declara dentro del bucle. La variable obj_actual es local para cada iteración, por lo que cada función handler recordará y modificará únicamente el objeto VrayLight que le fue asignado.
Otra opción, si necesitas mantener la estructura con addHandler, es usar una función de callback que reciba el objeto como parámetro. Puedes crear una función que devuelva otra función (un closure). Sin embargo, la forma más directa y legible en MAXScript para un rollout dinámico es la mostrada arriba, integrando el handler directamente en la definición del control dentro del bucle.
Por lo tanto, modifica tu código para que, en lugar de intentar construir un string de código (codestr) y asignarlo mediante addHandler, declares el evento changed dentro del contexto del bucle donde la variable obj_actual está correctamente asociada a cada luz. Esto asegurará que cada spinner controle solo a su luz correspondiente.