[Closed] updating object names in listbox or listview
I was wondering if it were possible to update object names in a listbox or listview as they are changed in the viewport, or even if there is a better way to store a list of scene objects than listbox or listview. I’m after something along the lines of the reactor rigid body collection rollout
It is possible. One way would be to register a callback that is called when objects are renamed.
A plugin like RBC uses a ParamBlock2 though, if you were to write a scripted plugin or Custom Attribute that contains a nodeTab parameter in a paramBlock, it would get notified whenever a referenced node has changed in the scene, then you would have to update the listbox.
thanks for the speedy reply Bobo! i’m am not yet an advanced scripter and i’m unfamiliar with the concepts you mentioned. I quickly checked the maxscript refererence and it looks like callbacks might be easier to get into at this stage but which would you recommend using?
Also, a bit off topic but are you planning anymore maxscript dvds anytime soon?
Try callbacks first – check out “How To … Develop a Selected Objects Inspector using ListView ActiveX Control – Part Two” in the MAXScript Reference – it uses a callback to repopulate the list when the scene selection changes. Same concept.
I am planning more DVDs, but have to do my daily job, prepare a MasterClass for Siggraph, edit yet another MAXScript Reference and also have time for my family. Which means it is one of many things I have to do, and it takes time…
gravey i thought i will reply to this thread as you might have been working on listview…
the labeledit property of listview only allows u to edit the first cell of each column… whereas i want two subitem cells to be editable by user. cant find any such editable property in the reference. is this possible?
Sorry abyjoe, when I was using listview it was more for a learning exercise and I discovered the script I was making would be much more efficient without an interface.
Maybe there’s another solution to what magicm suggested. What do you need the user to do that requires 2 editable columns?
Unfortunately, subitems cannot be dynamically edited in mxs. C++ allows you to subclass the control allowing you to add all kinds of functionality to it, but this can’t be done using maxscript. The only way I know of is to use a standard editTest control. By querying the subitem’s position you could move the editText control to that location/size. Then, by using the editText control’s events (eg. onChange) you can update the subitem’s contents accordingly.
This gets tricky though when the cell is outside the listviews’ borders. Then you’d need to get the current scroll positions and add those to the location of the subitem.
If you need any help with this I’ll try to post an example of how this could be done.
Cheers,
Martijn
Unfortunately, subitems cannot be dynamically edited in mxs. C++ allows you to subclass the control allowing you to add all kinds of functionality to it, but this can’t be done using maxscript. The only way I know of is to use a standard editTest control. By querying the subitem’s position you could move the editText control to that location/size. Then, by using the editText control’s events (eg. onChange) you can update the subitem’s contents accordingly.
This gets tricky though when the cell is outside the listviews’ borders. Then you’d need to get the current scroll positions and add those to the location of the subitem.
One would think this is a trivial thing to do, but unfortunately it’s not…
Cheers,
Martijn
comeon u guys… u are elite… if you cant do it then who will
my listview gets all layer names in scene… i need two editable fields to enter some properties for each layer in the listview. those properties like a 1.material prefix will prefix all the materials in that layer and 2.mesh file name that gets written to the file i format to with each material…
now out of the topic i have another problem:
like i am checking each layer and going through each geometry object in that layer to get a list of unique materials… those unique materials are stored in a temp array called arrmultimaterial = multimaterial()… i used the code below to assign the unique materials found to a new slot in the temp arrmultimaterial array
arrmultimaterial.material[i] = g.material
everything was working fine until i tried to add a prefix to the material name right after it
arrmultimaterial.material[i] = g.material
arrmultimaterial.material[i].name = "L1_" + arrmultimaterial.material[i].name
as soon as i add the prefix code the actual materials of scene also get updated with the prefix… at this stage this means everytime i run the script the materials will already have a prefix and keep adding more to it… like first time L1_materialname, secondtime L1_L1_materialname and so on
i dont understand how can they update now when i am not issuing any command to do so… because i am also sorting the arrmultimaterial and it doesnt update the actual materials when i sort it so why now?
The easiest way to do this is to add two text fields below the listview control. Whenever the user selects a row in the listview, the text fields can be used to edit that particular row. If you need any help with this, I can probably post an example script tomorrow.
This above command stores an instance of the original material in the array. So whenever you modify an item in the arrmultimaterial array, it will affect the original material as well. If you want to create a copy of the original material instead, you should use:
arrmultimaterial.material[ i ] = [b]copy[/b] g.material
This will create a copy instead of an instance, allowing you to modify its properties without affecting the original material.
Hope this helps,
Martijn
I’m sure this is what magicm had in mind:
try(DestroyDialog layers_listview)catch()
rollout layers_listview "Layer Options"
width:325 height:155
(
fn initListView lv =
(
lv.gridLines = true
lv.View = #lvwReport
lv.fullRowSelect = true
lv.backColor = color 224 224 224 --225 215 210
lv.checkboxes = true
lv.LabelEdit = #lvwManual
layout_def = #(#("Layer Name",120), #("Input 1",60), #("Input 2",120))
for i in layout_def do
(
column = lv.ColumnHeaders.add()
column.text = i[1]
)
LV_FIRST = 0x1000
LV_SETCOLUMNWIDTH = (LV_FIRST + 30)
for i = 0 to layout_def.count-1 do
windows.sendMessage lv.hwnd LV_SETCOLUMNWIDTH i layout_def[1+i][2]
)
fn fillInSpreadSheet lv =
(
lv.ListItems.clear()
renderLayers = (for i = 0 to (LayerManager.count - 1) where
(matchPattern (layermanager.getlayer i).name pattern:"Tools_*") collect (layermanager.getlayer i).name)
if renderLayers != undefined then
(
for i = 1 to (renderLayers.count) do
(
li = lv.ListItems.add()
li.checked = True
li.text = renderLayers[i] as string
sub_li = li.ListSubItems.add()
sub_li.text = "lod"
sub_li = li.ListSubItems.add()
sub_li.text = "mesh file" -- try((o.mesh.numverts) as string)catch("--")
)
)
)
activeXControl lv_objects "MSComctlLib.ListViewCtrl" width:321 height:125 align:#left offset:[-10,0]
editText edt_One "" across: 2
editText edt_Two ""
on layers_listview open do
(
initListView lv_objects
fillInSpreadSheet lv_objects
)
--I used the reference to find out properties and event handlers such as the following:
--layers_listview.lv_objects.selecteditem.listSubItems[1]
on lv_objects ItemClick item do
(
edt_One.text = item.listSubItems[1].text
edt_Two.text = item.listSubItems[2].text
)
on edt_One changed txt do
(
lv_objects.selecteditem.listSubItems[1].text = txt
)
on edt_Two changed txt do
(
lv_objects.selecteditem.listSubItems[2].text = txt
)
)
createdialog layers_listview pos:[730,95] --style:#(#style_sysmenu,#style_titlebar,#style_mini mizebox)
Its very simple. I just looked at the maxscript reference based on magicm's post and added two editText fields that are updated with the text of the 2nd and 3rd colums of the selected row. Then when the editText fields are changed, they change the corresponding fields in the selected row.
I know from previous threads you’ve posted you’re still fairly new to maxscript, but nutting out the problem for yourself using the maxscript reference will usually have the answer. Please do not be discouraged from using the forum, I’m simply saying that the reference is the way I learnt, and I still continue to learn from it every day!
- Its how I answered your question
great one Martijn… thank you for that, now i feel a lot better after knowing that as i understand whats happening with it… it would be great if you can provide an example code because i am only about 1 week old to maxscript and the rollouts have taken me a lot of time, even more that doing the whole script itself.
this is my listview rollout code… i need to add editable text feature to the second and third column but after trying the fake textbox thing i cant seem to get it to work… please someone who knows how to do the move textbox to position on click give an example… and how to access its values when the listview item is clicked.
rollout layers_listview "Layer Options"
width:325 height:155
(
fn initListView lv =
(
lv.gridLines = true
lv.View = #lvwReport
lv.fullRowSelect = true
lv.backColor = color 224 224 224 --225 215 210
lv.checkboxes = true
lv.LabelEdit = #lvwManual
layout_def = #(#("Layer Name",120), #("Input 1",60), #("Input 2",120))
for i in layout_def do
(
column = lv.ColumnHeaders.add()
column.text = i[1]
)
LV_FIRST = 0x1000
LV_SETCOLUMNWIDTH = (LV_FIRST + 30)
for i = 0 to layout_def.count-1 do
windows.sendMessage lv.hwnd LV_SETCOLUMNWIDTH i layout_def[1+i][2]
)
fn fillInSpreadSheet lv =
(
lv.ListItems.clear()
renderLayers = (for i = 0 to (LayerManager.count - 1) where (matchPattern (layermanager.getlayer i).name pattern:"Tools_*") collect (layermanager.getlayer i).name)
if renderLayers != undefined then
(
for i = 1 to (renderLayers.count) do
(
li = lv.ListItems.add()
li.checked = True
li.text = renderLayers[i] as string
sub_li = li.ListSubItems.add()
sub_li.text = "lod"
sub_li = li.ListSubItems.add()
sub_li.text = "mesh file" -- try((o.mesh.numverts) as string)catch("--")
)
)
)
activeXControl lv_objects "MSComctlLib.ListViewCtrl" width:321 height:125 align:#left offset:[-10,0]
on layers_listview open do
(
initListView lv_objects
fillInSpreadSheet lv_objects
)
)
createdialog layers_listview pos:[730,95] style:#(#style_sysmenu,#style_titlebar,#style_minimizebox)
the listview is updated on rolloutopen with all the layers in scene that start with “Tools_” so pls add a few layers called tools_XXX to see it work.