Notifications
Clear all

[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)
11 Replies

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.

Page 1 / 2