1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Изменение свойств материалов

Тема в разделе "MAXScript", создана пользователем Александр Якушев, 25 апр 2014.

Модераторы: Savin Denis
  1. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Здравствуйте!
    Извините, если повторюсь. Можете поделиться способами изменения различных свойств материалов?
    Постараюсь начать.
    1. Скрип, который включает карты во вьюпорте:
    Код:
    ( 
    m = getclassinstances CoronaMtl
    join m (getclassinstances standardmaterial) 
    join m (getclassinstances  VrayMtl) 
    	
    if m.count ==0 do return 0 
    local SwithState=m[1].showInViewport 
    for i in m do 
    ( 
    	try(showTextureMap i i.texmapDiffuse true)catch()
    	try(showTextureMap i true)catch()
    ) 
    )
    
    код заимствованный с showTextureMap, добавил еще короновские материалы
    2. Скрипт меняет каналы карт:

    Код:
    rollout test "Material Editor. Active Slot." width:220 height:40
    (spinner sp_map_channel "Map Channel:" range:[1, 99, 1] pos:[5,10] scale:1 fieldwidth:50 type:#integer
    button btn_apply "Apply" pos:[150,7]; on btn_apply pressed do
    (maps = getClassInstances bitmaptexture target:meditMaterials[activeMeditSlot]
    for m in maps do m.coords.mapChannel=sp_map_channel.value )); createdialog test
    
    3. Здесь заготовка скрипта для поиска карт в сцене:
    Код:
    -- tested in 3DMax 2014
    (
    rollout MapsFinder "MapsFinder"
    (
    --Variables Declerations
    --------------------------------
    global FindMat = #()
    global FindMatName = #()
    
    --Function
    ---------------------------------
    
    --Interface
    --------	
    dropDownList ddl1 "Select type map:" items:#("ColorCorrect", "Color Edge", "Checker", "Color_Correction", "Cellular") selection:1
    button bnFind "Analyze" width:300 
    listbox ListMat "Please use DoubleClick for getting mat:"  height:43
    button bnGetMat "Get materials to MatEditor" width:150  across:2
    button bnSelObj "Select all objects " width:150 
    -------------------
    )
    --createDialog MapsFinder
    MapsFinder_float = newRolloutFloater "MapsFinder" 350 730 
    addRollout MapsFinder MapsFinder_float
    )
    
    Пытался доработать, но все время спотыкаюсь. Если получится, постараюсь все-таки добить.
    Какие полезные функции еще можно добавить ?

    Помогите систематизировать различные способы обращения и перебора свойств материалов(также врэеевских, короновских) плз.
    В каких случаях лучше использовать numsubs, getNumSubTexmaps, getSubTexmap и т.д.?
     
  2. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Всем привет еще раз. Постараюсь упростить вопрос.
    Не подскажете, как можно выделить материал по карте.
    Вот, к примеру, собираю карты colorcorrect
    Код:
    asd = getclassinstances ColorCorrect 
    
    возвращает, к примеру, такой массив
    Код:
    #(Map #3:ColorCorrect, Map #5:ColorCorrect, Map #7:ColorCorrect)
    
    Вот, хотелось бы, получить массив материалов, имеющих эти карты. Есть ли какой-нибудь простой способ? Или только перебор всех материалом с проверкой на наличие colorcorrect?
     
  3. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Почему вас не устраивает вариант с перебором всех материалов?
    Код:
    asd=for m in scenematerials where (getclassinstances ColorCorrect target:m).count>0 collect m
     
  4. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Спасибо igorznag!!! Очень лаконично и просто!
    Если вас не затруднит, оцените код, может быть избавите от "детских" ошибок.
    На радостях вот дописал скрипт:
    Код:
    -- tested in 3DMax 2014
    (
    rollout MapsFinder "MapsFinder"
    (
    --Variables Declerations
    --------------------------------
    global FindMat = #()
    global FindMatName = #()
    
    --Function
    ---------------------------------
    fn theAllMat = 
    (		
    		local allMat = #()
    		allMat = scenematerials
    		for i in meditMaterials do appendIfUnique allMat i
    		for i in objects do if i.material != undefined do appendIfUnique allMat i.material
    		return allMat
    	)
    	
    fn find_ColorCorrect mat =
    	(
    		for m in theAllMat() where (getclassinstances ColorCorrect target:m).count>0 do 
    		(
    			if (appendIfUnique FindMat m)== true do append FindMatName m.name
    			)
    	)
    		
    		
    fn find_Checker mat =
    	(
    		for m in theAllMat() where (getclassinstances Checker target:m).count>0 do 
    		(
    			if (appendIfUnique FindMat m)== true do append FindMatName m.name
    			)
    	)
    
    fn find_Color_Edge mat = 
    	(
    		for m in theAllMat() where (getclassinstances Color_Edge target:m).count>0 do 
    		(
    			if (appendIfUnique FindMat m)== true do append FindMatName m.name
    			)
    	)
    fn find_Color_Correction mat = 
    	(
    		for m in theAllMat() where (getclassinstances Color_Correction target:m).count>0 do 
    		(
    			if (appendIfUnique FindMat m)== true do append FindMatName m.name
    			)
    	)
    fn find_Cellular mat = 
    	(
    		for m in theAllMat() where (getclassinstances Cellular target:m).count>0 do 
    		(
    			if (appendIfUnique FindMat m)== true do append FindMatName m.name
    			)
    	)	
    	
    --Interface
    --------	
    
    dropDownList ddl1 "Select type map:" items:#("ColorCorrect", "Color Edge", "Checker", "Color_Correction", "Cellular") selection:1
    
    button bnFind "Analyze" width:300 
    
    listbox ListMat "Please use DoubleClick for getting mat:"  height:43
    		
    button bnGetMat "Get materials to MatEditor" width:150  across:2
    button bnSelObj "Select all objects " width:150 
    		
    		
    -------------------
    	on bnFind pressed do 
    	(	
    		FindMat = #()
    		FindMatName = #()
    		
    		if ListMat.items != 0 do ListMat.items = #()
    		
    		case ddl1.selection of 
    		(
    			1: find_ColorCorrect m 
    			2: find_Color_Edge m 
    			3: find_Checker m
    			4: find_Color_Correction m 
    			4: find_Cellular m
    		)
    	
    		if FindMat.count != 0 then ListMat.items = FindMatName
    	)
    --------------------	
    	on bnGetMat pressed do 
    	(	
    		try(
    			for i = 1 to FindMat.count do meditmaterials[medit.GetActiveMtlSlot() + i - 1]   = FindMat[i]
    			)catch()
    	)
    -------------------
    	on bnSelObj pressed do
    	(
    		local NeedObj = #()
    		for m in FindMat do join NeedObj (refs.dependentNodes m)
    		select NeedObj
    		)
    	
    	
    	on ListMat doubleClicked i do
    	(
    		for m in FindMat do
    			if m.name == (ListMat.items[i]) do meditmaterials[medit.GetActiveMtlSlot()]  = m
    		)
    
    )
    --createDialog MapsFinder
    MapsFinder_float = newRolloutFloater "MapsFinder" 350 730 
    addRollout MapsFinder MapsFinder_float
    )
    
     
  5. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Продолжаю тему. Не подскажете как лучше поменять, к примеру, параметр blur только в слоте Diffuse, с учетом того, что там могут быть смешанные карты произвольной глубины(вроде микс в миксе с colorcorrect и т.д)
    Как можно сюда прикрутить рекурсивную функцию, например:
    Код:
    fn recMatBlurDiffuse mat  blurVal=
    (
        if mat != undefined do
        (
            if iskindof mat texturemap do mat.coords.blur = blurVal
            if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i]  blurVal
            )
        )   
    for i in theAllMat() do recMatBlurDiffuse i  0.5    
    или такой вариант
    Код:
    for i in getclassinstances Bitmaptexture do try(i.coords.blur = 0.4)catch()
    Проблема в том, что данные способы меняют параметр blur везде где можно. Как можно их ограничить слотом diffuse или другими?
     
  6. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Пример для карты Diffuse материала Standard:
    Код:
    fn recMapBlurDiffuse mat blurVal=
    (
    if mat != undefined do
    (
    if iskindof mat Bitmaptexture do mat.coords.blur = blurVal
    if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMapBlurDiffuse mat[i] blurVal
    )
    )
    
    fn recMatBlurDiffuse mat blurVal=
    (
    if mat != undefined do
    (
    if findString (mat as string) "Diffuse_Color__Map"==9 do recMapBlurDiffuse mat blurVal
    if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal
    )
    )
    
    for i in scenematerials do recMatBlurDiffuse i  0.5
     
  7. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Спасибо igorznag за помощь, но немного не работает. Если строку
    Код:
    if findString (mat as string) "Diffuse_Color__Map"==9 do recMapBlurDiffuse mat blurVal
    немного поменять на
    Код:
    if findString (mat as string) "Diffuse_Color__Map"==9 do mat.coords.blur = blurVal
    тогда срабатывает, но на сложных миксовых картах уже не добирается до блюра. Помоги разобраться, пожалуйста.
     
  8. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Я не знаю как вам помочь. У меня все работает нормально.
     
  9. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Прилагаю скриншот ошибки. Помогите разобраться, пожалуйста.
     

    Вложения:

  10. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Почему вы скопировали только часть кода из сообщения 6?
    Нужно скопировать обе функции: recMatBlurDiffuse и recMapBlurDiffuse.
     
  11. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    :confused: Вот я слепой. Не заметил разницы между recMatBlurDiffuse и recMapBlurDiffuse ) Спасибо, все заработало! Еще небольшой вопрос. Не подскажете, можно ли как-то использовать подобный код?
    Код:
    for i in getclassinstances Bitmaptexture do try(i.coords.blur = 0.4)catch()
    В общем, что-бы максимально оптимизировать функцию.
     
  12. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Да, можно.
    Код:
    fn recMatBlurDiffuse mat blurVal=
    (
    if mat != undefined do
    (
    if findString (mat as string) "Diffuse_Color__Map"==9 do
    for i in getclassinstances Bitmaptexture target:mat do try(i.coords.blur = blurVal)catch()
    if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal
    )
    )
    
    for i in scenematerials do recMatBlurDiffuse i  0.5
     
    Александр Якушев нравится это.
  13. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
  14. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Опять застрял. Все отлично, только на короновских матах не работает. Не могу понять в чем причина.Стандартные и вирейские спокойно переваривает.
    Вот код:
    Код:
    -- tested in 3DMax 2014
    try destroyDialog editBlur catch()
    rollout editBlur "EditBlurMat"
    (
    --function
    fn theAllMat =
    (       
            local allMat = #()
            allMat = scenematerials
            for i in meditMaterials do appendIfUnique allMat i
            for i in objects do if i.material != undefined do appendIfUnique allMat i.material
            allMat
        )
    fn recMatBlurDiffuse mat blurVal nameMap =
    (
        if mat != undefined do
        (
        if (findString (mat as string) nameMap == 9 or findString (mat as string) nameMap == 16) do try(for i in getclassinstances Bitmaptexture target:mat do i.coords.blur = blurVal)catch()
        if mat.numsubs != 0 do for i = 1 to mat.numsubs do recMatBlurDiffuse mat[i] blurVal nameMap
        )
    )
    --Interface
    dropDownList ddl1 "" items:#("Diffuse", "Reflection", "Refraction", \
        "Bump", "Displacement", "Opacity") selection:1 across:3
    spinner theBlurVal "Blur:" range:[0,40, 1] type:#float
    button addToList  "Add to list"   
    listbox ListMap ""  height:4
    button theGo "Execute"
           
    -------------------
    global theListData = #()
    on execute editBlur do theListData = #()
    on addToList  pressed do
    (
        ListMap.items = append ListMap.items  (ddl1.selected + "  blur - " + (theBlurVal.value as string))
        append theListData    #(ddl1.selected, theBlurVal.value)
        )   
    on theGo pressed do
        for mat in theAllMat() do    for i in theListData do recMatBlurDiffuse mat i[2] i[1]
    )
    createDialog editBlur width:280
    
    Если убрать в строчке try(for i in getclassinstances Bitmaptexture target:mat do i.coords.blur = blurVal)catch() - try()catch(), то выдает такую ошибку -- No "map" function for undefined <<
    Даже если вместо recMatBlurDiffuse использовать вариант из сообщения 6, все равно на короновских не срабатывает.
    Текст "findString (mat as string) nameMap == 16", как раз для короновского материала - "SubAnim:usemap_diffuse". igorznag помоги плз.
     
  15. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Еще одна проблема. Как сделать материалы инстансными из копий в мультисабе?.

    В мультиматериале есть одинаковые неинстансные материалы. Написал код для поиска копий и замены их инстансами, но, почему-то, не работает:
    Код:
    fn compareMat m1 m2 =
    (
        try(if m1.diffuseMap.fileName == m2.diffuseMap.fileName then return 1 else return 0)catch(return 0)
        )
     
        theMatArray = getclassinstances Standardmaterial
        for i = 1 to theMatArray.count do
            for j = 1 to theMatArray.count do
                if i != j do if (compareMat theMatArray[i] theMatArray[j]) == 1 do theMatArray[i] = theMatArray[j]
    https://yadi.sk/i/hJDGsDmVZR8bR - скрин с примером мультимата
     
  16. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.256
    Симпатии:
    173
    Баллы:
    65
    Код:
    fn compareMat m1 m2 =
    (
        try(if m1.diffuseMap.fileName == m2.diffuseMap.fileName then return 1 else return 0)catch(return 0)
        )
     
        theMatArray = getclassinstances Standardmaterial
        for i = 1 to theMatArray.count do
            for j = 1 to theMatArray.count do
                if i != j do if (compareMat theMatArray[i] theMatArray[j]) == 1 do replaceInstances theMatArray[i] theMatArray[j]
     
    Александр Якушев нравится это.
  17. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    :D Спасибо igorznag, в очередной раз выручил!!!
     
  18. Александр Якушев

    Александр Якушев Активный участник

    С нами с:
    13.08.2009
    Сообщения:
    77
    Симпатии:
    1
    Баллы:
    7
    Немножко не по теме, но все же.
    Не подскажете, возможно ли выделить объекты в сцене не по материалу а по конкретной карте в материале?
    К примеру, у нас несколько материалов с разными Cellular. Надо выделить объеты по конкретному Cellular.
     
Модераторы: Savin Denis

Поделиться этой страницей