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

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

Тема в разделе "MAXScript", создана пользователем Александр Чернега, 6 ноя 2010.

Модераторы: Savin Denis
  1. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    Создал эту тему, что бы задавать в ней маленькие вопросы, которые по смыслу не подходят ни к одной из существующих тем.
    И ответ на которые – да, нет, либо пару строк кода.



    Ps: Если конечно администрация одобрит:)
     
  2. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    1) Господа, можно ли заблокировать орто виды (нижний левый, верхний левый правый) от поворота и превращения их в вид юзер.
    Стандартными средствами макса (допустим с помощью скрипта в старапе).

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

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

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

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

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    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) Нет специального обработчика нет.

    Замерь время между нажатиями, будет тебе функция:
    Scripted Mouse Tools
     
  4. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    Так смысла особого нет, слишком долго нужно ждать чтобы чтобы выбрать объект да и то промахнешься.

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

    Код:
    -- -- --------------------------------------------------------------------------
    -- -- 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
    Не знаю насколько пригодиться но можно прикрутить свой набор любимых кофейников или еще чего.

     
  5. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    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)
     
  6. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    1) Это точно, но кому нужно сам до ума доведет.
    2) Давай, глядишь и сам начнешь нас радовать кодом, а то идей у тебя много =)
    а украшательством пока еще не переболел. Это тоже хорошо.
    3) Да было дело, поправил но пока нету времени проверить его.

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

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Нужно нажать клавишу 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)
    Попробуй такой вариант.
    Нужно нажать клавишу 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)
     
  8. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Примечание.
    В каждом скрипте, посаженный на клавишу нужно использовать глобальные перемены с разным названием.
    Например:
    1. global pos_last_key_z, pos_can_create_key_z;
    2. global time_last_align_normal_align, time_can_create_align_normal_align;
     
  9. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Добрый вечер.
    Если в глобальной перемене хранится ссылка на слой и потом вручную удалить слой, то каким способом можно узнать был ли удален слой или нет?

    Пример:
    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" 
    )
    Но я не полностью уверен, если такой способ является правильный. Может нужно что-то изменить или вообще делать по-другому.
     
  10. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    igorznag, будет надежнее если сравнишь ее со всеми текущими интерфейсами
    В таком варианте у меня были глюки.
     
  11. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Savin Denis, большое спасибо за ответ.
     
  12. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    Добрый день.

    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, второй – не оставлять.
     
  13. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Такое нельзя сделать, потому что в макроскриптах невозможно использовать таймер (без использования окон-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;
    )
    )
    )
    )
     
  14. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    Igorznag большое спасибо, работает.
    Оба варианта прикрутил к скрипту с двойным нажатием клавиши.
     
  15. Bames Jond

    Bames Jond Активный участник

    С нами с:
    06.02.2010
    Сообщения:
    54
    Симпатии:
    0
    Баллы:
    5
    Здравствуйте. Была задача просчитать 80 текстов с надписями по 150 кадров каждый, по сути в тексте менялись только числа. Я решил осуществить эту задачу скриптом:
    Проблема в том что с каждым следующим текстом он пожирает все больше и больше ресурсов компьютера. Очень хотелось бы знать как этого можно избежать чтобы не наступать на те же грабли в будущем =) заранее очень признателен.
    К критике отношусь нормально, только если она адекватная, на счет того что скрипт не очень и составлен не грамотно я и сам знаю =)
     
  16. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Вместо (hide TText), напиши (delete TText), чтобы удалить временный объект "TText" и освободить память.
     
  17. Bames Jond

    Bames Jond Активный участник

    С нами с:
    06.02.2010
    Сообщения:
    54
    Симпатии:
    0
    Баллы:
    5
    Я больше склонялся к тому что как бы это все остается в оперативной памяти или файл подкачки не обновляется, потому что если просчитывать это все вручную все работает нормально, есть ли возможность что то добавить чтобы он выключал макс чтоли подргужал нужный файл и сам автоматом начал его просчитывать. Т.е. по большей части меня интересовало может ли скрипт работать на уровне системы, запускать приложения открывать файлы и все такое?
     
  18. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.254
    Симпатии:
    172
    Баллы:
    65
    Нет такой возможности. Maxscript работает только, если запущенна программа "макс".
    Может. Прочитай в хелпе главу Executing External Commands and Programs.
     
  19. Александр Чернега

    Александр Чернега Знаток

    С нами с:
    24.12.2009
    Сообщения:
    1.058
    Симпатии:
    56
    Баллы:
    53
    Добрый день.

    Подскажите пожалуйста ссылочку на статью «Как создания MZP архив» (или что то подобное)
     
  20. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    Посмотри в хелпе главу Zip-file Script Packages
    Еще вариант как сделать установочный пакет с помощью инсталлятора - |Script Installation In 3ds max
     
Модераторы: Savin Denis

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