[Closed] Drag-Drop Material as String
I was checking out this thread about a way to simulate drag-and-droping materials outside of the Material Editor:
http://forums.cgsociety.org/showthread.php?f=98&t=685803&highlight=drag+drop
and in it PiXeL_MoNKeY suggested a way of doing it using the LoneRobot method since max stores materials as unique strings. In the end MarcoBrunetta came up with a different solution, but I was curious if what PiXeL_MoNKeY wrote can be done since his version would allow dropping into the material editor and not just objects in the scene.
My question is how do I find out this “unique string” for a material for example in a material library somewhere?
I tried just loading a Temp Material Library and getting its first material, but max gave an error saying that it couldn’t convert the material to a “type: System.Object”
try (destroyDialog ::DragDropOps) catch()
rollout DragDropOps "LoneRobot Drag Drop" width:136 height:150
(
dotNetControl btndragdrop "label" pos:[5,5] width:125 height:139
on DragDropOps open do
(
btndragdrop.allowdrop = true
btndragdrop.text = "Hooray! A Drag/Drop Enabled Label!!!
To drop a Texturemap, just pass the map path string in the dataobject instead of a max file path. This will also work if draging a map to the material editor"
btndragdrop.borderstyle = (dotNetClass "System.Windows.Forms.BorderStyle").fixedsingle
btndragdrop.backcolor = (dotnetclass "System.Drawing.Color").orangered
btndragdrop.forecolor = (dotnetclass "System.Drawing.Color").yellow
)
on btndragdrop mousemove sender args do
(
if (sender.clientrectangle.contains args.x args.y) then setSysCur #arrow
else setSysCur #move
)
on btndragdrop mouseup sender args do
(
if (sender.clientrectangle.contains args.x args.y) then (print "asd")
else
(
theIniFile = getdir #maxData + "3dsmax.ini"
theKeys = getIniSetting theIniFile "FileList"
-- filenameString = "D:\Object.max" -- max object
-- filenameString = "D:\Texture.jpg" -- texture
filenameString = "?????????" -- material
-- matLib = loadTempMaterialLibrary "D:\MatLib.mat"
-- filenameString = matLib[1]
dropfile = dotnetobject "System.String[]" 1
dropfile.setvalue filenameString 0
DataObj = dotnetobject "DataObject" ((dotnetclass "DataFormats").filedrop) dropfile
sender.dodragdrop Dataobj ((dotnetclass "DragDropEffects").Copy)
)
)
)
createdialog DragDropOps style:#(#style_toolwindow, #style_sysmenu)
where from do you want to drag and where on do you want to drop a material?
Well, in the example I posted you drag from the label with the text on it. And I want to be able to drag to an scene object, material editor slot, VrayBlendMtl slot, etc. Any place where max allows materials to be dropped.
they are all three different tricks. a universal solution i know is the using of hook procedures.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
but it’s too advanced for this topic
So you are saying it can’t be done without super-advanced tricks and that what PiXeL_MoNKeY wrote was wrong?
In the code I posted, if the variable filenameString is a file path for an image or max file somewhere on the hard drive, the dragging functionality seems to work universally. I don’t know enough about how max handles things behind the scene, but I assumed if would be possible since I can’t imagine the material and maps in the Material/Map browser not having some unique ID that max uses when handling the drag-drop action within it.
material name might not be unique. at least you can’t know it for sure. so you have use anything else. the anim handle is probably the best thing.
I see. Can you give me an example of what string you used so that you got drag-drop to work only on objects in the scene? I’m curious what I did wrong.
here is how i would do it easiest way:
try(destroydialog dialog) catch()
rollout dialog "Simple Mats" width:300
(
dotnetcontrol lv "ListView" width:296 height:200 pos:[2,2]
fn fillLv =
(
items = for mat in meditmaterials collect
(
item = dotnetobject "ListViewItem" mat.name
item.tag = dotnetmxsvalue mat
item
)
lv.items.addrange items
)
fn initLv =
(
lv.View = lv.View.Details
lv.MultiSelect = off
lv.AllowDrop = on
lv.Columns.add "Materials" 280
fillLv()
)
local drag_item
local effect = dotNetclass "System.Windows.Forms.DragDropEffects"
fn isDraggable item = item != undefined and iskindof item.tag dotnetmxsvalue and iskindof item.tag.value Material
on lv ItemDrag s arg do
(
local item = arg.item
if (isDraggable item) then
(
drag_item = item
lv.DoDragDrop drag_item effect.move
)
else drag_item = undefined
)
on lv QueryContinueDrag s arg do
(
if (arg.Action == arg.Action.Drop) and (isDraggable drag_item) do
(
mpos = mouse.pos
nodes = boxPickNode (box2 (mpos.x-2) (mpos.y-2) 4 4) crossing:on
if nodes.count > 0 do undo "Apply Material" on
(
nodes.material = mat = drag_item.tag.value
format ">> nodes: % %
" nodes mat
)
)
if (arg.Action != arg.Action.Continue) do drag_item = undefined
)
on dialog open do
(
initLv()
)
)
createdialog dialog
it’s not perfect but it gives you an idea
I have a similar question: Can you ‘trick’ the drag-drop function from the material editor into thinking a rollout is a scene object that can be dropped onto and then passing the drop info to it?
do you want to drag from mat editor and drop onto some ui control?
material drag-drop in implemented by system and material developer. it’s a black box. i don’t think we can capture that something is dragging at the moment.