_______________________________________________________________
Разберём на примере кнопки Align to Edge редактора Unwrap_UVW
1) Запустим скрипт MaxTroYx_PropertyInspector01.ms (можно скачать в документах группы)
нажмём квадратик и не отпуская перетащим его на нужную кнопку и отпустить.
Получаем уникальный идентификатор кнопки - дескриптор, но дело в том что это число постоянно меняется при каждом другом открытии окна, поэтому на прямую этот дескриптор использовать в скрипте не имеет смысла.
КОПИРУЕМ его пока куда нибудь.
Дескриптор в виде числа нужен нам для того чтобы формализовать его местоположение для сценария.
2) Для этого делаем следующее:
Если окно с нужной кнопкой плавающее 3dsMax (тоесть не влеплено среди панелей), то тогда берём детей вот этой функции windows.getDesktopHWND()
А если кнопка находится в свитках, встроенных в интерфейс самого 3dsMax, то поиск будет происходить среди windows.getChildrenHWND #max
DesktopChild=(windows.getChildrenHWND #max)
clearlistener(); for i in DesktopChild do format "%\n" i
Диалог редактора Unwrap_UVW плавающий, потэтому выведем всех детей от вот этой хреновины windows.getDesktopHWND()
|
|
Жмём F11, вызываем листенер.
Выполняем:
DesktopChild=(windows.getChildrenHWND (windows.getDesktopHWND()))
clearlistener(); for i in DesktopChild do format "%\n" i
В листенере выскочит огромный список. Кликнем по листнеру и давим Ctrl+F, вставляем в поиск наш дескриптор.
Если поискать несколько раз, то может быть найден не один искомый результат. Нужен тот, где пятым элементом стоит "CustButton", но не что то другое.
Теперь смотрим, ориентиры, рядом с чем находится наш дескриптор, видно есть слова "Quick Transform", очевидно это название свитка в диалоговом окне,
чтобы удостовериться, глянем на диалог редактора Unwrap_UVW, - да так и есть, это название свитка.
Всё, теперь осталось написать
UIAccessor.PressButton (for i=1 to DesktopChild.count where DesktopChild[i][4]=="RollupPanelTitle" and DesktopChild[i][5]=="Quick Transform" do exit with DesktopChild[(i+8)][1])
Расшифровка:
UIAccessor.PressButton - нажать кнопку по следующему дескриптору ()
for i=1 to DesktopChild.count where DesktopChild[i][4]=="RollupPanelTitle" and DesktopChild[i][5]=="Quick Transform" do
Для каждого элемента i, начиная с первого до количества элементов DesktopChild, где четвёртый элемент в каком то элементе будет "RollupPanelTitle", а пятый будет "Quick Transform", тогда делать...
exit with
Здесь стало быть при нахождении искомого нужно сделать выход из цикла, чтобы остановить процесс и выйти с результатом
DesktopChild[(i+8)][1]
Здесь вот что:
Нам нужен ведь дескриптор не свитка с названием "Quick Transform", а дескриптор кнопки, принадлежащей этому свитку, а кнопка эта находится на восемь позиций ниже в списке. Собственно это и показано справа на последнем изображении.
|
|
Поэтому выставляется не DesktopChild[i][1], а вот так DesktopChild[(i+8)][1]
Готовый код:
(
DesktopChild=(windows.getChildrenHWND (windows.getDesktopHWND()))
--clearlistener(); for i in DesktopChild do format "%\n" i
UIAccessor.PressButton (for i=1 to DesktopChild.count where DesktopChild[i][4]=="RollupPanelTitle" and DesktopChild[i][5]=="Quick Transform" do exit with DesktopChild[(i+8)][1])
)
---------------------------------------------------------------------------------------------------------------
BM_GETCHECKED = 0x00F0
BM_SETCHECKED = 0x00F1
BM_UNCHECKED = 0x0000
BM_CHECKED = 0x0001
BM_GETSTATE = 0xF2
BM_CLICK = 0xF5
BM_SETCHECK = 0xF1
BST_CHECKED = 0x1
WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202
VK_RETURN = 0x000D
WM_SETFOCUS = 0x007
WM_CHAR = 0x0102
for c in windows.getChildrenHWND #max where c[4] == "Button" and c[5] == "Union" do UIAccessor.SendMessage c[1] 0x007 0 0
or c in windows.getChildrenHWND #max where c[4] == "Button" and c[5] == "Union" do UIAccessor.PressButton c[1]
_______________________________________________________________
Перехват окна на примере STL Import и виртуальное нажатие в нём элементов UI
Аналогичным образом что и в предыдущем примере, через дескрипторы здесь при появлении диалога STL Import отключаются ненужные чекбоксы и жмётся “OK”
Добавлен коллбэк отслеживания появления окна.
-- определение дескриптора диалогового окна "Import STL File" и его потомков (элементов UI)
(
BM_GETCHECKED = 0x00F0 -- команда проверки нажат ли чекбокс
WM_SETFOCUS = 0x007 -- команда перевода фокуса на элемент UI
BM_CLICK = 0xF5 -- Клик
fn mf = (
-- Eсли название окна есть "Import STL File" тогда
if (UIAccessor.GetWindowText (DialogMonitorOPS.getWindowHandle())=="Import STL File") then(
DesktopChild=(windows.getChildrenHWND (windows.getDesktopHWND())) -- находим потомков (элементы) этого окна
--clearlistener(); for i in DesktopChild do format "%\n" i
--hwndSTLimport_EditTXT=(for i=1 to DesktopChild.count where DesktopChild[i][5]=="Import STL File" do exit with DesktopChild[(i+2)][1])
QuickWeld_hwnd=(for i=1 to DesktopChild.count where DesktopChild[i][5]=="Import STL File" do exit with DesktopChild[i+11][1])
UIAccessor.SendMessage QuickWeld_hwnd WM_SETFOCUS 0 0
UIAccessor.SendMessage QuickWeld_hwnd BM_CLICK 0 0
AutoSmooth_hwnd=(for i=1 to DesktopChild.count where DesktopChild[i][5]=="Import STL File" do exit with DesktopChild[i+18][1])
if (windows.sendMessage AutoSmooth_hwnd BM_GETCHECKED 0 0) do
(UIAccessor.SendMessage AutoSmooth_hwnd WM_SETFOCUS 0 0
UIAccessor.SendMessage AutoSmooth_hwnd BM_CLICK 0 0)
RemoveDoubleFaces_hwnd=(for i=1 to DesktopChild.count where DesktopChild[i][5]=="Import STL File" do exit with DesktopChild[i+20][1])
if (windows.sendMessage RemoveDoubleFaces_hwnd BM_GETCHECKED 0 0) do
(UIAccessor.SendMessage RemoveDoubleFaces_hwnd WM_SETFOCUS 0 0
UIAccessor.SendMessage RemoveDoubleFaces_hwnd BM_CLICK 0 0)
UnifyNormals_hwnd=(for i=1 to DesktopChild.count where DesktopChild[i][5]=="Import STL File" do exit with DesktopChild[i+21][1])
if (windows.sendMessage UnifyNormals_hwnd BM_GETCHECKED 0 0) do
(UIAccessor.SendMessage UnifyNormals_hwnd WM_SETFOCUS 0 0
UIAccessor.SendMessage UnifyNormals_hwnd BM_CLICK 0 0)
WindowHandle = DialogMonitorOPS.GetWindowHandle()
UIAccessor.PressButtonByName WindowHandle "OK"
)
)
return true
)
--включение отслеживания окна
DialogMonitorOPS.unRegisterNotification id:#Call_STL_Dialog
DialogMonitorOPS.RegisterNotification mf id:#Call_STL_Dialog -- вызов функции mf
DialogMonitorOPS.Enabled = true
actionMan.executeAction 0 "40010" -- File: Import File
--отключение отслеживания окна
DialogMonitorOPS.unRegisterNotification id:#Call_STL_Dialog
DialogMonitorOPS.Enabled = false
)
_______________________________________________________________
Функции-“синонимы”
(параграф будет дополняться)
scriptspath -- зарезервированное слово пути к папке Scripts
scriptspath_var = GetDir #scripts -- получение пути через enum
-- Массив выделенных объектов
getCurrentSelection()
selection as array
-- Проверка класса объекта Shape
isShapeObject $
superClassOf $
isKindOf $ Shape -- потомок суперкласса (в данном случае суперкласса Shape)
--класс текущего объекта панели modify
modPanel.getCurrentObject()
Filters.GetModOrObj()
-- количество вертексов в выделенном объекте класса geometry
numPoints $
(selection[1].mesh).numverts
(getvertselection selection[1].mesh).count
getNumVerts selection[1].mesh
--Выделить вершины Editable_Poly объекта
fco=modPanel.getCurrentObject() -- объект стека модификаторов
setVertSelection selection[1] fco #{} keep:off -- (Edit_Poly)
setVertSelection selection[1] fco #{1..5} keep:on -- (Edit_Poly)
polyop.setVertSelection $ #{1..5}
$.SetSelection #Vertex #{5..10}
$.selectedVerts =#{10..15}
--переключиться в панель modify
setCommandPanelTaskMode #modify
max modify mode
_______________________________________________________________
|
|