[Closed] Drag and drop from winform to material editor
I want to drag and drop from winform to the Material Editor slot, This is my first try:
rollout DragAndDropRol "Drag and Drop"
(
dotNetControl lbl "label" text:"Drag me."
on lbl mouseDown sender args do
(
dropfile = dotnetobject "System.String[]" 1
dropfile.setvalue "" 0
dataObj = dotnetobject "DataObject" ((dotnetclass "DataFormats").filedrop) dropfile
sender.DoDragDrop dataobj ((dotnetclass "DragDropEffects").Copy)
)
on lbl QueryContinueDrag sender args do
(
if args.Action == args.Action.drop do
(
print activeMeditSlot
)
)
)
createdialog DragAndDropRol
The only result that I’m looking for is which slot received the dropping.But problem is the slot will be flicker several times and after that activeMeditSlot shows the right slot.
What if you wait a bit longer before accessing activeMeditSlot ?
try DestroyDialog DragAndDropRol catch()
rollout DragAndDropRol "Drag and Drop"
(
dotNetControl lbl "label" text:"Drag me."
timer tt interval:50 active:false
on lbl mouseDown sender args do
(
dropfile = dotnetobject "System.String[]" 1
dropfile.setvalue "1" 0
dataObj = dotnetobject "DataObject" ((dotnetclass "DataFormats").filedrop) dropfile
sender.DoDragDrop dataobj ((dotnetclass "DragDropEffects").Copy)
)
on lbl QueryContinueDrag sender args do
(
if args.Action == args.Action.drop do
(
tt.active = true
)
)
on tt tick do
(
tt.active = false
format "Tick: %\n" activeMeditSlot
)
on lbl DragDrop sender args do format "DragDrop\n"
)
createdialog DragAndDropRol
How much time we should wait? it is differ from system to system.
I have another idea, Did you see the material drag and drop from one slot to another? It may be more close to what we can achieve. Do you know what is the type of “DataObject” for the Max’s material? Maybe we can pass that instead of string.
I think that the global variable value gets updated at the first tick event no matter what interval we set in the timer control.
But it needs to be checked of course.
I guess you can read about it in sdk reference. DADMgr class
And here’s how we can get the type of slot under the mouse cursor:
(
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
mateditor_hwnd = for w in UIAccessor.GetPopupDialogs() do
(
local data = windows.getHWNDData w
if UIAccessor.GetWindowResourceID data[1] == 2359953 do
(
exit with data[1]
)
)
hwnd = (windows.getChildHWND mateditor_hwnd "Custom1")[1] -- DragAndDropWindow
ptr = (dotnetobject "system.intptr" hwnd)
d = g.GetIDADWindow ptr
_pt = windows.screenToClient hwnd mouse.screenpos
pt = dotNetObject "system.drawing.point" _pt.x _pt.y
dragtype_scid = d.DadMgr.GetDragType ptr pt
fn GetSCIDName scid =
(
local type = ((dotNetClass "Autodesk.Max.SClass_ID").Texmap).GetType()
(dotNetClass "Autodesk.Max.SClass_ID").GetName type scid.value__
)
format "%\n" (GetSCIDName dragtype_scid)
-- and now lets drop something from one slot to another
-- GetInstance <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type
ref_target = d.DadMgr.GetInstance ptr pt dragtype_scid
pt = dotNetObject "system.drawing.point" (_pt.x + 30) (_pt.y + 30)
-- .Drop <Autodesk.Max.IReferenceTarget> dropThis <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type <Autodesk.Max.IDADMgr>srcMgr <System.Boolean>bSrcClone
d.DadMgr.Drop ref_target ptr pt dragtype_scid d.DadMgr false
)
)
I just changed your code little bit to find the right handler:
(
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
mateditor_hwnd = undefined
for h in UIAccessor.GetPopupDialogs() \
where MatchPattern (UIAccessor.GetWindowText h) pattern:"Material Editor - *" \
while mateditor_hwnd == undefined \
do mateditor_hwnd = h
hwnd = (windows.getChildHWND mateditor_hwnd "Custom1")[1] -- DragAndDropWindow
ptr = (dotnetobject "system.intptr" hwnd)
d = g.GetIDADWindow ptr
_pt = windows.screenToClient hwnd mouse.screenpos
pt = dotNetObject "system.drawing.point" _pt.x _pt.y
dragtype_scid = d.DadMgr.GetDragType ptr pt
fn GetSCIDName scid =
(
local type = ((dotNetClass "Autodesk.Max.SClass_ID").Texmap).GetType()
(dotNetClass "Autodesk.Max.SClass_ID").GetName type scid.value__
)
format "%\n" (GetSCIDName dragtype_scid)
-- and now lets drop something from one slot to another
-- GetInstance <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type
ref_target = d.DadMgr.GetInstance ptr pt dragtype_scid
pt = dotNetObject "system.drawing.point" (_pt.x + 30) (_pt.y + 30)
-- .Drop <Autodesk.Max.IReferenceTarget> dropThis <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type <Autodesk.Max.IDADMgr>srcMgr <System.Boolean>bSrcClone
d.DadMgr.Drop ref_target ptr pt dragtype_scid d.DadMgr false
)
It will return “Material”, Do you think we can use this type inside the first code?
I did my tests in 2014, maybe newer max versions have another resource id for mateditor window. I’ll check.
Window title can (and I’m pretty much sure will) be different in localized max version.
You can try to send some integer values with DoDragDrop that corresponds to certain classId or scid. But I don’t know if it will work.
What’re you going to drop? Texture filenames?
Material, actually I have a listview contain all material in the scene.I want to drag and drop listview item from/to material slot.
hmm… materials.
But what’s the purpose in handling drag-n-drop then?
Make sure that the cursor is above the slot using DadMgr.GetInstance
Activate the slot and simply assign the material
meditmaterials[ activemeditslot ] = mtl_from_listview
or simply find the slot index using reference target handle
ref_target = d.DadMgr.GetInstance ptr pt dragtype_scid
uptr = g.animatable.gethandlebyanim ref_target asdotnetobject:true
anim_handle = uptr.toUInt64()
mtl_or_tex = getAnimByHandle anim_handle
format "Slot index at cursor: %\n" (findItem meditMaterials mtl_or_tex)
and here’s the example how to create a node at mouse position in SME
...
mtl = VRayMtl()
anim = g.animatable.getanimbyhandle (dotNetObject "System.UIntPtr" (getHandleByAnim mtl) )
d.DadMgr.Drop anim ptr pt dragtype_scid d.DadMgr false
hi, i’m trying to make it work on the sme and this is the test with the sme hwnds
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
slate_hwnd = undefined
slate_hwnd = (windows.getChildHWND 0 "Slate Material Editor")[1]
hwnd = (windows.getChildHWND slate_hwnd "View1")[1]
ptr = (dotnetobject "system.intptr" hwnd)
d = g.GetIDADWindow ptr
_pt = windows.screenToClient hwnd mouse.screenpos
pt = dotNetObject "system.drawing.point" _pt.x _pt.y
dragtype_scid = d.DadMgr.GetDragType ptr pt
--print (d.DadMgr.GetDragType ptr pt)
fn GetSCIDName scid =
(
local type = ((dotNetClass "Autodesk.Max.SClass_ID").Texmap).GetType()
(dotNetClass "Autodesk.Max.SClass_ID").GetName type scid.value__
)
--format "%\n" (GetSCIDName dragtype_scid)
-- and now lets drop something from one slot to another
-- GetInstance <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type
--ref_target = d.DadMgr.GetInstance ptr pt dragtype_scid
--pt = dotNetObject "system.drawing.point" (_pt.x + 30) (_pt.y + 30)
-- .Drop <Autodesk.Max.IReferenceTarget> dropThis <System.IntPtr>hwnd <System.Drawing.Point>p <Autodesk.Max.SClass_ID>type <Autodesk.Max.IDADMgr>srcMgr <System.Boolean>bSrcClone
/*
mtl = VRayMtl()
anim = g.animatable.getanimbyhandle (dotNetObject "System.UIntPtr" (getHandleByAnim mtl) )
--d.DadMgr.Drop anim ptr pt dragtype_scid d.DadMgr false
*/
but two things happens,
1- the dragtype_scid is undefined no matter what i tried, i printed every step and there is the block.
2- if i embrace this in parenthesis it will error right away giving me an exception and i really dont understand
thanks
Seems like it’s not possible to get the drag type from the sme view. At least not like this.
You have an error because of the wrong hwnd. It must be a DragDropWindow window hwnd.
Last time it worked good and I could drop anything in a sme tab, but now it doesn’t.
upd
as you can see nothing really changed in code but now it is working… ridiculous
(
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
slate_hwnd = undefined
slate_hwnd = (windows.getChildHWND 0 "Slate Material Editor")[1]
hwnd = (windows.getChildHWND slate_hwnd "View1")[1]
hwnd = 0x3068E -- hardcoded hwnd from spy++
ptr = (dotnetobject "system.intptr" hwnd)
d = g.GetIDADWindow ptr
_pt = windows.screenToClient hwnd mouse.screenpos
pt = dotNetObject "system.drawing.point" _pt.x _pt.y
mtl_scid = (dotNetClass "Autodesk.Max.SClass_ID").Texmap
mtl = Checker()
anim = g.animatable.getanimbyhandle (dotNetObject "System.UIntPtr" (getHandleByAnim mtl) )
format "OkToDrop: %\n" (d.DadMgr.OkToDrop anim ptr ptr pt mtl_scid false)
d.DadMgr.Drop anim ptr pt mtl_scid d.DadMgr false
)
thanks sergey,
i ended up with this one since the hardcoded hwnd is not the way to go since it will change at every max instance.
this should work, i borrowed a function you made, hope you are ok with it
(
g = (dotNetClass "Autodesk.Max.GlobalInterface").Instance
slate_hwnd = undefined
slate_hwnd = (windows.getChildHWND 0 "Slate Material Editor")[1]
fn GetSMEWindowHandle =
(
max_hwnd = windows.getMAXHWND()
for m in windows.getChildrenHWND 0 where m[4] == "NodeJoeMainWindow" and m[5] == "Slate Material Editor" and m[6] == max_hwnd do exit with m[1]
)
sme_hwnd = GetSMEWindowHandle()
fn GetMainWindowHandle = (
for data in windows.getChildrenHWND sme_hwnd where data[4] == "DragDropWindow" and data[5] == "View1" do exit with data[1]
)
hwnd = GetMainWindowHandle()
ptr = (dotnetobject "system.intptr" hwnd)
d = g.GetIDADWindow ptr
_pt = windows.screenToClient hwnd mouse.screenpos
pt = dotNetObject "system.drawing.point" _pt.x _pt.y
mtl_scid = (dotNetClass "Autodesk.Max.SClass_ID").Texmap
mtl = Checker()
anim = g.animatable.getanimbyhandle (dotNetObject "System.UIntPtr" (getHandleByAnim mtl) )
format "OkToDrop: %\n" (d.DadMgr.OkToDrop anim ptr ptr pt mtl_scid false)
d.DadMgr.Drop anim ptr pt mtl_scid d.DadMgr false
)
as always, thank you master