Render.ru

Вопросы по Max Script (всего понемногу)

Рейтинг
47
#1
Создал эту тему, что бы задавать в ней маленькие вопросы, которые по смыслу не подходят ни к одной из существующих тем.
И ответ на которые – да, нет, либо пару строк кода.



Ps: Если конечно администрация одобрит:)
 
Рейтинг
47
#2
1) Господа, можно ли заблокировать орто виды (нижний левый, верхний левый правый) от поворота и превращения их в вид юзер.
Стандартными средствами макса (допустим с помощью скрипта в старапе).

2)В максе есть функция позволяющая при нажатии на скрипт находящийся в квадро меня (при зажатии алть, контрол или шифт) вызывать разные скрипты.
Есть ли что-то подобное для скриптов посаженных на клавишу.
Вызывать разные, по средствамудержания клавиши, а не быстрого щелчка.

Пример:
( case of
(
(keyboard.controlPressed): box ()
(keyboard.AltPressed): Sphere ()
(keyboard.shiftPressed): cylinder ()
default: Plane ()
)

Есть ли функция, чтоб по аналогии
быстро щелкнул - Плейн
1 сек держишь - Бокс
2 сек держишь - Сфера
3 сек держишь - Цилиндер

Либо
Быстро щелкнул -скрипт
держишь – квадро меню
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#3
1) Совсем нельзя, но отслеживать и поворачивать обратно можно
Код:
Global VP_TM_TMP = #()
unregisterRedrawViewsCallback  lockviews_cb_function
fn lockviews_cb_function = (
	local av = viewport.activeViewport
	if #{2,3}[av] do
	(		
	if not viewport.IsPerspView() do viewport.setType #view_persp_user
	local  v = viewport.getTM()	
	local vt = VP_TM_TMP[av]
	if  vt == undefined do vt = VP_TM_TMP[av] = v	
	vt.position = v.position
	viewport.setTM (vt)
	)
)
registerRedrawViewsCallback lockviews_cb_function
Только зачем такое извращение нужно ?

2) Нет специального обработчика нет.

Есть ли функция, чтоб по аналогии
быстро щелкнул - Плейн
1 сек держишь - Бокс
Замерь время между нажатиями, будет тебе функция:
Scripted Mouse Tools
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#4
Есть ли функция, чтоб по аналогии
быстро щелкнул - Плейн
1 сек держишь - Бокс
2 сек держишь - Сфера
3 сек держишь - Цилиндер
Так смысла особого нет, слишком долго нужно ждать чтобы чтобы выбрать объект да и то промахнешься.

Но ты меня натолкнул на мысль, получился вот такой гламурный селектор объектов:

Код:
-- -- --------------------------------------------------------------------------
-- -- Macro_ObjectScroller_v0.10.mcr
-- -- Version:		 0.10
-- -- Created: 	 Savin Denis (c) 2010, 
-- -- Tested using: Max 2011 
-- -- --------------------------------------------------------------------------
macroScript ObjectScroller
            category:"Objects Primitives" 
            internalCategory:"Objects Primitives" 
            tooltip:"Object Scroller" 
			ButtonText:"Object Scroller"
            icon:#("standard", 1)
(

tool ObjectScroller_mst
(
local fStart, gObj, curObj, curInd, vp1, ldiv, lmax
on start do 
( 
	fStart = true
	updateToolbarButtons()	
)
on mousePoint click do coordsys grid
undo on(
if click == 1 then -- create key, back & fill lights at mousedown
(
vp1 = viewPoint 
local c = (bezier_float())
c.value = 0.
gObj = #(
(box pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c)),
(sphere pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) recenter:on segs:32 radius:12.5),	
(Cylinder pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) radius:12.5),	
(Torus pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) smooth:2 radius1:8.5 radius2:4),
(Teapot pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) segs:8 radius:12.5),	
(Cone pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) radius1:12.5 heightsegs:1),	
(GeoSphere pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) smooth:off baseToPivot:on radius:12.5),	
(Tube pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c) radius1:12.5 radius2:8.5 height:25),		
(Pyramid pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c)),	
(Plane pos:gridPoint isHidden:on backFaceCull:on visibility:(copy c)) )	

curInd = gObj.count / 2
curObj = gObj[curInd]
curObj.isHidden = false
curObj.visibility.controller.value = 1
lmax = (getViewSize() / 5).x
ldiv = lmax * 2. / (gObj.count - 1)	
)

if click == 2 then 
(
	curObj.visibility.controller.value = 1
	curObj.isHidden = false	
	curObj.backFaceCull = false
	select curObj
	delObj = for obj in gObj where obj != curObj collect  obj
	delete delObj
	gObj = undefined
	#stop
)
)

on mouseMove click do
undo off (
if click == 2 then -- drag out & round on x-y plane
(
	local l = (viewPoint - vp1).x
	local d = ((lmax + l) / ldiv) 
	local d1 = cos (90.*(abs(mod d 1.) - 0.5)*2)
	local r = (abs(mod d (gObj.count)) + 1) as integer	
	if 	curInd != r	then 
	(
		curObj.visibility.controller.value = 0
		curObj.isHidden = true				
	)
	curInd = r
	curObj = gObj[curInd]
	curObj.isHidden = false	
	curObj.visibility.controller.value = d1
	curObj.scale = [1,1,1] * d1	
)
)
on mouseAbort click do 
( 
	undo off delete gObj
	gObj = undefined
)
on stop do fStart = undefined
)

on execute do startTool ObjectScroller_mst
on isChecked return (try(ObjectScroller_mst.fStart != undefined)catch(false))

)
Как устанавливать: (напоминалка для ленивых)
1. Запустить.
2.Дальше через UI Customize
3.В категории: "Objects Primitives"
4.Ищем: "Object Scroller"
5.Вешаем на кнопку или тулбар.

Как работает:
1) Жмем кнопку (что назначили)
2) В окне кликаем по любимому месту и не отпуская левой кнопки елозим мышкой в лево-право.

PS
Не знаю насколько пригодиться но можно прикрутить свой набор любимых кофейников или еще чего.

 
Рейтинг
47
#5
1) В предоставленном коде, блокируется верхнее правое окно (Front - перспектива) и нижнее левое (Left - перспектива).
Провозившись пару часов, понял что имелось в веду под словами:
Только зачем такое извращение нужно ?
Путаница с индексами окон. Что бы нормально срабатывало в #layout_4 и в #layout_1, нужно блокировать {2,3,4}, а окно перспективы переносить с правого нижнего в левое верхнее. Плюс заблокированные окна не отображаются Top, Front, left, поскольку в коде, нужно использовать #view_iso_user. А если блокировать одно окно {3} #view_left, его даже панорамировать невозможно.
В общем, ну его к черту, проще при случайном смещение ортографического окна в изометрическое, нажимать Shift Z (Undo View Change), и не заниматься ерундой!


2) Создание примитивов, было показано для примера. Я хотел применять эту функцию в других целях.
К примеру:
Щелчок – Shaps Toggle
1 сек держишь – Gird and Shap Settings
------------------------------------
Щелчок – Align
1 сек держишь – Normal Align
------------------------------------
Быстро щелкнул -скрипт
держишь – квадро меню
------------------------------------
Щелчок – Use Pivot Point Center
1 сек держишь – Use Selection Center
3 сек держишь – Use Transform coordinate Center
-----------------------------------
Хотя, при назначении кнопке белее 2-х действий, удобнее варьировать не «временем нажатия», а направлением движения мыши (как в скрипте "Object Scroller", приведенном выше. (Если можно использовать четыре направления движения мыши)).
Нашел в хелпе Scripted Mouse Tools. Буду разбираться.


3) Попробовал запустить "Object Scroller", не вышло. Проделывал в 2009 и 11 Design (Windows 7).
Создает чайник, и при попытке елозить мышкой, выдает одну и туже ошибку
-- No “+” function for undefined.
Подсвечивает в Макс скрипт Эдиторе 62-ю строчку:
61 local l = (viewPoint - vp1).x
62 local d = ((lmax + l) / ldiv)
63 local d1 = cos (90.*(abs(mod d 1.) - 0.5)*2)
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#6
1) Это точно, но кому нужно сам до ума доведет.
2) Давай, глядишь и сам начнешь нас радовать кодом, а то идей у тебя много =)
а украшательством пока еще не переболел. Это тоже хорошо.
3) Да было дело, поправил но пока нету времени проверить его.

PS Под 2009м должно идти тут ничего специфического нет.
 

igorznag

Мастер
Рейтинг
103
#7
Если можно использовать четыре направления движения мыши
Нужно нажать клавишу 1 раз, потом переместить курсор мыши в нужную сторону, потом нажать клавишу еще 1 раз. Если перемещать курсор вправо-создается бокс, влево - сфера, вверх - чайник, вниз - плейн. Если не перемещать курсор, создается торус.
Код:
global pos_last, pos_can_create;
pos_current=[mouse.screenpos.x,-mouse.screenpos.y,0] 
if(pos_last==undefined)then pos_last=pos_current
if(pos_can_create==undefined)then pos_can_create=false
pos_delta=pos_current-pos_last;
if(pos_can_create==true)then
(
if(length pos_delta>0)then
(
if(abs pos_delta.x>=abs pos_delta.y)then 
if(pos_delta.x>0)then box(); --right script1
else sphere();--left script2
if(abs pos_delta.x < abs pos_delta.y)then 
if(pos_delta.y>0)then teapot(); --up script3
else plane();--down script4
)
else torus();--default script5

pos_can_create=false
)
else (pos_last=pos_current; pos_can_create=true)
Есть ли функция, чтоб по аналогии
быстро щелкнул - Плейн
1 сек держишь - Бокс
Попробуй такой вариант.
Нужно нажать клавишу 2 раза, чтобы запустить нужный скрипт:
1. Быстро (интервал около половины секунды) нажать 2 раза - создается бокс
2. Медленно (интервал около 1 секунды) нажать 2 раза - создается сфера
Если нужно, можно создать более двух интервалов.

Код:
global time_last,time_can_create;
time_current=timeStamp(); 
if(time_last==undefined)then time_last=time_current
if(time_can_create==undefined)then time_can_create=false
time_delta=time_current-time_last
if(time_can_create==true)then
(
if(time_delta>0 and time_delta<=1500)then
(
if(time_delta>0 and time_delta<=500)then box();--0sec 0.5sec script1
if(time_delta>500 and time_delta<=1500)then sphere();--0.5sec 1.5sec script2
)
time_can_create=false
)
else (time_last=time_current;time_can_create=true)
 

igorznag

Мастер
Рейтинг
103
#8
Примечание.
В каждом скрипте, посаженный на клавишу нужно использовать глобальные перемены с разным названием.
Например:
1. global pos_last_key_z, pos_can_create_key_z;
2. global time_last_align_normal_align, time_can_create_align_normal_align;
 

igorznag

Мастер
Рейтинг
103
#9
Добрый вечер.
Если в глобальной перемене хранится ссылка на слой и потом вручную удалить слой, то каким способом можно узнать был ли удален слой или нет?

Пример:
1. В первом скрипте сохраняю в глобальной перемене ссылку на слой.
Код:
global mylayer;mylayer=LayerManager.newLayerFromName "my new layer";
2. Удаляю вручную слой "my new layer".
3. Во втором скрипте делаю проверку таким способом.
Код:
global mylayer;
if(mylayer!=undefined)then
(
layer_dependents=refs.dependents mylayer.layerAsRefTarg
if(layer_dependents.count==0)then print "layer was deleted" else print "layer exists" 
)
Но я не полностью уверен, если такой способ является правильный. Может нужно что-то изменить или вообще делать по-другому.
 

Savin Denis

Модератор форума
Команда форума
Рейтинг
138
#10
igorznag, будет надежнее если сравнишь ее со всеми текущими интерфейсами
В таком варианте у меня были глюки.
 
Рейтинг
47
#12
Добрый день.

Savin Denis
Заработал у мене твой скрипт, после переустановки виндовса. Древние греки считали, что истинно прекрасная вещь, должна быть неутилитарной. То есть дорогой, красивой, и совершенно бесполезной:) Твой скрипт очень эффектный, интерактивный, но чесно говоря, на мой взгляд, мало применимый. Хотя…на любителя.

Igorznag
1) Получив скрипт использование четырех направлений движения мыши, я понял, что не так то он удобен, как изначально казалось. Два нажима кнопки, а между ними щелчок мышью, практически полная аналогия стандартного алгоритма. Нажимаешь клавишу (вылетает квадроменю), двигаешь мышь (наводишь стрелку), щелкаешь мышью.
2) А вот это уже более применимо. Хотя конечно специфика двойного нажатия, сильно ограничивает скрипт. Нельзя к примеру использовать клавиши на которых настроены часто вызываемые инструменты (мув, ротейт, вкел, переключение подобъектов, так как их двойное нажатие будет только замедлять), а вот не сильно ходовые клавиши использовать можно.

Я немного покопался в скрипте. Обнаружил, что в последних строчках можно организовать так, что при очень медленном нажатии и непопадании ни в один отрезок времени, создается, допустим плэйн. Правда при попадании в time_delta , создается и бокс или сфера и плэйн

Можно ли сделать так, что если после первого нажатия, условие не соблюдено if(time_delta>0 and time_delta<=200), и в течении 0,2 сек скрипт не получает второго щелчка, он выполняет действие вписанное в else?
Получится что инструмент мув, будет включаться не сразу, а с 0,2 секундным опоздание. При очень быстром двойном нажатии, вмещающемся в 0,2 сек., вылетать квадроменю.


И вопрос по Edit_Poly Detach
Очень часто отделяя от модели полигоны, в последствии, именно с ними нужно работать. Но макс, после отделения выделенного фрагмента, остается в режиме редактирования объект, от которого отделили.

При выполнении команды детачь, макс скрипт лисинер записывает:
$.EditablePoly.detachToElement #Face keepOriginal:eek:ff
Эта функция срабатывает так, как будто включен флажек detach_To_Element

Вопрос:
Как нужно написать, что бы выделенный кусок становился отдельным объектом, И именно в этом отделенном объекте происходило редактирование полигонов.


Код
Код:
if (selection.count == 1 and classof $ == Editable_Poly and subobjectLevel == 4) do
(
Base_Obj = $
Detach_Obj = (отделение фрагмента в новый объект keepOriginal: off(on))
Detach_Obj.name = Base_Obj.name + "_Det"
subobjectLevel = 0
deselect selection
select Detach_Obj
subobjectLevel = 4
)
Кода будет два. Первый – оставлять копию отделенных элементов на Base_Obj, второй – не оставлять.
 

igorznag

Мастер
Рейтинг
103
#13
Можно ли сделать так, что если после первого нажатия, условие не соблюдено if(time_delta>0 and time_delta<=200), и в течении 0,2 сек скрипт не получает второго щелчка, он выполняет действие вписанное в else?
Такое нельзя сделать, потому что в макроскриптах невозможно использовать таймер (без использования окон-rollout).

Как нужно написать, что бы выделенный кусок становился отдельным объектом, И именно в этом отделенном объекте происходило редактирование полигонов.
Код:
if (selection.count == 1)then if(classof selection[1] == Editable_Poly)then
if(subobjectLevel == 4 or subobjectLevel == 5) then
(
objs_handle_array_old=#{};for obj in objects do  append objs_handle_array_old obj.inode.handle;

faces_sel=polyOp.getFaceSelection selection[1];
detach_result=polyOp.detachFaces selection[1] faces_sel delete:true asNode:true name:(selection[1].name+"_Det"); --keepOriginal off
--detach_result=polyOp.detachFaces selection[1] faces_sel delete:false asNode:true name:(selection[1].name+"_Det"); --keepOriginal on
if(detach_result==true)then
(
new_obj_handle=0;
objs_handle_array_new=#{};for obj in objects do  append objs_handle_array_new obj.inode.handle;
objs_handle_array_delta=objs_handle_array_new-objs_handle_array_old
if(objs_handle_array_delta.numberSet==1)then 
(objs_handle_array_delta=objs_handle_array_delta as array; new_obj_handle=objs_handle_array_delta[1])
if(new_obj_handle!=0)then
(
new_obj=undefined; for obj in objects do if(obj.inode.handle==new_obj_handle)then (new_obj=obj;exit)
if (new_obj!=undefined)then
(
select new_obj;
subobjectLevel = 4;
)
)
)
)
 

Bames Jond

Активный участник
Рейтинг
5
#15
Здравствуйте. Была задача просчитать 80 текстов с надписями по 150 кадров каждый, по сути в тексте менялись только числа. Я решил осуществить эту задачу скриптом:
for i = 1 to 80 do
(
Temp01 = "TVM 0"
Temp02 = "0"
Cicle = i as string
if i<10 then
(
Temp01=Temp01+Temp02
InText=Temp01+Cicle
)
Else
(
InText=Temp01+Cicle
)
TText = text size:100 kerning:0 leading:0 pos:[0,0,0] font:"Impact" Text:InText isSelected:eek:n
rotate TText (angleaxis 90 [1,0,0])
scale TText [0.0398553,0.0398553,0.0398553]
TText.pos = [0.251, -10.848, -2.116]
addmodifier TText (bevel ())
scale TText [1,5.19993,1]
macros.run "Modifier Stack" "Convert_to_Poly"
TText.material = meditMaterials[3]
rotate TText (angleaxis -10 [0,0,1])
set animate on
sliderTime = 150f
rotate TText (angleaxis 10 [0,0,1])
RLA_=".rla"
Folder = substring InText 5 4
FileName = Folder + "_Sms" + RLA_
PathToSave = "C:\Users\qwerty\Desktop\Sms\\" + Folder + "\\" + FileName
set animate off
render camera:$Camera001 outputFile:pathToSave fromframe:0f toframe:150f vba:eek:n
m = "_Sms.max"
Path01 = "C:\Users\qwerty\Desktop\Sms\\"
EndPath = Path01+InText+m
saveMaxFile EndPath
hide TText
)
Проблема в том что с каждым следующим текстом он пожирает все больше и больше ресурсов компьютера. Очень хотелось бы знать как этого можно избежать чтобы не наступать на те же грабли в будущем =) заранее очень признателен.
К критике отношусь нормально, только если она адекватная, на счет того что скрипт не очень и составлен не грамотно я и сам знаю =)
 

igorznag

Мастер
Рейтинг
103
#16
Проблема в том что с каждым следующим текстом он пожирает все больше и больше ресурсов компьютера.
Вместо (hide TText), напиши (delete TText), чтобы удалить временный объект "TText" и освободить память.
 

Bames Jond

Активный участник
Рейтинг
5
#17
Я больше склонялся к тому что как бы это все остается в оперативной памяти или файл подкачки не обновляется, потому что если просчитывать это все вручную все работает нормально, есть ли возможность что то добавить чтобы он выключал макс чтоли подргужал нужный файл и сам автоматом начал его просчитывать. Т.е. по большей части меня интересовало может ли скрипт работать на уровне системы, запускать приложения открывать файлы и все такое?
 

igorznag

Мастер
Рейтинг
103
#18
...чтобы он выключал макс чтоли подргужал нужный файл и сам автоматом начал его просчитывать.
Нет такой возможности. Maxscript работает только, если запущенна программа "макс".
...запускать приложения открывать файлы и все такое?
Может. Прочитай в хелпе главу Executing External Commands and Programs.
 
Сверху