From 9cd6d13ca37b3c3eed1b9900f6e059a4e7f5d0f7 Mon Sep 17 00:00:00 2001 From: henrique Date: Wed, 25 Feb 2026 22:25:49 -0300 Subject: [PATCH] plugin nao funciona. deixando apenas codigo. --- __pycache__/vr4life_cloud.cpython-311.pyc | Bin 0 -> 10514 bytes __pycache__/vr4life_engine.cpython-311.pyc | Bin 0 -> 35818 bytes __pycache__/vr4life_ui.cpython-311.pyc | Bin 0 -> 29971 bytes instalador/VR4Life Plugin - 3D Max.exe | Bin 8192 -> 0 bytes instalador/VR4Life Plugin - 3D Max.exe.config | 6 - instalador/VR4Life Plugin - 3D Max.pdb | Bin 22016 -> 0 bytes .../VR4Life Plugin - 3D Max.exe | Bin 8192 -> 0 bytes .../VR4Life Plugin - 3D Max.exe.config | 6 - .../VR4Life Plugin - 3D Max.pdb | Bin 22016 -> 0 bytes instalador/VR4Life_Plugin/run_vr4life.py | 15 - instalador/VR4Life_Plugin/vr4life_updater.py | 92 - instalador/install.ms | 28 - instalador/mzp.run | 8 - instalador/old/Instalador_Online_VR4Life.py | 88 - instalador/old/run_installer.ms | 1 - instalador/old/vr4life_startup.ms | 50 - instalador/vr4life-plugin-install.mzp | Bin 4122 -> 0 bytes instalador/vr4life.mnx | 12 - instalador/vr4life.ms | 42 - .../17.14.1593.33849/CodeChunks.db | Bin 69632 -> 0 bytes .../17.14.1593.33849/CodeChunks.db-shm | Bin 32768 -> 0 bytes .../17.14.1593.33849/CodeChunks.db-wal | Bin 824032 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db | Bin 49152 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db-shm | Bin 32768 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db-wal | Bin 572712 -> 0 bytes ...16a0fc13-034b-44a7-8fb8-e088c864a783.vsidx | Bin 6075 -> 0 bytes ...73ed949b-84be-45c9-a9ca-79230739efcd.vsidx | Bin 6371 -> 0 bytes .../VR4Life-dll/.vs/VR4Life-dll/v17/.suo | Bin 70144 -> 0 bytes .../v17/DocumentLayout.backup.json | 41 - .../.vs/VR4Life-dll/v17/DocumentLayout.json | 41 - .../VR4Life-dll/Properties/AssemblyInfo.cs | 33 - .../VR4Life-dll/VR4Life-dll.csproj | 57 - instaladorCsharp/VR4Life-dll/VR4Life-dll.sln | 25 - .../VR4Life-dll/VR4LifeConnector.cs | 36 - .../VR4Life-dll/bin/Debug/Autodesk.Max.dll | Bin 2543904 -> 0 bytes .../VR4Life-dll/bin/Debug/Autodesk.Max.xml | 163018 --------------- .../VR4Life-dll/bin/Debug/CSharpUtilities.dll | Bin 88856 -> 0 bytes .../VR4Life-dll/bin/Debug/CSharpUtilities.xml | 4079 - .../bin/Debug/CoreManagedUiControls.dll | Bin 329496 -> 0 bytes .../bin/Debug/CoreManagedUiControls.xml | 845 - .../VR4Life-dll/bin/Debug/ManagedServices.dll | Bin 347936 -> 0 bytes .../VR4Life-dll/bin/Debug/MaxPlusDotNet.dll | Bin 1714456 -> 0 bytes .../Debug/Microsoft.CodeAnalysis.CSharp.dll | Bin 6555408 -> 0 bytes .../bin/Debug/Microsoft.CodeAnalysis.dll | Bin 2988856 -> 0 bytes .../VR4Life-dll/bin/Debug/UiViewModels.dll | Bin 59680 -> 0 bytes .../VR4Life-dll/bin/Debug/UiViewModels.xml | 2438 - .../VR4Life-dll/bin/Debug/VR4Life-dll.dll | Bin 6144 -> 0 bytes .../VR4Life-dll/bin/Debug/VR4Life-dll.pdb | Bin 19968 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 433968 -> 0 bytes .../cs/Microsoft.CodeAnalysis.resources.dll | Bin 47888 -> 0 bytes .../de-DE/CoreManagedUiControls.resources.dll | Bin 260376 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 464696 -> 0 bytes .../de/Microsoft.CodeAnalysis.resources.dll | Bin 49960 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 453936 -> 0 bytes .../es/Microsoft.CodeAnalysis.resources.dll | Bin 49416 -> 0 bytes .../fr-FR/CoreManagedUiControls.resources.dll | Bin 261408 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 466184 -> 0 bytes .../fr/Microsoft.CodeAnalysis.resources.dll | Bin 49976 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 460600 -> 0 bytes .../it/Microsoft.CodeAnalysis.resources.dll | Bin 49936 -> 0 bytes .../ja-JP/CoreManagedUiControls.resources.dll | Bin 261912 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 508176 -> 0 bytes .../ja/Microsoft.CodeAnalysis.resources.dll | Bin 53544 -> 0 bytes .../ko-KR/CoreManagedUiControls.resources.dll | Bin 260896 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 465672 -> 0 bytes .../ko/Microsoft.CodeAnalysis.resources.dll | Bin 49960 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 466704 -> 0 bytes .../pl/Microsoft.CodeAnalysis.resources.dll | Bin 49960 -> 0 bytes .../pt-BR/CoreManagedUiControls.resources.dll | Bin 260384 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 446264 -> 0 bytes .../Microsoft.CodeAnalysis.resources.dll | Bin 48904 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 613648 -> 0 bytes .../ru/Microsoft.CodeAnalysis.resources.dll | Bin 60200 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 442152 -> 0 bytes .../tr/Microsoft.CodeAnalysis.resources.dll | Bin 48432 -> 0 bytes .../zh-CN/CoreManagedUiControls.resources.dll | Bin 260376 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 393016 -> 0 bytes .../Microsoft.CodeAnalysis.resources.dll | Bin 44848 -> 0 bytes ...icrosoft.CodeAnalysis.CSharp.resources.dll | Bin 392976 -> 0 bytes .../Microsoft.CodeAnalysis.resources.dll | Bin 44856 -> 0 bytes ...amework,Version=v4.8.AssemblyAttributes.cs | 4 - ...gnTimeResolveAssemblyReferencesInput.cache | Bin 14619 -> 0 bytes .../obj/Debug/VR4Life-.FA5A00BF.Up2Date | 0 ...VR4Life-dll.csproj.AssemblyReference.cache | Bin 98068 -> 0 bytes ...VR4Life-dll.csproj.CoreCompileInputs.cache | 1 - .../VR4Life-dll.csproj.FileListAbsolute.txt | 51 - .../VR4Life-dll/obj/Debug/VR4Life-dll.dll | Bin 6144 -> 0 bytes .../VR4Life-dll/obj/Debug/VR4Life-dll.pdb | Bin 19968 -> 0 bytes .../17.14.1593.33849/CodeChunks.db | Bin 69632 -> 0 bytes .../17.14.1593.33849/CodeChunks.db-shm | Bin 32768 -> 0 bytes .../17.14.1593.33849/CodeChunks.db-wal | Bin 601552 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db | Bin 49152 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db-shm | Bin 32768 -> 0 bytes .../17.14.1593.33849/SemanticSymbols.db-wal | Bin 403792 -> 0 bytes ...05916e46-a4c0-4e48-bac5-e7c854c6bdd5.vsidx | Bin 18610 -> 0 bytes .../.vs/VR4Life-installer/v17/.suo | Bin 52736 -> 0 bytes .../v17/DocumentLayout.backup.json | 41 - .../VR4Life-installer/v17/DocumentLayout.json | 41 - instaladorCsharp/VR4Life-installer/App.config | 6 - instaladorCsharp/VR4Life-installer/Program.cs | 74 - .../Properties/AssemblyInfo.cs | 33 - .../VR4Life-installer.csproj | 53 - .../VR4Life-installer/VR4Life-installer.sln | 25 - .../bin/Debug/VR4Life-dll.dll | Bin 6144 -> 0 bytes .../bin/Debug/VR4Life-installer.exe | Bin 8192 -> 0 bytes .../bin/Debug/VR4Life-installer.exe.config | 6 - .../bin/Debug/VR4Life-installer.pdb | Bin 22016 -> 0 bytes .../bin/Debug/run_vr4life.py | 30 - .../VR4Life-installer/bin/Debug/version.txt | 1 - .../bin/Debug/vr4life_updater.py | 92 - ...amework,Version=v4.8.AssemblyAttributes.cs | 4 - ...gnTimeResolveAssemblyReferencesInput.cache | Bin 1808 -> 0 bytes ...e-installer.csproj.AssemblyReference.cache | Bin 4061 -> 0 bytes ...e-installer.csproj.CoreCompileInputs.cache | 1 - ...Life-installer.csproj.FileListAbsolute.txt | 8 - .../obj/Debug/VR4Life-installer.exe | Bin 8192 -> 0 bytes .../obj/Debug/VR4Life-installer.exe.config | 6 - .../obj/Debug/VR4Life-installer.pdb | Bin 22016 -> 0 bytes instaladorv2/vr4life_startup.ms | 50 - run_vr4life.zip | Bin 9110317 -> 0 bytes vr4life_engine.py | 189 +- 121 files changed, 155 insertions(+), 171522 deletions(-) create mode 100644 __pycache__/vr4life_cloud.cpython-311.pyc create mode 100644 __pycache__/vr4life_engine.cpython-311.pyc create mode 100644 __pycache__/vr4life_ui.cpython-311.pyc delete mode 100644 instalador/VR4Life Plugin - 3D Max.exe delete mode 100644 instalador/VR4Life Plugin - 3D Max.exe.config delete mode 100644 instalador/VR4Life Plugin - 3D Max.pdb delete mode 100644 instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.exe delete mode 100644 instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.exe.config delete mode 100644 instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.pdb delete mode 100644 instalador/VR4Life_Plugin/run_vr4life.py delete mode 100644 instalador/VR4Life_Plugin/vr4life_updater.py delete mode 100644 instalador/install.ms delete mode 100644 instalador/mzp.run delete mode 100644 instalador/old/Instalador_Online_VR4Life.py delete mode 100644 instalador/old/run_installer.ms delete mode 100644 instalador/old/vr4life_startup.ms delete mode 100644 instalador/vr4life-plugin-install.mzp delete mode 100644 instalador/vr4life.mnx delete mode 100644 instalador/vr4life.ms delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-shm delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-wal delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-shm delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-wal delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/16a0fc13-034b-44a7-8fb8-e088c864a783.vsidx delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/73ed949b-84be-45c9-a9ca-79230739efcd.vsidx delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/.suo delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.backup.json delete mode 100644 instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.json delete mode 100644 instaladorCsharp/VR4Life-dll/Properties/AssemblyInfo.cs delete mode 100644 instaladorCsharp/VR4Life-dll/VR4Life-dll.csproj delete mode 100644 instaladorCsharp/VR4Life-dll/VR4Life-dll.sln delete mode 100644 instaladorCsharp/VR4Life-dll/VR4LifeConnector.cs delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.xml delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.xml delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.xml delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ManagedServices.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/MaxPlusDotNet.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/Microsoft.CodeAnalysis.CSharp.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/Microsoft.CodeAnalysis.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/UiViewModels.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/UiViewModels.xml delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/VR4Life-dll.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/VR4Life-dll.pdb delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/cs/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/cs/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/de-DE/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/de/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/de/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/es/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/es/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/fr-FR/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/fr/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/fr/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/it/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/it/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ja-JP/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ja/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ja/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ko-KR/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ko/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ko/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/pl/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/pl/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/pt-BR/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/pt-BR/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ru/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/ru/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/tr/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/tr/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/zh-CN/CoreManagedUiControls.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/zh-Hans/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/bin/Debug/zh-Hant/Microsoft.CodeAnalysis.resources.dll delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-.FA5A00BF.Up2Date delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-dll.csproj.AssemblyReference.cache delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-dll.csproj.CoreCompileInputs.cache delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-dll.csproj.FileListAbsolute.txt delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-dll.dll delete mode 100644 instaladorCsharp/VR4Life-dll/obj/Debug/VR4Life-dll.pdb delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/CodeChunks.db delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/CodeChunks.db-shm delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/CodeChunks.db-wal delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/SemanticSymbols.db delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-shm delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-wal delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/FileContentIndex/05916e46-a4c0-4e48-bac5-e7c854c6bdd5.vsidx delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/v17/.suo delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/v17/DocumentLayout.backup.json delete mode 100644 instaladorCsharp/VR4Life-installer/.vs/VR4Life-installer/v17/DocumentLayout.json delete mode 100644 instaladorCsharp/VR4Life-installer/App.config delete mode 100644 instaladorCsharp/VR4Life-installer/Program.cs delete mode 100644 instaladorCsharp/VR4Life-installer/Properties/AssemblyInfo.cs delete mode 100644 instaladorCsharp/VR4Life-installer/VR4Life-installer.csproj delete mode 100644 instaladorCsharp/VR4Life-installer/VR4Life-installer.sln delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/VR4Life-dll.dll delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/VR4Life-installer.exe delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/VR4Life-installer.exe.config delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/VR4Life-installer.pdb delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/run_vr4life.py delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/version.txt delete mode 100644 instaladorCsharp/VR4Life-installer/bin/Debug/vr4life_updater.py delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.csproj.AssemblyReference.cache delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.csproj.CoreCompileInputs.cache delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.csproj.FileListAbsolute.txt delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.exe delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.exe.config delete mode 100644 instaladorCsharp/VR4Life-installer/obj/Debug/VR4Life-installer.pdb delete mode 100644 instaladorv2/vr4life_startup.ms delete mode 100644 run_vr4life.zip diff --git a/__pycache__/vr4life_cloud.cpython-311.pyc b/__pycache__/vr4life_cloud.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9dfc639047134076a7654586ef5526e3a4a9e86 GIT binary patch literal 10514 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 literal 0 HcmV?d00001 diff --git a/__pycache__/vr4life_engine.cpython-311.pyc b/__pycache__/vr4life_engine.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a414ec31466651f504107c97e5f6ea44907d5ed1 GIT binary patch literal 35818 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 Jeu7s@|6ivq=s^Gg literal 0 HcmV?d00001 diff --git a/__pycache__/vr4life_ui.cpython-311.pyc b/__pycache__/vr4life_ui.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f234b607b55b2c4b1ce7bdcb82fb54aa86eef240 GIT binary patch literal 29971 zcmdsgYit`?b|zUArIPiuEcqe3+jQG*OSUBI>4)sL^`M^C`)R3V(yRI!RIigZie9bmDgQk`4(o^$TG=bn4+t;>6>eppnr%YXoBzsADd04pWt6T%%-&TqV#kw z=NqQkQpVI{;;i2=ak;#8X}3oGu?4*FuO72yoO#?-o%b2t4pp1uc|zD1@~rUHmU#YX zXxhUq@S$KlcQn-L7x=h!G}IIJxD&(*$ibD^{q`gT{EjK#6w(DXnLWQW$%3V1&wd&F$6lmmSH(l%4Fs++5 zQ#d5iImW2Q;0a*nCDW53BiBtfnUV}~79%$yXWisx%%*YE!%hy@>YSl?A#^*~es$X8 zz$EV&zO54LBKgS1`ZB1OzHt1Zd&X4CUI)lzoNQg5+NT5swDt)|gv^@~; zdfd*C$M1`mg#3X4{ub}ms*d&e7J0#gN-S7aGMey&ynK9DFys_M!BtOa5w&h!4N|Sy z{^gXtb#B2E;+=E1gl4a2p091Jb6dAR0tEUvq_ zd|V42nAXg*g{bab@e-=i4(BpI==3=kc)^|0PD~_|(u%qv#2=c!leHDCn~be!Qxh5t zl1C`TZjIJzv`RCz2E7d>=}mBU889=pF^++)LyBa}Hk%f}*P*vE4z};mB|?rFTZ~c8 z4fDErGe1=#EgUM>Lhu>|T6l?UPB}sqS_tVyT9~uapV9fHOAX12HT+b#o=F$FdrrmV zax-YHG!;V&8%t|8g^p?|kh)9@Z^1gDr2tFU18f4el-fZk9wu)nQad%)JkZzOWow_D z7_RMTztUx!YB+PYuHIH_8yvPz4z!Qix`rmY#zw~a#=AWK2`1>_P|Mw)okB(v)fI7T zFdX0ofpi*Y9S)Dr6LL6|MjkH?^5`JQcd0HVSKx!52waN`M(%(USqa9A9G;-V?ew{M zub1cIc>$-F4~6(R3))V<*DnZUC2@9iB$1G-azu}#B*RbfAuX)}VQNI(90VwC z{9zxMDnf-l0vSWR$nE8w!hk0j;(fdjxA4A&c$wGl;!&*#F)BAA~=;E1$UdU-@5n zpEo`i#PLb#(v*B@N;)(xADR|%&RmPlEJkM*MbDBnvn zQy(+P{5{?GFZ~R-+O7+yJ0rq>HaOQa)eU+%aZQ1 zmdMhSBfYhNkM5l`9D?a10(eVvX5Y1*Hg-UJ*2{;Ms{1ixdw$R4P==qB*L$WVJ)A|F zv=K#G9=azq=CNThNTN%%p2lq>$AG7M(=={Y16I!W-nbDIfopbIt*mNESNt450==vw5aOHrUy01l^dN_-md9TfbMn1~HrOAR^bYG2J z^l+A3^3!uM(4_QkT7Iz9UFkH2((lzULv>mRR=Hmb3niK3xq=8#d}glD$Q|V&*Qgwj zO%G=&&z8rNuSK@vglr{SWUEY(O%H!5*^>5Mx+Rx`DY@w3EV=A9QY-eY(|nPAL&Jx( zywdp?H2H>(g+S8AH*(i=GkYy?*7cLl`871U$zKSbFykp_f1wd7iOeT#=%&)KwTsj1NDZxu^P_6tW+ zF}3izh1;7hyTLB9^$d9itYpuS=H)h6175bCA>V+N^o9G3I)d+bOOqTmrH8Y$oc%^> zMIT9;FXIc3YPlOV4Y`hKDUeGKXOU}*PczUQ*Epp@?f_SrUQY(9w^OmTFn2Ir0|q_o z&jVXZQ>Af09(s5OrAg9cF3lnCjSQtpQe`g9o3AZR_PW6cQaw-_J-ma`Bxy32<}hc= zP?{uF=F%K_ZE2Ei;4LE_Z0%%9dGv6W@*Fi%V-%X7+0Pm*BROt9W~4XXW#`6`|JB=C zx^{Lb!*OG-#=F#xoRT*V9-n~Zh>QqbJt_+IKb$i%C#b)VU zwu~6p*{`j4$>UC@%VE$|w%%oz0V~WTJ3JiGJdY3{2R(7v)xiW(Wk~AsLKAQA+a;i_KG1N`=9_h5k1NEqT2|3$palX>%yxTJW{?(Yv^F>2eq>xIoj{#|ZpHyD@E)7_gFkblRNCMyUa> zP-BqBZMOkSpK~%|p-*ek=%I5xoW*aPH(G$wrzL65Xq-}EDCK5JmtyIx7M;$~Aa#+3 z#kCsoAon>f4RY(@EOK8kQY&)nG+#91qs(Yt{L(X;=Tqd=!&&5fCxe_xnpTZdD&#Ju z(-<_EeWvw-#s&J*!#j{GNwZD4QuA55sO6s7Zzwvy`~^DKt!ax*zoT(So_cr(WlPd* zvup;PXP4_zid=el2XZB8zKmSS*3@RS8MLO$DU#{oERwYwsg>50q}irqs2QE+i&`LX z+cf#o^EPNc+t{FNy)5h4K-XzH=hx8alBd%cq)9$WbQtlV?{=*`D4QP6qVG;4wW9AN z%{KL&MKZgQHzeywkxUQoK(ZvwHYHo%on;iz1>NYqOL~u*m5Sy`bl<*hs%}u}o_5<* zJ)qM4;I^rHL8W_`ZBzBFmu(xDbf8@MC@nHL%n!MnqhqKuJfRS1$k501yG!ScKyrME@^xz|;H8JNlrPgfL6W9N)Ox)m~ZdsjU$g4LMUkh_X z+;Dn5Z-Z)t8~qYgW8C=%rclajt`%nOnZr%0-Yvq(B;q*f%=X|^Tl zwQWm!-Iy079Z8W?4`-3oVWd_h)oHdR>5Xkm>NMsBNk>y8)x%jNbs4D@Np+fSN$TFV zq?|D?NII4xsUFTEX(l_>X|^RPzimn9w@5mkBB>tUfuuUkwj^EHwxo+&B%Mf+R1as7 z)MKPpYG0?>mZVEtB~A4?2NH=ZTkxOK@=E9Pn*K%S zpH8E!0$v%4RBEe$YqizCRfB#m>~#v&k*0aSFH}qGc3W+Y&4INGHYH+}_be=iT5T@B zm%Ctd(@Nb|+tK>^?(X{f3(j)0$uv6Qbg6p`T3Z87A8)$@WP#&>*AQ5<1^r$RXFGcK z?AZ%8m%dgPJer!CF4#6~MBd>PT3bU-7m=o-G&eUV^X%;GykHABInLu-0PA}2ZfMCO zX9fWp8ynNJYsI=>-W}q(^n6=dT9WxD%1WXRI90X(L>L>U;I!x4&T< z>*{PD8|&)9`s%^1G2B9 z9XI{RJXFmH^kb<&>oR_17HC0(veQFd;ruV`MXz(k#W^oUs?(P_Cl*!LUG)0hPH*rM z0xBx;3lcx9d;TXZkY+Y$?Qnz{vAlv+SSBrhPj^!mC34Dg-z1RSk)~7yB+8snsLPAm z&!o{XO>F($2aj#-AUMP;s#iO4Pot$BC!kMzt%3Oifp z&=8cExro8yGKmu@baY)E86KN(^bB;&MG6ws%8jM2t}fD;S|HWX6Cx$pZEZ*q>!35> zY>k^DyGESYfMbJTt&w6i49=%#`$k&Br6}~P55M!f|NH5;Yz=j`9$s*I!{pSuvD)1u z*m{I;z#p{voHl>pmp}aFfAHH*(DMEhMwOtQW@yR_-~D4c{`2Jp@WV0FmI&C}K5N9i z=l&l(GI^dBn6QOIIgTX|mOj@o-)oCh_W9giEV#FIW7Cn7^9wegE`-)fvMM25492fM z{Naym=o{>tRpKN0Q@jx3*KEgIBL#yz6gJ}b-VUlN z`nwMl4RyCq^r^^&*rJ9_O|~F!yVM%qt+4!q_ic@&LjMXM5DSu z4C#VELKk5)1Twsz+XhFPB1Xk*?WYp0_Ya=hCKkghE}zrmjT}y>Zb5L~&g68$N0c1C zd*3!0pq)6j!LT>v31I)BjoRPJFTWr1xc!k_G?H6$E|u&b(ExzKD36?LJcJ`@~IV^oF^P?wVgv;wKbkQ>{{YO{&?CLbeyVIXWWv7qGu7 zh%pmJA{it!m~W=u4Fj1JCataR#jtNVeF&tFdg8f2_J#bB{E>!M8*Qg@My3tA>#Cf z)Ux_4PBqf0wJh}VjjcAd*G^MjQ)8#S2_sWut!1cI&CZlz;TI}zyN-&scf!t+TQ)IR zWQMvEqs91MY%_Mc7ag?0F2HjRKkV2Y3Vu~Ba-_wio9ed=lEV5e9BGlacnB<80;J4- z%S|=yrmoDqk)~GLa3GYX$?ooRozz`_VH4h&CaLXxsX@2F40rnj*i4V%g=0Y-g53V9 zI^>O(*kkD@J@r`TNO{*_f>2(M#id5Nbmi?DX@(`zXiZ4d-?@(Z`g0v$yZ*j{B?>fA zteN7TAhx#i4m_(a@L!i5&S$YhC+W~-nJ2JlSyAoKr`n-US7q)R-WW6$S(z zy&~^e;e(4`)le3UhSF{6qk?o>rl@q&@LVvIZkUY{Ij5J79XZo#qh0ET@_k*kSr!od zZuDa6URa<7A!908@`;yHLG3&r!*m<6xvtJa|hk_OjtQOBrY+JnLF&i0|sF4`A=+Sc9G+1oz0#VYD??7&|(XB{CBph7q2!}#=bx58oM0ZKbD_Mc%zkDFyDuWe2BD(J1@&l@zeaA06=c_%6;9Qn%czh&pUNC^iF?UFL8NnDm zpDUp$dS1sH2{g1qLR<0BlbiQ8%0+j0=SeW47TD=fdMK3}M(FW;HA@QS1TkF@&!<-y zK(C%PL}0D}?^K}K0fANz2rWvsqDQ{u5zGx zK3)P@dwD0SOEKf1@{)*7zc;*sH`{O_6o%dl(V4KXB0LY%Jzl>6gTtF_QXWv^Ou(h6 zj?C2=iZiYT{5Rsi3IEObZ^8c={GY`eCm^BvmI>6j^0oA^Ol$UZ1TPuvDPl_>yr0%A&bIip^d7OkLfXD=xWM(LG zl5wiQ!@%cHGB@cZ7X*MQU@|%*0MAKgntBcbKq2t*jko1D>ZLat2&5&v zR0DKZ%)>-T0FenW%1lz^D9QlgM;R{(PXH(@Cq0+ued2q%A=M3tIJuBi8I~)<&}50YdI!AM%ss?=%{)oG34qNMvqrqv%*vb@0Ynmb zdEhPiK+Ug5$K_FnSR4B3*eBPY`lZ@I5hov#4us_c#JgDI-L3MTP<-JC7 zubJ0W-fOC=>Yr3d2hYj}&nlXFS}vdOi=Cg2o}UKgj9GanNvrZo5?m3bUPqV-;x)qD zP{AVQI>H1fR{}u139|;uO{Ry&dm~IQRW1Rf5l~voajEo#TzcYx^>M||4*&S@)AC=u zDOLB%)xBbM@AKn-d-|_Wi?i3|*(IreS?*sJ`!u9O6+l&Jub4xH^V=?_ow%sgryVj z$S2+rPrUOq9J@Rmy*w;k9+fYTia5uo;Sgfu?&vsVgE!ca#_!7Gcg69$J8P|q;fZy_ zQsszTIilFu*pxixjE(uDV}8hZ6XpfM$IVkDH~~Z^z*S~W(E_tT<-Q6-M!5+9C8*lW zRhT6y3ILG=6bEry+SefOYas9Nr1{f}v8KUj)1WvMkeY7FO*ciH!BshU4_rg$KH^FM z4Epho8-QV04}=OqHZUiE$OM>X-lfQC#!W&^s|}C0cK%&L55Rm6FF17s0s37jLUUIs$c|w zvH=-D$1$BG7y(2Q(EQ{T>EM8Ta6t8woIG?rHsp;Cd4c6Kk5HDw=27BK0FeX|jqnd= zri1V5&cFhyL=K1wf zP+p3F(K;A``!Y%i?gVgmUF}y003`t?nORZ`^(#;~0i?N@6#{;g8RUNE4v|ly%(x?f zv;??|!h-xReun@#0i<2Q6gFbL-(|dXM*wLF;IjmY+^0U}5Wp|3cPw`5 zWA9k5P$xT(bDjF#I~Io;>7YBG0;@peqt+nZ5daDS%~M(RcUx^* zW48LJtzNP<%C<()*7(H!Xn(F@b!)phB@hJ0Z|ys!cE zHpWiGZOjnyZ^M`d{0Sg!mbp&++Zcz6;-E;ndr8Bx8mYWaF0TXk{3kh|=Ev%LqV-Cl z>zC#FWf3P8`c`b^UUcOi2-}epKsRy%Q=d8K>T>0PO+TdwLBtGb`({B7}H7mL&H%F{QbUZ>pa6mhy2 zV(yz!_f3p>WZ{nFUYFhLqI(@o@1dN?{vO74$esWqhZw~L520j`;+|O<#S>5nW|$Xc zd%s<`dF-QVH07D6IltKT%>JtZarY>a^Of!d*9YzJifwA^?PZkC{tDU*__e`%qf`Vy zFk$Yrh~pFTxHC5HiH>{3B_Fy2Y5a~nen%X?1B@H+@4&x-5f>!Ap*}tkK$^fP&q#vW zr`=HdGyV55`uT*^GA6f-i7jJ0_Jh}?=Ie6v zb+P&S&ivrs!}8v0Y40g{FZsa&DDT}^ZFjV`TkN?j)!vh9?}@eK20EB-DsTtJMksKH z>Tn1^qqAu0NSlRWDc}}qv;$)^g!px6JU%{hK6IzHA)+UBZU-W$PflX0GK{?LD5zKo@2}?87%=|5_m~1 zuu7^pDOb=V>aNH3Px@mu_Gpb=?3$Nq7UY@*5vONG_5@>|yHSt&5Zpx)E}0cw5CAs< zUoST>?PZkb#a`9udoiX%d3(`FQC~<d`<$V`XsKTe*FTAl!SEHA%iZc=E(jEEI9q|%5le^{)%JZ&S zd9=HWCk;qP0BKWr(tucZ&B{{{0fk^rZB5nU$w6uFki2&Y85D>k6Y|Kru@O&n!~?8l z^8k^K!heE00YoOiFr!S346B3IVRd{$04Vbqk$`R(k29bnfJg$G_qzHh^uZm8JtecJ zME2C<$)C;rc<$+2DBiME+b`Gli?#jFyZ(0IuLr~#a`Uo#MH=wQ13nRFARG&PUI>(zIg$fwYAff)gyB)~cz zdqBR9=XsD5pltD*0l+AJ-vZsbI;}$hkp#5Djy)>>;E=?=EwgwL_1llFKP&uk;gd1U z0UVU7y5y=Zv8rpw&e|z8yX0n<*z8Kqo|S)aKw^)|>`{?D`kVbnyvUw^ zdM0+^O7y}N;v`*|l`qVS7iN{2x@xKXlw3~!Kc70!Sgk!;3pcnR)h^1liy}_y|AJ8A zve`~GKma**sr_9FfKbb3W#WkdPzWSu|7=m#wz+!~ueYs|*(#B(dVK7Y>e$JS=*f;} z4bR-t$$t4{zj(4A^7X|Axaa^U^7G>2k~FX^4=jr~m4PXw@WJCk3IfQYhv_BI508oL zeX6w+Kx6{w)_#@DXjmN%5dg{}x^RGHSQE&H;Tja9S6nRJAx$3@Dbrp7ri-j8zznK` zqd`*skVP344XGYuoHE^jE27lvl3KY-Fk8s8gq42~ zWC_jzf)D^=2bPg!1Yo$t2&8QSKp~J2Bws3Pl*=&r3ys)6?TIz_MVtG8a>dM%AT2y) zhbyAg>w@~|x1h?ifbk*(S->JZ2toje_tfHU1z@6k#wMF#II_^ zuWH1v3BpQc4RRSxz2#x*?QE>6H`>$-S^Ldy(nvE$8o?D&>Xn{}5jC%x%DnnSIFFU$ zWV--Byvry{R<;5#oM*0)AOwI(Afb_6QdyH+)}#nB@#%D|r9axz50n8jPlB9L=E`tI zlzLrMd%Z=*Px35c*ovxIR3A+V0I?18Fc|?Df}8{)02BfVL5iiavvL`xuOH^2@7NbR zKNLMb1e6i8GH2VW6dzYasaO5sSeZKVV(JKjc<~egjSv8$9X~^71Q5i_Oi~jk02BiB zfOO(f^9N@)?H~2P&reh9eH!}3>hqkx$rE>vh^!0egLZLjGB)Ojjyc2|PHD^~kGVwU zOuC3Y68i=^8IgVCH#D_-TCDGsD(!Nm9i=OI#{J44>vl)G-N=_WD}$;Yvofe6fXD=B zw{(%J+AYdj+jdNKp@8jhpeP^#U^*>4p*YngUhQa`3W3r@=`JZ!`3Hw3wpwPZMeS5J z5o}qMORF4y`v4bwFacNXNN$SQ)K^ewX$04|tbe1=4dCTOrX_vdMCQ*TtiuOHz#-FC z8)dtVWhhcHPWwx+>X5fNZTi~&e=*NhTeTnj>DO<&$B6|n@p61bqiYT8E3tgr?h&xg z&M(|ne-O{ZkEyg09BZMfk!RdIAEe^gZ0c`@HxZ5;N&n4o%kSm^par{e!E5RZE9Al> zvBERa!ZS}o;yV*k;iOzRseDyKWa}Pq4}G!XW6|Pco1>4*zkgLKu9J)FMEzvzfV8zD zXhDlo5zi3Vc||DSkH7+>pU@&B<(NY$H_UjyyIDB1ohnJM3+nlCHcz=ywk;W#=VP%h@5{6px;j@e z0^u*fEnb4k9}e(7vWFq(3NQS7#0vk7E)HC(ElR};e@VDz?dt@I>i+{oMk=#ZKg6R3 z5p>~#dRL}&VkOPdlIAB9;)P*xbX=TtNhNN%#Qk2*1M`Chd{;$eL$H9QSg|cyjG>)W zd=#SvvH0lb#7DESO2!! zDf}MDldFpoC8x;9!Ss@+tf5!~LU120_f6kx`rz{8X6azPe6U{B&ezC$5>(rjS6ecr z?y-tj(C2Ux3*2ZOhWZJNEz&5r#NpON-9m4mGDzUil(a!uDWPO7;g*IW^gUr~!d zD%K7%bVcPqMj&eu%$YqR)&pY&dh!z@#=8xyuM(;a8z%Lf(?2AT_VNq8QGX1nl55pc z8XPmEEQ5!0#I7TJzXO^W!b+Ep+e(ADN^!aBLhg8hz;l9gb;`r92CH*ard?x8d3FDKYF5q2{d~ znZJUS{_Tn2(Vcwv3LTsUJ`R&~E)E<+~Qh z&uUyy4l_u_q_s}Uv9-Tl_u$oO%3k_Ox1To=q(M?WZEQGu;tkL%^`y(XsM}kWRg(t_40 zmippTSIT0$Rj1&?5Jy<0qu{coOo=O{-gg&~EcN7lMWr!~K=rTf=F*Zo@w!Xo7Nt&)-02ZJJule;Wb~+6Vr?>O6It7fl0C7K>S#%|RB}o#!PHyR z&JB$lir#t{ z8@KA3s+pk)40Xwzu!7O+$41}u+WisIwvKs{EB?NT^dM~jyKj0NdUQ;#ta&o==d*t{ z`yb~%oqMAEDe_kr(YLI87;rfp@m&tb3hjocaG}F-Gwk%LDa!Ys1X`IV&`?{T0hc-; zQH+#&7JSIafsGe3ipkYY8cF zVe_riAWFIJHCa2%VorP7sVGd5yLwNY@naWT;P%Q|P@n-oqScSw9`|tk8FgGseVzJI zuY$f6T36pC2!0`+ry@1RixVFfbl}5WSQV_a|9FuWiE0mX>I(FHk3#PCU?r-+(|#`X zvtxOq>XVZq(~s2M<%))}n_aEQOTuRmg6uAM2-jB@v)TN@lz(6Odto{(8qXI{)@#qt zU*wgErnbac-X?zGX==l#4F9L;kf@z6Ob12nd|@gTwG-j{`Le0>{XLSYLN-;1riu(v zuX1wDrLYd|QhLj5?m+Ej2k(32y(j)&Mfk_p;038W{kOaJn*OMy%JM^VmF52ehOham literal 0 HcmV?d00001 diff --git a/instalador/VR4Life Plugin - 3D Max.exe b/instalador/VR4Life Plugin - 3D Max.exe deleted file mode 100644 index a9b361d1a598eea9764fa56eb586bda67dd3a545..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 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 - - - - - \ No newline at end of file diff --git a/instalador/VR4Life Plugin - 3D Max.pdb b/instalador/VR4Life Plugin - 3D Max.pdb deleted file mode 100644 index a25da9fa4ce7c48e8492d606496916dc420d31a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22016 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 diff --git a/instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.exe b/instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.exe deleted file mode 100644 index 983531fdaab30ddbfe2eb09d4639830304acbea5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeHMeQX@X6@R;TKHHc0!o}cx!*U_$NaC{{J0S^i;*0HsYwXzg3up|^-rd+<*xNm3 z_l!+ZWsqoz3N1)gC8Vk!pdz7G>W8RGTagNoN>wR;^{;}UpjK*ysv^`%r7a@;z1ds) z?8I%TQ2&8B@7tMqZ{BwcD?=Nm6v z|AIDf;rg*z%QMQ-osnkAD434p`bJ(Dvf>z)WAqJ;8YQ*~_`-uj$2wj~! z_m@!GTa==8T07Cz=!pltKiY@4fu{!#0|PHT&>J<1G2pU@2mM?kboLRVtJL4}yV?v$ z=q&gSalMCV`x28Xl3!kC}g4$Qvt|+XVPIdHH ziYUE-ZKsn~V^&3U1z=mdP7Vg*FG&)x%-rC_>$a!iiFiCFP3}yhzOG(A6V}()%U8mB zlY9@=#x%?kYmUkd+ESygLGDLOjc$%LrXx&IpNu8z)39TllCg9%-pvhCFqx7pzpch2 zmg24T@>MkU)XCp4`WkdqX?}}#G79{~0Dnqfi9dsOvTkksImS1v$v+uQHcT})CL8x| zCHZ~k9jMk639GcHiDYTHNpJ3Gj*~nR1>d*}hsSHwr8i0Xzyw^H&J$b;2@5H zPMH1}o*k&e)>?CWgnCeiO_LN!vo%^i)Z($d^^x>u9fj zT;GEFR;kycp56x9b$h6OcS=t~?>OzI91nZs0Z8y)vC}5$T zyhf)+Zv0d03cjX#UZU5u7+us`(BGxt0pfZr(xML$!V&zV zdK|C=wu_M!VfZ(VX^txTL14KAS_XE#iW0i7XVIt8u))|TX@~wGT7SAeXpKi6#@xG7 zL2F~=QCQ(&)%wEbN5H!d2u)dEqob(nWI-2=8udncMAr}yOtl3tPB#Hw1^pNvQZTDv zPQlw0yi-9F@EWpI{XPX36nv6Sg3D9%FD*mQ(QVX4KcsZzFyMQ75B*fZm*{=Hi_Xz5 z>c?ybBRTXJBIBUBJ936z!U~uHd|xloL*N;s46UQb0h{S-fZOQDfII0t;2wG%uv5WX z6zo;~r|50;kE)(C3Kr-e=((46LNAZnwXJlT@)TVRtxeUkA0fjL6c$fy^Qv`Z&@EPM zag;_EJYSSDxgjcf1y|Zuo<>C3HVcAggg-SXJkOjFbi%R)^}3Gd;ysPVX|p8gc4_%y zz;YN>%JchV#VTffEQ)-^7t|;6m6;hcZ;RzVP)=B$wW2TUd7_lJ7sf2VmUO9Gnnh7E z<-N;X#!LzIPT-&y_q(--a11LvA*5%y&hn@biHS^GGZkt2mqqspuOO}RN+k3yTecc8 zB5ZSB)x1l24@+3K;9rX9b;}FVnwh;Us#G?eh2=3L700(qf@MNZ-m)#f20Jm*HDFB( zW7w|DAhBsRI{S=4b3P;HMd;5egG|)~*rO=es^}!l=GsLehfRN$z;D#7za5b#e?#e=XCzfz$9ge~um!=^*7QQw zDYB=jR|>FOvJF<bStU>#z9nS&O0=`-{OBGPLYLtilVG_GZ5hDjNY96iS5v>??06OF$(+8#>JIFX` z*Ljf6dX&-Yp+Ar+(W;=2T36#&&SZ*)pDVhV%E?|QBX25BIXxGZ# zDJ7u@O?}K6!4Xikt)`k*mMMT{3LIU~vyGU(1a0Y-IJK&ufgO`A#+rMWEpuMWlEDaV z*BOkdoxedRAi=ImxJ!A8)}5d%e0M7#)eX@p%;XH@uRYW1xKsV``UtXp_IDN|?!y=h zwqakgx2>w(*vkg&7I;~pRsi0?Or)BvOWKBB@EJy2WT}t8A6n0>vhn4uS=B_%lWi0F z)xdm~Em@_yD~=PEe;lu@dk)sfQ7>e^O0Phwf%*{QrWd2f=>jy#US@7=dq>SNhzypR zA#IAs2hnL%<1>i%ITi7|1|)tsgj9_!WWd90jmi?oGARCv$hLrCd>+t+oxp$b!m|1+ z4R3(_a?44mV1FBI7|$jzAp~uRWK(6(KY@C*hXWkjWc|4fT&2i-d4j%)C9)~-!F#Q;M*K!YsnKl?ln6Mc= z{4C7LQJh&z4zpkuywR}40(wGyIMjG{CPuNt_(zdRJZ(e|X-&xbSb1J8?uu2jdUu;b zbeIswCY^;47RIC5!z^?L<0bZk!}#jXfhYS|LNFWPBxtzp0T+zo-HlhI54Fl_Ocq{e zr!e1@yHQHXNh@do%Re>%yMxVIfL4K_dABtvjfZz8A9^xfX#SAy1f*~{7|@0u>TH9^ zwHG}re3KF#z>i|Eai|e)gdexDcspdzTl4_l|7WA!+;&CV)N0$|=o~r!><9asA3pib z8{cW~T-fs>MGZ}Bh#enSube*4#{ZRsbjOlpj%I1 zI4YDBvHB?Jb&zee5;2N^K#$ggy3PoOXo($(hMznzIkBbdt#csLb}%2{z$cMt(5iPW z*YbzWnBH=`G|Q)5XDMMCo0abUo(8&ljkE9V8f{uDnV>pFvPq+jO9`X#@^glmVrCLs|#EVDTf$X|y$S zx_@jbVcuI!47>4_dk{(|u3kd*SswEL1y1lc@)%eiCui^(VNTA;E*oiWYiF@! z&bO9Tayz+(ohIGirTc@-){Cu3cKfd#C_2)$7Xsd7<)P^;IN9 zrfBo`KW-^^k}ff#ExR1J>P5eMhsX}tOL4a*(08C0RXK45CU z2A1_)c?ugVz6lKE=A8HS0R~?s1l<~H_y$Q{nqx_Y^ z8I#0!S!i{>D(ATjRb{Y8S#oG&ZUr9rU*|Nee8wpte-&1c^Y}HE;z+Ok68-PK>QcU1 z$#1pCR{QIq8k5DWIjbun8f{pWv$Y`83nORsxV=~~?`UE45xx8KUmQ6$U$Tw4;993U zh2t${2&do{@v+~X8Xr5+dN5_+dci50w(E%Q)PnF*$Bs6|o8m{z>K&5-7LM1Qsz~Rs zSD3}UlGj?Y3exr5X}`7LmJXXc&oaOr?6l#E#}r`iGzzN~mYU!Po|KKoK?9AtZj5eX_Z7Xy?(zav-5FBX>J;WEgpO#OC1#mF&|5~1}$ - - - - - \ No newline at end of file diff --git a/instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.pdb b/instalador/VR4Life_Plugin/VR4Life Plugin - 3D Max.pdb deleted file mode 100644 index e638b7a212525d3081e90e455ccbe5c08af56f3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22016 zcmeHO4RBP|6}~TtF$qn=ibM?*9)Bu<-Ry2Qe;CN$CXz}_6pIB@;br%2*s|FTyBi2} zI)(dpx^g?mJKE; z>?Si=cqg3q-QRQ1J@?*s?>l$t4EmyxSR@daTPs@^Es{G|w#&5+r?a@I+`CeMa}2QAdWdR_q*cwZ9YyhT^71w_Md&WW>EZTGMGj!${rCDrjgHq~GNjgqHfE}nXP zB-ApkM^;wzKoUstoN?QW7ocE+r3g8?s_)onWJrYJn`Y*|7hFYsK=-5*|EkJ zc++;MLWs`_Iu4Z{U%2xn+q9O4zqz^Op~rtxCL0=j>p$Goy`+N*W4ujy|;CqY?nO_ zm&f6>S2^6(9+%ruv&iSFsa5=Hpw8{;t?yOb0hiC?@wwf#O0`;B?^9f^y4o5~jVme6 z3QSrHjCB5=hA+U>@4rc_yro#i78q&#r(5Hnv0bx8z<8bitn+`ijQDUp$7}qp^Z#(W zW=rhc$#W-p^e@0YpYSf}=?lhHrDs#r6AA`YdzHUm8L|(A2K$2Ho>g~yRv=OC)}lBV zR(a)4WvHh+8tIEF{SF^K^8I5miIhphn|CHP&PHqaz%Mq~8PB+!Sc)88ie=!Bl7ke+q5^ZwCi3Ne&p_ zh=?YMNf*8wlF3#eODr(s1E+K%Mb{CAI3@SgyuSb~k zhjWQ}s!@)>d1jV9;Q#a#%TgB0GB33(=c8Hn^s&Evhh;f8S(bUJWf8UL5-h;)yfa{4 z|IwBtj+I4MhXpwP4pCuaZyR#-K8I7rA3-i}ZB2?!B^XAyOyt^F?*uZcr@>nJ{PYn-tEAjPW z7V1&m)Vx?+iN*&9lKFf$4a@gMg9GuHSB=HB`s~99`CS{3PWjhdls`D&SK?|knQy%J zl6r?C@QOvX=EYpp=f0RKU(auigyU*Bjy#qr7_m&-P%swP?o4uEe%hP1dkez82y6u6 zAJS!8(M9#uA^u(~U*r2lUf%B-KRWjF)o*tkTu_+v%DxxZp}6Q2Uf~Aj!GN>@*FJ4Y z&dV3Mi-A(&khHBr+O|{L_9y9qKIwr2(u0lCgWr?3FUZ-kN80&_Rz6?U7<1=(8XMH4 zJ@p6V<#T>eSAnBgFtDXL>~D<>Y|-aK6AHWmZbG(Mj(r_M+H2q$NPpC*Z;m&TllBe_ zhCPlJ5jD8(A`qhGTlaQ4EoS~PvT@9;I zOp6uT;3o%{{kRbYcY|5iEYE&W4w94o@P$+*tWO)Q?IoAr2faTxlu6Y66Ucv!9RW%B zqisp^!3T|Sp%4iMF@F-YMKKU8;0I1j2Vzbn<^Z8&!VbI+SPw*Aq8(TUwKoC|y%I1l&{5IQA_pvcWY8}Q?k=MvL_w;;~Jz(;PXd&G%mi#Cnt_nTvsVIT@TM^Bq4&ipRzWX}4oKIx9et<< zI}k5V>bo5I`ka@v`Oorv*EBEyx*c+Tgh2q0U2v~v`x%B8*mZueqax9^6tkIV(cq^ z{d0^r7rG>l>r^pomrb17%=5Sx310#7d@ZL8I==h(%?JAUum*UXKd*-M(ATL``*Db$wMm{T?J!=E!XnYUh8wr zXRG2{uZqeru2*BCG8Xk!u2<>u>doOkI`)7&1Lf&9Gs7nm+O{#RVOcu0S~t4f=ZdMu468^0BN z1Y+ud_u@4`G-)|rcqb6?gIR8U3d;x|ho(I!(*!<=Y0B+;^xC{W|nFaId)mOha(b;rrL3@wLFL@fBxD%Q6dC_y1WoVB@SV z_j=3!n~qVneRs4^=X3;Sbsfw9o1MeQ^>2Ou>tjb-Fl71z^wcZ=`(N+p?Ju{J)cJcy3SF-@()MGH_FpR|rT=d~#(uo~fAlBa0;d0O9vHvt y8|MF$5vTu;dkUSMbac`vBl-X4Abl=)0eC*x^8djI<4pAFT4Y(kvcT18f&T%;dgO`# diff --git a/instalador/VR4Life_Plugin/run_vr4life.py b/instalador/VR4Life_Plugin/run_vr4life.py deleted file mode 100644 index 6101b85..0000000 --- a/instalador/VR4Life_Plugin/run_vr4life.py +++ /dev/null @@ -1,15 +0,0 @@ -import sys, os -import importlib - -# Garante que o 3ds Max enxergue a sua pasta de plugins -script_dir = os.path.dirname(os.path.realpath(__file__)) -if script_dir not in sys.path: - sys.path.append(script_dir) - -# Importa a sua nova UI limpa e recarrega para sempre pegar atualizações -import vr4life_ui -importlib.reload(vr4life_ui) - -if __name__ == "__main__": - app = vr4life_ui.AutoBakeManager() - app.show() \ No newline at end of file diff --git a/instalador/VR4Life_Plugin/vr4life_updater.py b/instalador/VR4Life_Plugin/vr4life_updater.py deleted file mode 100644 index 7b5991a..0000000 --- a/instalador/VR4Life_Plugin/vr4life_updater.py +++ /dev/null @@ -1,92 +0,0 @@ -import os -import urllib.request -from pymxs import runtime as rt -try: from PySide6 import QtWidgets -except ImportError: from PySide2 import QtWidgets - -# URL Oficial do repositório da Immerse Games (Lendo a branch 'main') -# Obs: Se o seu Gitea estiver usando 'master' em vez de 'main', basta trocar a última palavra. -GITEA_RAW_URL = "https://git.immersegame.com/immersegame/vr4life-3dmax-plugin/raw/branch/main/" - -# Token de Leitura do Gitea -GITEA_TOKEN = "efebcde14ce96a2b80d0b3f207991bc155018ab8" - -FILES_TO_UPDATE = [ - "vr4life_ui.py", - "vr4life_engine.py", - "vr4life_cloud.py", - "run_vr4life.py", - "vr4life_updater.py" -] - -def check_and_update(ui_parent=None): - script_dir = os.path.dirname(os.path.realpath(__file__)) - local_version_file = os.path.join(script_dir, "version.txt").replace("\\", "/") - - if ui_parent: - ui_parent.pb.setFormat("Autenticando e checando versão no Gitea..."); QtWidgets.QApplication.processEvents() - - try: - # 1. Lê a versão local (Se não existir, assume 0.0) - local_version = "0.0" - if os.path.exists(local_version_file): - with open(local_version_file, "r") as f: - local_version = f.read().strip() - - # 2. Bate na Nuvem com o Token para ler o version.txt - remote_version_url = GITEA_RAW_URL + "version.txt" - req_version = urllib.request.Request(remote_version_url) - req_version.add_header("Authorization", f"token {GITEA_TOKEN}") - - response_version = urllib.request.urlopen(req_version) - remote_version = response_version.read().decode('utf-8').strip() - - # 3. Compara as versões: Só baixa se a do Gitea for mais nova - if remote_version == local_version: - if ui_parent: - ui_parent.pb.setFormat("Sistema já está atualizado!"); ui_parent.pb.setValue(100) - QtWidgets.QMessageBox.information(ui_parent, "Atualizador", f"Você já está usando a versão mais recente ({local_version}).") - return - - # 4. Inicia o Download Seguro dos Arquivos - if ui_parent: - ui_parent.pb.setFormat(f"Nova versão {remote_version} encontrada! Baixando..."); QtWidgets.QApplication.processEvents() - - updated_count = 0 - for file_name in FILES_TO_UPDATE: - remote_url = GITEA_RAW_URL + file_name - local_path = os.path.join(script_dir, file_name).replace("\\", "/") - - if ui_parent: - ui_parent.pb.setFormat(f"Baixando {file_name}..."); QtWidgets.QApplication.processEvents() - - # Puxa o código com o Token - req = urllib.request.Request(remote_url) - req.add_header("Authorization", f"token {GITEA_TOKEN}") - response = urllib.request.urlopen(req) - remote_code = response.read().decode('utf-8') - - # Sobrescreve na máquina local - with open(local_path, "w", encoding="utf-8") as f: - f.write(remote_code) - - updated_count += 1 - - # 5. Salva a nova versão local para a próxima checagem - with open(local_version_file, "w") as f: - f.write(remote_version) - - msg = f"Sucesso! Plugin atualizado para a versão {remote_version} ({updated_count} arquivos).\n\nPor favor, feche esta janela e abra o plugin novamente pelo menu superior." - if ui_parent: - ui_parent.pb.setFormat("Atualização Concluída!"); ui_parent.pb.setValue(100) - QtWidgets.QMessageBox.information(ui_parent, "Update VR4Life", msg) - else: - rt.messageBox(msg, title="Update VR4Life") - - except Exception as e: - erro_msg = f"Falha de Autenticação ou Download.\nVerifique seu Token e URL do Gitea.\n\nDetalhe técnico: {str(e)}" - if ui_parent: - QtWidgets.QMessageBox.critical(ui_parent, "Erro de Update", erro_msg) - ui_parent.pb.setFormat("Pronto"); ui_parent.pb.setValue(0) - else: - rt.messageBox(erro_msg, title="Erro de Update") \ No newline at end of file diff --git a/instalador/install.ms b/instalador/install.ms deleted file mode 100644 index b7a360c..0000000 --- a/instalador/install.ms +++ /dev/null @@ -1,28 +0,0 @@ -( - -- 1. Definir caminhos de destino seguros - local startupDir = getDir #userStartupScripts - local uiDir = (getDir #userMacros) + "\\..\\en-US\\UI\\" - local scriptsDir = (getDir #userScripts) + "\\VR4Life_Plugin\\" - - -- Caminho temporário onde o MZP extraiu os arquivos - local tempPath = symbolicPaths.getPathValue "$temp" - - -- 2. Garantir que as pastas existam - if not (doesFileExist uiDir) do makeDir uiDir all:true - if not (doesFileExist scriptsDir) do makeDir scriptsDir all:true - - -- 3. Mover os arquivos usando nomes fixos (os seus nomes) - copyFile (tempPath + "\\vr4life.mnx") (uiDir + "vr4life.mnx") - copyFile (tempPath + "\\vr4life.ms") (startupDir + "\\vr4life.ms") - - -- Copiar pasta Python (exemplo para os dois arquivos principais) - copyFile (tempPath + "\\VR4Life_Plugin\\run_vr4life.py") (scriptsDir + "run_vr4life.py") - copyFile (tempPath + "\\VR4Life_Plugin\\vr4life_updater.py") (scriptsDir + "vr4life_updater.py") - - -- 4. Executar o loader agora para o menu aparecer sem reiniciar - if (doesFileExist (startupDir + "\\vr4life.ms")) do ( - fileIn (startupDir + "\\vr4life.ms") - ) - - messageBox "Instalação VR4Life Concluída!\nO menu aparecerá após a inicialização da UI." title:"VR4Life" -) \ No newline at end of file diff --git a/instalador/mzp.run b/instalador/mzp.run deleted file mode 100644 index 2530fd5..0000000 --- a/instalador/mzp.run +++ /dev/null @@ -1,8 +0,0 @@ -name "VR4Life" -version 1.0 - -copy *.* to "$temp" - -run "install.ms" - -drop "install.ms" \ No newline at end of file diff --git a/instalador/old/Instalador_Online_VR4Life.py b/instalador/old/Instalador_Online_VR4Life.py deleted file mode 100644 index 6148b97..0000000 --- a/instalador/old/Instalador_Online_VR4Life.py +++ /dev/null @@ -1,88 +0,0 @@ -import os -import urllib.request -import shutil -from pymxs import runtime as rt - -# ========================================== -# CONFIGURAÇÕES DO GITEA - IMMERSE GAMES -# ========================================== -GITEA_RAW_URL = "https://git.immersegame.com/vr4life_public/vr4life-3dmax-plugin/raw/branch/main/" -GITEA_TOKEN = "3831a0da2f87e391f41f4649d48498136a1903c9" - -# Caminho onde os scripts são instalados (Documentos) -user_scripts_dir = rt.getDir(rt.name("userScripts")) -PLUGIN_DIR = os.path.join(user_scripts_dir, "VR4Life_Plugin").replace("\\", "/") - -FILES_TO_DOWNLOAD = [ - "vr4life_ui.py", - "vr4life_engine.py", - "vr4life_cloud.py", - "run_vr4life.py", - "vr4life_updater.py", - "install_vr4life.py", - "vr4life.mnx", - "version.txt" -] - -def install_from_cloud(): - rt.clearListener() - print("=== DEBUG DE CAMINHOS VR4LIFE ===") - print(f"Diretório de destino dos Pythons: {PLUGIN_DIR}") - - if not os.path.exists(PLUGIN_DIR): - os.makedirs(PLUGIN_DIR) - - try: - for file_name in FILES_TO_DOWNLOAD: - remote_url = f"{GITEA_RAW_URL}{file_name}?token={GITEA_TOKEN}" - local_path = os.path.join(PLUGIN_DIR, file_name).replace("\\", "/") - - req = urllib.request.Request(remote_url) - req.add_header("Authorization", "token " + GITEA_TOKEN) - response = urllib.request.urlopen(req) - - if file_name.endswith(".mnx"): - with open(local_path, "wb") as f: - f.write(response.read()) - print(f"MNX baixado para: {local_path}") - else: - remote_code = response.read().decode('utf-8') - with open(local_path, "w", encoding="utf-8") as f: - f.write(remote_code) - print(f"Script baixado para: {local_path}") - - # --- INSTALAÇÃO DO MENU --- - pasta_macros = rt.pathConfig.getDir(rt.name("userMacros")) - pasta_enu = os.path.dirname(pasta_macros) - pasta_ui_usuario = os.path.join(pasta_enu, "en-US", "UI") - - if not os.path.exists(pasta_ui_usuario): - os.makedirs(pasta_ui_usuario) - - # AGORA GARANTIMOS QUE O PATH DE ORIGEM É O PLUGIN_DIR - origem_mnx = os.path.join(PLUGIN_DIR, "vr4life.mnx") - destino_mnx = os.path.join(pasta_ui_usuario, "vr4life.mnx") - - print(f"Tentando copiar MNX da origem: {origem_mnx}") - print(f"Para o destino final: {destino_mnx}") - - if os.path.exists(origem_mnx): - shutil.copy2(origem_mnx, destino_mnx) - print(">>> Cópia do MNX realizada com sucesso!") - else: - print("!!! ERRO: O arquivo vr4life.mnx não foi encontrado na pasta PLUGIN_DIR após o download.") - - # Executa o instalador local - install_script = os.path.join(PLUGIN_DIR, "install_vr4life.py").replace("\\", "/") - if os.path.exists(install_script): - print(f"Executando script de instalação: {install_script}") - rt.python.ExecuteFile(install_script) - - rt.messageBox("Instalação Online concluída. Verifique o Listener para o log de caminhos.", title="VR4Life") - - except Exception as e: - print(f"ERRO TÉCNICO: {str(e)}") - rt.messageBox(f"Falha na instalação: {str(e)}", title="Erro") - -if __name__ == "__main__": - install_from_cloud() \ No newline at end of file diff --git a/instalador/old/run_installer.ms b/instalador/old/run_installer.ms deleted file mode 100644 index 7ffa1c4..0000000 --- a/instalador/old/run_installer.ms +++ /dev/null @@ -1 +0,0 @@ -python.executeFile (getDir #temp + @"\VR4Life_Install\Instalador_Online_VR4Life.py") \ No newline at end of file diff --git a/instalador/old/vr4life_startup.ms b/instalador/old/vr4life_startup.ms deleted file mode 100644 index 2d15f19..0000000 --- a/instalador/old/vr4life_startup.ms +++ /dev/null @@ -1,50 +0,0 @@ --- VR4Life Startup Loader - Versão Dinâmica 2026 -global LoadVR4LifeMNX - -fn LoadVR4LifeMNX = ( - -- Procura o arquivo MNX na pasta de UI do utilizador atual - local uiPath = (getDir #userMacros) + "\\..\\en-US\\UI\\vr4life.mnx" - - if (doesFileExist uiPath) then ( - try ( - menuMan.loadMenuFile uiPath - menuMan.updateMenuBar() - format ">>> VR4LIFE: Menu carregado dinamicamente via CUI. <<<\n" - ) catch ( - format ">>> VR4LIFE: Erro ao injetar menu. <<<\n" - ) - ) -) - --- 1. DETETAR O CAMINHO DOS SCRIPTS PYTHON DINAMICAMENTE --- O MaxScript procura na pasta de scripts do utilizador -local scriptsPath = (getDir #userScripts) + "\\VR4Life_Plugin\\" - --- 2. REGISTAR MACROS COM O CAMINHO DETETADO -macroScript VR4Life_Launcher -category:"Immerse Games" -tooltip:"Abrir VR4Life" -( - on execute do ( - local sPath = (getDir #userScripts) + "\\VR4Life_Plugin\\run_vr4life.py" - python.executeFile sPath - ) -) - -macroScript VR4Life_Update -category:"Immerse Games" -tooltip:"Atualizar VR4Life" -( - on execute do ( - local sPath = (getDir #userScripts) + "\\VR4Life_Plugin\\vr4life_updater.py" - python.executeFile sPath - ) -) - --- 3. GATILHOS DE EXECUÇÃO (Lógica Babylon) -callbacks.removeScripts id:#vr4life_setup -callbacks.addScript #cuiRegisterMenus "LoadVR4LifeMNX()" id:#vr4life_setup -callbacks.addScript #filePostOpen "LoadVR4LifeMNX()" id:#vr4life_setup - --- Tenta carregar agora -LoadVR4LifeMNX() \ No newline at end of file diff --git a/instalador/vr4life-plugin-install.mzp b/instalador/vr4life-plugin-install.mzp deleted file mode 100644 index e7170b6eaf9ab49f8e9352ae15dacb15c29337ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4122 zcmai%cT`hr*2V(?X(GKzZ(dqx(iH?kCxog%XoeQy(wkK2y+|PRB49v@bP&NrKq3N4 z?;=tK1r(G-iU^ZC%R4%sGvB;t?X%W-|M=~-p0)Sc&o(gxk}(4S07?L-yOpi$et?!Z zDFDDj4ggRSZ{5871K=JWlAiuK7KRy<>hz0(zKPG8eBvCb2Hb@dq=6|~T3RS;K0{Nu zWftp4FXKpo#Dz4gCdcOt;WD+8BeyGV^&6}QMc7}*S_U1TaO_R*_7$CPaFawyo7@zh zGP4m$j+~*Y?45YV>FM-%irk>-Li#>I9)U?D@AL`&04mTAfKUs%-$t!!r$OoZbgiWQ z=4_YpWVZ4W*DHp3~?B< z`E|6FknRkJp&~kVW!XQl6o6TKY%D4_F0xqXrzRMQo`FI*)3Nyu??bt_z+J-P)UC3> z!Dr4n?pZwOB8HgFu~REbPWrFnhht%4T@B=gddg|DUNtP}De1>k9`fv$KOB7%?o10W>A$hf$X(FNGV+|O`pUp^Rr#|k&e0)_&CZp+ z<+MQ->e@rVFF=-^7K>>9QzhnCD?zi+uRARli>7HDiar(kzcx|T>9t$JIIyzeH54hQnDci1u;BBeI)$?y{->5Q%CX91IFz3cr)$~YEU1iRV4(~ z(2!x7ura4bS}>l9D4?gzy@j^ zXBlFZFWG)(U3asx&7P}%2P6RiOo+uyL(CfFC+Fej>LTgs6^za5HSCjS?%$0$0}rT5 z+D)LNXZT}e-%Cz>tabZR5wF1QrucQUNJ**!h&{Z(pBdhL5OLSC0SdmGL0{#CXBqJl z(ODk8b>$4U;<>L*jp@QZ6;nKJBZ<5f^EI2ZuWVB!f0ZWX`df;z%W`W^69n-e1YrwF zOcRpi@;I3sh6^#s8@IF{Tg3laGCs4;F2DE&9Dh4{wgiYdjJu=p$9jprs%h6L&z-99 zMy)1Ib;%wE=?q;vd-`@~b(otvh{Xpw?DA|Ly1G-UR(x&tczKvJE{`CMOC}AS0z%H% zlZGHPUL5cX6;M6sYs}bZfKDe_t|=i;eF2+(BQnWcQgWy7%1^Dp&Q`XSA3_`~i8{so zX!?I?<&U)(_Ij;O|5Whv1@leEx)^h)NII%bKb|>D1XW8RBsUj3Kl3)w^)>@O{umGu zhp|F@XVOFgxA@iaT~zmn!7u;b^WVu_v~&xzRu{7%(t83iyqR@+nfvtcM!C=#hpOiD&u?(Ll_uR zhlENOjUd+0`VtVac1)LU#|0ndPN|d?T%C3~(;?+}f-#M#q69&~-LJ3%rcun%GFw|# zSKrd0t>06xKbziucg=49_8AKOos7^#uf}9ek*RR@QQg7iy-1wBz>7in*pN^1g^KUE+3{$&uc{{yEolc1C;P**D#!s4G81q(dijLhCD z16967qP9`2hLFhle#uTuTebp^YM`suk*0B^39E7B z^P7HD0lLxOux&tg*&J7}=XP1kxc+RlaA&oBf@5xb%ssUIv;wQZN~U$vg~m#yNo7k#1 z%;X@%R&_A(2t>GfNfG}Q4u4mqPl!=wGqg{dKH)$wB+=ZOk;)~Sss<=g4c6V59Je*2 zd7*%K!fc=P$1>Hiqit5g^7GTt)6u0!S4w+E+-NY3T5fy+0b{)nV|DQbjtZ?a_Jz6b z`ONCfO>)eYScifba1eTtOEJ0pb8k2w46kZH^yV%`*9Uo%Ryy4u8t<8|h#$;Iq;9^P z%dicTQ8`2e*(blDRJP_BA`Jkwl+(|(PrFwmwicOV8iGgeQQ8OHl;yB*9xfu=&z@{5-DMGFb_p%_WyxD0e#b4z!OgzD$) zIG7UXvOknhj^J_liMnp9r3MKbMg>vNz$Vb{(~jhOV%)M zk>Kia9}0f7#i6dpzJClira2F(scrLBQcCL*r5TOAW3mL%rvt87U=6*p-^+n%W# zGRW$0y@(WcR*Nkb_7ExP#^8g_0=yNK-hO9i@42#kzHMYW=)vUX>rLSSH8>uO407Ks zDSrbAPBSjm5#>}J%&r)1&2Y{unTX3E8S^!8C{7v8=dhv}2;?vDO=?H0oZ%Pg!V)(E z(wf_I>*hzPFG@gW#5WBo;B@sA8aVyLUL8aQEowxQ7iotGHh|nPQdULog$@U=}r1z zd(jdTz3iwKbzkIsdtt6|4B`{y>>|IU;&CXN`)=C?70r0y$S5~#M~SKO-5+=1DZw$* zS0~R-Fq`62-f@tEppr$+$$MAZI+JEXzfE!}pK7ZsP(9lHmT~a?A@tyz>T&ZgEPigsTCI#e2K%?csG! z=;b4wmm?kp=NqryB8VI`ywARaN?ou!R(E%`t>T}MQ42qP1{6}m>090c0{d)OXd9%m9?kQVh*Cl1+Q<39! z=>{KtypdqNuKK1F?YQ!!F*{JeiSwU<8Xl#`dj@C)O6EU{3L-1YKYj+uNb}09dgV9s z;511;->;ZpZ_zn!_x&i>iq6rdp>7XlW!a&sR4`*Zlsk2YQANnwHN}xKB+)w*n%@y>3LZ5T*GJ~1?XcR={^+Qa3kx+tA z##)<;WT?2Fd~OzX$(29RPWd= zPtGZ$O`xU@ifh5Z{CI)MEbSeJ92plf>!ZfQF~=r5VQNi{$@A~LZa;FCefgDYQY#8E zwuM~qyltJoe{{3UV_KzHftSRcW^&|BQcA`NmH zx3-XUpj{Haz=J)!WT-IjD?nJvZ?-Tqo5R`$>-G!Ca#;%YlCR(HPK0XRT?Z$F7tj-* zEycu-;ro@Hor{-^s7+mMvns1h1WF0Fxx(JBe&YC+mo+d|Z!Miz0(-t7QvBjdlUifP z!=B5$P%BNsD+zFiYkJluf8N>xlB4Ql&*Y1Msuj-5z3;;7V62OtFr)mMt)lW?Wl;!g zs;-YSV((&}r5;;LR@ma+0BsW$OXz7xP$@TuEF26U;utjO8=sQ5N}yWQh#E&5Ynx=8 z&Y0G?eBfeQ^?XHbqMZ@2guLV5AIjGOE$TnCbb2n1jMtYrjjhJ>W4GWDTd@S1Vs3Aq zv0~#8{kILGI4yXQLHj)@p{p%|R&JK+Q(NFL?fdntPDD3k^TA2=y{LfQ^R-Fc@WH5p z?Wuq-lB$9!Zjtv7OOV@6P_mm+8SjddzQSO`{0ak&rr9cFs;3~dr0AoSLRT&}Y*8d@ z+tHm$=uIDC+6RR%Tchn%aLnIuwYi3@?|PAF9x+x5?6*wH>j>k%Db3CAv?himq}Krd zZTk} - - - - - - - \ No newline at end of file diff --git a/instalador/vr4life.ms b/instalador/vr4life.ms deleted file mode 100644 index 8ec1960..0000000 --- a/instalador/vr4life.ms +++ /dev/null @@ -1,42 +0,0 @@ --- VR4Life Startup - Nomes de Arquivo Originais -global LoadVR4LifeMNX - -fn LoadVR4LifeMNX = ( - -- Busca o MNX na pasta de UI do usuario (en-US\UI) - local uiPath = (getDir #ui_ln) + "vr4life.mnx" - - if (doesFileExist uiPath) then ( - try ( - menuMan.loadMenuFile uiPath - menuMan.updateMenuBar() - format ">>> VR4LIFE: Menu carregado com sucesso! <<<\n" - ) catch ( - format ">>> VR4LIFE: Erro ao injetar o menu via MNX.\n" - ) - ) -) - --- Registro das Macros apontando para a pasta VR4Life_Plugin nos scripts do usuario -macroScript VR4Life_Launcher category:"Immerse Games" tooltip:"Abrir VR4Life" -( - on execute do ( - local pythonFile = (getDir #userScripts) + "\\VR4Life_Plugin\\run_vr4life.py" - python.executeFile pythonFile - ) -) - -macroScript VR4Life_Update category:"Immerse Games" tooltip:"Atualizar VR4Life" -( - on execute do ( - local pythonFile = (getDir #userScripts) + "\\VR4Life_Plugin\\vr4life_updater.py" - python.executeFile pythonFile - ) -) - --- Callbacks para garantir que o menu apareça após a UI carregar -callbacks.removeScripts id:#vr4life_setup -callbacks.addScript #cuiRegisterMenus "LoadVR4LifeMNX()" id:#vr4life_setup -callbacks.addScript #filePostOpen "LoadVR4LifeMNX()" id:#vr4life_setup - --- Tenta carregar imediatamente -LoadVR4LifeMNX() \ No newline at end of file diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db deleted file mode 100644 index aa5d6e1877ba096aaa27cf3251fef8ec933c4dcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69632 zcmeI&O>g5w7{GD6+l|w_wCTyGO0KGsM7vrxsw%_*iI6(QZ0dAV7g`Avg~q!Zwsp2` zDwdc&T`lbvi^~p*kjMw&+nP>B$^&Q?M-I3_H24} zF`8*RQcYS~l0MZmNs`LqZ(aOFuaekUj&{VSoY-EpS(Y9>`>VS4k5p5-((0dUzpehf z`a$)g`gi50@}r7X`gP^I;vYq+_>0n2eqYoG

~v00Id7KLy;%nxd+z?0!EReS2025)&8ufYjwY@t~IJ9O}y&HxULzdrSIzl&Fov6dED!1hXdoFJvh~# z=%-ry*yoU#4-`tn@N z@Wau~Z0he1{rba}|FQ0FR26k=OTLx;J2$)<_P9Gaw-cMI=_nFM-ZvKSLWiT-i-n== zt`<~dYf&hPI~leTJ8N#OqNv7>?6xLeM8?Um^Ww&N>Bro?vM+CJ=j?}|%ot}Js)i98 z=AM2c67|mdb**n|^^8`8PEafo-Mlr+in_BSzv=kW8K-9yRnqbqXT%xs4`y|#RLA+x z6W;RN?VDjk-Tpu~_D!#cHo}WGwSnH%2fEqOk2JsRVD#$M#ChH@#!ZiBPw(ks9CX@8 zo%Wud(U6}S@8m>7epz-4qL*Km6!qh6*h`w$W+l#Hcv>>(m5i*#t-aUaH%AwC_F##!+_RnM-hi5autdkhSQZ^mCO0@W zm6F6DTbP)SRtoBq?L}iY2{mjb_e$Se9lHRovAako%!c#MrZYJCFPQgV&H-QQf4ocMafR=lk^%Zj?YA-ifc)b^%lHy47+A7me==wu-Ya~7_6+Tfn_yP^vOVa0-X1h|A3tu!6LqKG>v`V_ z%)WRYMi0Y!Z*)ET>PpPj*5txIo}Jz8vte=r+eUPirpW4tO9i#Fu_&uiIKx)7bx(Yc zDth0gs@_}8d*g)w0tg_000IagfB*srAb;L)BF%cqw00IagfB*srAbt>u diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-shm b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-shm deleted file mode 100644 index 12f3be4dd3b5a2b5146f36630acbf7e99e490797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeIufdBvi0Dz$VsTV1P3IhfV7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj GFkoPS00031 diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-wal b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/CodeChunks.db-wal deleted file mode 100644 index 393ce4dcc30bb430294cca4f5c060333f2270ec4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824032 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 EKl|Vy?f?J) diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db deleted file mode 100644 index 330f6d0d57e6ebf2865f55f4876407ffcbef73e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49152 zcmeI)U2ob}7zc11l0e8?r(K||igwgVGpHo#G)0wKbsGUE^-4_(rY~A0~o&q^Bm*IRqOXF z7Ng|E^|}TlA15v)78Vkp5t2wGR`~B4|BV*0z8HPr@6yQnwAGcw?#b`#n|~!XmX;D5 zzis}!@x#W4t6yjS$$XdoHT@*@Q|goDAD4dNJF!3j0ucB=1p1$Eq%L3GN`LhQ^Q?B8 zdb-!Hzw92nw(9uQW5Ifa=|H4+@Oo;gsCRBb&& z_!90^HN6_{F1g)Pn=;FFa-Mr;nFZ2tp7jjdI8=NpRNyrdHqg2m@?&E(KiPZvfK`PF}b5WE|BMW@=(=pR~tI1RUfM5{?ckHd+V0e-<~`M({1_ItBYd`x3A6^Mc7Qv zSthR?T@htBHXi>KIjB?*^8I%+sqFr~)K@2u!!lo72$65g%;=vtk#jz6i@Idg>lVmq z+i?q{V;J3?kLi55lFDAcJ{`wk#)VOteB;WDVTm@=O^$81^)z64EvHl2ot^Zz$%!oS z&ckjWs5QM&tPp*2ZOEiiSG6N@!u{B~{E_1b%)|J@Gj z+8@vtJUNbGi>ejh=A>2z#feuE$8%^(bjmhkAxh{NAz8&*iiUzlm&h_{x76^{^j4 zuslnpvY&48Qn4J9zEB@EgWNP@u))@Jm?%{%E02ggwY4m+T;bf7N$x_H^8LkSK5cln zN3m|pZmZYjlByZ>n3~q(dBb>TBYO%&R(OgWR%eFCcqN1%E7WPTj-3DI{iRfPYfJim z^hy?VygX?t@L0mSQ%!l&g@F_sdR5i`+#PSkrU8+_p;;T}tmWp-pHhwU_8VlS&BO1!IRw2^VX5ve7 z#+gKuS*JO0&6hJyBbv-Q&1jyd4moHv>r_Dj+~JjZp5wUWUCKJHS-0Ab!FnDYPeYii z!)i@Yk2LWGmOC$jJgF&%N=?y9{H`L}oKwxbm^0z`K2Kh$SXTJ-bQbwM*_Qg*Xr4qz zG!HGC-ZNMy+OQNBY(rD;Hxy0~P0^^q@Q7f-M4QF@jLs$J?9&-nun^Ba_kD|3C zzs*jITkUo6a!I^kfdB*`009U<00Izz00bZa0SG`~UIj8DF#P>Lujxfx5P$##AOHaf zKmY;|fB*y_0D*x3p8ul|AOHafKmY;|fB*y_009U<00Q$bfam}7pJPM_0SG_<0uX=z z1Rwwb2tWV=5Ww?))Bpq^009U<00Izz00bZa0SG`~{sr*-fBtif2q6Fg2tWV=5P$## zAOHafKmY>x`yVv`0SG_<0uX=z1Rwwb2tWV=5SV`f@$df^HvdR${>@*oKmY;|fB*y_ z009U<00Izz00bZ~4+5D?GVxv*NK#5B*6{p)9@2^!AOHafKmY;|fB*y_009U<00M6o z!2kdEW*_W@00bZa0SG_<0uX=z1Rwwb2+V_kc>XVK{+ZxESReoa2tWV=5P$##AOHaf WKmY;|m?MGJq diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-shm b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-shm deleted file mode 100644 index 12f3be4dd3b5a2b5146f36630acbf7e99e490797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeIufdBvi0Dz$VsTV1P3IhfV7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj GFkoPS00031 diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-wal b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/CopilotIndices/17.14.1593.33849/SemanticSymbols.db-wal deleted file mode 100644 index 837253b1feaad481ba72a2bad459faff51a922d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572712 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 DXVTW( diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/16a0fc13-034b-44a7-8fb8-e088c864a783.vsidx b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/16a0fc13-034b-44a7-8fb8-e088c864a783.vsidx deleted file mode 100644 index 48c9143a5887ae308deafb29052a4ccf0ba5067b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6075 zcmYkA2Vj-e8HP^~0VjfcM^H%=B1!}WM{e%D3D@M_8}5H^3^Xl-A!1`dKx=o3-F6S{ z-gfU{cN?{>-P3Nm_tNfN+V}nb=TgI;_c`Y~-}%n^&Ot1e1{cgr>Gl&-{A|dPM#a+V z@$EbIZkrgtX?O4Bj%&6pTe0=}iJO=0n!IuQj;Zk-Q+xJKOipawxx2XM+KJt}#zz~y z!}i)bIoU23cTP=h+p>4(?w&1s=I%exyz`Fz9SdjYLmUz~G9`VpQkr^DK~=T(g}pPS zj+CZTQekOWG~1r|3ehAtHK~iVBPAK9qpzy^9v`Y`$3#qxrM`XfX&!P=7qy-imitqZ zQI<{7l)GtSvdFF>^cBKi4l3wVghOM*Em4)5K6O+~X-AB!5$_F8jjm}Zi0t_%x3$qR zUs@qTO-En3&BT&(qoT>P(D)G!4CI=0qb!i}-rkdoea$kG6 z{M==qiMfqDXsXlg$!par9~Is6a$i{Hq_ioFswzn|Jry(u6*Nj`s4N;zy_6673Sm@L z=PMt5vgp%(PRG!jqNDn1U9xL>`@&6@zHrb+-4;Fyt4)xq>EMWJRj=GrG3T}qPR4xZ z9Vy+?UaUH*ntwV(h1waz9kfq}=fNQqK_kkTFGMjlM7{|stCyxB?Tg)zsx1GR=%V$? zS#FwAM_A-M9cB5*qV>u_1^LTO1$}Coci-VDel)}Qk=af0s~ABYe^CBGO)#j*1vO~U zG2Hhs=+Leo0kzbq>#T!E!}(A<5cUOdAv_iy2aktZQTY2A^*ATNli?}wRHzgUztiCv z@J!eV&w`8KVt6(@2c8R;z%JMg&x7Z~rEnQk`o(-MfXm^9@FKVZ_QH$dO1KJM0xyND z;Tm`uyc}KuuY`TD0Q+GPmS7nUz(J@ijP+FDRd5In!z!%7Ivj!PU;}2b30rU!UJb|K zdg#Abofi**U|fY-r?!%28OoPv56VxGI;4RANy z1NXuk;Z5)n@Mic(_$c^j_!#(D_&BJ?A;zDEPk{U2E%1r(N$|<=De$TAY4GXrR`?9~ zO!zGLZ1^1bT=+creE0(RLUX(d1K$hZ2k(UMhaZ3+gdc(*h97|+g&%_-hcoal zcsINUegb|HehS_TKMg+vKMOwxKM%hEzX-nszYM!-S9kkK3ocy z!5(-4Tn;aU7r_;<7hVik!d37Rcqv>B*TBo*6{pk*^gl3_m(n_jIvs9Ljrbb$v zim4@ad5PKzsVjO~yH)N_b!k~GUHa`0Efd=#tkFL!3aKP5Dnd_qTE|o#&}cnrP_>?j z+>>e=t4DseWa`nQdM$J$El(@b%J^NKdi77YN?H}R)iJw*yvrJ?n1(`|F={E)_LBSy zF;+pPn#zt~9hO$3Z&hn4#CX<1lpUd=Raw1~hGG;nw@liMUd@Q(c@{KVk2|JSTQlv4 zXJl|njD^Kn}(v=Qo7N4L7~koKe$dsvDU zl{9L%EIvDHS$~{sWsTk~^~vX_WcB`eHP*b`Qn{o&v)aEsJ4bT1l(qZ0+Ow*)SPP-v zU!SAZF{?3tEh0Ow%GxE*q!C_?*ttgdG?d-makpj>)AM(EDAduiG!p7K&4|#9m}9Ct zn?0+I+6ik*bM?Bd#n5W#MyYep8B~p2EQK~>RhhIEcIT4M-lv-9sk6iTUJk8DeTLS$ z)Z_TxR;4~It1TYMYX4fa)}uC}6;xvV6|E~%ISY%=z~^fJ4J!L|bFD_%`;p1!EX+b% zQfIgCQZaNObc56_!KX8 zot4f+`&ShA|M#b^vTvsEk8{X3-6zp4^;ui(;dk0M%4NS9?lTyg_xG$F-}&WtzpmZ0 zdgr`W=crHHZ>!a}(OGJB1g|$s>!a>h#e3nM^BuJ2FHJSdjnKTm?fF~jvvAob>i5>U z=2oAT)xErWt6RMqt6M!czXjfRuidlp-vrKnYgOvoX0@MhgEPZE&SYyv>fE%JLhbJp zwvI}DO5P89dQH~6oaaO}G9!zVC`z4Q&Vb&~s_vPy+V4~*_5Abw@;&d0m#Yvj*GT*~ Tf@QXT=To}@-fE+Mw$t!G=z<|5 diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/73ed949b-84be-45c9-a9ca-79230739efcd.vsidx b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/FileContentIndex/73ed949b-84be-45c9-a9ca-79230739efcd.vsidx deleted file mode 100644 index 6571a06dbe6e48a8cbfd8c9255fd83f65f5e41d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6371 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 diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/.suo b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/.suo deleted file mode 100644 index ba284842ba6647653b44a10ba916cd7a3c6009a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70144 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 diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.backup.json b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.backup.json deleted file mode 100644 index 30edca4..0000000 --- a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.backup.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "Version": 1, - "WorkspaceRootPath": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\", - "Documents": [ - { - "AbsoluteMoniker": "D:0:0:{77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}|VR4Life-dll.csproj|d:\\gitea\\vr4life-3dmax-plugin\\instaladorcsharp\\vr4life-dll\\class1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}|VR4Life-dll.csproj|solutionrelative:class1.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - } - ], - "DocumentGroupContainers": [ - { - "Orientation": 0, - "VerticalTabListWidth": 256, - "DocumentGroups": [ - { - "DockedWidth": 200, - "SelectedChildIndex": 0, - "Children": [ - { - "$type": "Document", - "DocumentIndex": 0, - "Title": "Class1.cs", - "DocumentMoniker": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\Class1.cs", - "RelativeDocumentMoniker": "Class1.cs", - "ToolTip": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\Class1.cs", - "RelativeToolTip": "Class1.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-02-24T17:44:29.473Z", - "EditorCaption": "" - }, - { - "$type": "Bookmark", - "Name": "ST:0:0:{269a02dc-6af8-11d3-bdc4-00c04f688e50}" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.json b/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.json deleted file mode 100644 index b0b9efe..0000000 --- a/instaladorCsharp/VR4Life-dll/.vs/VR4Life-dll/v17/DocumentLayout.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "Version": 1, - "WorkspaceRootPath": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\", - "Documents": [ - { - "AbsoluteMoniker": "D:0:0:{77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}|VR4Life-dll.csproj|d:\\gitea\\vr4life-3dmax-plugin\\instaladorcsharp\\vr4life-dll\\vr4lifeconnector.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}|VR4Life-dll.csproj|solutionrelative:vr4lifeconnector.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - } - ], - "DocumentGroupContainers": [ - { - "Orientation": 0, - "VerticalTabListWidth": 256, - "DocumentGroups": [ - { - "DockedWidth": 200, - "SelectedChildIndex": 0, - "Children": [ - { - "$type": "Document", - "DocumentIndex": 0, - "Title": "VR4LifeConnector.cs", - "DocumentMoniker": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\VR4LifeConnector.cs", - "RelativeDocumentMoniker": "VR4LifeConnector.cs", - "ToolTip": "D:\\gitea\\vr4life-3dmax-plugin\\instaladorCsharp\\VR4Life-dll\\VR4LifeConnector.cs", - "RelativeToolTip": "VR4LifeConnector.cs", - "ViewState": "AgIAAAsAAAAAAAAAAAAAABsAAAAPAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-02-24T17:44:29.473Z", - "EditorCaption": "" - }, - { - "$type": "Bookmark", - "Name": "ST:0:0:{269a02dc-6af8-11d3-bdc4-00c04f688e50}" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/instaladorCsharp/VR4Life-dll/Properties/AssemblyInfo.cs b/instaladorCsharp/VR4Life-dll/Properties/AssemblyInfo.cs deleted file mode 100644 index 845a823..0000000 --- a/instaladorCsharp/VR4Life-dll/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// As informações gerais sobre um assembly são controladas por -// conjunto de atributos. Altere estes valores de atributo para modificar as informações -// associada a um assembly. -[assembly: AssemblyTitle("VR4Life-dll")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("VR4Life-dll")] -[assembly: AssemblyCopyright("Copyright © 2026")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Definir ComVisible como false torna os tipos neste assembly invisíveis -// para componentes COM. Caso precise acessar um tipo neste assembly de -// COM, defina o atributo ComVisible como true nesse tipo. -[assembly: ComVisible(false)] - -// O GUID a seguir será destinado à ID de typelib se este projeto for exposto para COM -[assembly: Guid("77a5dd7e-6edb-4b04-854f-7cca6d6195ea")] - -// As informações da versão de um assembly consistem nos quatro valores a seguir: -// -// Versão Principal -// Versão Secundária -// Número da Versão -// Revisão -// -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/instaladorCsharp/VR4Life-dll/VR4Life-dll.csproj b/instaladorCsharp/VR4Life-dll/VR4Life-dll.csproj deleted file mode 100644 index 26c66b0..0000000 --- a/instaladorCsharp/VR4Life-dll/VR4Life-dll.csproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Debug - AnyCPU - {77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA} - Library - Properties - VR4Life_dll - VR4Life-dll - v4.8 - 512 - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - C:\Program Files\Autodesk\3ds Max 2026\Autodesk.Max.dll - - - C:\Program Files\Autodesk\3ds Max 2026\ManagedServices.dll - - - - - - - - - - - C:\Program Files\Autodesk\3ds Max 2026\UiViewModels.dll - - - - - - - - \ No newline at end of file diff --git a/instaladorCsharp/VR4Life-dll/VR4Life-dll.sln b/instaladorCsharp/VR4Life-dll/VR4Life-dll.sln deleted file mode 100644 index 1223eac..0000000 --- a/instaladorCsharp/VR4Life-dll/VR4Life-dll.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.14.37012.4 d17.14 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VR4Life-dll", "VR4Life-dll.csproj", "{77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77A5DD7E-6EDB-4B04-854F-7CCA6D6195EA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EFB2829D-890A-4C8E-B553-764D075AE04F} - EndGlobalSection -EndGlobal diff --git a/instaladorCsharp/VR4Life-dll/VR4LifeConnector.cs b/instaladorCsharp/VR4Life-dll/VR4LifeConnector.cs deleted file mode 100644 index 3cd9143..0000000 --- a/instaladorCsharp/VR4Life-dll/VR4LifeConnector.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using Autodesk.Max; -using ManagedServices; - -namespace VR4LifeConnector -{ - public class VR4LifeMenuLoader - { - public static void Initialize() - { - string bootScript = @" - ( - fn setupVRMenu = ( - local mbar = menuMan.getMainMenuBar() - local existing = menuMan.findMenu ""Vr4Life"" - if existing != undefined do menuMan.unRegisterMenu existing - - local m = menuMan.createMenu ""Vr4Life"" - m.addItem (menuMan.createActionItem ""VR4Life_Launcher"" ""Immerse Games"") -1 - m.addItem (menuMan.createActionItem ""VR4Life_Update"" ""Immerse Games"") -1 - - mbar.addItem (menuMan.createSubMenuItem ""Vr4Life"" m) (mbar.numItems()) - menuMan.updateMenuBar() - ) - callbacks.removeScripts id:#vr4life - callbacks.addScript #cuiRegisterMenus ""setupVRMenu()"" id:#vr4life - setupVRMenu() - )"; - - // RESOLUÇÃO DO ERRO CS7036: - // Adicionamos o segundo argumento 'MaxscriptSDK.ScriptSource.Embedded' - // Isso indica ao Max que o script vem de dentro da DLL (embutido) - MaxscriptSDK.ExecuteMaxscriptCommand(bootScript, MaxscriptSDK.ScriptSource.Embedded); - } - } -} \ No newline at end of file diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.dll b/instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.dll deleted file mode 100644 index c309ffe550a37c5bc703b307926a3a3a12558ce9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2543904 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

nxgy5= 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 z

-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�LxSFqd_(sg-K&=N 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

e?3F`l>a$H9{L22e)-5_;O{f! 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�`%tOeIo7AD+AtI({ocYi0#R`6$QCWu*0Ppt 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 diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.xml b/instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.xml deleted file mode 100644 index ff8f37a..0000000 --- a/instaladorCsharp/VR4Life-dll/bin/Debug/Autodesk.Max.xml +++ /dev/null @@ -1,163018 +0,0 @@ - - - - Autodesk.Max - - - -

- Gets a singleton instance of IGlobal interface - - - - - IDs for drag and drop. - - - - - This enum type tells the viewport rendering system the usage of each texture. This enum type tells the viewport rendering system the usage of each texture while the viewport display is in best quality mode. Currently we don't support MAPUSAGE_BUMP, MAPUSAGE_FILTER_COLOR,MAPUSAGE_REFLECTION, MAPUSAGE_REFRACTION and MAPUSAGE_DISPLACEMENT. NOTE: MAPUSAGE_SUPPORT_PROGRAMMABLE_PIPELINE flag at least for texture stage 0, if you want to use the programmable pipeline to render this material, else it will be degraded to fixed pipeline even viewport is in the good or best quality mode. - - - - - Used for normal and vector displacement map generation. - Moved to SDK since FBX also depends on this - - - - - This enum can be used to specify axis under a variety of scenarios. For example, passing kXAxis to GetRow returns the vector that represents the X axis of the transform, and accessing a point3 the enum returns the X, Y, or Z component of the translation. - - - - - The TransComponent enum simply specifies the translation row index of a . The enum is used (along with Axis enum) to construct the MatrixComponent pseudo-enum via InheritEnum. This pseudo-enum can be used in places where programmers need to access the components of the matrix directly (for example, in the functions GetRow or directly in the internals via GetAddr). - - - - - The Clone type when copying nodes. - - - - - Values supported by function Interface7::DoUICustomization. - - - - - Message File From Max to Server. - - - - - Message File From Server to Max. - - - - - Errors - - - - - selection levels. MNM_SL_CURRENT is an acceptable argument to methods that take a selection level, indicating "use the current mesh selection level". - - - - - The 3ds Max file versions the maxscript save commands (saveMaxFile and saveNodes) work with. These values are converted by GetMaxVerFromMxsMaxFileVer() to the ones in Version Macros such as MAX_RELEASE, etc. - - - - - Identifies a parameter type. These enums identify types of parameters (or properties) that can be stored in parameter block and parameter block2, and can be used as argument types and return value types for function publishing. - - - - - Identifies a parameter type. ParamType values are compatible with ParamType2. These enums identify types of parameters (or properties) that can be stored in parameter block2 and can be used as argument types and return value types for function publishing. - - - - - Used to associate automatically-generated UI controls with parameters in a . - - - - - Used to associated automatically generated UI controls with parameters in a . Wherever ControlType2 is used, a ControlType can be used as well. - - - - - The ColorContext describes in what context a color or texture value is meant to be used. Depending on the context, a color value may be interpreted and displayed differently, based on the current color-management settings. - To be used in , following a p_colorContext tag. Only valid for TYPE_RGBA, TYPE_FRGBA and TYPE_TEXMAP. - Example: - - - - - Optional parameter definition tags. These tags are used in the constructor as part of the "optional_tagged_param_specs". The typical format in the var args list is: "tag", "optional_param_spec", - - - - - Return codes for reference handling and message processing methods. - - - - - Specified as argument to NotifyDependents to specify level of optimizations used. - - - - - BlockID Anisotropic - - - - - ParamID's for Anisotropic - - - - - BlockID Oren Nayer Blinn - - - - - ParamID's for Oren Nayer Blinn - - - - - BlockID for Strauss - - - - - ParamID's for Strauss - - - - - The Schematic traversal status - - - - - The Schematic reference types - - - - - The Schematic relationship types - - - - - Types - - - - - types (used by setColor) - - - - - Marker types. - - - - - Facing type - - - - - Various IGame Controller types. - - - These controllers types are used to define the type of controller being queried. - - - - - Enumeration of the Error codes produced by IGame. - - - - - Property types. - - - - - Used to specify the desired type of render when opening a renderer using Interface::OpenCurRenderer. - - - The following 3 types are not passed into plugin renderers: RENDTYPE_REGION_SEL, RENDTYPE_CROP_SEL and RENDTYPE_BLOWUP_SEL. Their purpose is for passing to the function Interface::OpenCurRenderer, which converts them into RENDTYPE_REGION, RENDTYPE_REGIONCROP and RENDTYPE_BLOWUP, respectively. The latter 3 are passed into renderers with the region dimensions specified by the system according to the bounding boxes of the selected objects. These are related to values in RenderUIType enum, but their values do not necessarily match. RendType and RenderUIType are not directly interchangeable. Please note that RENDTYPE_BAKE_SEL, RENDTYPE_BAKE_ALL, RENDTYPE_BAKE_SEL_CROP are not supported by OpenCurRenderer. If used they will act as if RENDTYPE_NORMAL has been used. - - - - - Used to change the current render type in the main user interface. - - - These values specify the render type selected in the main user interface, using Interface7::GetRenderType and Interface7::SetRenderType. These are related to values in RendType enum, but their values do not necessarily match. RendType and RenderUIType are not directly interchangeable. These values may also not match the order in which their corresponding values appear in the user interface. - - - - - Values that may be assigned to ShadeContext::mode. - - - - - Enumeration indexing axes of Cartesian coordinate system, in either possible sense, consistent with return value for UVWMapper::MainAxis function. - - - - - Enumeration indexing axes of Cylindrical coordinate system, including both possible senses of the cylindrical axial direction. - - - - - 3ds Max uses the ExecuteAction() method of an instance of this class when an is executed. Developers need to override this class and pass an instance of it to the system when they activate an using the method IActionManager::ActivateActionTable(). - - - - - Called by 3ds Max to execute the operation associated with an action item - This returns a BOOL that indicates if the action was actually executed. If the item is disabled, or if the table that owns it is not activated, then it won't execute, and returns FALSE. If it does execute then TRUE is returned. - Default Implementation: - - The ID of the item to execute. - - - - If the does produce a dynamic menu (i.e. IsDyamicAction() returns true), this method is called by the system to populate the new menu currently being created to add items, separators, and submenus. Each item is given an arbitrary id (see ICuiDynamicMenu interface). Default implementation is a no-op. - - - Pointer to dynamic menu interface. Pointer is owned by the system. - - Id of that produces the dynamic menu - - If the menu is requested by a right-click quad menu, then this hWnd is the handle of the window where the click occurred. If the item is used from a menu bar, this hwnd will be nullptr. - - If the menu is requested by a right-click quad menu, then this parameter is the point in the window where the user clicked. - - - - If the does produce a dynamic menu (i.e. IsDyamicAction() returns true), this method is called by the system when user clicks on a menu item that was added in PopulateDynamicMenu. Default implementation is a no-op. - - - Id of that produced the dynamic menu - - id of menu item that was clicked by user. Use this id to execute appropriate action. This id is passed to ICuiDynamicMenu functions when populating the menu (for example: AddItem(itemCmdId, ...)). - - - - Returns a pointer to the the callback uses. - - - - - An is an identifier of a group of keyboard shortcuts. Examples are the Main 3ds MaxUI, Track , and the Editable . They are registered using IActionManager::RegisterActionContext(). - - - - - Returns the name of this . - - - - - Returns the ID of this . - - - - - Returns true if this is active; otherwise false. An active means that it uses its keyboard accelerators. This corresponds to the "Active" checkbox in the keyboard customization UI. - - - - - Sets the active state of this . - - true for active; false for inactive. - - - - Represents an operation contained in an . is an abstract class with operations to support various UI operations. The system provides a default implementation of this class that works when the table is built with the ActionTable::BuildActionTable() method. However, developers may want to specialize this class for more special-purpose applications. For example, MAXScript does this to export macroScripts to an . Methods that are marked as internal should not be used. - - - - - Points to the table that owns the action. - This does not 'own' the memory for the pointer - - - - - Retrieves a unique identifier for the action. This action must be unique in the table, but not does not have to be unique between tables. - This should be a 16 bit value (in the range of 0-65,535) as it is also used as a Windows accelerator command ID for keyboard shortcuts, which is a WORD (16 bit unsigned short). - - - - - Executes the operation associated with the action item. This returns a BOOL that indicates if the action was actually executed. If the item is disabled, or if the table that owns it is not activated, then it won't execute, and returns FALSE. - TRUE if the action is executed; otherwise FALSE. - - - - - Called by 3ds Max to allow the to customize macroRecorder output for this action - - - - - Calls ExecuteAction() and handles macro recording etc. Called by 3ds Max. - - - - - Returns true if the action supports AltExecute. If an action supports AltExecute, then a mouse icon (with a dark click button) appears in the quad menu item that corresponds to the action. When the icon is clicked, the AltExecute method is called. - - - - - Returns true if AltExecute ran successfully. If an action supports AltExecute, then a mouse icon (with a dark click button) appears in the quad menu item that corresponds to the action. When the icon is clicked, the AltExecute method is called. - - - - - Returns true if the action supports CloseDialogs. This is called by the internal implementation of IActionItemToggleManager::FlipToggleState to close a dialog if when executing the action the action was registered via IActionItemToggleManager::RegisterToggleAction. If true, the CloseDialogs method is called when toggling the action state off. - - - - - Returns true if CloseDialogs ran successfully. - - - - - Retrieves the text that will be used when the is on a text button. The text is stored into the buttonText parameter. - - - The retrieved text. - - - - Retrieves the text to use when the item is on a menu (either Quad menu or main menu bar). This can be different from the button text. This method is called just before the menu is displayed, so it can update the text at that time. For example, the "Undo" menu item in 3ds Max's main menu adds the name of the command that will be undone. - - - The retrieved text. - - - - Retrieves the text that will be used for tool tips and menu help. This is also the string that is displayed for the operation in all the lists in the customization dialogs. - - - The retrieved text. - - - - Retrieves the text for the category of the operation. This is used in the customization dialog to fill the "category" drop-down list. - - - The retrieved text. - - - - Retrieves the persistent action id text. This can be used to store a reference to an action into a file, like it is done by the menu system. - - - The retrieved text. - - - - Retrieves the persistent action id text. This can be used to store a reference to an action into a file, like it is done by the menu system. - The persistent action id text. - - - - - Returns whether a menu item is in a checked state, or if a button is in a pressed state. For menus, this means that this function will return TRUE if a check mark appears next to the item. If the item is on a button, this is used to determine of the button is in the "Pressed" state. Note that button states are automatically updated on selection change and command mode changes. If your plug-in performs an operation that requires the CUI buttons to be redrawn, you need to call the method CUIFrameMgr::SetMacroButtonStates(TRUE). - TRUE if menu item is checked, or if a button is 'pressed'. FALSE otherwise - - - - - Returns whether an item is in an indeterminate state This is an optional state that can be implemented when the state of the action can be both checked and unchecked. When implemented return TRUE if the condition of your action is both checked and unchecked. For instance an action that sets/displays the state of a multiple nodes frozen property when you have nodes that are both frozen and unfrozen this would return TRUE and instead of a check the action will display a dash. If this returns TRUE the isChecked state is ignored. NOTE actions with pushbutton icons will not display this state - TRUE if menu item is in an indeterminate state - - - - - Determines if an item is visible on a context menu. If it returns FALSE, then the item is not included in the menu. This can be used to create items that a context sensitive. For example, you may want an item to appear on a menu only when the selected object is of a particular type. To do this, you have this method check the class id of the current selection. - - - - - Determines if the operation is available to the user. If this method returns FALSE, and the it is on a menu, or button, the item is grayed out. If it assigned to a keyboard shortcut, then it will not execute the operation if invoked. If your plugin performs an operation that requires the CUI buttons to be redrawn, you need to call the method CUIFrameMgr::SetMacroButtonStates(TRUE) - TRUE for enabled; FALSE for disabled. - - - - - Returns an icon associated with an . First checks the result of GetIconImp(), then looks at ActionTable::GetIcon(int). If both functions return NULL, then this action has no Icon associated with it. - Icon associated with this action. - - - - - Returns a pointer to the table that owns the . An item can only be owned by a single table. - Default Implementation - - - - - Returns the string that describes all the keyboard shortcuts associated with the item. This will look something like "Alt+A" or "C,Shift+Alt+Q". - NULL if no keyboard shortcut is associated with the item. - - - - - Returns the representation of the macroScript for the item, if it's implemented by a macroScript, it returns NULL otherwise. - A pointer to a - Default Implementation - - - - - Determines if a menu is created or if an action takes place. - If this method returns TRUE, then the creates a menu. If it returns FALSE then an action is performed. - Default Implementation - - - - - This method may be called after an action item is created to tell the system that it is a dynamic menu action. - Dynamic menus may be added to the quad menus procedurally (via the IMenuManager API) or 'manually'. - - - - - If the does produce a dynamic menu (i.e. IsDyamicAction() returns true), this method is called by the system to populate the new menu currently being created to add items, separators, and submenus. Each item is given an arbitrary id (see ICuiDynamicMenu interface). Default implementation is a no-op. - - - Pointer to dynamic menu interface. Pointer is owned by the system. - - If the menu is requested by a right-click quad menu, then this hWnd is the handle of the window where the click occurred. If the item is used from a menu bar, this hwnd will be nullptr. - - If the menu is requested by a right-click quad menu, then this parameter is the point in the window where the user clicked. - - - - If the does produce a menu (i.e. IsDyamicAction() returns true), this method is called by the system when user clicks a menu item thas was added in PopulateDynamicMenu. Default implementation is a no-op. - - - id of menu item that was clicked by user. Use this id to execute appropriate action. This id is passed to ICuiDynamicMenu functions when populating the menu (for example: AddItem(itemCmdId, ...)). - - - - ActionItems that are deleted after they execute should return TRUE. - - - - - Returns TRUE if the specifies an icon. - - - - - If the specifies an icon, accesses the icon filename. - true if the specifies an icon, otherwise false. - - - If the specifies an icon, then the icon filename is returned through this parameter. - - - - If the specifies an icon, returns the icon index. - If the specifies an icon then the icon index, otherwise -1. - - - - - Get the Action's tooltip key. The tooltip key may be associated with a product tooltip. By default, the tooltip key is built as "actionTableID-actionID" for native actions and as "Category-MacroName" for macros. - a string with the tooltip key - - - - - Get the Action's path to the icon of size specified by param. - This path can be relative to the Theme- specific Resources folder under the \UI folder, or it can be an absolute path. - The path to the icon of the size specified by the input parameter. - - an enum specifying the icon path to get - - - - Sets the Action's path to the icon of size specified by the input param. - This path can be relative to the Theme- specific Resources folder under the \UI folder, or it can be an absolute path. - - an enum specifying the icon path to set - The path to the icon of the size specified by the input parameter. - - - - Gets the Action's metadata. Metadata format is a single string with a comma - separating each individual metadatum. Metadata is used in global search command to list similar command names in other software, etc - - - - - Returns an icon associated with an . To supply a custom icon for an action item, override this method and supply a custom implementation. Default implementation: returns NULL - Icon for this action, or NULL if not specified by implementing class. - - - - - A table of action items that can be used by plug-ins to export tables of action items that can be used by the UI to attach to keyboard shortcuts, assigned to toolbar buttons, and add to menus. 3ds Max's core code exports several ActionTables for built-in operations in 3ds Max. Plug-ins can also export their own action tables via methods available in . - Every also has an ActionContextId associated with it. This ActionContextId can be shared with other tables. When assigning keyboard shortcuts to items in an , tables that share a unique context id are forced to have unique shortcuts. Tables with different context ids can have overlapping keyboard shortcut assignments. - All methods of this class are implemented by the system. Note that this class may be sub-classed if required and that many functions can be overridden. See the topic ~{ Action System }~ for details on sub-classing this class and . For details on implementing an please refer to the sample at /maxsdk/samples/modifiers/ffd. - - - - - Returns the handle of the current keyboard accelerator for the table. - - - - - Gets the default keyboard accelerator table used when the user has not assigned any accelerators. - - - - - Returns the name of the action table - - - - - Returns the ActionTableID - - - - - Returns the ActionContextId. - - - - - Get the current callback associated with this table. Returns NULL if the table is not active. - - - - - Returns the number of ActionItems in the table. - - - - - Returns a pointer to the nth . - - The zero based index in the list of ActionItems. - - - - Returns a pointer to the associated with the command ID passed. - - The command ID. - - - - Returns a pointer to the nth using the same algorithm as the operator[]. - A pointer to the - - The zero based index of the action. - - - - Appends an to the table. - - A pointer the to append. - - - - Removes an operation from the table - TRUE if the operation was deleted; FALSE if it could not be found and wasn't. - - Points to the to delete. - - - - Retrieves the text that will be used when the is on a text button. - TRUE if the command is in the table; otherwise FALSE. - - The unique ID of the command whose button text is retrieved. - The retrieved text. - - - - Retrieves the text to use when the item is on a menu (either Quad menu or main menu bar). This can be different from the button text. - - TRUE if the command is in the table; otherwise FALSE. - Default Implementation: - - The unique ID of the command whose menu text is retrieved. - Storage for the text. - - - - Retrieves the text that is used for tool tips and menu help. This is also the string that is displayed for the operation in all the lists in the customization dialogs. - TRUE if the command is in the table; otherwise FALSE. - - The unique ID of the command whose description text is retrieved. - The retrieved text. - - - - Returns TRUE if the menu item should be checked or a CUI button should be in the pressed state. - Default Implementation: - - The unique ID of the command. - - - - Returns TRUE if the menu item should be indeterminate - - Default Implementation: - - The unique ID of the command. - - - - Determines if an item is to be visible on a menu. Returns TRUE if visible; FALSE if not. - Default Implementation: - - The unique ID of the command. - - - - Determines if the operation is currently enabled and available. Returns TRUE if enabled; FALSE if disabled. - Default Implementation: - - The unique ID of the command. - - - - Converts an action item identifier to a string representation The textual representation of action item ids are used in .CUI and .KBD files. The default implementation is to convert the integer action item ID directly to a string. - - The unique command or action item ID. - The string where the action item ID is written to. - - - - Converts an action table string id to the action items numeric id. This method can be used to convert string based action item identifiers read from a .CUI or *.KBD file to a numeric identifier. It's default implementation expects the string passed in as argument to contain one number. - Returns -1 if the id could not be converted. - - The action ID string. - - - - Returns an optional icon for the command, or NULL if there is none. - - The unique ID of the command. - - - - Used internally by ~{ Function Publishing }~ - - - - - Description: - This class represents an edge adjacency list for meshes. For any given vertex in a mesh this class has a table of DWORDs. These DWORDs are indices into the edge table (> edge). The edges table stores the edges adjacent to the vertex. So, each vertex has a list of indices into the edge list that give it the list of edges adjacent to the vertex. All methods of the class are implemented by the system. - Data Members: - *list; - - This is an array of DWORDTabs, one per vertex. The is a list of indices into the edge list, one for each edge adjacent to the vertex. - - > edges; - - The table of edges. - - int nverts; - - The size of list. - - - - - This is used internally. - Operators: - - - - - access operator. Returns the 'i-th' list element. - - - - - Finds the edge in the edge table that has the two specified vertices. - Parameters: - DWORD v0, DWORD v1 - - The vertices. - The index into the edge table. - - - - - This method is used internally as part of the Optimize modifier. - - - - - This method is used internally as part of the Optimize modifier. - - - - - This method is used internally as part of the Optimize modifier. - - - - - This method simply calls OrderVertEdges() on all the vertices. - Parameters: - *faces - - A pointer to the faces for this mesh. - - - - - Appends the specified edge to the specified vertex. - Parameters: - DWORD v - - The vertex the edge is added to. - - DWORD e - - The edge to add. - - - - - Description: - This class describes a single face for use in AdjFaceLists. - Data Members: - DWORD f[3]; - - The indices of the faces adjacent to this one. These are indices into the mesh face table. - - - - - Description: - This class represents a face adjacency list for meshes. This class require the mesh to be constructed so that each edge has exactly one or two faces. It will work with other meshes but may give misleading results (developers may wish to call mesh.RemoveDegenerateFaces() to attempt to correct the mesh to work with this class). All methods of this class are implemented by the system. - Data Members: - > list; - - The table of adjacent faces, one for each face. - - - - - Access operator. Returns the set of adjacent face for the i-th face. - - - - - Description: - This class provides a representation for orientation in three space using an angle and axis. This class is similar to a quaternion, except that a normalized quaternion only represents -PI to +PI rotation. This class will have the number of revolutions stored. All methods of this class are implemented by the system. - - The rotation convention in the 3ds Max API is the left-hand-rule. Note that this is different from the right-hand-rule used in the 3ds Max user interface. - Data Members: - axis; - - The axis of rotation. - - float angle; - - The angle of rotation about the axis in radians. This angle is left handed. - - - - - Sets the angle and axis to the specified values. - Parameters: - float x - - Specifies the x component of the axis. - - float y - - Specifies the xycomponent of the axis. - - float z - - Specifies the z component of the axis. - - float ang - - Specifies the angle to set in radians. - A reference to this . - - - - - Sets the angle and axis to the specified values. - Parameters: - & ax - - Specifies the axis to set. - - float ang - - Specifies the angle to set in radians. - A reference to this . - - - - - Sets the angle and axis based on the rotations from the specified quaternion. - Parameters: - & q - - Specifies the angle and axis to use. - A reference to this . - - - - - Sets the angle and axis based on the rotations from the specified matrix. - Parameters: - & m - - Specifies the angle and axis to use. - A reference to this . - - - - - Returns the number of revolutions represented by the angle. This returns int(angle/TWOPI); - - - - - Description: - This is the base class for all animatable scene entity types, and for most plugin types. Methods are available for getting the ClassID and SuperClassID of the plug-in, deleting this instance of the plug-in class, and parameter editing in the command panel. There are also methods that deal with the sub-animatables of the plug-in. Most of the track view related methods are here as well. - Data Members: - protected: - - unsigned long aflag; - - The flags. These may be manipulated using the methods SetAFlag(), ClearAFlag(), and TestAFlag(). See List of Flags. - - aprops; - - This is a table of properties that a plug-in may use for its own storage needs. This table is also used by the system (for example Note Tracks and APP_DATA). A plug-in may use this, for example, when a class has some data that is used while its user interface is up. It can store the UI data on the property list temporarily and not have to carry around the data when it is not needed. See the methods of Class for how to add and delete items from the list. Also see the methods GetProperty() and SetProperty() and Class . Note that it's not safe to copy objects because the properties held in do not have a well-defined copy semantics - - - - - Retrieves the name of the plugin class. - - - This name is used in 3ds Max's UI and in MAXScript. For plug-ins this method is used to put up the material "type" name in the Editor. - - Reference to a string filled in with the name of the plugin class. - If true, then the class name returned should be localized in the language 3ds is currently using. Otherwise it should be the class name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the class name in English. - - - - Returns the name of the plugin class. - - - - If true, then the class name returned should be localized in the language 3ds is currently using. Otherwise it should be the class name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the class name in English. - - - - Retrieves a constant representing the type of the plugin. - - - A super class id that uniquely identifies the type (category) of the plugin. Note that several plugin classes can be of the same type, thus return the same super class id. Plugins are uniquely identified by their class ids. - - - - - Retrieves a constant that uniquely identifies the plugin class. - - - This method must return the unique ID for the plugin class. If two ClassIDs conflict, the system will only load the first conflicting one it finds. A program (gencid.exe) is provided to generate unique class id values. - A class id that uniquely identifies a plugin class - - - - - - The bits to turn on in the flags - - - - Clears one or more bits in the flags. - - - - The bits to turn off in the flags - - - - Tests one or more bits in the flags. - - - TRUE if one or more bit specified in the mask are also set in the flags, otherwise, false. - - The bits to test in the flags - - - - Sets one or more bits in the extended flags. - - - - The bits to turn on in the extended flags - - - - Clears one or more bits in the extended flags. - - - - The bits to turn off in the extended flags - - - - Tests one or more bits in the extended flags. - - - TRUE if one or more bit specified in the mask are also set in the extended flags - - The bits to test in the extended flags - - - - Tests the specified flag bit. - - - TRUE if the flag bit is set - - The flag bit index to test - - - - Sets the specified flag bit. - - - - The flag bit index to set - The value to set the flag bit index to - - - - Clears the specified flag bit. - - - - The flag bit index to clear - - - - This method is called by the system when the user may edit the item's (object, modifier, controller, etc.) parameters. - - pointer. The developer can use it to call methods such as . Note that this pointer is only valid between and . It should not be used outside this interval. - Describe which branch of the command panel or dialog the item is being edited in. The following are possible values: Indicates an item is being edited in the create branch. Indicates a controller is being edited in the motion branch. Indicates a controller is being edited in the Pivot subtask of the hierarchy branch. Indicates a controller is being edited in the IK subtask of the hierarchy branch. Indicates a controller is being edited in the Link Info subtask of the hierarchy branch. - Pointer to an object. This parameter may be used in the motion and hierarchy branches of the command panel. This pointer allows a plug-in to look at the ClassID of the previous item that was being edited, and if it is the same as this item, to not replace the entire in the command panel, but simply update the values displayed in the fields. This prevents the from 'flickering' when the current item begins its edit. For example, if you are in the motion branch and are looking at an item's PRS controller values, and then select another item that is displayed with a PRS controller, the will not change - only the values displayed in the fields will change. If however you selected a target camera that has a lookat controller (not a PRS controller) the will change because a different set of parameters need to be displayed. Note that for items that are edited in the modifier branch this field can be ignored. - - - - This method is called when the user is finished editing an objects parameters. The system passes a flag into the EndEditParams() method to indicate if the rollup page should be removed. If this flag is TRUE, the plug-in must un-register the rollup page, and delete it from the panel. - - An interface pointer. The developer may use the interface pointer to call methods such as . - The following flag may be set: If TRUE, the item's user interface should be removed. - pointer. Can be used in the motion and hierarchy branches of the command panel. It allows a plug-in to look at the ClassID of the next item that was being edited, and if it is the same as this item, to not replace the entire in the command panel. Note that for items that are edited in the modifier branch this field can be ignored. - - - - This method provides a mechanism for extending the class in the future. In 3ds Max 4.0 there are new interfaces that are accessed by passing an id to this method and it will respond by returning the corresponding interface pointer. - - This method has been used however for a different purpose. It currently is used to determine if an object is of a particular class. With controllers for example, there is one base class , however there are many super classes (CTRL_FLOAT_CLASS_ID, CTRL_SCALE_CLASS_ID, etc.). If you wanted to find out if a given was a controller you would need to compare its SuperClassID to all the known types and only if it wasn't one of the known types could you be sure it wasn't a controller. Having to do this is inconvenient for a developer. - - Instead the class implements this method. It looks at the id, and if it matches a predefined constant I_CONTROL, it returns its this pointer. In this way, given any , it is easy to find out if it is a controller by simply asking for the control interface. There is a macro that does this: - - A plug-in developer may use this macro as follows: - - ; - - This will either be NULL or a pointer to a valid controller. - - Note: Plug-in defined interfaces should be greater than the following value: - - #define I_USERINTERFACE 0x0000ffff - - If a plug-in implements this method for its own purposes, it would, in general, switch on the id and if it is not aware of the id it would call this method on the base class. Otherwise it could respond to the id as it needed. See the sample code below for the how the class implements this method. - Default Implementation: - { return NULL; } - Sample Code: - The following is the class implementation of this method. It looks at the id passed, and if it matches I_CONTROL it returns its this pointer. Otherwise it calls the base class method. - - - - The id of the interface. - - - - This method is not currently used. It is reserved for future use. Its purpose is for releasing an interface created with GetInterface(). - - - - - This is a general method for adding properties, when defining a new would be too cumbersome. This method provides another way to extend the class without actually adding any methods. Sample code that implements this method to add properties to the property list is in /MAXSDK/SAMPLES/CONTROLLERS/PATHCTRL.CPP. See below. - Nonzero if the property was set; otherwise zero. - Default Implementation: - { return 0; } - Sample Code: - This code is from /MAXSDK/SAMPLES/CONTROLLERS/path_cnstrnt.cpp. It is used to save the inverse kinematics user interface parameters of the path controller. It saves the property data on the aprops property list. See the Data Members at the beginning of for details on aprops. - - - - The id for the property. - A pointer to the data to store. - - - - This method is used to retrieve a property specified by the id passed (as stored by SetProperty()). - - Note for 3ds Max version 1.1: - - Two new property IDs have been added: - - PROPID_CLEARCACHES: When passed to a texture map or material, the material should dump any of its caches. For example, the bitmap texture responds to this by freeing the bitmap from memory. For sample code see /MAXSDK/SAMPLES/MATERIALS/BMTEX.CPP. - - PROPID_HAS_WSM: When passed to an , will return TRUE if the node has World Space Modifiers applied to it or FALSE if it does not. For sample code see /MAXSDK/SAMPLES/IMPEXP/3DSEXP.CPP. - - Note for 3ds Max version 1.2: - - A new id has been created and assigned the constant: - - #define PROPID_EVAL_STEPSIZE_BUG_FIXED 0x1000. - - This only effects the evaluation of objects when rendering them using motion blur. Motion blur works by evaluating the object numerous times (at fractions of a frame apart) and combining these images by blending them together. - - Originally, 3ds Max would make these evaluations in reverse order within a sub-frame - from the last one, to the second to the last one, back to the first one. There is a problem with this for certain plug-ins that need to compute their state from time 0 forward. For these objects, the backwards approach may be too computationally intensive. - - Both the forward and backward approaches exist in 3ds Max and the developer may choose which method to use. 3ds Max interrogates the object to see how it should handle the evaluation process - either going backwards or forwards. It calls this method with id set to the constant PROPID_EVAL_STEPSIZE_BUG_FIXED. If a plug-in implements this method to return nonzero, it means the plug-in works correctly using forward stepping, and 3ds Max will use that approach. If a plug-in does not implement this method and handle the id of PROPID_EVAL_STEPSIZE_BUG_FIXED it will return the default value of zero. This means the older method of backwards evaluation will be used. - - Therefore, a plug-in object that wants to handle motion blur using forward stepping should implement this method, and if passed an id of PROPID_EVAL_STEPSIZE_BUG_FIXED, should return nonzero. - Default Implementation: - { return NULL; } - Sample Code: - This code is from /MAXSDK/SAMPLES/CONTROLLERS/PATHCTRL.CPP. It is used to restore the inverse kinematics user interface parameters of the path controller. It retrieves the property data on the aprops property list. See the Data Members at the beginning of for details on aprops. - - - - The id of the property to retrieve. - - - - A function to directly add arbitrary properties to this object developers should ensure that the properties ID does not conflict with any Max-specific IDs. - - The new property to add - - - - Find any property. This allows developers to add arbitrary properties to Animatables. - the property if found, else null. - - the id of the property to find - - - - Adds application/plugin specific (custom) data to an . - - - This method is used to add an to this . The chunk is identified using the , and SuperClassID of the owner, and an ID for sub-chunks. - Developers who want to add appdata to the scene should see the method Interface::GetScenePointer(). - Not allocating on the heap the data passed to this method may lead to unexpected behaviour of the application. - Client code does not need to free the data that has been passed to this method. The system will free it when the is deleted or when client code explicitely removes the custom data chunk from the by calling Animatable::RemoveAppDataChunk. - - - The of the owner of the chunk. - - The SuperClassID of the owner of the chunk. - - An extra ID that lets the owner identify its sub-chunks. - - The length of the data in bytes. - - Pointer to the actual data. The data should be allocated on the heap by client code using . This will allow the system to free it safely (using MAX_free()). and MAX_free() are memory management routines implemented by the system. - - - - Retrieves the application/plugin specific (custom) data stored with an . - - - This method is used to retrieve a pointer to an . The chunk is identified using the , SuperClassID and sub-chunk ID of the owner. - A pointer to the previously stored , or NULL if it could not be found. - - - The of the owner of the chunk. - - The SuperClassID of the owner of the chunk. - - An extra ID that lets the owner identify its sub-chunks. - - - - Deletes the application/plugin specific (custom) data stored with an . - - - This method is used to delete an . The chunk is identified using the , SuperClassID and sub-chunk ID of the owner. - TRUE if the data was deleted, FALSE if it could not be found. - - - The of the owner of the chunk. - - The SuperClassID of the owner of the chunk. - - An extra ID that lets the owner identify its sub-chunks. - - - - Deletes all application/plugin specific (custom) data stored with an . - - - Calling this method will remove all the AppData associated with this . - Plugins that call this method will erase all appdata chunks, not just their own. Therefore, it is usually more appropriate to call RemoveAppDataChunk() to remove custom application data associated with a specific . - - - - - The system uses a virtual array mechanism to access the sub-anims of a plug-in. This method returns the total number of sub-anims maintained by the plug-in. If a plug-in is using a parameter block to manage its parameters it should just return 1 for all the parameters directed by the parameter block. - The number of sub-anims used by the plug-in. - Default Implementation: - { return 0; } - - - - - This method returns a pointer to the 'i-th' sub-anim. If a plug-in is using a parameter block to manage all its parameters it should just return a pointer to the parameter block itself from this method. This method may return NULL so developers need to check the return value before calling other sub anim methods (such as SubAnimName()). - Default Implementation: - { return NULL }; - - This is the index of the sub-anim to return. - - - - This method returns the name of the 'i-th' sub-anim to appear in track view. The system has no idea what name to assign to the sub-anim (it only knows it by the virtual array index), so this method is called to retrieve the name to display. Developer need to make sure the 'i-th' SubAnim() is non-NULL or this method will fail. - The name of the 'i-th' parameter. - - The index of the parameter name to return - If true, then the sub-anim name returned should be localized in the language 3ds is currently using. Otherwise it should be the sub-anim name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the sub-anim name in English. - - - - Returns TRUE if the specified sub-anim controller can be deleted; otherwise FALSE. - - A new "Delete Controller" button has been added to the Track toolbar that is enabled when one or more delete-able tracks are selected. This method allows a plug-in to indicate to the Track that one or more of its sub-controllers are delete-able. This provides a way to allow the user to delete node sub-controllers such as the visibility track, "Image Motion Blur Multiplier", "Object Motion BlurOn/Off", etc. If the user selects one of the above-mentioned tracks in the Track the "Delete Controller" button will become available. - Default Implementation: - {return FALSE;} - - The zero based index of the sub-anim. - - - - This method is called to delete the specified sub-anim controller. See the remarks in CanDeleteSubAnim() above. - Default Implementation: - {} - - The zero based index of the sub-anim. - - - - Return the suggested color to draw a sub-anim's function curve. For example, the independent X, Y, Z position controller implements this method to return the suggested color for each of it's sub-controllers. The Euler Angle Controller uses these so its 3 sub-controllers are drawn in different colors. - One of the following values: - - PAINTCURVE_GENCOLOR - - PAINTCURVE_XCOLOR - - PAINTCURVE_YCOLOR - - PAINTCURVE_ZCOLOR - Default Implementation: - {return PAINTCURVE_GENCOLOR;} - - The index of the sub-anim. - - - - This method is used for copying and pasting in the track view. It converts an anim index to a reference index or returns -1 if there is no correspondence. If a client does not wish an anim to be copied or pasted then it can return -1 even if there is a corresponding reference num. - Default Implementation: - { return -1} - The reference index corresponding to the anim index passed. Return -1 if there is no correspondence. - - The anim index to return the corresponding reference index of. - - - - In addition to SubNumToRefNum(), if an anim doesn't want to be copied (via Track or the Edit Modifier 'Copy' button) it can return FALSE from this method, otherwise it can use the default implementation to return TRUE. - Default Implementation: - {return TRUE;} - - - - - Implemented by the System. - - This method is used to determine if this has children or sub-anims. The type passed indicates what is tested. - Nonzero if the item has children or sub-anims; otherwise zero. - - One of the following values:: Test for node children.: Test for sub-anims. - - - - The values max and min should be initialized before calling this function. A plugin implementing this function should not reset the values passed - in this way if max is passed with a larger value than the curve extents calculated for the current anim, the value of max will be unchanged. - RGB controllers interpret X as red, Y as green and Z as blue. - If this method is processed, return nonzero; otherwise zero. - - - The index of the SubAnim to query for curve extents - - The dimension of the anim. - - The smallest value. These are in the units given by the dimension. For example, if it was an angle parameter that was displayed in degrees, the units returned through should be in degrees as well. A class should implement this method to not reset this value - - The largest value. These are in the units given by the dimension. For example, if it was an angle parameter that was displayed in degrees, the units returned through should be in degrees as well. - - One or more of the following values which are filters for controllers with more than one curve: - - - - Returns the type of dimension of the 'i-th' sub-anim. A dimension describes the type and order of magnitude of a sub-anim. - The dimension of the 'i-th' sub-anim (parameter). - Default Implementation: - {return defaultDim;} - - Specifies the sub-anim (parameter) to return the dimension of. - - - - This method is available in release 2.0 and later only. - - When a user is in Track in Edit Keys mode and clicks on the green triangle of a controller then this method will be called on the client with the appropriate sub number that corresponds to it. For instance, the Editable object implements this to allow the user to select vertices that are animated from the Track . - TRUE if implemented; otherwise FALSE. (Track will call RedrawViewports() if something returns TRUE from this method). - Default Implementation: - {return FALSE;} - - The index of the sub-anim that was clicked on. - - - - This method indicates to the system that this anim should not appear in the Track . Note: Track was formally referred to as Tree . This is what parameter blocks do for example. They don't show up in track view, just their sub-anims do. This prevents the extra level of the parameter block from appearing. - Return TRUE to not appear in the Track . Note that if you return TRUE your children will appear in the track view regardless. - Default Implementation: - { return FALSE; } - - - - - This method indicates to the system that this anim should not appear in the Track Bar. The anim won't show up in the Track Bar, just its sub-anims will. This function is similar to BypassTreeView(), but refers to the Track Bar instead of the Track . - Return TRUE to not appear in the Track Bar. Note that if you return TRUE your children will appear in the Track Bar regardless. - Default Implementation: - BypassTreeView(); } - - - - - Use this method in order to cause parameters in this (as a sub-anim) to appear to reside at the level of the parent in the scripter. Return TRUE and this won't appear as a property in the scripter however it's sub-anims children will. The default implementation returns FALSE indicating it will appear normally. - Default Implementation: - { return FALSE; } - - - - - This method controls the visibility of this and all of it sub-anims to appear as properties in the scripter. Return TRUE and it won't nor will it's sub-anims. Returning FALSE (the default implementation) causes this and it's sub-anims to appear as normal. - Default Implementation: - { return FALSE; } - - - - - This method returns the number of keys managed by the plug-in, or NOT_KEYFRAMEABLE if it does not work with keys. - Default Implementation: - {return NOT_KEYFRAMEABLE;} - - - - - This method returns the time of the key specified by index. - Default Implementation: - {return 0;} - - Specifies the key whose time should be returned. - - - - Returns the index of the key at time t or -1 if no key is found at the specified time. - Default Implementation: - {return -1;} - - Specifies the time at which to retrieve the key index. - - - - An item should implement this method to allow the Key Mode button in 3ds Max's UI to function properly. If Key Mode is set, and the user clicks the Previous Key or Next Key button, this method will be called to retrieve the next or previous key. - TRUE if the key time was retrieved; otherwise FALSE. - Default Implementation: - { return FALSE;} - - The current time (frame slider position). - One or more of the following values: Search to the left. Search to the right. Next position key. Next rotation key. Next scale key. - The time of the previous or next key is returned here. - - - - This method is called to copy or interpolate a new key from a source time to a destination time. - - The source time. - The destination time. - These filter flags are passed to a transform () controller. The TM can decide what to do with them. They have obvious meaning for the PRS controller. One or more of the following values: Copy the position key. Copy the rotation key. Copy the scale key. - - - - This method is called to delete the key at the specified time. - Default Implementation: - {} - - Specifies the time to delete the key. - - - - Returns TRUE if there is a key of the specified type at the specified time; otherwise FALSE. - Default Implementation: - {return FALSE;} - - Specifies the time to check for a key. - One or more of the following values: - - - - This method is called to build a table of time values, one time for each key within the interval passed. The plug-in should load up the table passed with the time of each key present over the specified time range. - The plug-in should return an offset so the system can access the keys using an index. Thus it should return the number of keys skipped because their times were before range.Start(). For example, say the first keyframe in the interval passed was actually the third key overall. The plug-in should return 2 (two keys preceded the first one stored). In this way, the system can access the key as the i-th key in the table plus 2. - Default Implementation: - {return 0;} - - The table of time values to build. See Class . - The range of time over which to retrieve the key times. See Class . - One of the following values: Return for Position keys only. Return for Rotation keys only. Return for Scale keys only. - - - - When this method is called, the plug-in should update the sel to indicate if its keys present in the interval passed are selected or deselected. - If the flags are passed as 0, use ALL keys within the range. - The number of keys skipped because their times were before range.Start(). - Default Implementation: - {return 0;} - - The bit array to update, one bit for each key within the interval . If the key is selected, the corresponding bit should be 1, otherwise it should be 0. See Class . - The range of time over which to retrieve the key selected state. See Class . - One or more of the following values: Return for Position keys only. Return for Rotation keys only. Return for Scale keys only. - - - - Implemented by the System. - - This method may be called to open the specified Track entry. The type parameter indicates if the child tree or the sub-anim (parameter) tree is opened. - - This value may be either 0 or 1. If 0, the child tree is opened. If 1, the sub-anim tree is opened. - This parameter specifies which Track are altered, one bit for each Track . The open/closed state is independent for each Track . The low-order 16 bits represent the 16 track views. - - - - Implemented by the System. - - This method may be called to close the specified Track entry. The type parameter indicates if the child tree or the sub-anim tree is closed. - - This value may be either 0 or 1. If 0, the child tree is closed. If 1, the sub-anim (parameter) tree is closed. - This parameter specifies which Track are altered, one bit for each Track . The low-order 16 bits represent the 16 track views. - - - - Implemented by the System. - - Returns nonzero if the specified tree is opened for this item, and zero if it is closed. - - This value may be either 0 or 1. If 0, the child tree is checked. If 1, the sub-anim (parameter) tree is checked. - This parameter is available in release 2.0 and later only. Specifies which Track to check one bit per Track . - - - - This method is available in release 2.0 and later only. - - Implemented by the System. - - Returns TRUE if this animatable is selected in the specified Track ; FALSE if not selected. - - Specifies which Track to check one bit per Track . - - - - This method is available in release 2.0 and later only. - - Implemented by the System. - - Sets the state of this animatable to selected or deselected in the specified Track . - - Specifies which Track to check one bit per Track . - TRUE to select; FALSE to deselect. - - - - This method is available in release 2.0 and later only. - - Implemented by the System. - - Returns TRUE if this animatable is in the specified selection set; otherwise FALSE. - - Indicates the Track selection set to check this should be and - - - - This method is available in release 2.0 and later only. - - Implemented by the System. - - Sets the selected or deselected state of this animatable in the specified selection set. - - Indicates the Track selection set to modify this should be and - TRUE for in; FALSE for out. - - - - This method is called to assign the controller to the sub-anim whose index is passed. - Default Implementation: - { return FALSE; } - Returns TRUE if the controller was assigned; otherwise FALSE. - - The controller to assign. - The index of the sub-anim to assign the controller to. - - - - Return true if we can reassign the subanim specified. - - - Implement this function to return false if we wish to prevent any subanim from being replaced. If this method returns false for any id, that subanim will not be able to be re-assigned via the UI or MaxScript controls. Note that this will not prevent re-assigning in C++ in any way (via the ReplaceReference or AssignController functions). - TRUE if it is legal to assign a new to the specified SubAnim - - - The ID of the SubAnim to check. - - - - An anim can implement this method to return FALSE to prohibit make unique from being applied to it. - Default Implementation: - {return TRUE;} - - - - - Implemented by the System. - - This method recursively enumerates the hierarchy. It will call the AnimEnum::proc() method passing it the anim, that anim's parent (the client), and the sub-anim index of that anim to the client, for every anim and sub-anim in the hierarchy. - One of the following values: - - ANIM_ENUM_PROCEED - - ANIM_ENUM_STOP - - ANIM_ENUM_ABORT - - The callback object, called once for each sub anim from 0 to subNum-1. See Class . - The client anim. This is the Animatalbe whose sub-anims are enumerated. - The sub-anim index of the client at which to begin the enumeration. Pass 0 to do them all. - - - - This method is used to enumerate any 'auxiliary' files maintained by the item and record the filename with the callback. Entities which actually need to load auxiliary files (for instance texture maps) must implement this method, possibly calling ReferenceMaker::EnumAuxFiles() also. The implementation simply calls itself on all its references (see below). - - Class has a method that may be used to call this on the entire system. This includes the renderer, materials editor, atmospheric effects, background, video post, lights, etc. - everything that may have auxiliary files associated with it. After specifying the appropriate flags a list of filenames is created that matched the enumeration conditions as specified by the flags. This is used for instance by the Archive function in 3ds Max to grab a list of bitmap files used by the system. - Sample Code: - - The callback object that may be used to record the asset. See Class . - See - - - - This method is called once at the beginning of each render. A plug-in can use this method to do any work required before a rendering actually begins. For example, some of the standard 3ds Max plug-ins use this method to toggle between their 'viewport' state and the 'rendering' state. The Optimize modifier has two settings, one for the viewports and one for the rendering. When this method is called it then performs the switch from viewport to renderer. - Nonzero if the method is implemented; otherwise 0. - Default Implementation: - { return 0; } - - The time that the render is beginning. - The following flag value can be checked: Indicates that the render is occurring in the Editor. - - - - This method is called once at the end of each render. - Nonzero if the method is implemented; otherwise 0. - Default Implementation: - { return 0; } - - The time of the last rendered frame. - - - - Implemented by the System. - - Returns an interval representing the tracks time range, based on the flags passed. - An interval representing the tracks time range. - - One or more of the following values: The bounding interval of selected keys only. Whatever the channel's time range is - usually the bounding interval of all keys. The node's time range should include its child nodes. A animatable's child anim ranges should be included. - - - - This method is called to change the range of the anim (usually a controller) to the given range. This is the range that is used to compute the Out of Range Types. For example, this method may be called when the user is working in Position Range mode in the Track . - - Keyframe controllers generally support this method. Other controllers may or may not support this method. For example, a procedural controller may want to maintain a range upon which the animation is based. The user may then move the range bar around to move the procedural animation around. - - The range passed is the range used to compute the Out of Range Types. This may be used for example with the Loop ORT to extend the range, either past the last key or before the first key, so there is some time to loop back to the start. - - The 3ds Max keyframe controllers maintain an interval that is their range. It is normally defined to be the first key to the last key. If the user goes into Position Range mode and moves the range around, this method is called. The keyframe controllers set a flag to indicate that the range is no longer linked to the first key or the last key. Then the range is stored in the interval, and this is considered the 'in range' portion of the controller. If time is evaluated outside of this range it applies the ORTs to determine the value. - Default Implementation: - {} - - The new range for the anim. - If this flag is set, the controller should re-establish the link between the start and end keys and its range. This is passed if the user presses the link to keys button in Track . Thus, if one of the ends of the interval is at a key, link it to the key so that if the key moves, the interval moves. - - - - This method is called to delete the specified interval of time (or the keys within the interval). - Default Implementation: - {} - - The interval of time to delete. - One or more of the following values: Include the left endpoint. Include the right endpoint. Delete any keys in the interval but don't actually remove the block of time. - - - - This method is called to reverse the data within the specified interval. For example, if the interval passed is from frame 10 to 20, and there is a key at frame 12, the key should be moved to frame 18. Considered another way, if all the times were normalized, and there was a value n between 0 and 1, n should be changed to 1-n. - Default Implementation: - {} - Sample Code: - - The interval of time over which to reverse the data. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is called to scale an interval of time by the specified scale factor. - Default Implementation: - {} - Sample Code: - - The interval of time to scale. The origin of the scale is at . - The scale factor for the time. - - - - This method is called to insert the specified amount of time at the specified insertion point. - Default Implementation: - {} - Sample Code: - - The time to begin the insertion. - The amount of time to insert. - - - - If an anim supports time operations in the track view (cut, copy, paste, etc.), it should implement this method to return TRUE. When it is FALSE the user cannot select blocks of time in the anim's track. - Default Implementation: - {return FALSE;} - - - - - The method is called to update the keys specified by the flags, using the passed. The plug-in should go through the specified keys and change their time to TimeMap::map(time). See the sample code below for how this is done. - Sample Code: - - Point to instance of Class . - The flags indicate the keys to operate on. One or more of the following values: Selected keys only. All the keys, ignore their selection state. Slide unselected keys to the right. Keys are slid by the amount the last key was transformed. Enumerate right to left. If is set, keys will slide to the left. Sub-Animatables keys as well. Child Nodes keys as well The range, if not locked to first and last key, should be mapped as well. - - - - This method is called to delete keys, as specified by the flags passed. - Default Implementation: - {} - - One or more of the following values: Delete selected keys only. Delete all keys (ignore selection state). Slide unselected keys to the right. Enumerate right to left. If is set, keys will slide to the left. - - - - Deletes the key specified by the index passed. - Default Implementation: - {} - - The index of the key to delete. - - - - This method is called to select or deselect a set of keys identified by the TrackHitTab and the specified flags. - Default Implementation: - {} - - The table of track hit records. See Class and Class . Note the following: - Either , , or a combination of and will be specified. One or more of the following values: The keys should be selected. The keys should be deselected. All keys should be deselected. All keys on the function curve should be deselected. Indicates that we are operating on the keys of a function curve, and not of a track. - - - - This method is available in release 2.0 and later only. - - This method is called on the client when the client takes over control of an anims function curves. It's called to select or deselect a set of keys identified by the TrackHitTab and the specified flags. - Default Implementation: - {} - - The index of the sub-anim to select or deselect - The table of track hit records. See Class and Class . Note the following: - Either , , or a combination of and will be specified. One or more of the following values: The keys should be selected. The keys should be deselected. All keys should be deselected. All keys on the function curve should be deselected. Indicates that we are operating on the keys of a function curve, and not of a track. - - - - This method is available in release 2.0 and later only. - - This method is called to set the selected state of the sub-curve whose index is passed. - Default Implementation: - {} - - The index of the sub-anim to select or deselect - TRUE to select the curve; FALSE to deselect it. - - - - This method is available in release 2.0 and later only. - - This method is called to set the selected state of the key whose index is passed. - Default Implementation: - {} - - The key to select or deselect. - TRUE to select the key; FALSE to deselect it. - - - - Returns TRUE if the key specified by the index is selected; otherwise FALSE. - Default Implementation: - {return FALSE;} - - The index of the key to test. - - - - This method is called to have the plug-in flag or mark a specific key identified by the . - - As an example, when the user goes to move a selection set of keys in the Track , a yellow marker is drawn. To move the group of keys, the user clicks on a single one. The system needs to track this one key as it is moved, and needs a way to identify it. This method is called so the developer can flag this key as the one that was selected. This is needed because the Track doesn't know anything about a specific controllers ordering of keys and thus cannot refer to it by index. - - The system will call GetFlagKeyIndex() (described below) to retrieve the index of the key that was flagged. - Default Implementation: - {} - Sample Code: - - The hit record that the controller gave the Track in the first place to identify the hit. Thus this is enough information to identify the key. See Class . - - - - Returns the index of the key that is flagged, or -1 if no keys are flagged. See the method above. - Default Implementation: - {return -1;} - Sample Code: - - - - - Returns the number of selected keys. - Default Implementation: - {return 0;} - - - - - This method is called to make a copy of the selected keys. - - If TRUE, set the new key time to be centered between the original key and the next key. - - - - This method is called to add a new key at the specified time. The value of the key is set to the value of the previous key, or interpolated between keys, based on the flags passed. - Default Implementation: - {} - - The time to add the key. - One or more of the following values: Select the new key and deselect any other selected keys. If TRUE then initialize the new key to the interpolated value at that time. If FALSE, initialize the key to the value of the previous key. Flag the newly created key as if was called for it. - - - - This method is called to move selected keys vertically in the function curve editor. This moves the key values but does not alter the key times. The developer adds the delta to the selected key values, after converting them using the dimension *dim passed. See the sample code below for how this may be done. - Default Implementation: - {} - Sample Code: - - Used to scale the parameter's values into and out of units used in the user interface. For example, if the parameter was an angle, it would be shown in degrees, but stored in radians. Methods of this class allow the value to be converted back and forth. This is needed because the delta passed is in user interface units. Thus the selected key values need to be converted before the delta is applied. See Class ParamDimensBase. - The amount to move the keys (move the values - not the times). This is in the units of the user interface. For example, if an angle has a value in the function curve editor of 100 degrees, 100 would be passed as the delta. - Not currently used. - - - - This method is called to scale selected keys values. This scales the key values but does not alter the key times. The developer scales the selected key values about the specified origin, after converting them using the dimension *dim passed. - - Note the following macro available for scaling about an origin: - - ScaleAboutOrigin(val,origin,scale)#define - - ((((val)-(origin))*(scale))+(origin)) - Default Implementation: - {} - Sample Code: - - Used to scale the parameter's values into and out of units used in the user interface. For example, if the parameter was an angle, it would be shown in degrees, but stored in radians. Methods of this class allow the value to be converted back and forth. See Class ParamDimensBase. - The origin about which the keys are scaled. - The scale factor to apply to the key values. - Not currently used. - - - - The plug-in keeps track of whether its function curve is selected or not. This method is called to have the plug-in select or deselect its function curve. - Default Implementation: - {} - - TRUE if the curve should be selected; FALSE if it should be deselected. - - - - Returns TRUE if the function curve is selected; otherwise returns FALSE. - - - Default Implementation: - {return FALSE;} - - - - - Returns the selected state of the sub-curve whose index is passed. - - - TRUE if subNum is seletected. - - The index of the sub-anim - - - - This method is used to determine the commonality of the selected keys for display in the time/value type in fields of Track . It is also used to retrieve the value and/or time of the selected keys (if there is only one selected, or they are common to the selected keys). The flags parameter specified which values to retrieve. The return value indicates if nothing, or several keys were selected. It also indicates if the selected keys shared a common time and/or common value. - This indicates what was selected, and what these keys had in common. One or more of the following values should be set: - - KEYS_NONESELECTED - This indicates that no keys are selected. - - KEYS_MULTISELECTED - This indicates that multiple keys are selected. Both of these last two bits could be set. - - KEYS_COMMONTIME - If the selected keys share the same time then this flag should be set. In this case it is appropriate to update t if required. - - KEYS_COMMONVALUE - If the selected keys share the same value then this flag should be set. In this case it is appropriate to update val if required. - Default Implementation: - {return KEYS_NONESELECTED;} - - The time of the selected keys is returned here (if appropriate). - The value of the selected keys is returned here (if appropriate). - One of the following values: Only the time needs to be updated. Only the value needs to be updated. - - - - This method is called to update the time and/or value of the selected keys as specified by the flags. This is called if the user uses the time/value type in fields of Track . - Default Implementation: - {} - - The time to set for the selected keys (if the flags indicate this is needed). - The value to set for the selected keys (if the flags indicate this is needed). - One of the following values: Only the time needs to be updated. Only the value needs to be updated. - - - - This method is similar to SetSelKeyCoords() above. In that case you're given a time and a value and are to update the selected keys with these values (based on the flags passed). In this case, you are instead passed time and value expressions (as strings). The ideas is that these strings are evaulated as expressions and the resulting values are used to updated the selected keys. For instance, the user could select a bunch of keys and then type in n+45. This would add 45 to all the values of the keys. - - Developers can use the 3ds Max expression parser (see Class ) to evaluate the strings. Debug SDK users can see /MAXSDKDB/SDKSRC/CTRLTEMP.H for an example (or see the sample code below)). If a plug-in doesn't support this feature it can return FALSE from this method and the old SetSelKeyCoords() method will be called. Note that the variable names are defined as KEYCOORDS_TIMEVAR and KEYCOORDS_VALVAR. - This indicates what was selected, and what these keys had in common. One or more of the following values should be set: - - KEYCOORDS_EXPR_UNSUPPORTED - Don't implement this method - - KEYCOORDS_EXPR_ERROR - Error in expression - - KEYCOORDS_EXPR_OK - Expression evaluated - Default Implementation: - {return KEYCOORDS_EXPR_UNSUPPORTED;} - - - Sample Code: - - This is used to convert the parameter value once you get it. - A string containing the time expression. - A string containing the value expression. - One of the following values: Only the time needs to be updated. Only the value needs to be updated. - - - - If a plug-in has tangent handles, this method is called if the user adjusts them. If a plug-in doesn't have tangent handles, this method may be ignored. This method is called if the user selects one of the handles and moves the mouse. This method is passed the dx, and dy of the mouse motion. - - The plug-in may have any types of handles it wishes, and it is responsible for processing whatever needs to be done when the user adjusts them. The method is passed information about the screen space, such as the overall rectangle, and time and value scroll and zoom factors. See Screen-Time-Value Macros for macros to convert in and out of screen space. - - This identifies the handle that was selected. - The parameter dimension. See Class . - This is the rectangle of the graph viewport. - This is the time zoom factor. - This is the time scroll factor. - This is the value zoom factor. - This is the value scroll factor. - The mouse movement in screen coordinates in the x direction. - The mouse movement in screen coordinates in the y direction. - One of the following values: ADJTAN_LOCK - Indicates the tangents are locked. ADJTAN_BREAK - Indicates the tangents have been broken. - - - - If a plug-in has tangent handles, this method is called if the user adjusts them. If a plug-in doesn't have tangent handles, this method may be ignored. This method is called if the user selects one of the handles in the viewport. This method is passed the change in angle and length of the handle the user wishes to perform. - The plug-in may have any types of handles it wishes, and it is responsible for processing whatever needs to be done when the user adjusts them. - - This identifies the handle that was selected. - The parameter dimension. See Class . - The change in angle the user is requesting (in radians). - The change in length the user is requesting. - One of the following values: ADJTAN_LOCK - Indicates the tangents are locked. ADJTAN_BREAK - Indicates the tangents have been broken. - - - - Returns TRUE if this animatable actually has animation; otherwise FALSE. This method is recursive, so for example, if you call IsAnimated()node-> it will return TRUE if any aspect of the node is animated; otherwise it will return FALSE. - Default Implementation: - The default implementation returns TRUE if a child anim has animation. - - - - - Returns TRUE if this item can copy its data over the specified range; otherwise returns FALSE. - Default Implementation: - {return FALSE;} - - The interval of time that would be copied. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - Returns TRUE if this item can paste its data over the specified range; otherwise returns FALSE. - Default Implementation: - {return FALSE;} - - The clipboard object that would be pasted. The item should look at the SuperClassID and of the creator of the clip object to determine if it is a suitable object to paste. See Class . - The interval of time that would be pasted. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is called to copy the item's track data over the specified interval. - The item should return an instance of a class derived from that contains the data for the item. See Class . - Default Implementation: - {return NULL;} - - The interval of time over which to copy the track data. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is called to paste the specified clip object to this track. This method will not be called unless CanPasteTrack() returned TRUE. - - The data to paste. - The interval of time to paste. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is available in release 2.0 and later only. - - If CanCopyTrack() returns FALSE then this method is called on the sub-anim (passing the sub number). - - This is used in particular for Parameter Blocks. In that case, if there is no controller plugged into the track, the copying and pasting of controllers can't be done (since there is no controller). However, this method allows the Parameter Block to handle it. - TRUE if the specified item can copy its data over the specified range; otherwise FALSE. - Default Implementation: - {return FALSE;} - - Specifies the sub-anim to check. - The interval of time over which to copy the track data. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is available in release 2.0 and later only. - - Returns TRUE if the specified item can paste its data over the specified range; otherwise returns FALSE. - - Plug-ins can implement pasting for cases where their sub-anims don't implement it. An example of this is the Parameter Block class. It implements this method to allow pasting parameters that don't have controllers assigned to them. These aren't called on the client unless the sub-anim doesn't implement CanPasteTrack(). - TRUE if the specified item can paste its data over the specified range; otherwise FALSE. - Default Implementation: - {return FALSE;} - - Specifies the sub-anim to check. - The data to paste. - The interval of time to paste. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is available in release 2.0 and later only. - - This method is called to copy the specified sub anim's track data over the specified interval. - The item should return an instance of a class derived from that contains the data for the item. See Class . - Default Implementation: - {return NULL;} - - The number of the sub-anim to copy. - The interval of time over which to copy the track data. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - This method is available in release 2.0 and later only. - - This method is called to paste the specified clip object to the specified sub-anim track. - Default Implementation: - {} - - The number of the sub-anim to paste. - The data to paste. - The interval of time to paste. - One or more of the following values: Include the left endpoint. Include the right endpoint. - - - - Returns the vertical space occupied by the track in units of one line. - Default Implementation: - { return 1; } - - The height of a single line in pixels. - - - - This method is called to determine which keys lie within the rcHit rectangle. Keys that are hit are added to the hits table. - One of the following values: - - TRACK_DONE - This indicates the track was hit tested. - - TRACK_DORANGE - This indicates that the system will handle hit testing to the range bar for the item. For example a node returns this value because it does not have any keys. Therefore it just lets the user hit test the range bar. In general, anything that is not a leaf controller will not implement this method and return the default. The system will then simply hit test the range bar. - - TRACK_ASKCLIENT - If a plug-in returns this value then the anim's client will be given a chance to paint the track in Track . If a client returns this value then the method PaintSubTrack() will be called. - Default Implementation: - { return TRACK_DORANGE; } - - The table of to update. Each key that lies within the hit rectangle (is hit) should be added to this table. It is up to the plug-in to define a scheme that allows it to identify its hits using the data members of Class . Also see Class for methods to add to the table. - This is the region that was selected for hit testing. This may be a small rectangle about the mouse pick point, or a larger rectangle if the user selected by window. - This is the entire rectangular region of the track. - The is the time zoom factor. - This is the time scroll factor. - One or more of the following value: Selected only. Unselected only. Abort hit testing on first hit. Hit test curve tangents. - - - - This method is called to display the item in the track view. If an item needs to draw itself in a special fashion, it implements this method to do so. For example, a sound plug-in may draw its waveform using this method. If an item does not need to draw itself, the default implementation may be used. This draws the range bar for the item. - - Note: When drawing something to appear in Track , a developer should not do any clipping of their own. 3ds Max will take care of all clipping itself. - RGB controllers interpret X as red, Y as green, and Z as blue. DISPLAY_ZCURVE - One of the following values: - - TRACK_DONE - Indicates the track was painted. - - TRACK_DORANGE - Indicates the system should draw the range bars for the item. - - TRACK_ASKCLIENT - Indicates the anim's client will be given a chance to paint the track in Track . See Animatable::PaintSubTrack() which will be called to do this. - Default Implementation: - { return TRACK_DORANGE; } - - The dimension for the parameter of this track. - The handle of the device context. - The entire rectangle of the inside of the track. - This is the rectangular region that needs to be repainted - the invalid region. - The time zoom factor. - The time scroll factor. - One or more of the following values which are filters for controllers with more than one curve: - - - - This method is available in release 2.0 and later only. - - This method will be called if PaintTrack returns TRACK_ASKCLIENT. This gives the anim's client a chance to paint the tracks in Track . - RGB controllers interpret X as red, Y as green, and Z as blue. - One of the following values: - - TRACK_DONE - Indicates the track was painted. - - TRACK_DORANGE - Indicates the system should draw the range bars for the item. - Default Implementation: - {return TRACK_DORANGE;} - - Specifies the sub-anim to paint. - The dimension for the parameter of this track. - The handle of the device context. - The entire rectangle of the inside of the track. - This is the rectangular region that needs to be repainted - the invalid region. - The time zoom factor. - The time scroll factor. - One or more of the following values which are filters for controllers with more than one curve: - - - - This method is called to draw the function curve of the anim. - RGB controllers interpret X as red, Y as green and Z as blue. - A plug-in should always return 0. - Default Implementation: - { return 0; } - - The parameter dimension. See Class . - The handle of the device context. - The entire rectangle of the inside of the graph region. - This is the rectangular region that needs to be repainted - the invalid region. - The time zoom factor. - The time scroll factor. - The value zoom factor. - The value scroll factor. - One or more of the following values which are filters for controllers with more than one curve: Show the curve tangent handles. Show the curve in a frozen state. Draw the curve in its standard color. The following options are passed to float controllers indicating a sugested color for drawing: Draw the curve in red. Draw the curve in green. Draw the curve in blue. - - - - This method is called to hit test the item's function curves. It is called to determine which keys on the curve lie within the rcHit rectangle. Keys that are hit are added to the hits table. - RGB controllers interpret X as red, Y as green and Z as blue. - One of the following values to indicate what was hit: - - HITCURVE_KEY - Hit one or more keys. - - HITCURVE_WHOLE - Hit the curve (anywhere). - - HITCURVE_TANGENT - Hit a tangent handle. - - HITCURVE_NONE - Nothing was hit. - - HITCURVE_ASKCLIENT - Ask the client to hit test the function curve. See Animatable::HitTestSubFCurves(). - Default Implementation: - { return HITCURVE_NONE; } - - The parameter dimension. See Class . - The table of to update. Each key that lies within the hit rectangle (is hit) should be added to this table. It is up to the plug-in to define a scheme that allows it to identify its hits using the data members of Class . Also see Class for methods to add to the table. - This is the region that was selected for hit testing. This may be a small rectangle about the mouse pick point, or a larger rectangle if the user selected by window. - This is the entire rectangle of the graph region. - This is the time zoom factor. - This is the time scroll factor. - This is the time zoom factor. - This is the time scroll factor. - One or more of the following values: Selected only. Unselected only. Abort hit testing on first hit. Hit Test curve tangent handles. The following are filters for controllers with more than one curve. - - - - This method is called to draw the specified sub-anim function curve. This allows the client to paint its function curve. - RGB controllers interpret X as red, Y as green and Z as blue. - A plug-in should always return 0. - Default Implementation: - { return 0; } - - The sub-anim number to paint. - The parameter dimension. See Class . - The handle of the device context. - The entire rectangle of the inside of the graph region. - This is the rectangular region that needs to be repainted - the invalid region. - The time zoom factor. - The time scroll factor. - The value zoom factor. - The value scroll factor. - One or more of the following values: Show the curve tangent handles. Show the curve in a frozen state. The following values are filters for controllers with more than one curve. Draw the curve in its standard color. The following options are passed to float controllers indicating a sugested color for drawing: Draw the curve in red. Draw the curve in green. Draw the curve in blue. - - - - This method is called if HitTestFCurves() returns HITCURVE_ASKCLIENT. It allows the client to hit test its sub-anim curves. - One of the following values to indicate what was hit: - - HITCURVE_KEY - Hit one or more keys. - - HITCURVE_WHOLE - Hit the curve (anywhere). - - HITCURVE_TANGENT - Hit a tangent handle. - - HITCURVE_NONE - Nothing was hit. - Default Implementation: - { return HITCURVE_NONE; } - - The sub-anim number to hit test. - The parameter dimension. See Class . - The table of instances to update. Each key that lies within the hit rectangle (is hit) should be added to this table. It is up to the plug-in to define a scheme that allows it to identify its hits using the data members of Class . Also see Class for methods to add to the table. - This is the region that was selected for hit testing. This may be a small rectangle about the mouse pick point, or a larger rectangle if the user selected by window. - This is the entire rectangle of the graph region. - This is the time zoom factor. - This is the time scroll factor. - This is the time zoom factor. - This is the time scroll factor. - One or more of the following values: Selected only. Unselected only. Abort hit testing on first hit. Hit Test curve tangent handles. The follow are filters for controllers with more than one curve. (RGB controllers interpret X as red, Y as green and Z as blue.) - - - - This method is called for the plug-in to put up a modal dialog and let the user edit the tracks parameters for the selected keys. This function should not return until the user has completed editing at which time any windows that were created should be destroyed. Unlike BeginEditParams() and EndEditParams() this interface is modal. - Default Implementation: - {} - - This time represents the horizontal position of where the user right clicked to bring up the modal edit track parameters dialog. See the flags below for when this parameter is valid. - The parameter dimension. See Class . - The name of the parameter as given by the client. - This is the parent window that should be used to create any dialogs. - An interface pointer available for calling functions in 3ds . - One or more of the following values: The user is in the function curve editor. The user is in one of the track views. The user is editing a path in the scene. The user invoked by choosing the properties button. In this case the time parameter is NOT valid. The user invoked by right clicking with the mouse. In this case the time parameter is valid. - - - - This method returns a value that indicates how the track parameter editing is invoked. - One of the following values: - - TRACKPARAMS_NONE - - Has no track parameters. If this is returned then EditTrackParams() will not be called. - - TRACKPARAMS_KEY - - Entered by right clicking on a selected key. This should be used if the dialog provides parameters for the entire controller (for example as the Noise controller's dialog does). - - TRACKPARAMS_WHOLE - - Entered by right clicking anywhere in the track. This should be used if the dialog will represent the selection of keys (as a key info type dialog does). - Default Implementation: - {return TRACKPARAMS_NONE;} - - - - - This method is called to calculate the largest and smallest values of the anim. - - - The values max and min should be initialized before calling this function. A plugin implementing this function should not reset the values passed - in this way if max is passed with a larger value than the curve extents calculated for the current anim, the value of max will be unchanged. - RGB controllers interpret X as red, Y as green and Z as blue. - If this method is processed, return nonzero; otherwise zero. - - - The dimension of the anim. - - The smallest value. These are in the units given by the dimension. For example, if it was an angle parameter that was displayed in degrees, the units returned through should be in degrees as well. A class should implement this method to not reset this value - - The largest value. These are in the units given by the dimension. For example, if it was an angle parameter that was displayed in degrees, the units returned through should be in degrees as well. - - One or more of the following values which are filters for controllers with more than one curve: - - - - Implemented by the System. - - This method adds the specified note track. - - The note track to add. The Note Tracks provided by 3ds are derived from Class (which is derived from ). See that class for the methods and data members used to access Note Tracks. - - - - Implemented by the System. - - This method deletes the specified note track. - - The note track to delete. The Note Tracks provided by 3ds are derived from Class (which is derived from ). See that class for the methods and data members used to access Note Tracks. - If delNote is FALSE the note track will be removed from the anim but not deleted. - - - - Implemented by the System. - - This method returns TRUE if the track has note tracks; otherwise FALSE. - - - - - Implemented by the System. - - This method returns the number of note tracks. - - - - - Implemented by the System. - - This method retrieves the 'i-th' note track. - A pointer to a Note Track. The Note Tracks provided by 3ds Max are derived from Class (which is derived from ). See that class for the methods and data members used to access Note Tracks. - - Specifies the note track to retrieve. - - - - Implemented by the System. - - This method removes and deletes all note tracks on object. - - - - - This method is available in release 2.0 and later only. - - This method frees all bitmaps in this but doesn't recurse. This is used for freeing all the scene bitmaps after a render. - Default Implementation: - {} - - - - - The driver controller of a system plug-in should implement this method to give 3ds Max a list of nodes that are part of the system. The driver controller should fill in the given table with the pointers of the nodes that are part of the system. This will ensure that operations like cloning and deleting affect the whole system. - - Said another way, GetSystemNodes() should be implemented for the driver controller of a system, and should return a list of pointers to all nodes that are part of the system. GetInterface() should be implemented for the driven TM controllers of the system and return a pointer to the driver controller. - - 3ds Max will use GetInterface() in the TM controller of each selected node to retrieve the driver controller and then call GetSystemNodes() on the driver controller to get the list of nodes. - Default Implementation: - {} - - The table of nodes that are part of the system. - This parameter is available in release 4.0 and later only. This parameter can be used to specify the context under which the "system nodes" are used. These are; , , , and . - - - - returns true if the animatable has sub-classed off the given class - - - If an object is a sub-class of a particular class, it will have a different ClassID() because it is a different class. This method allows an object to indicate that it is a sub-class of a particular class and therefore can be treated as one. For example, a class could be derived from . This derived class would have a different ClassID() then the 's class ID however it still can be treated (cast) as a because it is derived from . Note the default implelementation: a class is considered to also be a subclass of itself. - TRUE if this class is a sub-class of classID; otherwise FALSE. - Default Implementation: - ClassID();} - - The of the item that this class is a sub-class of. - - - - This method is available in release 2.0 and later only (previously in Class in 1.x). - - This method is called on whatever controller the user is modifying with the mouse - when the mouse button is released. For example when the user selects a node in the viewports, then drags, then releases the mouse button, this method is called. This method will also be called when the user clicks on a key in the track view and lets up. If a controller performs extensive calculation in its evaluation this method is handy. The controller could perhaps perform a simplified calculation during interactive adjustment of a node. Then when the user releases the mouse button this method is called and the extensive calculations are performed. - - The default implementation of this method is recursive so it gets called on all sub-anims affected by a range bar operation. - - The time the mouse was released. - - - - This method is called on whatever controller the user is modifying with the mouse - when the mouse button is pressed. - - The default implementation of this method is recursive so it gets called on all sub-anims affected by a range bar operation. - - The time the mouse was first pressed. - - - - This method is available in release 3.0 and later only. - - This method returns the number of ParamBlock2s in this instance. - Default Implementation: - { return 0; } - - - - - This method return 'i-th' ParamBlock2 in this instance (or NULL if not available). - Default Implementation: - { return NULL; } - - The zero based index of the ParamBlock2 to return. - - - - This method returns a pointer to the ParamBlock2 as specified by the ID passed (or NULL if not available). - Default Implementation: - { return NULL; } - - The BlockID of the ParamBlock2 instance. - - - - This method is available in release 3.0 and later only. - - Implemented by the System. - - This is the save method for schematic view data. For classes derived from , there is no need to call these. However, if you have a class derived from and it appears in the schematic view and you want to save schematic view properties for the object (node position, selection state, etc.) then you have to call this in your Save() method. - Returns true if saved okay; otherwise false. - - An interface for saving data. See Class . - The Chunk id (choosen by the developer). - - - - Implemented by the System. - - This is the load method for schematic view data. For classes derived from , there is no need to call these. However, if you have a class derived from and it appears in the schematic view and you want to load schematic view properties for the object (node position, selection state, etc.) then you have to call this in your Load() method. - Returns true if loaded okay; otherwise false. - - An interface for loading data. See Class . - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - Operators: - - - - - This method is available in release 3.0 and later only. - - This method traverses the graph of objects in the 3ds Max scene, adding desired objects to the schematic view. Developers can specialize this behaviour by overriding this method and adding whatever objects are interesting to the schematic view. Objects are added to the schematic view by calling IGraphObjectManager::AddAnimatable(...). Reference lines are added to the schematic view by calling IGraphObjectManager::AddReference(...). Implementers of this method should call it recursively to process other objects in the scene. - - See Class . - A object. - - Points to the schematic view window manager. - The owning animatable. - This is usually the sub-anim number (but can actually be any value the developer chooses). - See . - - - - This method is a default graph traversal function which can be called from SvTraverseAnimGraph(...) above to handle graph traversal in simple cases. This traversal follows the sub-anim and child references. See the code below. - A object. - Default Implementation: - - Points to the schematic view window manager. - The owning animatable. - This is usually the sub-anim number (but can actually be any value the developer chooses). - See . - - - - Returns true if this animatable can be the initiator of a link operation in the schematic view. - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - Returns true if this animatable can be the receiver (parent) of a link operation in the schematic view. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - Points to the child node in the schematic view. - - - - Returns the name of the object as it appears in the schematic view. - Default Implementation: - - Points to the schematic view window manager. - Points to this node in the schematic view. - TRUE if the item is being edited; FALSE if not. - - - - Return true to permit the object's name to be edited in the schematic view. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - Called when the user changes the name of the object in the schematic view. - TRUE if the name was changed; FALSE if not. - - Points to the schematic view window manager. - Points to this node in the schematic view. - The new name to set. - - - - This method is available in release 3.0 and later only. - - Return true if this object can be removed in the schematic view; false if not. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - Called when the user deletes this object in the schematic view... - - - true if deleted; false if not. - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - Returns true if the object is selected in its schematic view. - - - - - Returns true if the object is to be highlighted in the schematic view; otherwise false. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - This method is available in release 3.0 and later only. - - Returns the highlight color for this node. The highlight color is used to outline nodes in the schematic view when SvIsHighlighted(...) returns true. - See . - Default Implementation: - { return gom->SvGetUIColor(SV_UICLR_PLUGIN_HIGHLIGHT); } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - This method is available in release 3.0 and later only. - - Returns a color which is used to paint the triangular color swatch that appears in the upper-right hand corner of the node in the schematic view. One can return SV_NO_SWATCH to indicate that no swatch is to be drawn. - See . - Default Implementation: - { return SV_NO_SWATCH; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - This method is available in release 3.0 and later only. - - Returns true if this object is inactive; false is active. The schematic view draws inactive nodes in a grayed-out state. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - - - - This method is called to link this object to the gNodeChild passed. - true if linked; false if not. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to this node in the schematic view. - Points to the child node in the schematic view. - - - - This method is available in release 3.0 and later only. - - This method is called when this node is double-clicked in the schematic view. - true is handled; false if not interested in the event. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - This method is called before a multiple select/deselect operation in the schematic view. Returns a callback used to perform the (de)selection. May return NULL if this object cannot be selected in some principle editor outside the schematic view. - A pointer to the callback object. See Class . - Default Implementation: - { return NULL; } - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - Returns true if this object can be selected in some editor (viewport, material editor, plug-in specific editor, etc.). Selection is actually accomplished by via the SvGetMultiSelectCallback(...) mechanism described above. - Default Implementation: - { return false; } - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - This method is reserved for future use. - Default Implementation: - { return false; } - - - - - Returns a string to be displayed in the tip window for this object in the schematic view. - Default Implementation: - { return SvGetName(gom, gNode, false); } - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - Returns a string to be displayed in the tip window in the schematic view for a reference from "gNodeMaker" to this. - Sample Code: - - Points to the schematic view window manager. - Points to the node in the schematic view. - Points to the node in the schematic view. - - - - Returns true is this object can respond to the SvDetach(...) method; false if not. - Default Implementation: - { return false;} - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - This method is called to detach this object from its owner. - Returns true if detached; otherwise false. - Default Implementation: - { return false;} - - Points to the schematic view window manager. - Points to the node in the schematic view. - - - - Returns a string to be displayed in the tip window in the schematic view for a relationship from "gNodeMaker" to "gNodeTarget"... - - - A string to be displayed in the tooltip - Sample Code - - Points to the schematic view window manager. - the that represents the target of the relationship. - The value passed as the ID parameter. Usually the subanim number. - The that represents the maker of the relationship (the animatable being called) - - - - Returns true if this object can respond to the SvDetachRel(...) method... - - - true if this animatable can process a call to SvDetachRel - Default Implementation: - - Points to the schematic view window manager. - the that represents the target of the relationship. - The value passed as the ID parameter. Usually the subanim number. - The that represents the maker of the relationship (the animatable being called) - - - - Detach this relationship. - - - gNodeMaker is called to detach gNodeTarget - true if the relationship was detached - Default Implementation: - - Points to the schematic view window manager. - the that represents the target of the relationship. - The value passed as the ID parameter. Usually the subanim number. - The that represents the maker of the relationship (the animatable being called) - - - - Called when this relationship is double-clicked in the schematic view... - - - true if the double click was handled - Default Implementation: - - Points to the schematic view window manager. - the that represents the target of the relationship. - The value passed as the ID parameter. Usually the subanim number. - The that represents the maker of the relationship (the animatable being called) - - - - This method returns a pointer to the custom attributes container interface class. See Class for more information. - - - - - This method allocates space for a custom attributes container. - - - - - This method deletes space used by a custom attributes container. - - - - - This is called to delete any item that can be rebuilt. For example, the procedural sphere object has a mesh that it caches. It could call Mesh::FreeAll() on the mesh from this method. This will free the vertex/face/uv arrays. If the sphere is ever evaluated again it can just rebuild the mesh. If an object (like a sphere) has modifiers applied to it, and those modifiers are not animated, then the result of the pipeline is cached in the node. So there is no reason for the sphere to also have a cache of its representation. Therefore when this method is called, the sphere can free the data of the mesh. - Default Implementation: - {} - - - - - This method is used internally. - - - - - This method is used internally. - - - - - This method is used internally. - - - - - returns true if the sub-anim has a "Set Key" buffer present - - - TRUE if the SubAnim has a SetKey buffer present - Default Implementation: - - - The index of the SubAnim to test. - - - - returns true if there is a "Set Key" buffer present - - - This method should be implemented for a keyframeable controller to support the "Set Key" animation mode. When in the "Set Key" mode, if the user modifies a keyframe controller the controller should create a temporary buffer to hold the new value until the user either commits or cancels the change. - - - It is the plugins responsibility to ensure that the correct value (either the temp buffer or the permanent keyframed value) is returned from GetValue. For an example implementation of this method, look at samples/controllers/boolctrl.cpp - True if a buffer is present - - - - - Commit any "Set Key" buffers on the given sub-anim. - - - Default Implementation: - - - The index of the SubAnim to commit. - - The time of the SubAnim to commit. - - - - Commit any "Set Key" buffers. - - - This function will be called whenever the user clicks the the large "Set Keys" button. If this animatable is keyable, it should commit any temporary "Set Key" buffers to its permanent keyframe storage. For an example implementation of this method, look at samples/controllers/boolctrl.cpp - - - - - Revert any "Set Key" buffers on the given sub-anim. - - - Default Implementation: - - - The index of the SubAnim to revert. - - - - Revert any "Set Key" buffers. - - - If this animatable currently has a "Set Key" buffer, revert the value and remove the buffer. For an example implementation of this method, look at samples/controllers/boolctrl.cpp - - - - - This function is obsolete. - - - - - Tells whether it is a . - - - This function differentiates things sub classed from from subclasses of . The implementation of this method (in ) returns FALSE and its implementation in returns TRUE. - Default of FALSE. - - - - - Returns true if the passed description is being used. - - - When plugins use a dynamic Paramblock2 system, and build a on demand, the list maintained by the may not reflect the active configuration in the plugin. This method lets the system filter the list maintained by asking the plugin (such as the DxMaterial) whether the current is currently used by the plugin. Anybody querying the for the needs to make sure that the descriptor is currently being used by the plugin. - This mostly goes for maxscript. - true if the plugin is currently using a parameter block built from desc. - Default Implementation: - - The description to test - - - - This method is called to access the object specified name to use for the Maxscript macrorecorder. - - - The Maxscript macrorecorder will determine the name of the object to use when emitting code. In some cases it cannot determine a name for the object, for example when setting a value on a ParamBlock when the ParamBlock owner is a utility plugin singleton. This method allows the object to specify the name to be used. - If this method returns true and objectSpecifiedName is empty, no code will be emitted. This is useful in the case where you don't changes to an object's parameters to be macro recorded. - Returns true if a name is specified; otherwise false. If true and objectSpecifiedName is empty, no code will be emitted. - - [in] The object is being assigned to a property, return constructor expression (i.e., "box()"). - [out] The object name for Maxscript macrorecorder to use. - - - - Suspends the "animate" mode in an exception safe manner. - - - The system is in "animate" mode when animation keys are being created. Create an instance of this class to suspend the "animate" mode. When the instance is destructed the "animate" mode is resumed. It's a good idea to suspend the "animate" mode whenever new instances of a plugin are being created, or their parameters are modified programatically. Examples of when the "animate" mode is suspended include assigning controllers and copying key frames from a controller to another, cloning objects, etc. - accomplishes the same thing as a call to SuspendAnimation(), but in a manner that is safe when exceptions are thrown. - - - - - Restores "animate" mode to its initial state. - - - - - A callback class for Animatable::EnumAnimTree(). This class automatically keeps track of the depth of the enumeration. - - - - - Implemented by the System. - - Returns the scope. - One or more of the following scope values: - - SCOPE_DOCLOSED - - Do closed animatables. - - SCOPE_SUBANIM - - Do the sub anims - - SCOPE_CHILDREN - - Do the node children - - SCOPE_OPEN - - Do all open animatables - - Equal to (SCOPE_SUBANIM|SCOPE_CHILDREN) - - SCOPE_ALL - - Do all animatables. - - Equal to (SCOPE_OPEN|SCOPE_DOCLOSED) - - - - - Implemented by the System. - - Increments the depth count. - - - - - Implemented by the System. - - Decrements the depth count. - - - - - Implemented by the System. - - Returns the depth count. - - - - - This is a method called by EnumAnimTree(). - - - If anim is an and client is not either an or the scene root pointer, node_subAnim_proc is called instead of this method. - One of the following values: - - ANIM_ENUM_PROCEED - - Continue the enumeration process. - - ANIM_ENUM_STOP - - Stop the enumeration process at this level. - - ANIM_ENUM_ABORT - - Abort the enumeration processing. - - The sub anim. - The client anim. This is the parent with a sub-anim of . - The index of the sub-anim that is to . For example, if you were to call it would return . The exception to this is the handling of the scene node hierarchy. In this case anim would be an and client would be either its parent or the scene root pointer, and subNum would be the child index. - - - - This is a method called by EnumAnimTree(). - - - Normally, if anim is an then client would be either its parent or the scene root pointer. However it is possible that an can return an as a sub-anim. In the event that client is a sub-anim somewhere under a node, and anim is a parent node of that node, the potential for infinite recursion exists since continuing enumeration into that parent node will result in returning to this point. Calling proc and then stopping enumeration at this level would result in the method implementation flagging the node as visited. If the method implementation returns ENUM_STOP if it is passed an anim that has been previously visited, and the node is processed again as the node hierarchy is enumerated, ENUM_STOP would be returned resulting in its sub-anims not being visited. Due to this issue, if anim is an and client is not either an or the scene root pointer, this method is called instead of proc The default implementation for this method is to just return ANIM_ENUM_STOP. An implementation of this method should account for the potential for recursion. A sample scene to test implementations against can be created by running the following script. - One of the following values: - - ANIM_ENUM_PROCEED - - Continue the enumeration process. - - ANIM_ENUM_STOP - - Stop the enumeration process at this level. - - ANIM_ENUM_ABORT - - Abort the enumeration processing. - - The sub anim. - The client anim. This is the parent with a sub-anim of . - The index of the sub-anim that is to . For example, if you were to call it would return . - - - - Description: - This is the base class for classes that can be hung off an animatable's property list. When an animatable is deleted, its properties will be deleted and their virtual destructor will be called. - - - - - When the animatable is destroyed it will normally delete all the properties. If a plug-in wants to add a property to the list that it does not want deleted it can implement this method to return TRUE. - TRUE if the item should not be deleted; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - Returns the ID of the property. Values above PROPID_USER can be used by plug-ins. Note: that a plug-in should only put user defined properties on its own list. So IDs only have to be unique within a plug-in. If a plug-in needs to attach data to another object, it can do so via APP_DATA. - - - - - Description: - This class is simply a table of anim properties. It has a single method to locate a given id in the list. See Class for details on how to manipulate the table. - - - - - Implemented by the System. - - Returns the table index of the property whose id is passed. - Parameters: - DWORD id - - The id to find. - - int start=0 - - A table index that may be used to define an alternate starting point for the search. This is a index into the table of properties. - The table index of the property, or if not found, -1. - - - - - Description: - This class enables implementing undo of Gizmo assignment in Atmosphere and Effects classes. This class provides implementations of the methods. An instance of this class can be put on the stack when a Gizmo is appended. For example: - All methods of this class are implemented by the System. - Data Members: - *fx; - - Points to the Atmosphere of . - - *node; - - Points to the gizmo node. - - - - - An application/plugin specific custom data that can be attached to animatables. Instances of this class store custom data defined by plugins and are attached to animatables when plugins call Animatable::AddAppDataChunk. Plugins don't need to instantiate directly objects of type , but can get to the instances stored on animatables by calling Animatable::GetAppDataChunk. - - - Example - This example is from samples/utilities/appdata.cpp: - - - - - The of the owner of this chunk. - - - - - The SuperClassID of the owner of this chunk. - - - - - An extra ID that lets the owner identify its sub chunks. - - - - - The length of the data in bytes. - - - - - The chunk data itself. - - - - - Loads this . - - - The system implements this method to load the from disk. - - - - - Saves this . - - - The system implements this method to save the to disk. - - - - - Description: - This class takes a chunk-ified data stream (as written by Class ), and provides routines for decoding it. - - All methods of this class are implemented by the system. - - - - - This method is used to open a chunk. If OpenChunk() returns IO_OK, use the following 3 functions to get the information about the chunk. If it returns IO_END this indicates there are no more chunks at this level. - IO_OK - The result was acceptable - no errors. - - IO_END - This is returned when the end of the chunks at a certain level have been reached. It is used as a signal to terminate the processing of chunks at that level. - - IO_ERROR - This is returned if an error occurred. - - - - - This method returns the ID of the most recently opened chunk. - - - - - This method returns the type of the most recently opened chunk. This may be one of the following values: - - NEW_CHUNK - - CONTAINER_CHUNK - - DATA_CHUNK - - - - - This method returns the chunk length not including the header. - - - - - This method is used internally for checking for balanced OpenChunk/CloseChunk pairs. - - - - - This method is used to close the currently opened chunk, and position at the next chunk. - A return value of IO_ERROR indicates there is no open chunk to close; otherwise IO_OK. - - - - - This method returns the ID of the next chunk without opening it. It returns 0 if there are no more chunks. - - - - - This method is used to read a block of bytes. - Parameters: - void *buf - - A pointer to the buffer to read. - - ULONG nbytes - - The number of bytes to read. - - ULONG *nread - - The number of bytes that were read. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - This method read a string that was stored as Wide characters. Note: This method reads a string from a string chunk. It is assumed the chunk is already open, it will NOT close the chunk. - Parameters: - char** buf - - A pointer to an array of characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - This method read a string that was stored as Wide characters. Note: This method reads a string from a string chunk. It is assumed the chunk is already open, it will NOT close the chunk. - Parameters: - wchar_t** buf - - A pointer to an array of wide characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - This method reads a string that was stored as single byte characters. - Parameters: - char** buf - - A pointer to an array of single byte characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - This method read a string that was stored as Wide chars. Note: This method reads a string from a string chunk. It is assumed the chunk is already open, it will NOT close the chunk. - Parameters: - wchar_t** buf - - A pointer to an array of wide characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - Description: - This class is a general chunk-ifying code useful for writing hierarchical data structures to a linear stream, such as an AppData block. - - All methods of this class are implemented by the system. - - will write hierarchical chunks into a private buffer, enlarging it as needed. When completed, use the methods BufferPtr() and NBytesWritten() to get at this buffer. ( will delete the buffer in its DeleteThis() method , so you need to copy the buffer to save the data.) - - The chunk hierarchy should always have a single highest level chunk. Chunks can be nested to any depth. - - A Chunk can contain either sub-chunks, or data, but not both. - Sample Code: - - - - - This method is used after saving to get a pointer to the buffer created. - - - - - This method returns the number of bytes that were written in the buffer. - - - - - This method is used to begin a chunk. The ID passed need only be unique within the plug-ins data itself. - Parameters: - USHORT id - - The id for the chunk. - - - - - This method is used to end a chunk, and back-patch the length. - - - - - This method is used internally for checking balanced BeginChunk/EndChunk. - - - - - This method writes a block of bytes. - Parameters: - const void *buf - - The buffer to write. - - ULONG nbytes - - The number of bytes to write. - - ULONG *nwrit - - The number of bytes actually written. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - This method is used to write wide character strings. - Parameters: - const char *str - - The string to write. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - This method is used to write wide character strings. - Parameters: - const wchar_t *str - - The string to write. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - This method is used to write single byte character strings. - Parameters: - const char *str - - The string to write. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - This method is used to write single byte character strings. - Parameters: - const wchar_t *str - - The string to write. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - Description: - This class provides methods to work with a general arcball dialog box for doing 3D rotations. This dialog appears below: - - To use these APIs you'll need to #include "arcdlg.h" - - All methods of this class are virtual. - - Sample code can be found in /MAXSDK/SAMPLES/HOWTO/CUSTCTRL/CUSTCTRL.CPP. - - - - - This method is called when a drag operation begins. The developer may want to save the start state at this point. - - - - - This method is called when a drag operation ends. - - - - - This method is called during a drag operation. - Parameters: - q - - The relative rotation from the start rotation. - - BOOL buttonUp - - If TRUE this indicates if the mouse button is up (has been released); if FALSE the button is down. - - - - - This method is called when the right mouse button is clicked during a drag operation to cancel it. - - - - - This method is called if the dialog box window was closed. - - - - - Description: - An instace of this class is created when the global function is called. The DeleteThis() method of this class is used to free the memory allocated by CreateArcballDialog(). Call it when you are done using the dialog box. - - - - - interface class used to access Max volumes for rendering, etc. - - - - - Query for volume step size at the given time. - Parameters: - TimeValue t - The time to use for the data - the step size for the volume. - - - - - Query for volume step scale at the given time. - Parameters: - TimeValue t - The time to use for the data - the step scale for the volume. - - - - - Query for volume bounds padding amount at the given time. - Parameters: - TimeValue t - The time to use for the data - the padding amount for the volume bounds. - - - - - Query for velocity value at the given time. - Parameters: - TimeValue t - The time to use for the data - the velocity for the volume. - - - - - Query for velocity scale at the given time. - Parameters: - TimeValue t - The time to use for the data - the velocity scale for the volume. - - - - - Description: - This class is the callback object passed to Interface::EnumAuxFiles() and to Animatable::EnumAuxFiles(). A developer derives a class from this class and implements the RecordAsset() method to store each asset as it's passed to it. At the end of the EnumAuxFiles() processing, the table of names may be used. See Class for help storing the names. - - - - - This method is used to record the asset passed. - Parameters: - & asset - - The asset to store. - - - - - Description: - This is the base class for the creation of plug-ins. Developers may look to the text below for information on the techniques used to create these types of effects: - - Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley, Texturing and Modeling A Procedural Approach (Cambridge, MA: Academic Press, Inc., 1994). ISBN: 0-12-228760-6. - - Chapter 6 on Hypertexture, particularly the section on 'Raymarching', describes essentially the method 3ds Max uses. - - - - - This is the function that is called to apply the atmospheric effect. The line segment defined by the world space points p0 and p1 represent a segment of volume that needs to be shaded. This line segment is a line along the ray defined by the line between the viewer's eye (the camera) and the pixel being rendered in the image plane and continuing through world space. This ray is broken up into segments, with the boundaries defined by surfaces. If there are no surfaces, there will just be a single segment from the eye point going off into space (p1 will be a large number). If there is a surface that is hit, and the surface is opaque, there will still be one segment from the eye to the surface. If the surface is transparent there may be two segments, the segment before and the segment after. Therefore the ray may be broken up into many segments depending on the number of transparent surfaces hit. - - The shader does not need to be directly concerned with this however. It only knows it's shading the segment between p0 and p1. It will get called repeatedly for different pixels and different segments. - - The output of this method is the computed color and transparency. - - An example implementation of this method is 3ds Max's Simple Fog. It takes the distance of the line segment and essentially interpolates towards the fog color based on the distance. This is a very simple effect. - - 3ds Max's Volume Fog traverses along the segment and evaluates its 3D noise function. It integrates the density across the segment, and uses the density to compute the fog color. - Parameters: - & sc - - The . - - & p0 - - The start point of the segment to shade. This point (and p1) are in an undefined 'internal' space specific to the renderer (which for the 3ds Max renderer is in fact is camera space). To get to world space the plug-in would call sc.PointTo(p0,REF_WORLD). - - & p1 - - The end point of the segment to shade. - - & color - - This method shades the volume between p0 and p1 and modifies this color. - - & trans - - This method shades the volume between p0 and p1 and modifies this transparency. - - BOOL isBG=FALSE - - TRUE if the background is being shaded; otherwise FALSE. If TRUE then p1 will be infinity (a large number). This is used when the option to not fog the background is on. - - - - - Description: - This class provides a general way for objects to handle the attach materials dialog presented when users attach objects to each other. To use this class do the following: - - 1) Subclass your modifier or editable object off this class as shown below. Implement the four functions that give access to the attach/condense options. - - 2) Now your class simply calls the global DoAttachMatOptionDialog() function, which deals with the parameters uniformly for all users. The implementation in Edit Spline is like so: - - - And the statics are defined as: - - - - - - - Returns the attach material setting. One of the following values: - - ATTACHMAT_IDTOMAT - - Match material IDs to material. - - ATTACHMAT_MATTOID - - Match to IDs. - - ATTACHMAT_NEITHER - - Do not modify IDs or . - - - - - Returns the condense material and IDs settings. - - - - - A class used for listing the fonts we currently have available - - - - - Description: - This is the callback used with Interface::RegisterAxisChangeCallback(). - - - - - This callback object will be notified any time the user changes the reference coordinate system by: - - Changing the transform coordinate system drop-down menu. - - Changing the state of the transform center fly-off. - - Changing X, Y, Z, XY, YZ, ZX constraint buttons/fly-off. - - Using an accelerator or anything else that changes the above. - Parameters: - *ip - - A pointer available for calling methods provided by 3ds Max. - - - - - Description: - This class represents color as four floating point values: r, g, b, and an alpha channel a. Also note the following typedef: RGBA; - - - - - These values are in the range 0.0 to 1.0. - - - - - Sets this to black. r = g = b = 0.0f; a= 1.0f - - - - - Sets the to white. r = g = b = a = 1.0f - - - - - Makes all the components of the <= 1.0 - - - - - Makes all the components of the >= 0.0 - - - - - Makes all the components of the fall in the range 0.0 to 1.0. - - - - - Access operators. - Parameters: - int i - - The index of the component to return. - 0=r, 1=g, 2=b, 3=a. - - - - - Convert the to a Windows RGB color. See COLORREF. - A Windows RGB color. - - - - - Unary - operator. - The with the components negated, i.e. - - (-r,-g,-b, -a)); } - - - - - Unary + operator. - The itself. - - - - - Subtracts an from this . - A that is the difference between two Colors. - - - - - Adds an to this . - An that is the sum of two AColors. - - - - - Multiplies the components of this by a float. - An multiplied by a float. - - - - - Divides the components of this by a float. - An divided by a float. - - - - - Performs element-by-element multiplying between two AColors. - This element-by-element multiplied by another . - - - - - Test for equality between two AColors. - Nonzero if the AColors are equal; otherwise 0. - - - - - Tests for inequality between two AColors. - Nonzero if the AColors are not equal; otherwise 0. - - - - - Subtracts an from an . - An that is the difference between two AColors. - - - - - Adds an to an . - An that is the difference between two AColors. - - - - - Divides an by an . - An divided by an . r/r, g/g, b/b, a/a. - - - - - Multiplies an by an . - An multiplied by an . r*r, g*g, b*b, a*a. - - - - - Client information for ATS Providers. - - - This object provides application specific information to the ATS Provider - - - - - Get client name. - - - The client name is typically the name of the application utilizing the ATS Provider. - string containing the name of the client. - - - - - user name. - - - - string containing the name of the user. - - - - Window handle of client. - - - HWND handle of parent window - - - - - Get Provider plugin path location. - - - This is used to specify a location in which additional plugins would reside. - string containing the path - - - - - Get Provider configuration file path location. - - - This is used to specify a location in which additional configuration files would reside. - string containing the path - - - - - Get interface. - - - pointer to interface - - - - - ATS Explore Provider . - - - describes the parameters for the IATSProvider::ExploreProvider method - - - - - Get title. - - - Defines the title for the explore provider dialog - string containing the title - - - - - Get multiple selections state. - - - Defines if multiple selections should be allowed within the explorer dialog - true if multiple selections are allowed, false if not - - - - - Get download files state. - - - Defines if the provider should automatically download the files selected - true if download should occur, false if not - - - - - Add filter for explorer dialog. - - - A filter defines the "Type of File" that should be available for selection and/or display. Some examples: For all files: AddFilter( "All files (*.*)", "*.*" ); For jpeg files: AddFilter( "JPEG (*.jpg,*.jpeg)", "*.jpg;*.jpeg" ); - new number of filters - - name of filter as it should be displayed in the dialog. Example: "Add files (*.*)" - List of extensions. Example: "*.jpg;*.jpeg" - - - - of filters. - - - number of filters - - - - - Get filter name. - - - string containing filter name - - 0-based index of filters - - - - Get filter extensions. - - - string containing filter extensions - - 0-based index of filters - - - - ATS File . - - - describes a file monitored by the Asset Tracking System. It contains information about the status, children (or dependent) files, and any attachment files to this file. Children define the file dependency tree for a particular . Attachments do not define a hierarchy and are single entries associated with the . Attachments are not considered a dependency and are simply files associated with the . - - - - - Get file name. - - - string containing the filename - - - - - Get the In Flags for this file. - - - The In flags are typically used to select, activate, exclude, etc. an within a . - In flags (ATSStatus) - - - - - Get the client pointer associated with this file. - - - Client pointer specified for this file - client pointer (ATSClientPtr) - - - - - Get the Out Flags for this file. - - - The Out flags are typically set by an ATS Provider to specify the version control status of this file. - Out flags - - - - - Add child. - - - New number of children - - Pointer to object to add as child - - - - of children. - - - of children - - - - - Get child. - - - pointer to object - - 0-based index of child - - - - Remove child. - - - true if success, false if failure - - 0-based index of child - - - - Remove all child. - - - true if success, false if failure - - - - - Add attachment. - - - New number of attachments - - string that contains file name - default is NULL. Pointer to parent object - default is kATSStatusActive. ATSStatus value that specified initial In flags. - default is NULL. Client defined pointer. - - - - Add attachment. - - - New number of attachments - - Pointer to object to add as an attachment. object will be copied. - - - - of attachments. - - - number of attachments - - - - - Get attachment. - - - pointer to object - - 0-based index of attachment - - - - Remove attachment. - - - true if success, false if failure - - 0-based index of attachment - - - - Remove all attachments. - - - true if success, false if failure - - - - - Get parent. - - - Pointer to object - - - - - ATS File List. - - - is a list of objects. It maintains three lists: 1) List of objects added, 2) List of root objects (those without parents), and 3) List of Active objects as specified and order by BuildActiveList method. - - - - - Create and add new . - - - pointer to object or NULL if failure - - string containing filename - default is NULL. Pointer to parent object - default is kATSStatusActive. ATSStatus value that specified initial In flags. - default is NULL. Client defined pointer. - - - - Copy and add new . - - - pointer to object or NULL if failure - - This object is copied and added to the entry list. - - - - Remove entry. - - - true if success, false if failure - - Pointer to object. - - - - of entries. - - - number of entries in file list - - - - - Remove entry by index. - - - true if success, false if failure - - 0-based index into file entry list - - - - Remove all entries. - - - true if success, false if failure - - - - - Get entry. - - - pointer to object or NULL if failure - - 0-based index into file entry list - - - - Build an active list. - - - This method builds (or rebuilds) the active file list as defined by a status and traversal criteria. - number of files in active list - - default kATSStatusActive. Only add file entries that contain this flag in their In flags. - default false. When false, the active file list will be generated by an inorder traversal of the file list. When true, the list will be generated using a depth first traversal as defined by the hierarchy. When performing in which dependent files need to be added or checked in first, the active file list should be built with bDepthFirstTraversal set to true. - - - - Add entry to active list. - - - number of files in active list - - Pointer to object to add to active list. - - - - Remove active entry. - - - true if success, false if failure - - Pointer to object. - - - - of active entries. - - - number of active entries in file list - - - - - Get active entry. - - - pointer to object or NULL if failure - - 0-based index into active file entry list - - - - of root entries. - - - number of root entries in file list - - - - - Get root entry. - - - pointer to object or NULL if failure - - 0-based index into root file entry list - - - - Register for and Broadcast ATS Notification Messages. - - - - - Asset Tracking System Notification Parameter class. - - - This class is created and configured by an object send an ATS notification message. - - - - - Returns the Notification ID. - - - returns the ID of the notification message - - - - - Returns the index of the provider. - - - Returns the index of the provider that is associated with the message - - - - - Specifies if this notification message was cancelled. - - - If a message is cancelled by an object that has registered for notifications, all objects that received the notification before it was cancelled will be notified again, but this method will return true to allow the objects to perform any cleanup or undo any action taken. - true if cancelled, false if not cancelled - - - - - Sets the cancel state of a notification message. - - - - true if cancelled, false if not. - - - - Returns the file list associated with the notification message. - - - pointer to object - - - - - ATS User . - - - describes public data about a provider's user - - - - - user name. - - - - string containing the user's name - - - - Get user's first name. - - - string containing the user's first name - - - - - Get user's last name. - - - string containing the user's last name - - - - - Get user's email. - - - string containing the user's email - - - - - ATS User List. - - - Maintains a list of objects - - - - - Create and add new . - - - pointer to object or NULL if failure - - string containing user name - - - - Copy and add new . - - - pointer to object or NULL if failure - - This object is copied and added to the entry list. - - - - Remove entry. - - - true if success, false if failure - - Pointer to object. - - - - of entries. - - - number of entries in file list - - - - - Remove entry by index. - - - true if success, false if failure - - 0-based index into user entry list - - - - Remove all entries. - - - true if success, false if failure - - - - - Get entry. - - - pointer to object or NULL if failure - - 0-based index into user entry list - - - - All behaviors must inherit from this base class. - - - - - Gets the name of the behavior. - - - Usually this name will be stored internally within a paramblock. The name usually starts out being the same as the behavior's class name. The name can then be changed from within the Crowd system, which sets it by calling this function. - the behavior name - - - - - Returns the behavior's type, either FORCE, CONSTRAINT, or ORIENTATION. - - - - - - - Queries whether or not the behavior may be modified by the behavior weight scalar. - - - For the user, this weight appears in the assignment dialog for each assignment. - Usually FORCE types are weightable, while CONSTRAINT and ORIENTATION behaviors aren't. - 1 if the behavior is weightable, 0 if not. - - - - - Queries whether or not the behavior can convert itself to a script. - - - This function is for future versions of Crowd. It is not used now. - true if the behavior can convert itself to maxScript, false if not - - - - - Sends the behavior a list of all delegates which will participate in the simulation. - - - At the beginning of a simulation, this function is called for each behavior in the simulation. - All active delegates assigned via an active assignment to any behavior or cognitive controller in the crowd system are included in the participants . - So this function tells the behavior the maximum number of delegates that could possibly perform this behavior during the simulation, and which delegates those are. - With this information, the behavior can set up whatever data structures it requires to keep track of parameters on a per delegate basis. At the end of the simulation, this function is again called for each behavior, this time with an empty participants list, in order to allow the behavior to clear its data structures. - - - a tab of all of the delegates in the simulation. The delegates must be active, and they must be assigned, via an active assignment, to at least one behavior or cognitive controller. - - - - Notifies the behavior that it should start to act upon a particular delegate. - - - This function is called during a simulation, whenever a cognitive controller activates the behavior for a particular delegate. It allows a behavior to keep track of which delegates it is acting upon. - - - the current simulation time. - - the delegate which started the behavior - - - - Initializes a behavior at the start of each simulation frame. - - - This function is called at the beginning of each frame of the simulation. - It allows the behavior to set up or clear out any information that it might need each frame. - - - the current simulation time - - - - Initializes the behavior at the start of a simulation. - - - This function is called once just before the beginning of the simulation. - It is called so that the behavior knows which frame the simulation is actually starting at so it can perform any actions necessary to assure its repeatability. For example, if a behavior knows that the simulation is starting at frame 10 instead of frame 0, it may run it's random number generator 10 times so that the value it generates will be consistent with what it normally computes when the simulation starts from the beginning, as specified by the SimStart parameter. - - - the value of the first frame for this particular run of the simulation. This is the same as Start Solve in the crowd solve rollout. It is not in time ticks, but in frames. - - the delegate - - the value of the frame when the simulation starts This is the same as Simulation Start in the crowd solve rollout. It is not in time ticks, but in frames. - - the index of the assignment used to apply this behavior to the delegate. If this equals -1, the behavior has been assigned using a cognitive controller. The AssignIndex can be used as a parameter to the class's IsAssignmentActive function, which allows you to find out if this assignment is active at a given time. You may need this information to properly initialize a behavior before a simulation. - - - - This is the main function for FORCE behaviors. - - - It is called every frame for each delegate the behavior is acting upon. - It is within this function that the behavior may set any combination of the following: the force acting upon the delegate, the delegate's speed, or a goal towards which the delegate should move. - 0 if the behavior isn't active for this particular delegate, or if the behavior, for any reason, wishes to have no effect on the delegate at this time. Otherwise, it returns the union of three #defines, BHVR_SETS_FORCE, BHVR_SETS_GOAL, and BHVR_SETS_SPEED, depending upon whether or not the behavior sets a force, a goal or the speed. For example, a behavior that sets both a force and goal will return BHVR_SETS_FORCE | BHVR_SETS_GOAL. - Which of these values are returned determines which items in the PeformOut structure are valid. - - - the delegate - - the current simulation time - - how many subsamples are being computed per frame. Currently not used. - - whether or not the behavior should display it's visual information. This parameter exists so that the Crowd system has global control over when the behavior information is displayed. - - A float value, greater than or equal to 0.0, that corresponds to the BehaviorWeight value in the Crowd Assignment dialog. This value should be used to scale the returned force value in the out parameter. - - A structure that is used to pass out information that the behavior calculates. The structure has 4 items that may be set, depending upon whether the behavior sets a force, a speed or a goal. - - - - This is the main function for CONSTRAINT behaviors. - - - It is called multiple times per frame for each delegate the behavior is acting upon. - It is within this function that the behavior may set a modified velocity or modified position for a delegate. - 0 if the behavior isn't active for this particular delegate, or if the behavior, for any reason, wishes to have no effect on the delegate at this time. Otherwise, it returns 1. - - - the delegate - - the current simulation time - - how many subsamples are being computed per frame. Currently not used. - - whether or not a goal currently exists for this delegate. If it exists, it will be passed in via the inOut parameter. - - whether or not the behavior should display it's visual information. This parameter exists so that the Crowd system has global control over when the behavior information is displayed. - - whether or not this is the final time that the constraint will be called during the frame. Currently, each constraint behavior is called two times per frame (this may change in the future) - once after all of the forces have been assembled and just before a possible avoid behavior, and then once again at the end of the frame. It is called multiple times per frame so that the behavior may work correctly with any active avoid behavior. This flag lets the behavior know if it is the last time it will be called during that frame and thus should cache any information that it needs for the next frame calculation. Usually if the behavior isn't doing any sort of per frame caching it should just ignore this flag. - - a structure that is used to pass in information that the behavior will modify and then pass out. The structure contains 4 parameters: - - - - This is the main function for ORIENTATION behaviors. - - - It is called every frame for each delegate the behavior is acting upon. - It is within this function that the behavior may set a quaternion representing the delegate's orientation. - 0 if the behavior isn't active for this particular delegate, or if the behavior, for any reason, wishes to have no effect on the delegate at this time. Otherwise, it returns 1. - - - the current velocity of the delegate - - the delegate - - the current simulation time - - The quaternion specifying the new orientation of the delegate - - - - Using this function, a behavior can display text or graphics inside the viewports. - - - This is typically used to display a bounding area or a target. Often the behavior will allow the user to turn on or off this display by providing a checkbox in its interface. - 1 if something is drawn, otherwise 0. - - - the time to display the object. - - an interface pointer that may be used to call functions associated with the viewports - - - - Gets the world bounding box of what the behavior draws. - - - - - the time at which to compute the bounding box - - an interface pointer that may be used to call functions associated with the viewports - - the bounding box - - - - Description: - This class represents the base class for interfaces in 3ds Max. The class should be used as the base class for any new interface class in 3ds Max and provides basic identity, memory management, and cloning methods. Class , which is part of the ~{ Function Publishing }~ system, has the class as its base class. - - - - - This method returns the unique interface ID. - - - - - This method allows inquiries into the actual lifetime policy of a client and provide a server-controlled delete notify callback. - One of the following LifetimeTypes: - - noRelease - - Do not call release, use interface as long as you like. This is the default. - - immediateRelease - - The interface is only good for one call. The release is implied so a call to release is not required. - - wantsRelease - - The clients are controlling the lifetime, so the interface needs a Release() when the client has finished. - - serverControlled - - The server controls the lifetime and will use the to inform the code when it is gone. - Default Implementation: - { return noRelease; } - - - - - This method allows you to register an interface notify callback. - Parameters: - InterfaceNotifyCallback* incb - - A pointer to the interface notify callback. - Default Implementation: - { return false; } - - - - - This method allows you to un-register an interface notify callback. - Parameters: - incb - - A pointer to the interface notify callback. - Default Implementation: - { } - - - - - This method is part of the interface reference management and can be implemented by dynamically allocated interfaces for ref-count based lifetime control). This method should return TRUE if it needs Release() to be called. - Default Implementation: - { return false; } - - - - - This method is called when a reference to this object is deleted. - Default Implementation: - { } - - - - - This method can be used as a direct interface delete request. - Default Implementation: - { } - - - - - This method allows you to clone the base interface. - Parameters: - void* remapDir - - The passed to the clone method. - Default Implementation: - { return NULL; } - - - - - Description: - The server class specializes the class with an implementation based on a <> of interface pointers for storing interfaces, typically extension interfaces, and providing an interface iteration protocol. class in the Function Publishing System specializes class . The class contains a protected table of pointers. Class is an example of a class which is based on the class. - - - - - This method returns the number of interfaces. - Default Implementation: - { return interfaces.Count(); } - - - - - This method returns a pointer to the of the I-th interface. - Parameters: - int i - - The index of the interface in the table. - Default Implementation: - { return interfaces[i]; } - - - - - - - This is the base class for objects and modifiers. Anything with a representation in the 3D viewports is derived from (including modifiers and controllers whose gizmos appear in the viewports). The methods here are things such as displaying the object in the viewports, checking for intersection of the object and points the user clicks with the mouse, snapping to the object, and computing various bounding boxes for the object. Also there are methods for returning the name of the object to appear in the modifier stack, a method to deal with creating the object in the viewports (if appropriate), and named selection set related methods. There are also methods that allow other plug-ins to access the changeable parameters of the object. Finally there are several method that deal with sub-object selection, sub-object display, sub-object hit testing, and moving/rotating/scaling sub-object components of the object. - - - - - This method is called to determine if the specified screen point intersects the item. The method returns nonzero if the item was hit; otherwise 0. - Nonzero if the item was hit; otherwise 0. - - The time to perform the hit test. - A pointer to the node to test. - The type of hit testing to perform. See for details. - The state of the crossing setting. If TRUE crossing selection is on. - The hit test flags. See for details. - The screen point to test. - An interface pointer that may be used to call methods associated with the viewports. - - - - This method is used for storing mode-dependent display attributes. Before an object's Display() method is called, the appropriate bits of the extended display flag variable are set and this method is called. After that, the Display() method is called. If the object must display itself differently based on the settings of the extended display bit fields, then the object must save the flags passed into the this method. Otherwise, there is no need for the object to store the flags. - - The flags to store. - - - - This is called by the system to have the item display itself (perform a quick render in viewport, using the current TM). Note: For this method to be called the object's validity interval must be invalid at the specified time t. If the interval is valid, the system may not call this method since it thinks the display is already valid. - Default return value is -1, means this object doesn't have display function. 0 means it didn't draw anything in current frame. Otherwise return positive values.. - - The time to display the object. - The node to display. - An interface pointer that may be used to call methods associated with the viewports. - See . - - - - Checks the point passed for a snap and updates the structure. - Developers wanting to find snap points on an Editable object should see the method XmeshSnap::Snap() in /MAXSDK/SAMPLES/SNAPS/XMESH/XMESH.CPP. - - The time to check. - The node to check. - The snap info structure to update. - The screen point to check. - An interface pointer that may be used to call methods associated with the viewports. - - - - This method returns the world space bounding box for Objects (see below for the Sub-object gizmo or Modifiers gizmo version). The bounding box returned by this method does not need to be precise. It should however be calculated rapidly. The object can handle this by transforming the 8 points of its local bounding box into world space and take the minimums and maximums of the result. Although this isn't necessarily the tightest bounding box of the objects points in world space, it is close enough. - - The time to compute the bounding box. - The node to calculate the bounding box for. - An interface pointer that can be used to call methods associated with the viewports. - Contains the returned bounding box. - - - - This is the object space bounding box, the box in the object's local coordinates. The system expects that requesting the object space bounding box will be fast. - - The time to retrieve the bounding box. - The node to calculate the bounding box for. - An interface pointer that may be used to call methods associated with the viewports. - Contains the returned bounding box. - - - - This method allows the system to retrieve a callback object used in creating an object in the 3D viewports. This method returns a pointer to an instance of a class derived from . This class has a method proc() which is where the programmer defines the user/mouse interaction during the object creation phase. - A pointer to an instance of a class derived from . - - - - - the name that will appear in the modifier stack. - - If true, then the object name returned should be localized in the language 3ds is currently using. Otherwise it should be the object name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the object name in English. - - - - Implemented by the System. This method is called to see if any modifiers down in the pipeline depend on topology. It sends the message REFMSG_IS_OK_TO_CHANGE_TOPOLOGY to see if any modifiers or objects down the pipeline depend on topology. - TRUE if it is okay to change the topology; FALSE if it is not okay to change the topology. - - This parameter is set to the dependent modifier's name if there is an item that depends on topology. - - - - This method asks the question of an object or modifier "Do you changetopology"? An object or modifier returns TRUE if it is capable of changing topology when its parameters are being edited; otherwise FALSE. When an item is selected for editing, and there is a modifier in the pipeline that depends on topology, the system calls this method to see if it may potentially change the topology. If this method returns TRUE the system will put up a warning message indicating that a modifier exists in the stack that depends on topology. - - - - - Notifies dependents of a change - - - - - An object or modifier should implement this method if it wishes to make its parameter block available for other plug-ins to access it. The system itself doesn't actually call this method. This method is optional. - A pointer to the item's parameter block. See Class . - - - - - If a plug-in makes its parameter block available (using GetParamBlock()) then it will need to provide #defines for indices into the parameter block. These defines should not be directly used with the parameter block but instead converted by this function that the plug-in implements. This way if a parameter moves around in a future version of the plug-in the #define can be remapped. A return value of -1 indicates an invalid parameter id. - The parameter block index or -1 if it is invalid. - - The parameter block id. See . - - - - When this method is called the plug-in should respond by moving its selected sub-object components. - - The time of the transformation. - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the modifier's space and convert them into world space points. This is constructed as the node's transformation matrix times the inverse of the 's transformation matrix. The node whose transformation is used is the node the user clicked on in the scene - modifiers can be instanced so there could be more than one node. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This value is a vector with X, Y, and Z representing the movement along each axis. - When TRUE the transformation is occurring about the sub-object's local origin. - - - - When this method is called the plug-in should respond by rotating its selected sub-object components. - - The time of the transformation. - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the modifier's space and convert them into world space points. This is constructed as the node's transformation matrix times the inverse of the 's transformation matrix. The node whose transformation is used is the node the user clicked on in the scene - modifiers can be instanced so there could be more than one node. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - The amount to rotate the selected components. - When TRUE the transformation is occurring about the sub-object's local origin. Note: This information may be passed onto a transform controller (if there is one) so they may avoid generating 0 valued position keys for rotation and scales. For example if the user is rotating an item about anything other than its local origin then it will have to translate in addition to rotating to achieve the result. If a user creates an object, turns on the animate button, and rotates the object about the world origin, and then plays back the animation, the object does not do what the was done interactively. The object ends up in the same position, but it does so by both moving and rotating. Therefore both a position and a rotation key are created. If the user performs a rotation about the local origin however there is no need to create a position key since the object didn't move (it only rotated). So a transform controller can use this information to avoid generating 0 valued position keys for rotation and scales. - - - - When this method is called the plug-in should respond by scaling its selected sub-object components. - - The time of the transformation. - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the modifier's space and convert them into world space points. This is constructed as the node's transformation matrix times the inverse of the 's transformation matrix. The node whose transformation is used is the node the user clicked on in the scene - modifiers can be instanced so there could be more than one node. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This value is a vector with X, Y, and Z representing the scale along X, Y, and Z respectively. - When TRUE the transformation is occurring about the sub-object's local origin. See the note above in the Rotate method. The following methods may be used to receive notification about the starting and ending phases of transforming the item when in sub-object selection. - - - - This method is called before the first Move(), Rotate() or Scale() call and before a hold is in effect. - - The current time when this method is called. - - - - This method is called before the first Move(), Rotate() or Scale() call and after a hold is in effect. - - The current time when this method is called. - - - - This method is called after the user has completed the Move(), Rotate() or Scale() operation and before the undo object has been accepted. - - The current time when this method is called. - - - - This method is called after the user has completed the Move(), Rotate() or Scale() operation and the undo object has been accepted. - - The current time when this method is called. - - - - This method is called when the transform operation is canceled by a right-click and the undo has been canceled. - - The current time when this method is called. - - - - This method is used in modifier gizmo hit testing. It is called to determine if the specified screen point intersects the gizmo. The method returns nonzero if the item was hit; otherwise 0. - Nonzero if the item was hit; otherwise 0. - - The time to perform the hit test. - A pointer to the node to test. - The type of hit testing to perform. See for details. - The state of the crossing setting. If TRUE crossing selection is on. - The hit test flags. See for details. - The screen point to test. - An interface pointer that may be used to call methods associated with the viewports. - A pointer to the modifiers . - - - - When this method is called the plug-in should respond by performing a quick render of the modifier gizmo in viewport using the current TM. Note for Modifiers: For this method to be called properly, one must send two reference messages using NotifyDependents. In BeginEditParams send: NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_ON); - - In EndEditParams send: NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_OFF); - Default return value is -1, means this object doesn't have display function. 0 means it didn't draw anything in current frame. Otherwise return positive values.. - - The time to display the item. - The node to render. - An interface pointer that may be used to call methods associated with the viewports. - See . - A pointer to the modifiers . - - - - This method computes the world space bounding box of the modifier gizmo (or any object that when in sub-object mode has a gizmo). - - The time to compute the bounding box. - The node to calculate the bounding box for. - An interface pointer that may be used to call methods associated with the viewports. - The returned bounding box. - A pointer to the modifiers . - - - - This method is called to make a copy of the selected sub-object components of the item. If this is called on an object, the selection level of the object is used to determine which type of sub-objects are cloned. For instance in a , the selection level determines if selected verticies, edges or faces are cloned. If this is called on a then the selection level of the modifier is used. Modifiers call Interface::GetModContexts() to get a list of ModContexts, one for each object the modifier is applied to. Then the selected sub-objects are cloned for each object in the list. - - The time at which to clone the selected sub-object components. - - - - This method is called when the user mouses up after shift-cloning a sub-object selection. - - The time at which the clone of the selected components is being done. - - - - This method is called to change the selection state of the component identified by hitRec. - - Identifies the component whose selected state should be set. See Class . - TRUE if the item should be selected; FALSE if the item should be de-selected. - TRUE if all components in the chain should be selected; FALSE if only the top-level should be selected. (A contains a Next() pointer; typically you want to do whatever you're doing to all the Next()'s until Next() returns NULL). - This is set to TRUE when all is also set to TRUE and the user is holding down the Shift key while region selecting in select mode. This indicates the items hit in the region should have their selection state inverted - - - - This method is called to clear the selection for the given sub-object level. All sub-object elements of this type should be deselected. This will be called when the user chooses Select None from the 3ds Max Edit menu. - - Specifies the selection level to clear. - - - - This method is called to select every element of the given sub-object level. This will be called when the user chooses Select All from the 3ds Max Edit menu. - - Specifies the selection level to select. - - - - This method is called to invert the specified sub-object level. If the element is selected it should be deselected. If it's deselected it should be selected. This will be called when the user chooses Select Invert from the 3ds Max Edit menu. - - Specifies the selection level to invert. - - - - Returns the index of the sub-object element identified by the hitRec. See Class . The sub-object index identifies a sub-object component. The relationship between the index and the component is established by the modifier. For example an edit modifier may allow the user to select a group of faces and these groups of faces may be identified as group 0, group 1, group 2, etc. Given a hit record that identifies a face, the edit modifier's implementation of this method would return the group index that the face belonged to. - - - - - When the user changes the selection of the sub-object drop down, this method is called to notify the plug-in. This method should provide instances of a class derived from to support move, rotate, non-uniform scale, uniform scale, and squash modes. These modes replace their object mode counterparts however the user still uses the move/rotate/scale tool buttons in the toolbar to activate them. If a certain level of sub-object selection does not support one or more of the modes NULL may be passed. If NULL is specified the corresponding toolbar button will be grayed out. - Sample Code: - - The sub-object selection level the command modes should be set to support. A level of 0 indicates object level selection. If level is greater than or equal to 1 the index refers to the types registered by the object in the order they appeared in the list when registered by . See Class . - The command modes to support - - - - An object that supports sub-object selection can choose to support named sub object selection sets. Methods in the interface passed to objects allow them to add items to the sub-object selection set drop down list. A modifier that wishes to support this capability maintains its list of named sub-object selections. When a user enters the sub-object selection mode, the modifier adds its named selection sets into the drop down (using Interface::AppendSubObjectNamedSelSet()). - true if the plug-in supports named sub-object selection sets, false otherwise. - - - - - When the user chooses a name from the drop down list this method is called. The plug-in should respond by selecting the set identified by the name passed. - - The name of the set to select. - - - - If the user types a new name into the named selection set drop down then this method is called. The plug-in should respond by creating a new set and give it the specified name. - - The name for the selection set. - - - - If the user selects a set from the drop down and then chooses Remove Named Selections from the Edit menu this method is called. The plug-in should respond by removing the specified selection set. - - The selection set to remove. - - - - To support the Edit Named Selections dialog, plug-ins must implement this method. It is called to rebuild the named selection set drop down list. This is usually done by calling Interface::ClearSubObjectNamedSelSets() followed by calls to :: AppendSubObjectNamedSelSet(). - - - - - To support the Edit Named Selections dialog, plug-ins must implement this method. - the number of named selection sets. - - - - - To support the Edit Named Selections dialog, plug-ins must implement this method. - the name of the 'i-th' named selection set. - - The index of the selection set whose name is returned. - - - - To support the Edit Named Selections dialog, plug-ins must implement this method. It sets the name of the selection set whose index is passed to the name passed. Note: Developers need to implement Undo / Redo for modifications to their named selection sets. - - The index of the selection set whose name is to be set. - The new name for the selection set the plug-in should store. - - - - To support the Edit Named Selections dialog, plug-ins must implement this method. The user may bring up the Edit Named Selections dialog via the Edit / Edit Named Selection ... command. This dialog allows the user to create new selection sets using 'boolean' operations to the sets including 'Combine', 'Subtract (A-B)', 'Subtract (B-A)' and 'Intersection'. This method is called on the plug-in to generate a new selection set via one of these operations. This method assumes the developer will append a new seleciton set with the name passed. This will result in two sets with identical names. Then the system will call RemoveSubSelSet() afterwards, so that the first one that is found (the old one, since the new one was appended) will be deleted. Note: Developers need to implement Undo / Redo for modifications to their named selection sets. See /MAXSDK/SAMPLES/MODIFIERS/MESHSEL.CPP for an example. - - The new name for the selection set is passed here. - A table of the selection sets to operate on. There are sets.Count() sets in the table. - One of the following values defined in - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current modifier being edited so that it can display the axis. This method specifies the position of the center. The plug-in enumerates its centers and calls the callback cb once for each. - - The callback object whose methods may be called. See Class . - The time to enumerate the centers. - A pointer to the node. - A pointer to the . - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current modifier being edited so that it can display the axis. This method returns the axis system of the reference coordinate system. The plug-in enumerates its TMs and calls the callback cb once for each. See ~{ Sub-Object Coordinate Systems }~. - - The callback object whose methods may be called. - The time to enumerate the TMs. - A pointer to the node. - A pointer to the . - - - - This method is called before a modifier or object is collapsed. - - Points to the node for the object being collapsed. - If the object associated with node above is a this points to the derived object.If it's an object then this is NULL. - If the object associated with node above is a this is the index of this modifier in the DerivedObject.. If it's an object then this is 0. - - - - This method is called after a modifier or object is collapsed. - - Points to the node for the object being collapsed. - - If the object associated with node above is a this points to the derived object. If it's an object then this is NULL. - If the object associated with node above is a this is the index of this modifier in the DerivedObject. If it's an object then this is 0. - - - - Objects and modifiers that support subobjects have to overwrite this method - as well as GetSubObjType() - and return a class derived from in GetSubObjType(). Developers can use the for convenience. If the parameter passed into GetSubObjType is -1, the system requests a , for the current SubObjectLevel that flows up the modifier stack. If the subobject selection of the modifier or base object does not affect the subobj selection that flows up the stack, the method must return NULL. See meshsel.cpp for a sample implementation. - The number of sub-object types supported by the object or modifier. - - - - - Returns a pointer to the sub-object type for the sub-object whose index is passed. If the parameter i passed is -1 the system requests an for the current SubObjectLevel that flows up the modifier stack. If the subobject selection of the modifier or base object does not affect the sub-object selection that flows up the stack NULL must be returned. See the sample code in /MAXSDK/SAMPLES/MODIFIERS/MESHSEL.CPP. - The sub-object type. See Class . - - The zero based index of the sub-object type to get. See the remarks above. - - - - This method returns an integer which indicates the current sub-object level of the modifier or base object. - A value of 0 indicates object level. A value of 1 through NumSubObjTypes() are the sub-object levels in the same order as they are returned by GetSubObjType(int i) (with an offset of 1 of course). - - - - - Call this method to find out if the object has UVW coordinates. This method returns TRUE if the object has UVW coordinates; otherwise FALSE. In 3ds Max 2.0 and later there is code in the renderer that will automatically turn on the UVW coordinates of the base object if UV's are missing (and needed). The base object has to implement two simple methods to make this work: HasUVW() and SetGenUVW(). Developers are encouraged to put these methods in their objects: it makes using the program easier for the user. If they are not implemented, it doesn't cause any real harm: it will just operate as before and put up the missing UVW's message. Here is how the procedural sphere implements these methods: Important Note: The pblock->SetValue() will cause a call to NotifyDependents(FOREVER, PART_TEXMAP, REFMSG_CHANGE), which will invalidate the UVW cache. It is essential that this call be made, so if the 'generate UVW' boolean is not handled by a parameter block, then NotifyDependents() needs to be called explicitly. Also Note: For "modifiable objects" that pass up the pipeline getting modified, such as , EditTriObject, etc., which cannot generate their own UVWs, but can carry them in their data structures, only this HasUVW() method needs to be implemented. For example, here is the implementation for : BOOL TriObject::HasUVW() { return mesh.tvFace?1:0; } - - - - - Call this method to find out if the object is has UVW coordinates for the specified mapping channel. This method returns TRUE if the object has UVW coordinates; otherwise FALSE. See the method HasUVW() above for more details. - - See ~{Mapping Channels}~. - - - - This method is called to change the state of its Generate UVW boolean. If the state changes, the object must send a REFMSG_CHANGE up the pipeline by calling NotifyDependents(). This applies to map channel 1. - - The new state for the generate UVW flag. - - - - This method is called to change the state of its Generate UVW boolean for the specified mapping channel. If the state changes, the object must send a REFMSG_CHANGE up the pipeline by calling NotifyDependents(). - - The mapping channel index. See ~{Mapping Channels}~. - The new state for the generate UVW flag. - - - - This method notifies the that the end result display has been switched (the "Show End Result" button has been toggled). Sometimes this is needed for display changes. This method is implemented in Edit , which uses it as shown below: void EditMeshMod::ShowEndResultChanged(BOOL showEndResult) { - - NotifyDependents(FOREVER, PART_DISPLAY, REFMSG_CHANGE); - - } - - This allows the Edit modifier to update itself in repsonse to a user click of the "Show End Result" button in the modifier panel. - - TRUE if Show End Result is on; FALSE if off. - - - - This method return true if GetWorldBoundBox returns different boxes for different viewports. It is used to inhibit a caching of the bounding box for all viewports. This was added to allow developers to disable the bounding box cache. It may be overridden to return true if an object has a dynamic drawing style, or as the method suggests is view dependent. - true if the bounding box should not be cached for use on all viewports, false otherwise. - - - - - One of the base classes for the creation of the Shaders, which plug-in to the Standard material[?]. Note that developers should derive their plug-in from Class and not from this class directly. If not, the interactive renderer will not know how to render the in the viewports. Developers of this plug-in type also need to have an understanding of how the Standard material and the work together. Every material has a . The is the piece of code which controls how light is reflected off the surface. The Standard material is the mapping mechanism which handles all the texturing for the material. Managing the user interface is also done by the standard material. This way the plug-in needs only to worry about the interaction of light on the surface. - - Prior to release 3, developers could write plug-ins that performed their own shading. However, this was usually a major programming task. Release 3 provides the simpler plug-in that would benefit from sharing all the common capabilities. The Standard material, with its 'blind' texturing mechanism, makes this possible. It doesn't know what it is texturing - it simply textures 'stuff'. The shader names the channels (map), fills in the initial values, and specifies if they are a single channel (mono) or a triple channel (color). The Standard material handles the rest including managing the user interface. The main part of the code in a is responsible for supplying this information to a Standard material. The values are passed and received back in class . There is a specific method named Illum() in a shader, which actually does the shading. - Plug-In Information: - Class defined in: SHADER.H - Super class ID: SHADER_CLASS_ID - Standard file name extension: DLB - Extra include file needed: SHADERS.H - - - - - Put up a dialog that lets the user edit the plug-ins parameters. This method creates and returns a pointer to a object and puts up the dialog which lets the user edit the 's parameters. - - The window handle of the old rollup. If non-NULL, the method is usually used instead of to present the rollup. - The window handle of the material editor. - The interface pointer for calling methods in 3ds . - Pointer to the Standard material being edited. - True to have the rollup open; false to have it closed. - This parameter is available in release 4.0 and later only. Specifies the number of the rollup to create. Reserved for future use with multiple rollups. - - - - Returns a pointer to the object which manages the user interface. - - Specifies the rollup to get for. Reserved for future use with multiple rollups. - - - - Sets the object which manages the user interface to the one passed. - - Points to the new object. - Specifies the rollup to set for. Reserved for future use with multiple rollups. - - - - Returns the number of rollups this shader is requesting. - - - - - Std parameter support. Returns a value which indicates which of the standard parameters are supported. - A Standard Parameter Flags. - - - - - Required for R2.5 shaders to convert the previous Standard material parameter blocks to the current version. - - Pointer to the old parameter block descriptor. - The number in the array of parameters above. - Pointer to the old parameter block. - - - - Updates the "channels"(as well as other) data member of the "IllumParams" object passed to it with the "local" variables of the material for possible mapping prior to being given to the 's Illum() method. The shader plug-in copies the state of all its parameters (at their current animation state) into the data members of the "IllumParams" passed. - - The which provides information on the pixel being shaded. - Pointer to the to update. - - - - This is the illumination function for the . Developers will find it very helpful to review the Mtl::Shade() method of the Standard material. This is the main method of the material which computes the color of the point being rendered. This code is available in /MAXSDK/SAMPLES/MATERIALS/STDMTL2.CPP. This code shows how the Standard calls Shader::GetIllumParams(), sets up mapping channels, calls this Illum() method, and calls the Shader::CombineComponents() method when all done. - Sample Code: - Below is a brief analysis of the standard Blinn shader Illum() method. This is the standard 'computer graphics look' type shader supplied with 3ds Max. The entire method follows: - - Some of the key parts of this method are discussed below: - - The is_shiny line sets a boolean based on if the has a shininess setting > 0. Note that the Blinn shader uses the same channel ordering as the original Standard material so it can index its channels using the standard ID ID_SS. - - BOOL is_shiny= (ip.channels[ID_SS].r > 0.0f) ? 1:0; - - Next the 'Phong Exponent' is computed. This is just a function that is used to give a certain look. It uses 2^(Shinniness *10) * 4. This calculation simply 'feels right' and gives a good look. - - double phExp = pow(2.0, ip.channels[ID_SH].r * 10.0) * 4.0; - - The following loop sums up the effect of each light on this point on surface. - - for (int i=0; i<sc.nLights; i++) { - - Inside the loop, the light descriptor is grabbed from the : - - l = sc.Light(i); - - The LightDesc::Illuminate() method is then called to compute some data: - - if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) { - - To Illuminate() is passed the (sc), and the normal to the surface (ip.N) (pointing away from the surface point). - - The method returns the light color (lightCol), light vector (L) (which points from the surface point to the light), the dot product of N and L (NL) and the diffuse coefficient (diffCoef). The diffuse coefficient is similar to NL but has the atmosphere between the light and surface point taken into account as well. - - The next piece of code checks if the light figures into the computations: - - if (NL<=0.0f) - - continue; - - If NL<0 then the cosine of the vectors is greater than 90 degrees. This means the light is looking at the back of the surface and is therefore not to be considered. - - The next statement checks if the light affect the diffuse channel (lights may toggle on or off their ability to affect the diffuse and specular channels.) - - if (l->affectDiffuse) - - ip.diffIllumOut += diffCoef * lightCol; - - If the light affects the diffuse channel then the diffuse illumination output component of the is added to. This is done by multiplying the diffuse coefficient (returned by LightDesc::Illuminate()) times the light color (also returned by LightDesc::Illuminate()). Notice that the diffIllumOut is being accumulated with each pass of the light loop. - - The next section of code involves the specular component. If the light is shiny, and it affects the specular channel a vector H is computed. - - if (is_shiny&&l->affectSpecular) { - - Note the following about this H vector computation. Most vectors are considered pointing from the point on the surface. The view vector (IllumParams::V) does not follow this convention. It points from the 'eye' towards the surface. Thus it's reversed from the usual convention. - - H is computed to be the average of L and V. This is (L+V)/2. Since we normalize this we don't have to divide by the 2. So, if V followed the standard convention this would be simply L+V. Since it doesn't it is L+(-ip.V) or L-ip.V. - - H = Normalize(L-ip.V); - - Next the dot product of N and H is computed and stored in c. When you take the dot product of two normalized vectors what is returned is the cosine of the angle between the vectors. - - float c = DotProd(ip.N,H); - - If c>0 and the diffuse coefficient is less than the soften threshold then c is modified by a 'softening' curve. - Note that the Soften() function is defined in /MAXSDK/SAMPLES/MATERIALS/SHADERUTIL.CPP and developers can copy this code. Next, c is raised to the power of the Phong exponent. This is effectively taking a cosine (a smooth S curve) and raising it to a power. As it is raised to a power it becomes a sharper and sharper S curve. This is where the shape of the highlight curve in the Materials Editor UI comes from. - - That completes the pre computations for the specular function. Then c is multiplied by the specular strength (ip.channels[ID_SS].r) times the light color (lightCol). The result is summed in specular illumination out (ip.specIllumOut). - - That completes the light loop. It happens over and over for each light. - - Next the self illumunation is computed. If the Self Illumination is not on, then the original code for doing mono self illumination is used. Then, we multiply by the colors for ambient, diffuse and specular. - - The results are ambIllumOut, diffIllumOut, and specIllumOut. Note that these components are not summed. In R3 and earlier these results would be returned to the Standard material. However, R4 introduces a couple extra steps. - - Finally, we call ShadeTransmission() and ShadeReflection() to apply the transmission/refraction and reflection models. The core implementation of 3ds Max provides the standard models, but the shader can override these methods to compute its own models. - - In R4, It is a shader's responsibility to combine the components of the shading process prior to exiting Illum() (in R3, this was the responsibility of the Standard material). In order to combine these values together to produce the final color for that point on the surface (IllumParams.finalC), the shader should call CombineComponents() method. The base class provides a default implementation which simply sums everything together and multiplies by the opacity. - - - - The which provides information on the pixel being shaded. - The object whose data members provide communication between 3ds and the shader. Input values are read from here and output values are also stored here. Note that the "XOut" (ambIllumout, etc) data members of this class are initialized to 0 before the first call to this method. The input to this method has the textured illumination parameters, the bump perturbed normal, the view vector, the raw (unattenuated) colors in the reflection and refraction directions, etc. - - - - Compute the reflected color from the sc, ip, and reflection map (or ray) color. The core implementation of this provides the standard 3ds Max reflection model. To support the standard reflection model, a shader may call this default implementation. - - The context which provides information on the pixel being shaded. - The object whose data members provide communication between 3ds and the shader. - The input reflection (or ray) color is passed in here and the resulting 'affected' color is stored here. - - - - Compute the transmission/refraction color for the sample. The core implementation of this provides the standard 3ds Max reflection model. To support the standard transmission/refraction model, a shader may call this default implementation. - - The context which provides information on the pixel being shaded. - The object whose data members provide communication between 3ds and the shader. - The input refraction (or ray) color is passed in here and the resulting 'affected' color is stored here. - The level of the amount spinner for the refraction channel. - - - - This method was superseded by ShadeReflection() and is obsolete in release 4.0 and later. This method provides the shader with an opportunity to affect the reflection code. - Sample Code: - A simple example like Phong does the following: If a color can affect the reflection of light off a surface than it can usually affect the reflection of other things off a surface. Thus some shaders influence the reflection color using the specular color and specular level. For instance the Multi Layer does the following: - - The which provides information on the pixel being shaded. - The object whose data members provide communication between 3ds and the shader. - The input reflection color is passed in here, and the resulting 'affected' color is stored here too. - - - - Finalizes the compositing of the various illumination components. A default implementation is provided which simply adds the components together. Developers who want to do other more specialized composition can override this method. For example, a certain might want to composited highlights over the underlying diffuse component since the light is reflected and the diffuse color wouldn't fully show through. Such a would provide its own version of this method. - - The which provides information on the pixel being shaded. - The illumination parameters to composite and store. - - - - Returns the number of texture map map channels supported by this . - - - - - Returns the name of the specified texture map channel. - - The zero based index of the texture map channel whose name is returned. - If true, then the channel name returned should be localized in the language 3ds is currently using. Otherwise it should be the channel name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the channel name in English. - - - - Returns the internal name of the specified texture map. The Standard material uses this to get the fixed, parsable internal name for each texture channel it defines. - - The zero based index of the texture map whose name is returned. - - - - Returns the channel type for the specified texture map channel. There are four channels which are part of the which are not specific to the . All other channels are defined by the (what they are and what they are called.) The four which are not the province of the are Bump, Reflection, Refraction and Displacement. For example, Displacement mapping is really a geometry operation and not a shading one. The channel type returned from this method indicates if the specified channel is one of these, or if it is a monochrome channel, a color channel, or is not a supported channel. - Texture channel type flags. - - The zero based index of the texture map whose name is returned. - - - - Returns the index of this 's channels which corresponds to the specified Standard materials texture map ID. This allows the to arrange its channels in any order it wants in the IllumParams::channels array but enables the Standard material to access specific ones it needs (for instance the Bump channel or Reflection channel). - The zero based index of the channel. -1 if there is not a corresponding channel. - Sample Code: - This can be handled similar to below where an array is initialized with the values of this plug-in shader's channels that correspond to each of the standard channels. Then this method just returns the correspond index from the array. - - The ID whose corresponding channel to return. - - - - Called when the is first activated in the dropdown list of choices. The should reset itself to its default values. - - - - - Returns the requirements of the for the specified sub-material. Many objects in the rendering pipeline use the requirements to tell the renderer what data needs to be available. The shader's requirements are OR'd with the combined map requirements and returned to the renderer via the Stdmtl2's GetRequirements() function. - One or more flag from Material Requirements Flags - - This parameter is not used. - - - - Indicates the number of UserIllum output channels used by the shader. - - - - - Returns a static array of channel names for matching by render elements. - - - - - Computes two components of a basis vector given a single input component. - - - - - This is the interface to the actual bevel profile curve. It contains methods necessary to select presets, get validity intervals, and get a that is scaled for use. - All methods are implemented by the system. - - - - - Returns a unique identifier for the curve type. For possible future expansion. For internal use only. - A curve type ID used to validate the curve - - - - - Reset the curve to a straight bevel. - - - - - the for this profile curve. - - - The - - - - Instructs the curve to dispose of any cached data - - - - - Tells the curve to load a preset of a given name. This should be a name in a ComboBox control that you have previously populated via use of the BevelProfileInterface::LoadBevelProfilePresetList method (see above) - - - The name of the preset curve to load. - - - - Tells the bevel profile curve to change the selected name in its preset list to the specified name. - - - The window handle of a ComboBox control containing preset curve names - - - - Tells the curve to select its current preset name from the list in a ComboBox indicated by the supplied window handle. This should be a control that you have previously populated via use of the BevelProfileInterface::LoadBevelProfilePresetList method (see above) - - - The (the plugin) - - The preset name to switch to - - - - Tells the BevelProfileCurve to copy its data from another curve. - - - The curve to copy from - - - - Instructs the bevel profile curve to create that is scaled to the specified values. - - - The time at which to sample the curve - - The width in world units to fit the curve (X) - - The height in world units to fit the curve (Y) - - The amount to push the curve - - The number of interpolation steps - - When true, straight curve segments will use 0 steps instead of bevelSteps - [out] - The object that will receive the curve - - - - Returns the validity interval of the curve (it may be animated) - The validity interval at the specified time - - - The time at which to sample the validity interval - - - - Query the curve to see if it is a custom curve or an unmodified preset - true if the curve is custom; false if it is an unmodified preset. - - - - - A plugin which wants to use the Bevel Profile Curves should derive from this class and implement the following methods. - - - - - Lets the curve user know that the bevel profile has changed in some way. This can be via the user selecting a different profile or other editing methods if the Bevel Profile Editor is in use. The plugin should update its model if it has not been inhibited via the InhibitMesh call (see below) - - - - - Tells the plugin to update or not update its mesh on changes to the profile. The plugin should maintain an internal switch to keep track of this setting. - - - If true, the plugin should ignore changes to the bevel profile curve untin this method is called again with 'sw' set to false. - - - - When this is called, if the plugin is using the Bevel Profile Editor, it should call bevelProfileEditorInfo->Notify(WM_BEVELPROFILE_REDRAW, 0, 0) to force a redraw - - - - - When this is called, the plugin should return its auto bevel update switch state. This lets the editor call beck to tell the plugin to update itrs mesh when changes to the curve are made. - true if the mesh should auto-update on changes to the bevel profile curve - - - - - Get the bevel profile editor window handle - Plugins should return bevelProfileEditorInfo->GetHWND() (see above) - - - - - When this is called, the plugin should return its bevel profile curve interface. - The in use by the plugin - - - - - This is called when the bevel peset selection has changed. When this call is received, the plugin should update its current bevel preset selection in the UI by calling BevelProfileInterface::LoadBevelProfilePresetList(presetList, true); - - - - - When called, the plugin should return its pointer. - The plugin's pointer - - - - - When called, the plugin should return the handle of the window that owns the Bevel Profile Editor. - The handle of the window which owns the editor. Typically this will be the plugin's main rollup window. - - - - - This class provides information on the Bevel Profile Editor to plugins which want to use the standard editor (initially implemented by TextPlus). If you wish to use the Bevel Profile Editor, call BevelProfileInterface::GetBevelProfileEditorInformation (see below), which will return a pointer to this object, which you can use to control the editor. - All methods are implemented by the system. - - - - - Returns the window handle of the Bevel Profile Editor - The window handle of the Bevel Profile Editor - - - - - Get the zoom factor of the Bevel Profile Editor - true if the zoom factor is valid for use; false if it is not - - [out] - The zoom factor of the window if the return value is true - - - - Get the horizontal and vertical scroll values of the Bevel Profile Editor - true if the scroll values are valid for use; false if they are not - - [out] - The horizontal scroll value - [out] - The vertical scroll value - - - - Sets the zoom factor of the curve window - - - The zoom factor - - - - Get the horizontal and vertical scroll values of the Bevel Profile Editor - - - The horizontal scroll value - - The vertical scroll value - - - - Send a message to the Bevel Profile Editor window. - - - The message to send - - Additional message-specific parameter - - Additional message-specific parameter - - - - Tells the Bevel Profile Editor to display or hide its window - - - The handle of the window that owns the editor. This is usually the plugin's parameter rollup window. - - If true, displays the editor window. If false, hides it. - - - - Tells the Bevel Profile Editor window to close - - - - - Deletes the object. - - - - - This object is a system interface which allows plugins to work with Bevel Profiles. When a plugin wants to work with a bevel profile editor or bevel profiles in general, this interface provides several useful functions. To get this interface, call the CreateBevelProfileUtilityInterface function: - All methods are implemented by the system. - - - - - Utility function to load a specified ComboBox control with the available bevel profile preset names - - - The window handle of the ComboBox control that will be loaded with the bevel profile preset names - - If true, includes the "(Custom)" bevel profile name - - - - Readies a Bevel Profile Editor for use. Plugins which want to use the standard Bevel Profile Editor should call this method and store the returned pointer so that they can control the editor. - A pointer to the (see above) - - - A pointer to a object (i.e. the plugin which is using the editor) - - - - Delete this interface. When you are through using this interface, it should be destroyed using this method. - - - - - Defines a basic bezier shape object. The is effectively a collection of Bezier Splines. For example the 3ds Max Donut object has two splines in a hierarchy to make a shape. The contains these splines. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - This lets you add another shape to this one. - - - - - Returns a copy of the 'i-th' vertex of the specified spline. - Parameters: - int poly - - The index into the splines list where poly >= 0 and poly < splineCount. - - int i - - The index of the control point in the spline. - - - - - Sets the 'i-th' vertex of the specified spline. - Parameters: - int poly - - The index into the splines list where poly >= 0 and poly < splineCount. - - int i - - The index of the vertex in the spline. - - &xyz - - The point to set. - - - - - This is used internally to render the shape. - - - - - This is used internally to snap to the shape. - - - - - This is used internally to snap to the shape. - - - - - This method is used internally to perform sub-object hit testing of the shape. - - - - - This is used for hit testing. This method returns a value from 0.0 to 1.0 that tells you where a hit was found on a particular segment. Sample code that uses this is the edit spline modifier in /MAXSDK/SAMPLES/MODIFIERS/EDITSPL.H. This allows a refinement of the hit testing. - Parameters: - int poly - - The index of the spline. - - int segment - - The index of the segment. - - *gw - - The graphics window where the hit test was done. - - *ma - - The list of materials. - - *hr - - The hit region. See Class . - - int ptype = PARAM_SIMPLE - - This parameter is available in release 4.0 and later only. - - This allows the caller to get the location on the segment in either parameter space or normalized distance space. Both return values of 0-1. For proper backward compatibility, the default parameter type is PARAM_SIMPLE. The other option is PARAM_NORMALIZED. - - - - - Computes the bounding box of the splines making up this bezier shape object. The result is stored in the bdgBox data member. - - - - - Returns the bounding box of the splines making up this bezier shape object. The optional TM allows the box to be calculated in any space. - Parameters: - *tm=NULL - - The matrix to transform the points before computing the bounding box. - - - - - This method is used internally in data flow evaluation - - - - - This method is used internally in data flow evaluation - - - - - This method is used internally in data flow evaluation - - - - - This method is used internally in data flow evaluation - - - - - Sets the state of the specified display flags. - Parameters: - DWORD f - - The flags to set. See Display Flags. - - - - - Returns the state of the specified display flags. - Parameters: - DWORD f - - The flags to get. See Display Flags. - - - - - Clears the specified display flags. - Parameters: - DWORD f - - The flags to clear. See Display Flags. - - - - - Constructs a vertex selection list based on the current selection level for the specified spline. For example if the selection level is at object level all the bits are set. If the selection level is at vertex level only the selected vertex bits are set. See Class . - Parameters: - int poly - - The index into the splines data member. - - int level = -1 - - This allows a selction level to be optionally specified. For example if the selection level is at object level all the bits are set. If the selection level is at vertex level only the selected vertex bits are set. One of the following values: - - SHAPE_OBJECT - - SHAPE_SPLINE - - SHAPE_SEGMENT - - SHAPE_VERTEX - - - - - This method looks at the selection state for the selection level and sets the appropriate bits based on the selection set unlessforceSel is TRUE. If forceSel is TRUE, it acts as if every item in the selection set for the specified spline was set. It's an easy way to select entire splines. - - See Class . - Parameters: - int poly = -1 - - The index into the splines data member (-1 means use all). - - BOOL includeVecs = FALSE - - If set, this method will set the bits for vectors associated with selected knots. - - int level = 0 - - This allows a selction level to be optionally specified. For example if the selection level is at object level all the bits are set. If the selection level is at vertex level only the selected vertex bits are set. One of the following values: - - SHAPE_OBJECT - - SHAPE_SPLINE - - SHAPE_SEGMENT - - SHAPE_VERTEX - - BOOL forceSel = FALSE - - If TRUE, it acts as if every item in the selection set for the specified spline was set. It's an easy way to select entire splines. For example, selecting spline 2 regardless of the spline-level selection state: - - VertexTempSelAll(2, FALSE, SHAPE_SPLINE, TRUE); - - This just builds the selection set as if spline 2 was completely selected. Otherwise, the spline bits would have only been selected if BezierShape::polySel.sel[2] was set. - - Incidentally, the following calls will do exactly the same thing: - - VertexTempSelAll(2, FALSE, SHAPE_VERTEX, TRUE); - - VertexTempSelAll(2, FALSE, SHAPE_SEGMENT, TRUE); - - For what it's worth, the SHAPE_SPLINE version is the most efficient. - - - - - This is a very important call to make. When you are done adding polygons to the shape you should call this method. This method updates a set of embedded selection set data within the shape. This selection set data tells what polygons are selected, what segments are selected, and what control points are selected. This resets the sizes of the selection bit arrays for this shape. - Parameters: - BOOL save = FALSE - - This parameter is available in release 4.0 and later only. - - This optional parameter preserves the selection set information when set to TRUE, and erases it when set to FALSE. The default, FALSE, is present for backward compatibility, where there was no argument. - - - - - Saves the shape data to the .MAX file. - - - - - Loads the shape data from the .MAX file. - - - - - Returns the number of splines in this shape. - - - - - Returns a pointer to the spline specified by the index passed. - Parameters: - int index - - Specifies which spline to return. This is an index into the splines data member. - - - - - Creates and adds an empty spline to the shape. - Parameters: - int itype = KTYPE_CORNER - - The initial knot type you get when you click and release the mouse during spline creation. See Knot types. int dtype = KTYPE_BEZIER - - The drag knot type used when you click and drag to create a vertex during spline creation. See Knot types. int ptype = PARM_UNIFORM - - This parameter is not used. Let it default to PARM_UNIFORM. - A pointer to the newly created spline. - - - - - Add an existing spline to this shape as the last one in the list. Note that this copies only the pointer, it does not copy the entire spline, so do not delete the spline anywhere else. This will do it when it's done with it. - Parameters: - Spline3D* spline - - The spline to add. - A pointer to the spline passed or NULL if the call failed. - - - - - Deletes the specified spline. - Parameters: - int index - - The index into the splines data member. - Nonzero on success; otherwise zero. - - - - - Inserts the specified spline into the spline list at the location passed. - Parameters: - Spline3D* spline - - The spline to add. - - int index - - The index in to the splines data member indicating where to insert the spline. - Nonzero on success; otherwise zero. - - - - - This method deletes every spline in the shape. - - - - - This method is used for adding the splines from one to another, with a weld threshold that will weld endpoints of the new splines onto endpoints of existing splines. Calling this method will cause the splines of the "from" shape to be added to those of the shape. If any endpoints in the "from" shape are within the specified weld threshold, they will be automatically welded. - Parameters: - &from - - The shape whose splines are added. - - float weldThreshold - - The endpoint weld threshold. - - - - - Returns the total number of vertices in the entire shape. - - - - - Returns the total number of segments in the entire shape. - - - - - This method is passed a capping information structure and it will compute the information it needs to make a mesh cap for this shape. - Parameters: - TimeValue t - - This parameter is not used. - - &capInfo - - The capping information. See Class . - - int capType - - See Shape Capping Types. - Nonzero if the method succeeded; otherwise zero. - - - - - This method is passed a capping information structure and it will compute the information it needs to make a patch cap for this shape. - Parameters: - TimeValue t - - This parameter is not used. - - &capInfo - - The capping information. See Class . - Nonzero if the method succeeded; otherwise zero. - - - - - This method is used internally by the code. When you call BezierShape::MakeCap &capInfo), if the patch cap data isn't cached, this method is called to build it. Calling it is not normally necessary, or a good idea - it builds the data structure regardless of whether it's cached or not. Just call the MakeCap() method to get the cap information and the caching is done automatically. - - - - - This method is used internally, automatically. - - - - - This method returns an index for any knot in any spline in the shape. - Parameters: - int poly - - The input poly number. - - int knot - - The input know number. - The zero based index of the knot. - - - - - This method computes a poly / knot pair from an index (see GetKnotIndex() above). - Parameters: - int index - - The input knot index. - - int &polyOut - - The output index of the poly it is a part of. - - int &knotOut - - The output knot number. - - - - - Returns the total number of knots in the shape. - - - - - This method is available in release 3.0 and later only. - - This method binds a knot to a segment. A bind acts as a constraint, it constrains the first point or the end point of a spline to the mid point of a segment. - Parameters: - BOOL isEnd - - Specifies whether the first or last point is bound. TRUE for the end; FALSE for the start. - - int segIndex - - The index of the segment to be bound to. - - int splineSegID - - The index of the spline that contains the segment. - - int splinePointID - - The index of spline that is being bound. - - - - - This method unbinds the specified spline. - Parameters: - int splineID - - The index of spline that is being bound. - - BOOL isEnd - - Specifies whether the first or last point is unbound. TRUE for the end; FALSE for the start. - - - - - This method is available in release 3.0 and later only. - - This method needs to be called when the topology changes to update the bind list. - Parameters: - BOOL useGeomTracking=FALSE - - This parameter is available in release 4.0 and later only. - - This allows the update to be dependant on previous recorded topology or geometry. If this flag is set to TRUE it uses the old method of using the geometry to rebuild the binds, else it uses the new method which uses the aux flags of the splines which store the old topology indices. Normally this will be FALSE since most of the times the topology tracking is more accurate, it should be set to TRUE when there is no initial topology to work from for instance when attaching or detaching geometry. - - - - - List of bind points. - - - - - capping cache (mesh capping and hierarchy caches stored in cache). - - - - - Indicates if the patch cap is valid or not. - - - - - A pointer to the list of splines. - - - - - The number of splines in this shape. - - - - - of steps (a value of -1 will use adaptive). - - - - - Setting this to TRUE optimizes linear segments. - - - - - The selected vertices. - - - - - The selected segments. - - - - - The selected polygons. - - - - - If hit bezier vector, this is its info. This is used internally in hit testing. - - - - - This is used internally in hit testing. - - - - - The Selection level. - - - - - Display attribute flags. They can be one of the following: - - - - - Initializes the . The data members are initialized as follows: - - - - - This method should be called when a shape changes. It invalidates the caches of the shape. This resets the bounding box, and removes the hierarchy, cap and shape caches. - - - - - This method is used internally. - - - - - Constructs a vertex selection list of the specified poly. - - - Constructs a vertex selection list of the specified poly based on the setting of the specified flag on the vertex. The implementation calls GetFlag() on each checking the specified flag value. - - - Specifies the polygon to construct the list from. - - The flag value each vertex will be tested for. - - - - Computes the bounding box of this shape. - Parameters: - TimeValue t - - This parameter is not used. - - & box - - The result is stored here. - - *tm - - The points of each spline in this shape are deformed using this matrix. - - BOOL useSel - - If TRUE the box is computed about the selected vertices only; otherwise all points. - - - - - For each spline in this shape, this method sets the corresponding bit if the shape is closed and clears the bit is the shape is open. - Parameters: - & array - - The to update. - - - - - Sets the closed state of each spline in this shape based on the passed. - Parameters: - & array - - Indicates which shapes should be closed: 1 = closed; 0 = open. - - - - - Reverses the spline whose index is passed. - Parameters: - int poly - - The spline to reverse. - - BOOL keepZero = FALSE - - This optional parameter is available in release 2.0 and later only. - - This parameter defaults to FALSE in order to retain backwards compatibility. Setting it to TRUE insures that a closed spline will have the same vertex as its first point when it is reversed. The parameter is ignored on open splines. - - - - - Reverses the splines of this shape if the corresponding bit in reverse is set. - Parameters: - &reverse - - If the bit is set the spline is reversed; otherwise it is left alone. - - BOOL keepZero = FALSE - - This optional parameter is available in release 2.0 and later only. - - This parameter defaults to FALSE in order to retain backwards compatibility. Setting it to TRUE insures that a closed spline will have the same vertex as its first point when it is reversed. The parameter is ignored on open splines. - - - - - This methods looks at the shape organization, and puts together a shape hierarchy. This provides information on how the shapes are nested. For example on a donut object with two circles, this method determines which circle is inside the other one. - Parameters: - TimeValue t - - This parameter is not used. - - *hier = NULL - - If non-NULL the result is store here (in addition to being returned). See Class . - The result is returned here. - - - - - Makes a from this shape. - Parameters: - &pshp - - The results are stored here. - - int nSteps = -1 - - The number of steps between knots in the spline. - - BOOL doOptimize = FALSE - - If TRUE, linear segments between control points in the spline will not generate steps in between. It will just be one line segment. - - - - - Sets the specified vertex of the specified poly as the first vertex. On an open polygon this has to be one of the end control points. On a closed shape it doesn't matter. - Parameters: - int poly - - The poly to update. - - int vertex - - The vertex to make first. - - - - - Transforms the points of each poly in the shape by the matrix passed. - Parameters: - &tm - - The transformation matrix. - - - - - This method is used internally. - - - - - This method copies the shapes, selection sets and any caches from the source object. It does not copy selection level, or display information. - Parameters: - &fromShape - - The shape to copy from. - - - - - This method is used internally. - - - - - This method provides an easy way to derive a simple index for any vertex in any spline in the shape. - Parameters: - int poly - - The zero based index of the spline. - - int vert - - The zero based index of the vertex. - A zero based index for vertex. - - - - - This method takes a vertex index and turns it back into a poly / vertex pair (see GetVertIndex() above). - Parameters: - int index - - The input index. - - int &polyOut - - The output poly. - - int &vertOut - - The output vertex. - - - - - Returns the total number of vertices in the shape. - - - - - Deletes the selected vertices for the specified poly in the shape. - Parameters: - int poly - - The zero based index of the polygon. - TRUE if any were deleted; FALSE if none were deleted. - - - - - Deletes the selected polygons for the specified poly in the shape. - Parameters: - int poly - - The zero based index of the polygon. - TRUE if any were deleted; FALSE if none were deleted. - - - - - Deletes the selected vertices for all polys in the shape. - TRUE if any were deleted; FALSE if none were deleted. - - - - - Deletes the selected segments for all polys in the shape. - TRUE if any were deleted; FALSE if none were deleted. - - - - - Deletes the selected polygons for all polys in the shape. - TRUE if any were deleted; FALSE if none were deleted. - - - - - Copies the selected geometry (segments or polys), reversing if needed. - Parameters: - BOOL reverse=FALSE - - TRUE to reverse; FALSE to leave alone. - Returns TRUE if anything was copied. - - - - - Tags the points in the spline components to record the topology of the shape. (This stores identifying values in the 's Knot::aux fields for each control point). This info can be used after topology-changing operations to remap information tied to control points. - Parameters: - int channel=0 - - This parameter is available in release 3.0 and later only. - - Specifies which auxiliary channel. One of the following values: - - 0=aux2 - - 1=aux3 - Returns FALSE if > 32767 knots or polys (it can't record that many). - - - - - This method returns a point interpolated on the specified spline on the entire curve. This method returns the point but you don't know which segment the point falls on. See method InterpPiece3D(). - Parameters: - int poly - - The zero based index of the spline. - - float param - - The position along the curve to return where 0 is the start and 1 is the end. - - int ptype=PARAM_SIMPLE - - The parameter type for spline interpolation. See Parameter types for shape interpolation. - The interpolated point on the curve. - - - - - This method returns a tangent vector interpolated on the entire curve of the specified spline. Also see method TangentPiece3D(). - Parameters: - int poly - - The zero based index of the spline. - - float param - - The position along the curve to return where 0 is the start and 1 is the end. - - int ptype=PARAM_SIMPLE - - The parameter type for spline interpolation. See Parameter types for shape interpolation. - The tangent vector - - - - - This method returns the interpolated point along the specified sub-curve (segment) for the specified spline. For example consider a shape that is a single circle with four knots. If you called this method with curve=0 and piece=0 and param=0.0 you'd get back the point at knot 0. If you passed the same parameters except param=1.0 you'd get back the point at knot 1. - Parameters: - int poly - - The zero based index of the spline. - - int piece - - The sub-curve (segment) to evaluate. - - float param - - The position along the curve to return where 0 is the start and 1 is the end. - - int ptype=PARAM_SIMPLE - - The parameter type for spline interpolation. See Parameter types for shape interpolation. - The point in world space. - - - - - Returns the tangent vector of the specified spline on a sub-curve at the specified 'distance' along the curve. - Parameters: - int poly - - The zero based index of the spline. - - int piece - - The sub-curve (segment) to evaluate. - - float param - - The position along the curve to return where 0 is the start and 1 is the end. - - int ptype=PARAM_SIMPLE - - The parameter type for spline interpolation. See Parameter types for shape interpolation. - - - - - This method is available in release 3.0 and later only. - - Returns the material ID for the specified spline and segment of this shape. - Parameters: - int poly - - The zero based index of the spline. - - int piece - - The zero based index of the segment of the spline. - - - - - Returns the length of the specified spline. - Parameters: - int poly - - The index of the spline to check. - - - - - This method is available in release 3.0 and later only. - - Retrieves information on the shape topology. - Parameters: - &topo - - The object which is updated with the shape data. See Class . - - - - - This method is available in release 3.0 and later only. - - This method provides a way for a to trim and extend splines. This method is meant to perform as part of a mouse-centered operation - Click on the part of the spline and pass the hitrecord, viewport and mouse point to the trim function. - Parameters: - *ip - - The interface pointer. See Class . - - *vpt - - The viewport the user clicked in. See Class . - - *hit - - The hit record for the selection. See Class . - - &m - - The point the user clicked on in the viewport. See Class . - - &cb - - The callback object. See Class . - - int trimType - - Specifies if the operation is a Trim or an Extend. One of the following values: - - SHAPE_TRIM - - SHAPE_EXTEND - - int trimInfinite - - This is set to TRUE for infinite projections. - This returns TRUE if the trim or extend was performed. - - - - - Hides the selected segments. - TRUE if any were hidden. FALSE if none were hidden. - - - - - Hides the segments attached to the selected vertices. - TRUE if any were hidden. FALSE if none were hidden. - - - - - Hides the segments attached to the selected splines. - TRUE if any were hidden. FALSE if none were hidden. - - - - - Unhides all the segments in the shape. - TRUE if any were unhidden. FALSE if none were unhidden. - - - - - Delete multiple splines at once. - - - Deleting multiple splines at once is faster than deleting one by one by calling DeleteSpline(), because the internal bookkeeping only needs to be done once. - false if any of the vertex indices are invalid. - - Point to an array of indices to delete. Indices should be unique, and sorted in ascending order. - of entries in the indices array. - - - - - - class : public - - - Description: - Extension to Class to use area selection to jump between splines in soft selection. Contains two public data members, mUseAreaSelect and mAreaSelect, in the interface extension class. mUseAreaSelect to TRUE to enable the use of area selection to jump between splines when doing soft selection with edge distance enabled. mAreaSelect is the distance allowed to jump from one node in a spline to another node in another spline. - - BOOL mUseAreaSelect - - TRUE if use area selection - - float mAreaSelect - - Radius of area selection - - - - - Description: - This class has data members and methods used to build and store topology information on a . This class is used with the BezierShape::GetTopology() method. - Data Members: - BOOL ready; - - TRUE if the data has been built; otherwise FALSE. - - IntTab kcount; - - A table of integers containing the knot count for each bezier spline in the shape. - - closed; - - A bit array containing a 1 for each closed spline or a 0 for each open one in the shape. - - - - - Builds the topology data for the specified shape. - Parameters: - &shape - - The shape whose topology data will be built. - - - - - Assignment operator. - - - - - Used internally to save the shape topology data. - - - - - Used internally to load the shape topology data. - - - - - This class is the basic bezier font class. It declares a common interface to all implementation - - - - - A class for listing font input dlls - - - - - This is a callback class which is used to process font enumerations - - - - - This class extends class It adds GetFont() which returns the font handle currently opened. - - - - - Get the handle to a logical font currently opened. - HFONT, handle to a logical font - - - - - This class extends the class which extends the function BuildCharacter() to obtain glyph outline data from a character based on its TrueType glyph index. - - - - - Build the character shape. - BOOL, TRUE on success, FALSE on failure - - TrueType Glyph Index of a character if ggo_native is true, or a character code if ggo_native is false - the request height - the width to return - The version. Default value of 1 - the built result of the character - if true, build character shape of glyph outline data on TrueType Glyph Index, otherwise on a character code - - - - Manages Bezier Fonts in 3ds Max. This is the interface into Bezier fonts within the 3ds Max. This includes TrueType fonts and any other fonts supported via plugins. - - - - - Returns TRUE if the font is available, FALSE otherwise. - - - - - Returns TRUE if the font is still in use, FALSE otherwise. - - - - - Build the given bezier from of the character in the given shape, and send back its relative width. - Returns FALSE and zero width if character not available. - - - The handle - - The index - - The height - - The bezier shape - - The out parameter containing the width of the character - - The version. Default value of 1 - -if true, build character shape of glyph outline data on TrueType Glyph Index, otherwise on a character code - - - - A special enumerator for the font manager - - - - - Description: - This class implements an m x n matrix for situations & calculations where the usual 4x3 class is not adequate. implements several useful matrix operations, including matrix multiplication and inversion, but is not guaranteed to be especially efficient. All methods are implemented by the system. - Data Members: - int m, n - - The dimensions of the matrix. There are m rows and n columns. - - float *val - - The elements of the matrix. val[i*n+j] is the value in the i'th row and the j'th column. - - - - - Frees the internal arrays and sets the matrix's size to 0x0. - - - - - Sets the matrix's size to mm by nn, and allocates space for the contents. - Returns the total size of the matrix (mm * nn) or -1 if there's an error. - - - - - Returns a pointer to the i'th row in the matrix. Thus for a A, A[i][j] is the value in the i'th row and the j'th column. - - - - - Sets this equal to from. - - - - - Sets trans to be the transpose of this . - - - - - Inverts this matrix. Note that this only works if this matrix is "square", i.e. if m = n. This algorithm is CUBIC in the number of rows, so be careful! - The determinant of the matrix (before inversion) is returned. If the return value is 0, the matrix could not be inverted. - - - - - If m and n are equal, this method sets this matrix to the identity. If m and n are not equal, it does nothing. - - - - - Creates a random matrix for testing purposes. Reseeds the random number generator with the current system time, for a non-reproducible result. Values of the matrix are set to anything in the range (-scale, scale). - - - - - This method prints the contents of the to the IDE debugging window using DebugPrints. - - - - - This class is used as a helper class to remove a binding modifier when the node it is bound to deleted. For example, if create a Bend WSM node and use 'Bind to Space Warp' to bind another node to the Bend WSM node, a 'Bend Binding (WSM)' modifier is placed on that node. If then delete the Bend WSM node, this class is used to cause the 'Bend Binding (WSM)' modifier to be automatically removed. The class uses an instance of this class, as does the BombMod class which is used as a binding modifier but does not derive from . Example usage in BombMod class: - - - - - This method potentially adds the binding modifier to the list of modifiers to modifiers to be removed from nodes. The modifier is added to the list if 3dsmax is in the middle of deleting one or more nodes, and 3dsmax is not in the middle of an undo or redo. The list of modifiers is processed at the end of deleting the nodes. - - The binding modifier. - - - - Class for image input and output. - - - Description: - The class is the bitmap itself. All image access is done through this class. The class has methods to retrieve properties of the bitmap such as image width, height, whether it is dithered, has an alpha channel, etc. There are methods to retrieve and store pixels from the image. Additional methods allow a developer to copy bitmaps. This class also has methods to open outputs and write multi-frame files. All methods of this class are implemented by the system. Then define the output file or device: or use the : Then define your parameters for the : Then create the : Then do something with the bitmap: Then you actually open, write and close the bitmap: - To write a multi-frame file, just keep doing something different to the and keep writing. - To write a sequence of images to a file/device. Create class Define the output file/device, either directly or using the user interface. The customize or define the : Then create the Then open the for writing - Note that in a localized environment there is no need to call BitmapInfo::SetDevice. This is because calling Bitmap::OpenOutput will automatically determine the device type or type based off of the extension of the filename. Another alternative to manually setting the device type that even works in a localized environment is to call BitmapInfo::FixDeviceName which will find the correct type based off of the extension. - Note: You can add any number of outputs to a bitmap. Just keep calling map->OpenInput() with different outputs (Targa file AND Frame Buffer for instance). To write or close a specific output, use Write() and Close(). To write and close them all at once, use WriteAll() and CloseAll(). - It is ok to use WriteAll() and CloseAll() if you have just one output defined. - - - - - Returns the state of the bitmap flags. These flags describe properties of the bitmap such as if the bitmap is flipped horizontally or inverted vertically, is paletted, is dithered, etc. See Bitmap Flags. - - - - - Sets the specified flag bit(s). - Parameters: - DWORD flag - - The flag(s) to set. See Bitmap Flags. - - - - - Toggles the specified flag bit(s) on/off. - Parameters: - DWORD flag - - The flag(s) to toggle. See Bitmap Flags. - - - - - Clears the specified flag bit(s) (sets them to zero). - Parameters: - DWORD flag - - The flag(s) to clear. See Bitmap Flags. - - - - - Returns the width of the bitmap (the horizontal dimension). - If storage has been allocated the width of the bitmap; otherwise 0. - - - - - Returns the height (vertical dimension) of the bitmap. - If storage has been allocated the height of the bitmap; otherwise 0. - - - - - Returns the aspect ratio of the bitmap. - If storage has been allocated the aspect ratio of the bitmap; otherwise 0.0f. - - - - - Returns the gamma value for the bitmap. - If storage has been allocated the gamma of the bitmap; otherwise 0.0f. - - - - - Returns whether the bitmap uses a palette (is not true color). - If storage has been allocated returns nonzero if the bitmap uses a palette (returns the number of palette slots used); otherwise 0. - - - - - Returns whether the bitmap is dithered or not. - If storage has been allocated returns nonzero if the bitmap is dithered; otherwise 0. - - - - - Returns whether the bitmap uses pre-multiplied alpha. - If storage has been allocated returns nonzero if the bitmap uses pre-multiplied alpha; otherwise 0. - - - - - Returns whether the bitmap has an alpha channel. - If storage has been allocated returns nonzero if the bitmap has an alpha channel; otherwise 0. - - - - - Returns nonzero if this is a bitmap that supports high dynamic range data; zero if it doesn't. - - - - - This method returns the number of bits per pixel for each color component. For example a 24-bit TARGA has a MaxRGBLevel() of - - - - - Implemented by the System. - - Returns the number of bits per pixel in the alpha channel. - If storage has not been allocated returns 0. - - - - - This method is used with multi-frame bitmaps (FLI's, AVI's, DDR devices, etc.). It is used to load a frame to replace a previously saved image. To define the desired frame, use: - - bi->SetCurrentFrame(frame); - Parameters: - *bi - - A pointer to the . The frame number information is passed here. - If used with single frame drivers or if the driver doesn't support this function, it returns BMMRES_SINGLEFRAME. If the return value is BMMRES_SUCCESS, a new frame has been loaded into the given bitmap. - - - - - Implemented by the System. - - Returns a copy of the instance maintained by the storage. - If the instance maintained by the storage. - - - - - Implemented by the System. - - whether colors are scaled (on) or clamped (off) when converting from to . If storage is not allocated, does nothing. - - - - - Implemented by the System. - - Returns the last value set by UseScaleColors. If storage is not allocated, returns 0. - - - - - Implemented by the System. - - Converts in to out, using the value of ScaleColors() to determine the clamping or scaling. The alpha component is not copied. If the storage is not allocated, the clamping is performed. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out, using the value of ScaleColors() to determine the clamping or scaling. If the storage is not allocated, the clamping is performed. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Opens the image for output. - - - This method will open the image for output. This allows the image to be written to. Note that you can pass a to this method on which you simply set the file name 'by hand' (bi->SetName(_T("D:\renders\output.jpg"))). This will work and the correct driver (i.e. ) will be selected based on the filename extension. This will work even in a localized environment, therefore there is no need to manually call BitmapInfo::SetDevice on the that is passed to this function. However you won't be able to set any driver specific settings (such as compression settings for JPEGs). The alternative way is to use the BitmapManger methods. - - BMMRES_SUCCESS - Indicates success. - - BMMRES_ERRORTAKENCARE - Indicates that 3ds Max could not find a device to handle the image. - - BMMRES_INTERNALERROR - Indicates the IO module handling the image could not be opened for writing. - - - Contains the name of the image or device to open for output. - - - - Write the image from to disk. - - - Write the image from the to disk. Note that you must pass the same used when the file was first "Openedfor Output". The main reason is that any device specific settings are kept in the object. Also, the custom options such as gamma value, optional channels, etc (if any) are kept in this instance. These are assigned when the bitmap is first opened (for either read or write). - BMMRES_SUCCESS - Indicates success. - - BMMRES_ERRORTAKENCARE - Indicates that 3ds Max could not find a device to handle the image. - - BMMRES_INTERNALERROR - Indicates the IO module handling the image could not be opened for writing. - - - Contains the name of the file or device to write to. - - Specifies the frame number to write. If this is a single image, allow frame to default to single frame. This argument determines if the file will have the frame number appended to it. If you want the file to have a normal name (no frame number attached to it), you must set the frame argument to BMM_SINGLEFRAME (the default). Any other value is considered to be a frame number and it will be appended to the given filename. - - - - Write the image to all the open outputs. - Parameters: - DWORD frame = BMM_SINGLEFRAME - - Specifies the frame number to write. If this is a single image, allow frame to default to single frame. - BMMRES_SUCCESS - - Indicates success. - - BMMRES_ERRORTAKENCARE - - Indicates that 3ds Max could not find a device to handle the image. - - BMMRES_INTERNALERROR - - Indicates the IO module handling the image could not be opened for writing. - - - - - Close the bitmap. This means the bitmap is no longer open for writing. - Parameters: - *bi - - Identifies the bitmap to close. - - int flag = BMM_CLOSE_COMPLETE - - See Bitmap Close Types. - Nonzero if the image output was closed without error; otherwise 0. - - - - - Closes all the open outputs. - Parameters: - int flag = BMM_CLOSE_COMPLETE - - See Bitmap Close Types. - Nonzero if the image outputs were closed without error; otherwise 0. - - - - - Stores the specified 16-bit pixel values into the bitmap. The pixel value pointer you pass to this method may be freed or reused as soon as the function returns. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - float *ptr - - Pixel values to store. - Returns nonzero if pixels were stored; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Retrieves the specified 16-bit pixel values from the bitmap. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - float *ptr - - Pointer to storage for the retrieved pixel values. - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Retrieves the specified 64-bit pixel values from the bitmap. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixel values. See . - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Stores the specified 64-bit pixel values into the bitmap's own local storage. The pointer you pass to this method may be freed or reused as soon as the function returns. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - *ptr - - Pixel values to store. See . - Returns nonzero if pixels were stored; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Retrieves the specified 64-bit pixel values from the bitmap. These pixels are NOT gamma corrected (i.e. they have linear gamma - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixel values. See Structure . - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Retrieves the specified pixels from the paletted bitmap. The palette for the image may be accessed using GetPalette(). Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - BYTE *ptr - - Pointer to storage for the pixel values. - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Stores the pixels into the specified location of the paletted bitmap. The pixel value pointer you pass to this method may be freed or reused as soon as the function returns. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - BYTE *ptr - - Pixels to store. - Returns nonzero if pixels were stored; otherwise 0. If storage has not been allocated 0 is returned. - - - - - - - This method is not currently implemented. - - - - - Copies the specified bitmap to this bitmap. - Parameters: - *from - - The source bitmap. - - int operation - - The type of copy to perform. See Copy Image Operationsint fillindex - - Vacant areas of the bitmap are filled with fillindex pixels if the operation specified is COPY_IMAGE_CROP and one of the source bitmap dimensions is less than the size of this bitmap. - Nonzero if the copy was performed; otherwise 0. - - - - - Creates a new Windows Device Independent (DIB) and returns a pointer to it. The DIB bitmap is created from this . The DIB is allocated using LocalAlloc(). The pseudo-code below show how one may be created and freed. Note that the DIB is never used or accessed inside 3ds Max (the call to ToDib() is the first and last time that 3ds Max sees this pointer): - - - When you are done using the DIB call: - - LocalFree(pDib); - Parameters: - int depth = 24 - - The bitmap depth; either 24 (BGR) or 32 (BGRO). If not specified the default is 24. - - UWORD *gam=NULL - - Specifies a pointer to an optional gamma table that is used to apply gamma correction to the color components as part of the conversion to a DIB. The table has RCOLN entries. - - BOOL doDither=FALSE - - Specifies if a random dither is applied when reducing the color components from 16 bits per channel to 8 bits per channel (to reduce banding effects). - - BOOL doDisplayTransform=FALSE - - Specifies whether the output should be transformed to screen color space. If so, the gamma table parameter is ignored, and the DIB colors are transformed using display gamma (for the gamma mode) or the default "Frame Buffer" display/view transform (for the OCIO modes). - - - - - Retrieves a portion of the palette from the bitmap. - Parameters: - int start - - The index into the palette of where to begin retrieving palette entries. - - int count - - The number of palette entries to retrieve. - - *ptr - - Storage for the palette entries. See Structure . - Nonzero if the palette entries were retrieved; otherwise 0. - - - - - Sets the specified portion of the palette of this bitmap. - Parameters: - int start - - The index into the palette of where to begin storing palette entries. - - int count - - The number of palette entries to store. - - *ptr - - The palette entries to store. See Structure . - Nonzero if the palette entries were stored; otherwise 0. - - - - - Returns a pointer to the specified channel of the bitmap, and determines its type in terms of bits per pixel. - Parameters: - ULONG channelID - - The channel to return a pointer to. See Image (G-Buffer) ChannelsULONG& chanType - - The type of the returned channel. One of the following values: - - BMM_CHAN_TYPE_UNKNOWN - - Channel not of a known type. - - BMM_CHAN_TYPE_8 - - 1 byte per pixel - - BMM_CHAN_TYPE_16 - - 1 word per pixel - - BMM_CHAN_TYPE_32 - - 2 words per pixel - - BMM_CHAN_TYPE_48 - - 3 words per pixel - - BMM_CHAN_TYPE_64 - - 4 words per pixel - - BMM_CHAN_TYPE_96 - - 6 words per pixel - - - - - Returns a pointer to the for the bitmap (or NULL if none). - - - - - This method creates the specified channels. After creation, these may be accessed using void *GetChannel(). - Parameters: - ULONG channelIDs - - Specifies the channels to create. See Image (G-Buffer) Channels. - The channels that are present. - - - - - Delete the specified channels. - Parameters: - ULONG channelIDs - - Specifies the channels to delete. See Image (G-Buffer) Channels. - - - - - Returns the channels that are present. See Image (G-Buffer) Channels. - - - - - This is used internally. It returns a pointer to the associated with the storage if available; otherwise NULL. See Class . - - - - - This is used internally. It returns a pointer to the instance allocated by the storage. If this could not be allocated NULL is returned. See Class . - - - - - This method is used internally. This method will check with the plug-in (file or device) defined in the given and prepare (create) the proper channels. If a given channel already exists, no new channel will be created. After creating a bitmap, use this function to define the optional channels that may be required by the given handler. - Parameters: - *bi - - Points to an instance of that defines the properties of the image. - TRUE if the channels were created; otherwise FALSE. - - - - - This method uses summed area table or pyramidal filtering to compute an averaged color over the specified area. You must have a filter plugged in for this to work. See SetFilter() below. - Parameters: - float u, float v - - The location in the bitmap to filter. These values go from 0.0 to 1.0 across the size of the bitmap. - - float du, float dv - - The size of the rectangle to sample. These values go from 0.0 to 1.0 across the size of the bitmap. - - *ptr - - The result is returned here - the average over the specified area. See Structure . - to compute an averaged color over the specified area. You must have a filter plugged in for this to work. See SetFilter() below. - Parameters: - float u, float v - - The location in the bitmap to filter. These values go from 0.0 to 1.0 across the size of the bitmap. - - float du, float dv - - The size of the rectangle to sample. These values go from 0.0 to 1.0 across the size of the bitmap. - - *ptr - - The result is returned here - the average over the specified area. - - - - - Sets the type of dithering used on the bitmap. - Parameters: - UINT nDitherType - - The type of dither to perform. - - BMM_DITHER_NONE - - Specifies no dithering is to be performed. - - BMM_DITHER_FLOYD - - Specifies the Floyd-Steinberg dithering algorithm. - Nonzero if the bitmap dithering was set; otherwise 0. - - - - - Establishes a filtering algorithm to be used by the bitmap. - Parameters: - UINT nFilterType - - See Bitmap Filter Types. - Nonzero if the bitmap filtering was set; otherwise 0. - - - - - Determines if the bitmap has a filter. - Returns nonzero if the bitmap has a filter; otherwise 0. - - - - - This method is used internally. It returns a pointer to the bitmap filter used by the bitmap. - - - - - Establishes a bitmap storage to manage this bitmap. - Parameters: - *pstorage - - The storage to manage the bitmap. - Nonzero if the storage was assigned; otherwise 0. - - - - - Returns the storage that is managing this bitmap. - A pointer to the storage. - - - - - Sets the storage pointer to nullptr. - - - - - This method creates a window for the display of this bitmap and displays it. - Parameters: - MCHAR *title = NULL - - The title to display in the title bar of the window. - - int position = BMM_CN - - Specifies how the bitmap should be positioned. One of the following values: - - BMM_UL - Upper Left - - BMM_LL - Lower Left - - BMM_UR - Upper Right - - BMM_LR - Lower Right - - BMM_CN - Center - - BMM_RND - Used internally. location. - - BMM_VPP - Used internally. Video Post Primary location. - - BMM_VPS - Used internally. Video Post Secondary location. - - BOOL autonomous = FALSE - - This is reserved for internal use, always let it default to FALSE. - - BOOL savebutton = TRUE - - This is reserved for internal use, always let it default to TRUE. - - *crop=NULL - - This parameter is available in release 2.0 and later only. - - When non-NULL this will cause the VFB to display, instead of its normal toolbar, a set of sliders for adjusting cropping and also will allow interactive adjustment of the cropping rectangle in the image window. See Class . - - *cloneMyVFB = NULL - - This parameter is available in release 4.0 and later only. - - A pointer to a bitmap to clone the VFB to. - Nonzero if the bitmap was displayed; otherwise 0. - - - - - Close the display window associated with this bitmap (if any). - Always returns nonzero. - - - - - Get the window handle for the displayed bitmap. - Returns the window handle, or NULL if it's not displayed in a window. - - - - - Refreshes the interior of the display window with the bitmap contents. In release 3.0 and later this method respects the Bitmap::ShowProgressLine() setting. See that method for more details. - Parameters: - RECT *rect = NULL - - The region of the display window to refresh (specified in image coordinates). If the pointer is NULL the entire window is refreshed. - - - - - Sets the title displayed in the display window's title bar. - Parameters: - MCHAR *title - - The title to display. - - - - - This method is used when the VFB is being displayed and you want to change the cropping rectangle from your plug-in. An example of this is available in /MAXSDK/SAMPLES/MATERIALS/BMTEX.CPP. - Parameters: - float u - - The U value to set. - - float v - - The U value to set. - - float w - - The U value to set. - - float h - - The U value to set. - - BOOL placeImage - - TRUE for place mode; FALSE for crop. - - - - - Returns TRUE if the virtual frame buffer (VFB) is autonomous; otherwise FALSE. For instance, Video Post has an associated VFB. When Video Post is closed so is its VFB since it belongs to it. In that case the VFB is not autonomous. If the user does a File command, that VFB is autonomous. - - - - - Sets every pixel of the bitmap to the specified color and alpha value. - Parameters: - int r - - Specifies the red value to fill with. - - int g - - Specifies the green value to fill with. - - int b - - Specifies the blue value to fill with. - - int alpha - - Specifies the alpha value to fill with. - Nonzero if the operation succeeded; otherwise FALSE. - - - - - Print the bitmap (if supported by the host app) - - - - - This method is used for showing a moving scanline in a virtual frame buffer displaying this bitmap. Here's how it works. If you call ShowProgressLine(y), it clears any previously set white line, and sets an internal counter: you have to call Bitmap::RefreshWindow() to get the new white line to show up. From then that line will be displayed as white. To Clear it call ShowProgressLine(-1). - Parameters: - int y - - The scanline to display as white (the count begins at zero). Use a value of -1 to hide the line. - - - - - Returns a pointer to the callback used to notify a developer when the 's storage changes. - Default Implementation: - { return bmNotify; }; - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Returns a pointer to the bitmap manager being used. - - - - - Copies the specified bitmap to this bitmap. - Parameters: - *from - - The source bitmap. - - int operation - - The type of copy to perform: - - COPY_IMAGE_CROP - - Copy image to current map size using cropping if necessary. - - COPY_IMAGE_RESIZE_LO_QUALITY - - Resize the source image to the destination map size (draft quality). - - COPY_IMAGE_RESIZE_HI_QUALITY - - Resize source image to the destination map size (final quality). - - COPY_IMAGE_USE_CUSTOM - - Resize based on the Image Input Options ( *). - - fillcolor - - Vacant areas of the bitmap are filled with fillcolor pixels if the operation specified is COPY_IMAGE_CROP and one of the source bitmap dimensions is less than the size of this bitmap. See Structure . - - *bi = NULL - - When using custom options (resize to fit, positioning, etc.) this is how the flags are passed down to the Manager. This is an optional argument - for simple copy operations, *bi can default to NULL. If present, the code checks the option flags and acts accordingly. - Nonzero if the copy was performed; otherwise 0. - - - - - Used by Maxscript. - Parameters: - fillColor - - - - - - - Used by Maxscript. - Parameters: - fillColor - - - - - Description: - This class represents the bitmap and is available through the built-in type instance bitmapDropType. - - - - - Custom browse bitmap file for input dialog. - - - Description: - This class can be used to replace the standard 3ds Max Browse Images for Input dialog such as: Select Image File dialog. - - - - - This method is called in BitmapManager::SelectFileInput() (or BitmapManager::SelectFileInputEx()) which will bring up the custom browse images for input dialog box. - Parameters: - See BitmapManager::SelectFileInput(). - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - Custom browse bitmap file for output dialog. - - - Description: - This class can be used to replace the standard 3ds Max Browse Images for Output dialog such as: Render Output File dialog, Create Preview Animation Output File dialog. - - - - - This method is called in BitmapManager::SelectFileOutput() which will bring up the custom browse images for output dialog box. - Parameters: - See BitmapManager::SelectFileOutput(). - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - Information about an image file or in-memory bitmap, including settings for loading/saving, gamma, etc. - - - Description: - This class describes the properties of a bitmap such as its path name or device name, width, height, gamma, number of frames, etc. Methods are available to set and retrieve these properties. All methods are implemented by the system unless noted otherwise. - In general, should be used and saved for user-defined files rather than filenames, because the encodes information beyond the filename, including file-format specific settings (e.g. compression on .JPG files) and so on. - The file dialog functions (such as BitmapManager::SelectFileInput() or BitmapManager::SelectFileOutput()) can be seen as "BitmapInfo editors", since they allow the user to edit its content. - - - - - Returns the flags of this . See Bitmap Flags - - - - - Sets the flags for this . These are bitwise OR-ed into the current flags. - Parameters: - DWORD f - - The flag bits to set. See Bitmap Flags - The revised flags are returned. - - - - - Determines if a set of flag bits are set. - Parameters: - DWORD f - - The flag bits to test. See Bitmap Flags - TRUE if the bits are set; otherwise FALSE. - - - - - Returns the width (horizontal dimension) property of this . - - - - - Returns the height (vertical dimension) setting of this . - - - - - Returns the gamma setting property of this . - - - - - Returns the name of the color space that's assigned to the bitmap. - You can not directly set the color space of a bitmap, but you can request a color space via the SetRequestedColorSpace function. The system will assign a color space based on the available and requested color spaces. Based on the color space availability the assigned color space may be different from the requested color space. If no color space is requested, system will use input rules and/or other system heuristics to assign a suitable color space. - Name of the currently assigned color space. - - - - - Returns color space assignment source. - This value indicates how the current color space is assigned to this bitmap (user request, rules etc). - - ColSpaceSource enum for the current source of the assigned color space. - - - - - - Returns the status of the color space assignment. - - You can ValidateColorSpace() or SetRequestedColorSpace to re-assign color space and update the status. - ColSpaceStatus enum for the current status of the assigned color space. - - - - - - Returns the input rule that's used for color space assignment. - If the ColorSpaceSource is ColSpaceSource::InputRules, this will return the name of the rule that's used for assigning the color space. Otherwise it will return an empty string. - - - - - - Returns the color conversion specified for an output. - - - - - Sets the OutputColorConversion. - - The status indicating if the requested color space or display view transform could be assigned. - - - The OutputConversion to be used. If set to Automatic or NoConversion, no other parameter has to be present. - If outputConversion is set to ColorSpaceConversion, pass the requested color space in here. If outputConversion is set to DisplayViewTransform, pass the requested Display in here. - If outputConversion is set to DisplayViewTransform, an optional view transform can be passed in here. - - - - Returns the assigned output color space. - If OutputColorConversion is set to ColorSpaceConversion, this function returns the assigned output color space, into that the image is converted during saving. Note that this can be different than what was requested, as not all color spaces may be available in the currently used OCIO config. - - The output color spaces that is being used to save this bitmap, if the ColorConversion is set to ColorSpaceConversion. - - - If this is passed in by the caller, it will receive the status of the output color space. - If present, this will receive the output color space that was originally requested. - - - - Returns the assigned output display color space. - If OutputColorConversion is set to DisplayViewTransform, this function returns the assigned display color space, into that the image is converted during saving, along with some optional view transform. Note that this can be different than what was requested, as not all display color spaces may be available in the currently used OCIO config. - - The output display used to save this bitmap along with some optional view transform, if ColorConversion is set to DisplayViewTransform. - - - If this is passed in by the caller, it will receive the status of the output display color space. - If present, this will receive the output display that was originally requested. - - - - Returns the assigned output view transform. - If OutputColorConversion is set to DisplayViewTransform, this function returns the assigned view transform, that is applied to the image during saving along with the conversion into the assigned display color space. Note that this can be different than what was requested, as not all view transforms may be available for the assigned display in the currently used OCIO config. - - The output view transform applied to the image during saving along with the conversion into the assigned display color space, if ColorConversion is set to DisplayViewTransform. - - - If this is passed in by the caller, it will receive the status of the output view transform. - If present, this will receive the output view transform that was originally requested. - - - - Returns the aspect ratio property of this . - - - - - Returns the type property of this . See Bitmap Types - - - - - Sets the width (horizontal dimension) property of this . - Parameters: - WORD w - - Specifies the width setting in pixels. - The old (previously set) width of the bitmap. - - - - - Sets the height (vertical dimension) property of this . - Parameters: - WORD h - - Specifies the height setting in pixels. - The old (previous) height setting. - - - - - Sets the gamma property of this to the value passed. - Parameters: - float g - - Specifies the gamma setting. - The old (previous) gamma setting. - - - - - Returns the requested color space. - Color space of a bitmap can not be directly set but can be requested either by the user or by the input rules. The system will assign a color space based on this request and the currently available color space. This function will return the requested color space. See ColorSpace for the currently assigned space. - Name of the requested color space. - - - - - Sets the requested color space. - The actual color space assigned may differ if the requested color space is not available. This function internally calls ValidateColorSpace to assign a color space based on the availability of the requested color space. Actually assigned color space may differ from the requested color space. - Status of the current color space assignment. - - Name of the requested color space that's being requested. This is either based on the user selection or input rules. See IModSettings::GetNumFileIOColorSpaces for list of currently available spaces. - one of the ColSpaceSource enum values indicating why this color space is being requested. - - - - Returns the source of the color space request. - - Source of the requested color space, this may be the parameter passed to the SetRequestedColorSpace if the color space was requested explicitly or an internally assinged value if no request is made yet. - - - - - Checks and validates the assigned color space against the currently available color spaces. If the assigned color space is missing or not available in the current setup, then it assigns a valid color space based on the requested color space, file input rules and other settings and/or heuristics. - Status of the assigned color space after the validation an potential assignment. - - - - - Clears all the color space information (including the requested and assigned color space data) to uninitialized state. After this function is called, the bitmap won't have any color space assigned to it before ValidateColorSpace or SetRequestedColorSpace is called. Various functions of the class or other internal functions working on bitmaps may validate and auto assign a color space if the color space is in unassigned state. - - - - - the aspect ratio property of this to the specified value. - Parameters: - float a - - Specifies the aspect ratio setting. - The old (previous) aspect ratio of the bitmap. - - - - - Sets the type property of this to the specified value. - Parameters: - int t - - Specifies the type of bitmap. See Bitmap Types - The old (previous) type setting. - - - - - Returns the first frame property of this . Note that for a multi-frame bitmap some sequences may start with something other than 0. - - - - - Returns the last frame property of this . - - - - - Returns the total number of frames setting of this . - - - - - Returns the current frame setting of this . - - - - - When multi-frame loaders are reading a sequence of frames, this method is called to indicate what to do when reading beyond the end of available frames. The defaults is BMM_SEQ_WRAP. - One of the following values: - - BMM_SEQ_WRAP - - Wraps around back to start point. - - BMM_SEQ_ERROR - - Generates an error if reading goes beyond the end. - - BMM_SEQ_PINGPONG - - This causes the sequence to turn around and goes the other direction, back and forth. - - BMM_SEQ_HOLD - - When the last frame is reached it is held and used over and over. - - - - - Sets the first frame property of this . - Parameters: - int f - - Specifies the first frame setting. - The old (previous) first frame setting. - - - - - Sets the last frame property of this . - Parameters: - int f - - Specifies the last frame. - The old (previous) frame setting. - - - - - Sets the current frame setting of this . - Parameters: - int v - - Specifies the current frame. - The old (previous) current frame setting. - - - - - Sets the sequence out of bounds property of this . When reading a sequence of frames, this specifies what to do when reading beyond the end of available frames. - Parameters: - WORD s - - One of the following values: - - BMM_SEQ_WRAP - - Wraps around back to start point. - - BMM_SEQ_ERROR - - Generates an error if reading goes beyond the end. - - BMM_SEQ_PINGPONG - - This causes the sequence to turn around and goes the other direction, back and forth. - - BMM_SEQ_HOLD - - When the last frame is reached it is held and used over and over. - The old (previous) value that was set. - - - - - Returns the currently set path of the image file. - - - The currently set path of the image file. full path name. See MCHAR *Filename() for just the file name. - - - - - Returns just the file name of this (not the entire path name). - - - - - Returns the device name responsible for producing this image. For file types, this is just informative. For non-file types (devices) this is the way this image is identified. Therefore, it is important to save both name and device in order to properly identify an image. - - - - - This method will compare names taking in consideration both file names and device names. As devices don't have a file name, this method will first determine what type of image this is, and then perform a proper comparison. - Parameters: - *bi - - The other with which to compare names. - TRUE if the BitmapInfos have the same name and device name; otherwise FALSE. - - - - - the path to the image file. - - - This is a convenience method and calls SetPath under the hood. - Parameters: - const MCHAR *n - - Specifies the name of the bitmap. - The old (previous) name that was set. - - New path for the bitmap. should have a fully qualified filename. When reading, it only matters if the image is not in the MAP path. Note that a "feature" of the MAP path system is that if an image with same name is found more than once (in different paths), only the first one is seen. Note: If loading an image from a device, make sure the name is empty (). This is automatic if you use . If you just create a instance and set the device name by hand (), this is also automatic as both name and device names are by default set to NULL (""). This is only a concern if you reuse a class previously used for image files. - - - - Sets the device name. - - - This copies the supplied string into the member variable device. The string corresponds with the long description of a plugin: BitmapIO::LongDesc(). However it is not necessary to call this as the system will do it automatically when Bitmap::OpenOutput is called. Or as alternative, it can properly be set in a localized environment by calling BitmapInfo::FixDeviceName(). - The device name that was set. - - - The name to set. - - - - Returns the custom width setting of this . - - - - - Returns the custom height setting of this . - - - - - Returns the custom start frame property of this . - - - - - Returns the custom end frame setting of this . - - - - - Returns the custom x offset setting of this . - - - - - Returns the custom Y offset setting of this . - - - - - Returns the custom gamma setting of this . - - - - - Returns the bitmap's currently used input gamma value. This is taken from either the image file's gamma, the system defaults, or the user override, according to the custom flags. - - - - - Returns the custom frame step setting of this . - - - - - Returns the optional alignment setting of this . This indicates where to place the image if the image being copied from one to another is smaller. - See Bitmap Alignment Positions - - - - - Retrieves the custom flags setting of this . See Custom Bitmap Flags - - - - - Sets the custom flag(s) for this . - Parameters: - DWORD f - - Specifies the custom flags. See Custom Bitmap Flags - - - - - Clears the specified flag(s) of this . See Custom Bitmap Flags - Parameters: - DWORD f - - Specifies the flag bits to reset. - - - - - Tests the custom flags of this . See Custom Bitmap Flags - Parameters: - DWORD f - - The flag bits to test. - Returns TRUE if the specified flags were set; otherwise FALSE. - - - - - Assignment operator. The data members of the specified are copied to this . - Parameters: - &from - - The source . - - - - - Returns the currently set path of the image file. - - - The currently set path of the image file. - - - - - Copies the image information of the from to this bitmap. Only the name, device, image characteristics and color management related data are copied. User info, such as Custom Width, etc. is not copied. - - - The following properties of the from are copied: - - Name(), from-> - - - The bitmap whose information will be copied. - - - - the path to the image file. - - - - New path for the bitmap. - - - - returns this bitmap's asset - - - - - Returns the plugin data stored on the . The plugin data is set by class responsible for producing this image. The class stores its image specific data in the plugin data. For example, the avi class stores the compressor name, quality, and keyframe in the plugin data. The owns the memory associated with the plugin data and will free the memory when deleted. - Pointer to the plugin data. - - - - - Returns the size of the plugin data stored on the . - Size of the plugin data. - - - - - Resets the plugin data stored on the . Frees existing plugin data memory and sets plugin data size to zero. - - - - - Allocates the plugin data memory and set the plugin data size. Acquire the pointer to the plugin data memory via GetPiData() - - Requested size of the plugin data. - - - - Returns the subject info of the proxy. When create is TRUE, the subject info will be allocated if it was null. - - - - - Deletes the subject info and sets it to null. - - - - - Creates the subject info. Info is initialized as per the default constructor - - - - - This method is available in release 2.0 and later only. - - This method provides some access to device specific data (for instance the compression ratio in a JPEG file). This method will return a buffer containing a given device specific data (or NULL if the device referenced is unknown or doesn't have "specific data"). The buffer structure will depend on the device. For all drivers shipped with the SDK, this structure is defined in their header files (which must be included in the project for which this method is used). Internally, this method validates the driver, calls its EvaluateConfigure() method to define the buffer size, creates this buffer and, if the returned size is greater than zero, calls the driver's SaveConfigure() method in order to set default values. The developer may then change whatever they want, create and write a file using this which includes the device's specific data. - - There is no need to free this buffer as this is handled by the destructor. - - Note: The name and/or device properties must be defined before using this method. - - - - - Assignment function. The data members of the specified are copied to this , with option to also copy the proxySubject info. - - - - - Implemented by the System. - - This method is used to check the width, height, aspect ratio, and gamma settings to make sure they are within an acceptable range of values. The comparison is as follows: - - if (width < 1 || - - height < 1 || - - aspect <= 0.0 || - - gamma < MINGAMMA || - - gamma > MAXGAMMA) - - return (FALSE); - - else - - return (TRUE); - - Where: - - #define MINGAMMA 0.2f - - #define MAXGAMMA 5.0f - TRUE if the 's settings are valid ; otherwise FALSE. - - - - - Returns the window handle to send progress or check abort messages to. - - - - - Sets the appropriate device name, as derived from the filename. - - - - - Base class for image IO plugins. - - - Description: - This is the base class used by developers creating image loader / saver plug-ins. Developers implement pure virtual methods of this class to load the image, open it for output, write to it, close it, and to provide information about the image loader/saver they are creating. These are properties such as the author name, copyright, image format description, filename extension(s) used, and the capabilities of the image loader / saver. - - When a derived image reader reads an image, it creates a storage class that makes sense to it. For example, a paletted 8 bit is perfect for loading GIF's but not for loading 32 bit Targas. The inverse is also true. There is no point in creating a TRUE_64 storage to load a GIF. Because this is how image buffers are managed, it is also important to note that if a developer writes an image loader that creates images from scratch (a gradient generator for instance), there is no need to have any real memory allocated. The plug-in would simply derive a new type of and provide the pixels through the common methods (virtual buffer), creating them as they are requested. - Automatic gamma correction / BitmapIOMetaData - If a particular is intended to read/write floating point data, or in general does not want to have the data encoded with a gamma curve, it can choose to expose the interface. This is done by exposing an interface with the ID of BITMAPIOMETADATA_INTERFACE_ID (retrievable via BitmapIO::GetInterface(BITMAPIOMETADATA_INTERFACE_ID)). This returns a pointer to the 's interface. This exposes a function BitmapIOMetaData::UseLinearStorage() that will return true if that would like to (by default) load and save data linearly (i.e. with a gamma of 1.0). - See for more information. - - - - - Implemented by the System. - - This method is used by the subclassed to get pixels for output with the appropriate output gamma correction. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixels. See Structure . - - BOOL preMultAlpha=TRUE - - This parameter is available in release 3.0 and later only. - - Setting this parameter to FALSE will cause pixels with non-pre-multiplied alpha to be returned. - Nonzero if the pixels were retrieved; otherwise zero. - - - - - Implemented by the System. - - This method is used by the subclassed to get 32 bit pixels for output with the appropriate output gamma correction and dither. Note that this method works on only a single scanline of pixels at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixels. See Structure . - - BOOL preMultAlpha=TRUE - - This parameter is available in release 3.0 and later only. - - Setting this parameter to FALSE will cause pixels with non-pre-multiplied alpha to be returned. - Nonzero if the pixels were retrieved; otherwise zero. - - - - - Implemented by the System. - - This method is used by the subclassed to get a DIB for output with the appropriate output gamma correction. - Parameters: - int depth = 24 - - Specifies the depth of the DIB. This may be either 24 or 32. - - - - - Implemented by the System. - - This methods is used by the subclassed to get a DIB for output with the appropriate output gamma correction and dither. - Parameters: - int depth = 24 - - Specifies the depth of the DIB. This may be either 24 or 32. - - - - - Implemented by the System. - - Returns the output gamma setting. - - - - - Implemented by the System. - - If a wants to do its own dithering, it should call this method to find out if dithering is wanted for true color images. If it is a 24 bit or 32 bit format, it would usually just call GetDitheredOutputPixels() instead. - TRUE if dithering is desired; otherwise FALSE. - - - - - Implemented by the System. - - If a wants to do its own dithering, it should call this method to find out if dithering is wanted for paletted images. - TRUE if dithering is desired; otherwise FALSE. - - - - - Calculate a color palette for output color packing for the map that is using this output handler (this is the map pointed at by the protected data member *map). This method performs gamma correction. See Class , Class . - Parameters: - int palsize - - The size of the palette to compute. - - *pal - - Storage for the palette. - Nonzero if the palette was computed; otherwise zero. - - - - - Implemented by the System. - - Returns the open mode setting. See Bitmap Open Mode Types - - - - - Implemented by the System. - - Returns a pointer to the for this image input handler. - - - - - Implemented by the System. - - Returns a pointer to the using this output handler. - - - - - Returns the number of filename extensions supported by this IO module. For example the EPS plug-in supports "EPS" and "PS", and thus returns 2. - - - - - The extensions are accessed using a virtual array. This method returns the 'i-th' filename extension supported by the IO module, (i.e. "EPS"). - Parameters: - int i - - Specifies which filename extension to return. - - - - - Returns a long ASCII description of the image format (i.e. "Targa 2.0Image File"). - - - - - Returns a short ASCII description of the image format (i.e. "Targa"). - - - - - Returns the ASCII Author name of the IO module. - - - - - Returns the ASCII Copyright message for the IO module. - - - - - Returns the IO module version number * 100 (i.e. v3.01 = 301) - - - - - Returns the IO module capability flags. These describe the capabilities of the plug-in such as if it supports reading images, writing images, multiple files, and whether it has its own information and control dialog boxes. See BitmapIO Capability Flags. - - - - - This method is called to show the plug-in's "About" box. This is called, for example, from the About button of the Add Image Input Event dialog in Video Post. - Parameters: - HWND hWnd - - The handle of the owner window. - - - - - If the BMMIO_OWN_VIEWER flag is set in the flags returned from the Capability() method, this method will be called whenever the user wants to view an image for this device. This is for devices which can "play" image sequences such as AVIs, FLCs, etc. - Parameters: - HWND hWnd - - The handle of the owner window. - - *pbi - - The bitmap to view. - TRUE if the viewing the image was successful; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - Displays the Panel of the IO module. This function is only called if the plug-in has defined it supports it (through the Capability flag returned from Capability(), ie. BMMIO_CONTROLREAD, etc.). See BitmapIO Capability Flags. - Parameters: - HWND hWnd - - The handle of the owner window. - - DWORD flag - - Indicates to the plug-in what operation the control is for (read, write, or generic). See BitmapIO Capability Flags - If the user exits the box through an OK, this function should return TRUE. If the user cancels out, it will should FALSE. FALSE indicates nothing has changed so the system won't bother asking the plug-in if it wants to save data. - Default Implementation: - { return FALSE; } - - - - - This method is called by 3ds Max to determine the buffer size required by the plug-in. The plug-in implements this method and returns the number of bytes of configuration data it needs to save. - The buffer size required by the plug-in (in bytes). - - - - - This method is called by 3ds Max to allow the plug-in to load any configuration data. - Returns TRUE if the data was loaded properly; otherwise FALSE. - - - Pointer initialized to point to the previously saved configuration data. - - The size of the previously saved configuration data. - - - - This method is called by 3ds Max to allow the plug-in to save any configuration data. - Returns TRUE if the data was saved; otherwise FALSE. - - - Pointer initialized to a pre-allocated buffer where the plug-in may save data. - - - - This is the configuration file containing the default options. - - - - - Loads the defaults into 's parameter block. - TRUE. - - - - - Saves the parameter block as the new defaults. - - - - - Implemented by the System. - - Returns the state of the silent mode flag. If this flag is TRUE the plug-in should NOT post a dialog displaying any error messages. - - - - - Implemented by the System. - - This method is for use with multi-frame sequences. It processes the desired frame based on the user options. For example the user can tell the system to hold on the last frame of the sequence, loop back to the beginning, or return an error. This method does all the checking automatically based on the object passed and computes the proper frame number. - Parameters: - *fbi - - A pointer to the that contains the user options. This is the instance passed to Load(). - - int *frame - - A pointer to an integer to receive the frame number - One of the following values: - - BMMRES_SUCCESS - - BMMRES_BADFRAME - - - - - Implemented by the System. - - This method may be called to present the user with the 3ds Max Image IO Error dialog box. The dialog displays the bitmap file name or device name, and the specified error message. The user may choose Cancel or Retry from the dialog. An appropriate value is returned based on the users selection. - - This method is used to handle hardware I/O errors automatically or display the given string. - - In this method, if Silent Mode is on (for example network rendering is being done), no dialog is presented and BMMRES_ERRORTAKENCARE is returned. - Parameters: - *pbi - - A pointer to the . This is used to retrieve the file or device name (using pbi-> or pbi->Device()). - - MCHAR *string = NULL - - The error message to present in the dialog. If NULL this method will query the operating system for the last I/O error and give its own interpretation of the error. This will work for all "File Not Found", "Permission Denied", etc. type errors. - One of the following values: - - BMMRES_ERRORTAKENCARE - - Returned if the user selected OK from the dialog or the error was taken care of (silent mode was on). - - BMMRES_ERRORRETRY - - The user has selected Retry from the dialog. - - - - - Implemented by the System. - - This method may be called to present the user with the 3ds Max Image IO Error dialog box displaying the specified error message based on the error code passed. The user may choose Cancel or Retry from the dialog. An appropriate value is returned based on the users selection. If Silent Mode is on (for example network rendering is being done) no dialog is presented and BMMRES_ERRORTAKENCARE is returned. - Parameters: - *pbi - - A pointer to the . This is used to retrieve the file or device name (using pbi-> or pbi->Device()). - - int errorcode - - The error code. Pass one of the following values and the string shown to its right will be presented. - - BMMRES_INTERNALERROR - Internal Error - - BMMRES_NUMBEREDFILENAMEERROR - Error Creating Numbered File . - - BMMRES_BADFILEHEADER - Invalid Image File Header - - BMMRES_CANTSTORAGE - Error Creating Image Storage - - BMMRES_MEMORYERROR - Memory Error - - BMMRES_BADFRAME - Invalid Frame Requested - - Any other values produce - Unknown Error - One of the following values: - - BMMRES_ERRORTAKENCARE - - Returned if the user selected Cancel from the dialog or the error was taken care of (silent mode was on). - - BMMRES_ERRORRETRY - - The user has selected Retry from the dialog. - Sample Code: - From: MAXSDK/samples/images/jpeg/jpeg.cpp - - - - - These are the channels required for output. By setting this flag, the plug-in can request that 3ds Max generate the given channels. Prior to rendering, 3ds Max will scan the plug-ins in the chain of events and list all types of channels being requested. The plug-in, at the time of the Write() method, will have access to these channels through the channel interface described in . - See Image (G-Buffer) Channels - Default Implementation: - { return BMM_CHAN_NONE; } - - - - - This method will display a dialog with information about the given bitmap (either defined in bi.Name()/bi.Device() or explicitly in the filename passed). The default method will retrieve image information using the mandatory GetImageInfo() and display a generic information dialog. If an image loader / writer wants to show its own info dialog, perhaps showing an image property not found in the generic dialog, it can implement its own function (and notify the system using the BMM_INFODLG flag in the capabilities flag). - Parameters: - HWND hWnd - - The parent window handle calling the dialog. - - *pbi - - Defines the name of the bitmap or device (unless specified below). - - const MCHAR *filename = NULL - - Specifies the filename to use explicitly. - The result of the operation. See Bitmap Error (result) Codes - - - - - The module implements this method to initialize the instance passed in with information about the image. This information might be obtained from read the image header for example. The passed contains the name of the image to get the information about. - Parameters: - *pbi - - A pointer to an instance of the class . - If an error occurs, the plug-in should process the error (display a message if appropriate) and return BMMRES_ERRORTAKENCARE. If everything went OK, the plug-in should return BMMRES_SUCCESS. - Sample Code: - - - - - This method is implemented by image file loaders (IFL handlers). It is called to update the filename passed based on the properties of the passed. See the implementation of this method in /MAXSDK/SAMPLES/IO/IFL.CPP. - Parameters: - *pbi - - Specifies the properties of the IFL sequence. - - MCHAR *filename - - The filename to update based on the properties of bi. - See Bitmap Error (result) Codes - - - - - The bitmap manager caches images in order to speed its process. When a new image is requested, if it's - - already loaded, a pointer to it is passed around as opposed to loading an entire new copy of it. It does so by comparing the image name and the frame number requested (in case of multiframe files and/or devices). - - This works fine in most cases, however consider the following scenario. The Accom device generates images just as if you were loading Targa files. The comparison explained above works fine. The problem however, is that within the Accom private setup, you can determine where in the Accom to start reading frames. In other words, you may have a sequence of images recorded in the Accom starting at frame 300 for instance. Once in the Accom setup, you define your starting frame at 300 and whenever 3ds Max requests a frame, the Accom driver offsets the requested frame number by 300. For example, when 3ds Max is rendering its 10th frame and requests a frame from the Accom (for a Map or for a background, etc.), the Accom will see that 3ds Max wants frame 10 and the user had setup the starting frame at 300. After computing the offset the Accom driver returns frame 310. Now, if two or more maps are used in a scene, the cache match mechanism explained above fails as it does not take in consideration the "starting frame" parameter of the Accom driver. For it, the name matches (Accom) and the frame number matches (frame 10 in the example above). If two or more maps start at different positions within the Accom, the first one defined will be used as it satisfies the match. - - To handle this condition this new method saves extra information (driver private information) about a frame. Basically, part of the match process is now handled by those drivers that implement this method. - - If a driver has some private data (handled by its own setup dialogue) that defines anything in how images are returned (in other words, if different images are returned because of those private settings being different), it must define the BMMIO_EVALMATCH return flag and must also implement this method. The flag is necessary to avoid wasting time setting up instances of the driver just to call the (possibly unimplemented) method. - Parameters: - MCHAR *matchString - - The match string. The driver simply builds a string made of its own "perframe" parameters and returns it so 3ds Max can compare it with another instance of the driver. - - - - - This is the method that is called to actually load and store the image. This method usually creates the storage for the image data, allocates storage space, and puts the image to the storage one scanline at a time. If the image header contains known gamma information, it can call SetGamma() with the relevant value. This method also usually sets the BitmapIO::openMode flag to BMM_OPEN_R to indicate the image is loaded and open for reading. - Parameters: - *pbi - - Points to an instance of class . This has the name of the bitmap / device to load. - - *pmap - - This points to the bitmap to be loaded. - - BMMRES *status - - The result of the bitmap load operation. See Bitmap Error (result) Codes - The created to manages this bitmap. - Sample Code: - See the Load() method of /MAXSDK/samples/images/jpeg/jpeg.cpp. - - - - - Opens the image for writing to file. - - - This method opens the image for output and prepares to write to it. This is the time that the plug-in receives the information about what to write, the flags, etc. The only thing to call after this the Write() method which takes just a frame number. - Returns nonzero if everything was OK; otherwise 0. - Sample Code: - See the OpenOutput() method of /MAXSDK/samples/images/jpeg/jpeg.cpp. - - - The image information. - - Points to the bitmap to save. - - - - This method is called to write the image from the to disk. The data member bi contains the relevant information (for example bi.Name() contains the name of the file to write). - Parameters: - int frame - - Specifies the frame to write. For single image formats this will be BMM_SINGLEFRAME. - Returns nonzero if everything was OK; otherwise 0. - Sample Code: - See the Write() method of /MAXSDK/samples/images/jpeg/jpeg.cpp. - - - - - Closes the output file and saves or discards the changes based on the flag passed. - Parameters: - int flag - - See Bitmap Close Types - Returns nonzero if output was closed successfully; otherwise 0. - Sample Code: - From MAXSDK/samples/images/gif/gif.cpp - - - - - Describes the properties of the bitmap being handled by the instance of this class. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - This is used to make sure plugin data on the belongs to this plugin. It is also called on file load to allow the plugin to version the plugin data. In this case, the iload parameter will be non-NULL. If a plugin implements this method, it must first call the method on and immediately return false if that implementation returns false. - - The holding the plugin data - The ILoad* if called when loading the from a scene file, NULL otherwise. - - - - Implemented by the System. - - This method is used internally. - Default Implementation: - { return NULL; } - - - - - Implemented by the System. - - This method is used internally to build the output gamma table. - - - - - Extends with additional information for automatic gamma correction etc. - - - Description: - This class exposes extended parameters for the class that relates to things like gamma correction preferences. It is returned as an extended interface of , returned by calling GetInterface(BITMAPIOMETADATA_INTERFACE_ID) on it. - If this interface is exposed, it can make a decision whether that implementation would prefer to save or load data linearly. It is called by the code in BitmapManager::Load() when loading and Bitmap::OpenOutput() when saving. - Any that does not expose this interface is simply assumed to use the default gamma value when reading and writing the files (the sRGB gamma of 2.2), very similar to how things worked in older 3ds Max versions. - - - - - Does this prefer linear data or not? - - - true if we prefer linear storage, false if we want to use the the default - generally sRGB - gamma. - - Usage: - If this always wants to work with linear data, this function can just blindly return true. If, however, it can support both float formats and non-float formats depending on settings (like, for example, the DDS or RPF plugins), it needs to be able to make decisions on what to return. - To do this properly, one needs to understand the calling sequence; this function is called in two cases: - An example of this is available in /MAXSDK/SAMPLES/IMAGES/RLA/RLA.CPP. - - is true if we are saving, false for loading. - - - - Description: - This class is used to manage the use of bitmaps within 3ds Max. There is a global instance of this class provided by 3ds Max that developers may use to call these methods. It is called TheManager. This class provides methods for things such as creating and loading bitmaps, and access to the bitmap Map Path directories. There are also methods for displaying some general dialogs that let users select input and output files and devices, as well as dialogs for setting options for the bitmap such as its custom width, height and positioning. - - Note: In the 3ds Max release 3.0 SDK these methods were made virtual. - Data Members: - *pal; - - This is used internally as the virtual framebuffer palette. - Defines: - #define BMM_FLUSH_RELATIVE_FILE_RESOLUTION_CACHE 5 - - Used to flush the internal cache used to avoid having to re-resolve relative paths on each LoadInto call - - - - - - - Returns the application instance handle of 3ds Max itself. - - - - - Returns the window handle of 3ds Max's main window. - - - - - Implemented by the System. - - Retrieves the specified standard 3ds Max directory name (fonts, scenes, images, etc.). - Parameters: - int i - - Specifies the directory name to retrieve. See MAX Directory IDs - The name of the specified directory. - - - - - For internal use only - This is used to add a MAP PATH to the Map path list. - - - - - Returns the number of map paths (used in conjunction with the method below). - The number of map paths. - - - - - Map paths are accessed using a virtual array mechanism. This method returns the 'i-th' map path. - Parameters: - int i - - Specifies the map path to retrieve. - The name of the 'i-th' map path. - - - - - Implemented by the System. - - Returns an interface pointer for calling methods provided by 3ds Max. See Class . - - - - - This method is called to allocate and return a pointer to a new instance of the class. The default constructor is used. - - - - - This method creates a new bitmap using the properties of the passed. For more details on creating bitmaps, see the section ~{ Working with Bitmaps }~. Make sure you delete the created when you are done using it. - Parameters: - *bi - - A pointer to an instance of the class describing the bitmap to create. - A pointer to a newly created instance of class . - - - - - This method loads a bitmap using the parameters specified by the pointer. Make sure you delete the created when you are done using it. - - Note: When several plug-ins call this method to load the same image, they all receive the same pointer to one instance of the . So if one plug-in manipulates the image, the changes will get reflected everywhere. A developer may use BitmapManager::Create() followed by Bitmap::CopyImage() to create a unique instance of . - - Also Note: One of the methods in returns a window handle to send progress report messages. If you want to receive these messages (for purposes of putting up a progress bar during the load), set the window handle (bi->SetUpdateWindow(hWnd)) and process BMM_PROGRESS and BMM_CHECKABORT messages. - Parameters: - *bi - - Specifies the properties of the bitmap to load. - - BMMRES *status - - The result of the bitmap load operation. See Bitmap Error (result) Codes. - A pointer to a new instance of the class . - - - - - This method loads the bitmap specified by bi into the bitmap pointed to by map. The normal Load() method creates a new bitmap. However, if you already have an existing bitmap and simply want to load in a new frame, this method may be used. Specify which bitmap to use using bi and the map to load into using map. For instance, if you have an AVI file and you want to load a new frame, you can simply update the frame number specified in the and call this method passing the bitmap associates with the previous frame. - Parameters: - *bi - - Specifies the properties of the bitmap to load. - - **map - - A pointer to a pointer to a bitmap. This is the bitmap that will be loaded into. - - BOOL forceReload=FALSE - - If an existing bitmap that matches bi is already loaded, then calling calling LoadInto() won't load from the disk or device. Rather it will just use the existing in memory version. If you want to force the bitmap to be reloaded from the file or device set this to TRUE. - The result of the bitmap load operation. See Bitmap Error (result) Codes. - - - - - Applies OpenColorIO based color conversion into a new bitmap of type BMM_FLOAT_RGBA_32 according to the given parameters. - This function uses the IColorPipelineManager to convert the pixel data of one into a new with the same dimensions as the source bitmap and the type BMM_FLOAT_RGBA_32. - Internally, this function calls ColorConvertInto, so all the parameters behave the same: If toColorSpaceOrDisplay is passed in only, this function does a color space conversion (interpreting toColorSpaceOrDisplay as the name of the color space to convert to). - If both toColorSpaceOrDisplay and toViewTransform are passed in, the function does a display/view transform conversion (taking toColorSpaceOrDisplay as the name of the display). - The source color space used for the conversion is extracted from the of the source . - - For information about the available color spaces or display / view transforms please check the documentation of . - The newly created with the data converted according to the given parameters. - - - The bitmap to be converted. Note that the color space of this bitmap must not be invalid. - The name of the color space or display (if toViewTransform is present) to convert the pixel data into. - The name of the view transform for the display /view transform conversion used to convert the pixel data into. Note that this view transform has to be valid for the given display (toColorSpaceOrDisplay). - - - - Applies OpenColorIO based color conversion from a given into another according to the given parameters. - This function uses the IColorPipelineManager to convert the pixel data of one bitmap into another. If toColorSpaceOrDisplay is passed in only, this function does a color space conversion (interpreting toColorSpaceOrDisplay as the name of the color space to convert to). - If both toColorSpaceOrDisplay and toViewTransform are passed in, the function does a display/view transform conversion (taking toColorSpaceOrDisplay as the name of the display). - The source color space used for the conversion is extracted from the of the source . - For information about the available color spaces or display / view transforms please check the documentation of . - BMMRES_SUCCESS or BMMRES_INTERNALERROR if some error occurs. - - - The bitmap to be converted. Note that the color space of this bitmap must not be invalid. - The bitmap to receive the converted pixel data. It has to have the same dimensions as the source . - The name of the color space or display (if toViewTransform is present) to convert the pixel data into. - The name of the view transform for the display /view transform conversion used to convert the pixel data into. Note that this view transform has to be valid for the given display (toColorSpaceOrDisplay). - - - - Determines if silent mode is on. Silent mode specifies if developers should display error messages. If this method returns FALSE, error messages should be displayed. If TRUE, error message dialogs should not be shown. - Returns TRUE if silent mode is on; FALSE otherwise. - - - - - This is reserved for future use. - - - - - Sets the silent mode on/off. The silent mode disables any message box pop-ups that may interrupt the process. - The previous state of the silent mode. - - - - - This method is used internally. - - - - - This method will display information about the given bitmap in a dialog. The source of the information is either defined in bi->/bi->Device() or explicitly in the filename passed). This method is an interface into BitmapIO::GetImageInfoDlg(). It is not normally called by developers. - - The default implementation is within the Manager. There is a generic Image Info dialog that is used unless the proper class implements it own dialog (and notifies the system through the BitmapIO::Capabilities() method). - Parameters: - HWND hWnd - - The parent window handle calling the dialog. - - *bi - - Defines the name of the bitmap or device (unless specified below). The image information fields of *bi are set with the information loaded from the image. - - const MCHAR *filename = NULL - - Specifies the filename to use explicitly. - The result of the operation. See Bitmap Error (result) Codes. - - - - - This method is used to get information about an image, ie things like image resolution (bi->Width()/bi->Height()), number of frames, etc. This is an interface into BitmapIO::GetImageInfo(). Given an image definition in bi.Name() / bi.Device() or explicitly in filename (this function will place filename, if not NULL, into bi.Name() before calling BitmapIO::GetImageInfo()), the proper device will fill the data members in *bi with information about the image. - Parameters: - *bi - - Defines the name of the bitmap or device (unless specified below). - - const MCHAR *filename = NULL - - Specifies the filename to use explicitly. - The result of the operation. See Bitmap Error (result) Codes. - - - - - This method brings up the standard 3ds Max Image Input Options dialog box. If the users selects OK from the dialog, the appropriate data members of *bi are filled specifying the user's choices. These are the 'Custom' fields accessed using methods such as GetCustomX(), GetCustomGamma(), GetCustomStep(), etc. - Parameters: - *bi - - The instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - Returns TRUE if the users selects OK from the dialog; otherwise FALSE. - - - - - Brings up the standard 3ds Max Select Image Input Device dialog box. If the users selects OK from the dialog, then bi->Device() is set to the name of the users device choice. - Parameters: - *bi - - Points to the instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - Brings up the standard 3ds Max Select Image Output Device dialog box. If the users selects OK from the dialog, then bi->Device() is set to the name of the users device choice. - Parameters: - *bi - - Points to the instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - Brings up the standard 3ds Max Browse Images for Output dialog box. If the users selects OK from the dialog, then bi-> is set to the name of the users file choice. - Parameters: - *bi - - Points to the instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - - MCHAR *title = NULL - - The optional title string to display in the title bar of the dialog. - - ULONG *pflags = NULL - - This parameter is available in release 4.0 and later only. - - One of the following: - - BMM_ENABLE_SAVE_REGION - - This flag will cause the "SaveRegion" check box to appear in the dialog. - - BMM_DO_SAVE_REGION - - This flag will return the state of the check box. const MCHAR *extension = NULL - - The optional extension string to display in the Save as type field of the dialog. - - const MCHAR *config = NULL - - The optional name template configuration, used to load according name templates and display in template dropdown combobox of the dialog. Currently support only two name template configurations: PreviewNTP (the default) and TextureNTP. The name templates for these configurations are: - - PreviewNTP: - - <scene> - - <scene>_<camera/view> - - <scene>_<camera/view>_<mm>-<dd> - - <scene>_<camera/view>_<mm>-<dd>-<yyyy> - - CustomTemplate_<scene>_<camera/view>_<mm>-<dd> - - TextureNTP: - - <object>_<map> - - CustomTemplate_<object>_<map> - - These templates provide convenience to users in the following conditions: - - Save preview animation or rendering output based on scene, camera/view name, even with date information - - Save texture for a object based on object, map name. - - If choose a specific template, the File name field text will be replace automatically with specific scene, camera/view, object, map name and date information - - const MCHAR *map = NULL - - The optional map string used to replace <map> when using TextureNTP template. - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - Brings up the standard 3ds Max Browse Images for Input dialog box. If the users selects OK from the dialog, then bi-> is set to the name of the users file choice. - Parameters: - *bi - - The instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - - MCHAR *title = NULL - - The optional title string to display in the title bar of the dialog. - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - This method brings up the standard 3ds Max Browse Images for Input dialog box (the same as SelectFileInput()) but a "Devices" button is present so the user can select both image files and image devices. - Parameters: - *bi - - The instance of that is updated based on the users dialog selections. - - HWND hWnd - - The parent window handle for the dialog. - - MCHAR *title = NULL - - The optional title string to display in the title bar of the dialog. - - BOOL viewonly = FALSE - - If viewonly is set to TRUE, the button is hidden in the dialog. - TRUE if the user exited the dialog using OK; otherwise FALSE. - - - - - This method is used for accumulating the names of bitmap files that didn't load. Instead of having the display the missing file dialog, it now just collects the names (which can be retrieved using GetLoadErrorFileList() below). - - - - - This method will return a list of names of bitmap files that were not found as discussed in the method above. See Class . - - - - - This method ends the accumulation of a list of bitmap files that didn't load, and frees the list. See the two methods above. - - - - - Returns true if the extension of the specified file name is one of the supported types (i.e. there is a module for it); otherwise false. - Parameters: - const MCHAR* filename - - The file name to check. - - - - - This method refreshes the interior of all the virtual frame buffer windows with each bitmap's contents. - - - - - This method calls Bitmap::DeleteThis() on all the bitmaps whose virtual frame buffers are set to autonomous. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Updates color management related settings and caches in all bitmap storages. This includes gamma tables, color spaces names and color pipeline caches used to convert native colors into rendering space. This will also update all the VFB's. - - - - - Implements the 'strip path' action. - - - - - Description: - This class is a callback for notifying bitmaps that their storage has changed, and if any on screen displays need to be refreshed. This is installed as a callback via the method Bitmap::SetNotify(). - - All methods of this class are implemented by the system. - - - - - This method is called when the storage for the has changed. - Parameters: - ULONG flags - - One of the following: - - BMNOTIFY_FLAG_STORAGE_CHANGE, notifies that the storage (the contents of the bitmap) has changed. - - BMNOTIFY_FLAG_FILE_CHANGE, notifies that that bitmap file has changed, probably by an external program. The bitmap should be reloaded. Note that by the time this call is made, the API has already checked to see if the user has set the global preferences asking for these changes to be automatically reloaded. - - - - - This method is called when Virtual Frame Buffer is closed. - Default Implementation: - {} - - - - - Useful Guard class for temporarily disabling bitmap proxies. - - - proxies are disabled in the constructor, and disabled in the destructor, using NOTIFY_PROXY_TEMPORARY_DISABLE_START and NOTIFY_PROXY_TEMPORARY_DISABLE_END. - For more details on the way this disables bitmap proxies, see NOTIFY_PROXY_TEMPORARY_DISABLE_START. - Recursive calls are handled correctly; a count of recursive calls is maintained and bitmap proxies are only re-enabled once all instances of this class have been destroyed. - - - - - Description: - When an image is loaded the buffer that will hold it is an instance of this class. This class provides methods that allow developers to access the image data in a uniform manner even though the underlying storage might be 1-bit, 8-bit, 16-bit, 32-bit or 64-bit. Standard methods are available for getting / putting pixels: Get/PutPixels(), Get/Put16Gray(), Get/Put64Pixels(), Get/PutTruePixels(), Get/PutIndexPixels(), etc. - - Since a developer accesses the storage through this standard interface, certain plug-in types may not need to allocate memory for the storage. For example, an image loader that creates an image from scratch (such as a gradient generator). This plug-in would simply derive a new type of and provide the pixels through the common methods, creating them as requested. - - Note: The "<b>Get/PutPixels()</b>" methods of this class access the image a single scanline at a time. - - Also note: The following global function may be used by image loader/saver plug-ins to create an instance of : - - - - - Implemented by the System. - - Sets the gamma setting to the value passed. - Parameters: - floag gam - - The gamma setting to set. - - - - - Implemented by the System. - - Returns nonzero if the gamma table has been allocated; otherwise 0. - - - - - Implemented by the System. - - This method allocates or deallocates the gamma table. - Parameters: - BOOL onOff - - If TRUE the gamma table is allocated; otherwise it is deleted. - - - - - Implemented by the System. - - This methods returns a pointer to a gamma table that can be used for converting pixels using whatever gamma value is appropriate for the storage. It is typically called inside of the GetLinearPixels() method of the particular subclasses which then use the gamma table to convert pixel values to linear values. Plug-In developers in most cases will not need to call this method directly. - - - - - This function will return the pointer of the IColorPipeline object that is used to convert the colors from bitmap's input color space into the currently active rendering color space. Do not delete the returned pointer. - - - - - Implemented by the System. - - Returns the bitmap manager for the storage. - - - - - Implemented by the System. - - Returns the mode the storage was opened in. See Bitmap Open Mode Types - - - - - Implemented by the System. - - Returns the width (horizontal dimension) of the storage's instance (bi.Width()). - - - - - Implemented by the System. - - Returns the height (vertical dimension) of the storage's instance (bi.Height()). - - - - - Implemented by the System. - - Returns the aspect ratio of the storage's instance (bi.Aspect()). - - - - - Implemented by the System. - - Returns the gamma setting of the storage's instance (bi.Gamma()). - - - - - Implemented by the System. - - Determines if the image is paletted. If the image has a palette (indexed color), the number of palette slots used is returned; otherwise zero. - - - - - Implemented by the System. - - Returns the dithered state of the image. If the image is dithered nonzero is returned; otherwise 0, - - - - - Implemented by the System. - - Determines if the image has pre-multiplied alpha. If the image has pre-multiplied alpha nonzero is returned; otherwise 0. - - - - - Implemented by the System. - - Determines if the image has an alpha channel. If the image has an alpha channel nonzero is returned; otherwise 0. - - - - - Implemented by the System. - - whether colors are scaled (on) or clamped (off) when converting from to . - - - - - Implemented by the System. - - Returns the last value set by UseScaleColors. - - - - - Implemented by the System. - - Converts in to out, using the value of ScaleColors() to determine the clamping or scaling. The alpha component is not copied. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out, using the value of ScaleColors() to determine the clamping or scaling. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Returns the number of times this image is being used in the system. - - - - - Implemented by the System. - - Returns the type of bitmap managed by this storage. See Bitmap Types. - - - - - Implemented by the System. - - Returns the bitmap flags. See Bitmap Flags. - - - - - Implemented by the System. - - Sets the specified flag bits. See Bitmap Flags. - Parameters: - DWORD f - - The flags to set. - - - - - Clears the given flags. - - - - - This method returns the number of bits per pixel for each color component. For example a 24-bit TARGA has a MaxRGBLevel() of 8 (8 red, 8 green, and 8 blue). - - - - - Returns the number of bits per pixel in the alpha channel. - - - - - Returns nonzero if this storage uses high dynamic range data; otherwise zero. See the Advanced Topics section ~{ Working With Bitmaps }~ for details on High Dynamic Range bitmaps. - - - - - This method is used to get a pointer to the beginning of the image storage. Not all storage types can return a valid pointer. In those cases, this method will set the passed type to BMM_NO_TYPE and return NULL. - Parameters: - int *bmmType - - The type of storage is returned here. See Bitmap Types. - Default Implementation: - { *bmmType = BMM_NO_TYPE; return (NULL); } - - - - - This method will attempt to get a pointer to the beginning of the image alpha storage. Not all storage types can return a valid pointer. In those cases, this call will fail and the user should use some other method described below. - Parameters: - int *bmmType - - The type of storage is returned here. See Bitmap Types. - Default Implementation: - { *bmmType = BMM_NO_TYPE; return (NULL); } - - Below are the standard methods for accessing image pixels. Important Note: The following "GetPixels()" methods operate on a single scanline of the image at a time. Thus the number of pixels+x must be less than the width of the image. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - This method is used internally. - - - - - Implemented by the System. - - Retrieves the specified 16 bit grayscale pixels from the storage. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - WORD *ptr - - Pointer to storage for the retrieved pixels. - Nonzero if pixels were retrieved; otherwise 0. - - - - - Implemented by the System. - - Stores the 16 bit grayscale pixels to the specified location in the storage. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - WORD *ptr - - Pointer to storage for the pixels. - Nonzero if pixels were stored; otherwise 0. - - - - - Implemented by the System. - - Retrieves the specified 16 bit grayscale pixels from the storage. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - float *ptr - - Pointer to storage for the retrieved pixels. - Nonzero if pixels were retrieved; otherwise 0. - - - - - Implemented by the System. - - Stores the 16 bit grayscale pixels to the specified location in the storage. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - float *ptr - - Pointer to storage for the pixels. - Nonzero if pixels were stored; otherwise 0. - - - - - This method retrieves the specified 64 bit true color pixels from the storage. Pixels returned from this method are NOT gamma corrected. These have linear gamma (1.0). This method operates on a single scanline of the image at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to store. - - *ptr - - Pointer to storage for the pixels. - Nonzero if pixels were retrieved; otherwise 0. - - - - - Retrieves the specified 64-bit pixel values from the bitmap. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixel values. See Structure . - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Stores the specified 64-bit pixel values into the bitmap's own local storage. The pointer you pass to this method may be freed or reused as soon as the function returns. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - *ptr - - Pixel values to store. See Structure . - Returns nonzero if pixels were stored; otherwise 0. If storage has not been allocated 0 is returned. - - - - - This method retrieves the specified 64 bit true color pixels from the storage. Pixels returned from this method are NOT gamma corrected. These have linear gamma (1.0). This method operates on a single scanline of the image at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to store. - - *ptr - - Pointer to storage for the pixels. - Nonzero if pixels were retrieved; otherwise 0. - - - - - Retrieves the specified 64-bit pixel values from the bitmap. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - *ptr - - Pointer to storage for the retrieved pixel values. - Returns nonzero if pixels were retrieved; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Stores the specified 64-bit pixel values into the bitmap's own local storage. The pointer you pass to this method may be freed or reused as soon as the function returns. Note: This method provides access to pixel data one scanline at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - *ptr - - Pixel values to store. - Returns nonzero if pixels were stored; otherwise 0. If storage has not been allocated 0 is returned. - - - - - Implemented by the System. - - Retrieves the specified index color pixels from the storage. This is used to retrieve pixels from a paletted image. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Source x location. - - int y - - Source y location. - - int pixels - - of pixels to retrieve. - - unsigned char *ptr - - Pointer to storage for the pixels. - Nonzero if pixels were retrieved; otherwise 0. - - - - - Implemented by the System. - - Stores the index color pixels to the specified location in the storage. This method operates on a single scanline of the image at a time. - Parameters: - int x - - Destination x location. - - int y - - Destination y location. - - int pixels - - of pixels to store. - - unsigned char *ptr - - Pointer to the pixels to store. - Nonzero if pixels were stored; otherwise 0. - - - - - Adjusts the bitmap size to the specified dimensions. The image is not resized to fit; it is cropped or filled with fillcolor pixels to accommodate the new size. - Parameters: - int width - - The new horizontal size for the bitmap. - - int height - - The new vertical size for the bitmap. - - fillcolor - - If the bitmap's new size is bigger than its current size, this is the color used to fill the new pixels. See Structure . - Nonzero if the image was cropped; otherwise 0. - - - - - Adjusts the bitmap size to the specified dimensions. The image is not resized to fit; it is cropped or filled with fillcolor pixels to accommodate the new size. - Parameters: - int width - - The new horizontal size for the bitmap. - - int height - - The new vertical size for the bitmap. - - fillcolor - - If the bitmap's new size is bigger than its current size, this is the color used to fill the new pixels. See Structure . - Nonzero if the image was cropped; otherwise 0. - - - - - Adjusts the bitmap size to the specified dimensions. The image is not resized to fit; it is cropped or filled with fillindex pixels to accommodate the new size. - Parameters: - int width - - The new horizontal size for the bitmap. - - int height - - The new vertical size for the bitmap. - - int fillindex - - If the bitmap's new size is bigger than its current size, this is the color used to fill the new pixels. - Nonzero if the image was cropped; otherwise 0. - - - - - This method is no longer used. - - - - - Copies the specified bitmap to this storage. The image is cropped to fit. - Parameters: - *from - - The bitmap to copy to this bitmap. - - fillcolor - - The color to use if the source image is smaller than the destination image. See Structure . - Nonzero if the copy/crop was performed; otherwise zero. - - - - - Copies the specified bitmap to this storage. The image is cropped to fit. - Parameters: - *from - - The bitmap to copy to this bitmap. - - fillcolor - - The color to use if the source image is smaller than the destination image. See Structure . - Nonzero if the copy/crop was performed; otherwise zero. - - - - - Implemented by the System. - - This method copies the specified bitmap to this storage. The source bitmap is scaled to fit using a lower quality but faster algorithm than CopyScaleHigh().This is an internal function implemented within BMM.DLL for copying bitmaps back and forth. If a developer creates new storage type, they will automatically get these copy functions as these are implemented in the base class. - Parameters: - *from - - The source bitmap. - Nonzero if the copy/scale was performed; otherwise zero. - - - - - Implemented by the System. - - This method copies the specified bitmap to this storage. The source bitmap is scaled to fit using a higher quality but slower algorithm than CopyScaleLow(). This is an internal function implemented within BMM.DLL for copying bitmaps back and forth. If a developer creates new storage type, they will automatically get these copy functions as these are implemented in the base class. - - - - - Implemented by the System. - - This method copies the specified bitmap to this storage. The source bitmap is scaled to fit using a higher quality but slower algorithm than CopyScaleLow(). This is an internal function implemented within BMM.DLL for copying bitmaps back and forth. If a developer creates new storage type, they will automatically get these copy functions as these are implemented in the base class. - - - - - Copies the specified bitmap to this storage. The image is cropped or resized as specified. - Parameters: - *from - - The source bitmap. - - int operation - - The type of copy to perform: - - COPY_IMAGE_CROP - - Copy image to current map size using cropping if necessary. - - COPY_IMAGE_RESIZE_LO_QUALITY - - Resize the source image to the destination map size (draft quality). - - COPY_IMAGE_RESIZE_HI_QUALITY - - Resize source image to the destination map size (final quality). - - COPY_IMAGE_USE_CUSTOM - - Resize based on the Image Input Options ( *). - - fillcolor - - Vacant areas of the bitmap are filled with fillcolor pixels if the operation specified is COPY_IMAGE_CROP and one of the source bitmap dimensions is less than the size of this bitmap. See Structure . - - *bmInfo - - When using custom options (resize to fit, positioning, etc.) this is how the flags are passed down to the Manager. This is an optional argument - for simple copy operations, *bmInfo can default to NULL. If present, the code checks the option flags and acts accordingly. - Nonzero if the copy was performed; otherwise 0. - - - - - Copies the specified bitmap to this storage. The image is cropped or resized as specified. - Parameters: - *from - - The source bitmap. - - int operation - - The type of copy to perform: - - COPY_IMAGE_CROP - - Copy image to current map size using cropping if necessary. - - COPY_IMAGE_RESIZE_LO_QUALITY - - Resize the source image to the destination map size (draft quality). - - COPY_IMAGE_RESIZE_HI_QUALITY - - Resize source image to the destination map size (final quality). - - COPY_IMAGE_USE_CUSTOM - - Resize based on the Image Input Options ( *). - - fillcolor - - Vacant areas of the bitmap are filled with fillcolor pixels if the operation specified is COPY_IMAGE_CROP and one of the source bitmap dimensions is less than the size of this bitmap. See Structure . - - *bmInfo - - When using custom options (resize to fit, positioning, etc.) this is how the flags are passed down to the Manager. This is an optional argument - for simple copy operations, *bmInfo can default to NULL. If present, the code checks the option flags and acts accordingly. - Nonzero if the copy was performed; otherwise 0. - - - - - Copies the specified bitmap to this storage. - Parameters: - *from - - The source bitmap. - - int operation - - The type of copy to perform. - - COPY_IMAGE_CROP - - Copy image to current map size using cropping if necessary. - - COPY_IMAGE_RESIZE_LO_QUALITY - - Resize the source image to the destination map size (draft quality). - - COPY_IMAGE_RESIZE_HI_QUALITY - - Resize source image to destination map size (final quality). - - COPY_IMAGE_USE_CUSTOM - - Resize based on the Image Input Options ( *). - - int fillindex - - Vacant areas of the bitmap are filled with fillindex pixels if the operation specified is COPY_IMAGE_CROP and one of the source bitmap dimensions is less than the size of this bitmap. - Nonzero if the copy was performed; otherwise 0. - - - - - Retrieves the specified portion of the palette of this storage. - Parameters: - int start - - Zero based index of the first palette entry to retrieve. - - int count - - of palette entries to retrieve. - - *ptr - - Points to storage for the palette values. See Structure . - Nonzero if the palette was retrieved; otherwise 0. - - - - - Sets the specified portion of the palette for this storage. - Parameters: - int start - - First palette index entry to store. - - int count - - of palette entries to store. - - *ptr - - Points to storage for the palette values. See Structure . - Nonzero if the palette was stored; otherwise 0. - Sample Code: - From samples/images/bmp/bmp.cpp - - - - - This method uses summed area table or pyramidal filtering to compute an averaged color over a specified area. - Parameters: - float u, float v - - The location in the bitmap to filter. These values go from 0.0 to 1.0 across the size of the bitmap. - - float du, float dv - - The size of the rectangle to sample. These values go from 0.0 to 1.0 across the size of the bitmap. - - *ptr - - The result is returned here - the average over the specified area. See Structure . - - - - - This method uses summed area table or pyramidal filtering to compute an averaged color over a specified area and outputs to a floating point color structure. - Parameters: - float u, float v - - The location in the bitmap to filter. These values go from 0.0 to 1.0 across the size of the bitmap. - - float du, float dv - - The size of the rectangle to sample. These values go from 0.0 to 1.0 across the size of the bitmap. - - *ptr - - The result is returned here - the average over the specified area. - - - - - Implemented by the System. - - This method is called to allocate image storage. - Parameters: - *pbi - - Points to an instance of the class describing the properties of the bitmap. - - *pmanager - - Points to the for the bitmap. - - int iOpenMode - - See Bitmap Open Mode Types. - Nonzero if storage was allocated; otherwise 0. - - - - - Returns a pointer to specified geometry/graphics buffer channel, and determines its pixel depth. - Parameters: - ULONG channelID - - The channel to return a pointer to. See Image (G-Buffer) ChannelsULONG& chanType - - The type of the returned channel. One of the following values: - - BMM_CHAN_TYPE_UNKNOWN - - Channel not of a known type. - - BMM_CHAN_TYPE_1 - - 1 bit per pixel - - BMM_CHAN_TYPE_8 - - 1 byte per pixel - - BMM_CHAN_TYPE_16 - - 1 word per pixel - - BMM_CHAN_TYPE_32 - - 2 words per pixel - - BMM_CHAN_TYPE_48 - - 3 words per pixel - - BMM_CHAN_TYPE_64 - - 4 words per pixel - - BMM_CHAN_TYPE_96 - - 6 words per pixel - Default Implementation: - { return NULL;} - - - - - Returns a pointer to the G-Buffer associated with this storage. - - - - - Create the specified channels. - Parameters: - ULONG channelIDs - - Specifies the channels to create. See Image (G-Buffer) Channels. - The channels that are present. - Default Implementation: - { return 0;} - - - - - Delete the specified channels. - Parameters: - ULONG channelIDs - - Specifies the channels to delete. See Image (G-Buffer) Channels. - - - - - Returns the channels that are present. See Image (G-Buffer) Channels. - Default Implementation: - { return 0; } - - - - - Output bitmaps can get an instance of the class , which is written by the renderer. This method will allocate an instance only if a doesn't yet exist. - A pointer to a . See Class . - - - - - Returns a pointer. See Class . - - - - - Description: - This is the base class for the development of plug-in Storage plug-ins that use Hight Dynamic Range bitmaps. - - All methods of this class are implemented by the System. - - - - - Description: - This is the base class for the development of plug-in Storage plug-ins that don't use Hight Dynamic Range bitmaps. - - Note that bVirtual is actually a short-cut macro for BMMExport virtual. - - All methods of this class are implemented by the System. - - - - - Description: - This class is an interface into the texture. All methods of this class are implemented by the system. - - - - - The Mono Channel Intensity may be either RGB Intensity or Alpha. - Parameters: - BOOL onoff - - TRUE for Alpha; FALSE for RGB Intensity. - - - - - The Alpha Source may be either from the RGB channels or Image Alpha channel. - Parameters: - BOOL onoff - - TRUE for RGB; FALSE for Alpha channel. - - - - - Changes the name of the bitmap file. - - - Changes the file name of the image to be used. - - - The new file name. - - Should be set to true if and only if the renaming of the file is the result of a action from the user. When this is set to true, the bitmap texture may, for example, display a dialog asking the user whether the map should be cached by the bitmap proxy system. - - - - Change the bitmap file. - - - Changes the asset to be used. - - - The new asset. - - Should be set to true if and only if the renaming of the file is the result of a action from the user. When this is set to true, the bitmap texture may, for example, display a dialog asking the user whether the map should be cached by the bitmap proxy system. - - - - Returns the filter type. - One of the following values: - - FILTER_PYR - - Pyramidal. - - FILTER_SAT - - Summed Area Table. - - FILTER_NADA - - None. - - - - - Returns the alpha source. - One of the following values: - - ALPHA_FILE - - ALPHA_RGB - - ALPHA_NONE - - - - - Returns the end condition setting. - One of the following values: - - END_LOOP - - END_PINGPONG - - END_HOLD - - - - - The Mono Channel Intensity may be either RGB Intensity or Alpha. - Parameters: - BOOL onoff - - This parameter is ignored. - TRUE if Alpha; FALSE if RGB Intensity. - - - - - The Alpha Channel may be either RGB or Image Alpha. - Parameters: - BOOL onoff - - This parameter is ignored. - TRUE for RGB; FALSE for Image Alpha. - - - - - Returns the name of the bitmap file. - - - - - Returns an AssetUser of the bitmap file. - - - - - Returns the start frame setting as a TimeValue. - - - - - Returns the playback rate setting. - - - - - Retrieves a pointer to the interface for this bitmap. This allows access to the mapping parameters such as UV offsets, blur, angle, noise level, etc. - bitmap. This allows access to the mapping parameters such as UV offsets, blur, angle, noise level, etc. - - - - - Returns a pointer to a class to access properties of this texture. - - - - - This will swap the bitmap pointer without updating . - Parameters: - *bm - - A pointer to the bitmap. - Default Implementation: - { } - - - - - Returns a pointer to the associated with this Texture. - Parameters: - TimeValue t - - The time at which to return the bitmap. - - - - - This method brings up a bitmap loader dialog. - Default Implementation: - { return 0; } - - - - - This method forces the bitmap to reload and the view to be redrawn. - Default Implementation: - { return 0; } - - - - - This method reloads the bitmap texture and operates as if the user pressed the reload button. - - - - - This method will view the bitmap texture image and operates as if the user pressed the view image button. - - - - - This method will update the bitmap name and layer information of the texture with the information from the structure - - - - - Description: - This class allows the developer to define a set of bit flags that may be treated as a virtual array and are stored in an efficient manner. The class has methods to set, clear and return the i-th bit, resize the , etc. All methods are implemented by the system. - - - - - Sets the number of bits used. - - - The number of bits in to be in the array. If this value is a negative number, or equal to the current size of the then nothing will happen. - - If passed as 1, the old bit values will be preserved when the array is resized. - - - - Returns the size of the bit array in bits. - - - - - Clears all the bits in the array (sets them to 0). - - - - - Sets all the bits in the array to 1. - - - - - the i-th bit to 1. - - - The array index of the bit to set. - - - - Sets the i-th bit to 0. - Parameters: - int i - - The array index of the bit to clear. - - - - - the i-th bit to b. - - - The index of the bit to set. - - The value to set, either 1 or 0. - - - - Gets the i-th bit. - - - The index of the bit. If the index is a negative or bigger than the array size, it returns 0 - - - - Gets the i-th bit. - - - The index of the bit. If the index is a negative or bigger than the array size, it returns 0 - - - - Returns true if no bits are set; otherwise false. This method is much faster than checking if NumberSet() returns 0. - - - - - how many bits are 1's? use IsEmpty() for faster checks - Returns a proxy object which can optimize client code depending on the type of access required (ie: != 0 would call IsEmpty(), etc) - - - - - This is not currently implemented and is reserved for future use. - - - - - This is not currently implemented and is reserved for future use. - - - - - Reverses the bits in the . - Parameters: - BOOL keepZero = FALSE - - If TRUE the zero bit is kept where it is. - - - - - Rotates the bits in the (with wraparound). - Parameters: - int direction - - The direction to rotate. - - int count - - The number of bits to rotate. - - - - - Shifts the bits in the (without wraparound). - Parameters: - int direction - - One of the following values: - - LEFT_BITSHIFT - - RIGHT_BITSHIFT - - int count - - The number of bits to shift. - - int where=0 - - This indicates where the shift will begin. For example, if you have a containing: 10101010 - - and you Shift(LEFT_BITSHIFT, 1, 4) you'll get: 10100100 - - All the bits from 4 to 8 are shifted one bit left, with zeroes shifted in from the right. The first bit affected is the where bit. If you leave off the where parameter you'd get the usual: 01010100 - - The RIGHT_BITSHIFT starts at that bit; it is unaffected because the operation proceeds to the right: 10101010. - - Shift(RIGHT_BITSHIFT, 1, 4) results in: 10101101. - - - - - This method is used to enumerate all the elements that have a "1" value, and call the callback proc() with the index of the element. - Parameters: - &cb - - The callback object whose proc() method is called. - - - - - This method allows you to delete a selection of elements from this . This is useful, for instance, if you're deleting a set of vertices from a mesh and wish to keep the vertSel and vertHide arrays up to date. - Parameters: - & dset - - This is a bit array which represents which elements should be deleted. Typically (if mult==1) dset will have the same size as (this). - - int mult=1 - - This is a multiplier which indicates how many elements in (*this) are deleted for each entry in dset. For instance, when deleting faces in a mesh, you also need to delete the corresponding edge selection data. Since edgeSel[f*3], edgeSel[f*3+1], and edgeSel[f*3+2] correspond to face f, you'd use mult=3: - - If the bit array has more values than correspond to the size of dset, the extra values will be retained at the end after deleting. The alternate method 'DeleteSetAndResize' will remove the extra values by resizing if needed. - - faceSel.DeleteSet (fdel); - - edgeSel.DeleteSet (fdel, 3); - - - - - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. Due to how they are saved, values need to be saved in their own Chunk. If they are not saved in their own Chunk, and other data values are stored in the same Chunk after the , in some cases the loading of the will try loading the data saved after the , resulting in load failure or incorrect results. In 3dsmax 2026, a warning dialog will be displayed if a is not saved in its own Chunk. If this dialog is displayed, the outer save code should be modified to Begin/End a Chunk around the save. In order to support Save To Previous though, the old behavior may still be required. To handle this, method ISave::DisableChunkWarnings(bool) was added to disable the warning dialog. An example of the Save code usage is: /code The following is writing a , but it was not in its own Chunk prior to 3dsmax 2026 DWORD saveVersion = isave->SavingVersion(); IOResult ioRes; if ((saveVersion != 0) && (saveVersion <= MAX_RELEASE_R27)) { isave->DisableChunkWarnings(true); ioRes = mCategories.Save(isave); isave->DisableChunkWarnings(false); } else { isave->BeginChunk(TargetedIORootNodeCategory_chunkid); ioRes = mCategories.Save(isave); isave->EndChunk(); } /endcode An example of the corresponding Load code would be: /code prior to 3dsmax 2026, mCategories was not stored in its own chunk USHORT chunkID = iload->PeekNextChunkID(); if (chunkID == TargetedIORootNodeCategory_chunkid) { iload->OpenChunk(); mCategories.Load(iload); iload->CloseChunk(); } else mCategories.Load(iload); /endcode - - - - - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - - - - This operator is available in release 3.0 and later only. - - Comparison operator. - Parameters: - & b - - The to compare with this one. - true if the BitArrays are 'equal' (same size and same bits set); otherwise false. - - - - - Assignment operator. - - - - - AND= this with the specified . - - - - - XOR= this with the specified . - - - - - AND two BitArrays - - - - - XOR two BitArrays - - - - - Unary NOT function - - - - - Swap the contents of two bitarrays. - - - This is an efficient way of transfering the contents of a temporary bitarray object into a more permanent instance, such as a data member. For instance: would be more efficient than using operator= in this case. - - The contents of 'other' will be swaped with the contents of 'this' - - - - Description: - This is the callback object for the method BitArray::EnumSet(). The proc method is called for each "1" in the . - - - - - This method is called for each "1" in the . - Parameters: - int n - - This is the zero based index into the of the element which is "1". - - - - - Description: - This class describes a 2D rectangular region using integer coordinates. This class is sub-classed from RECT (from the Windows API). provides methods that return individual coordinates of the box, scale and translate it, retrieve its center, modify its size, expand it to include points or other boxes, and determine if points are inside the box. All methods are implemented by the system. - - - - - Determines whether the box has been '' (see below). When a box is created using the default constructor it is set to 'empty'. - true if the box is empty; false otherwise. - - - - - Sets the box to 'empty'. This indicates the box has not had specific values set by the developer. - - - - - Adjusts the coordinates of the box such that top<bottom and left<right. - - - - - Scales the coordinates of the box about the center of the box. - Parameters: - float f - - Specifies the scale factor. - - - - - Translate the box by the distance specified. - Parameters: - t - - The distance to translate the box. - - - - - Returns the center of the box (the midpoint between the box corners). - - - - - Returns the minimum x coordinate of the box. - - - - - Returns the minimum y coordinate. - - - - - Returns the width of the box. - - - - - Returns the height of the box. - - - - - Sets the box width to the width specified. The 'right' coordinate is adjusted such that: - - right = left + w -1 - Parameters: - int w - - The new width for the box. - - - - - Sets the height of the box to the height specified. The 'bottom' coordinate is adjusted such that: - - bottom = top + h -1; - Parameters: - int h - - The new height for the box. - - - - - Sets the left coordinate of the box to x. - Parameters: - int x - - The new value for the left coordinate. - - - - - the top coordinate to y. - Parameters: - int y - - The new value for the top coordinate. - - - - - Sets both the width and height of the box. - Parameters: - int w - - The new width for the box. - - int h - - The new height of the box. - - - - - Sets both the left and top coordinates of the box. - Parameters: - int x - - The new left coordinate. - - int y - - The new top coordinate. - - - - - Assignment operators. Copies the specified source RECT into this object. - - - - - Expands this to completely include box b. - - - - - Expands this to include point p. - - - - - Equality operator. Determines whether b is equal to this box. Returns true if the boxes are equal; false otherwise. - - - - - Inequality operator. Determines whether b is different from this box. Returns true if the boxes are different. - - - - - Determines if the point passed is contained within the box. Returns true if the point is inside the box; otherwise false. - - - - - Intersection test between a line and a rectangle. Returns true if they intersect. - Parameters: - int x0 - - Line start x coordinate. - - int y0 - - Line start y coordinate. int x1 - - Line end x coordinate. - - int y1 - - Line end y coordinate. - - - - - - - Description: - A 2D floating-point box class. This class has methods and operators to clear the box, and update its size (bounding rectangle) by specifying additional points. All methods of this class are implemented by the system. - Data Members: - BOOL empty; - - Indicates if the box is empty. When the += operator is used to update the size of the box, if the box is empty, the box corners are set to the point. - - min, max; - - The corners of the 2D box. - - - - - Sets the box to an empty status. - Operators: - - - - - Expand this box to include p. If this box is empty, the box corners are set to the point p. - Parameters: - & p - - This box is expanded to include p. - - - - - Description: - This class represents a 3D box volume described by two 3D corner coordinates. provides methods that return individual coordinates of the box, scale and translate it, retrieve its center, modify its size, expand it to include points or other boxes, and determine if points are inside the box. All methods are implemented by the system. - Data Members: - pmin,pmax; - - The corners of the 3D box. - - - - - Initializes this box such that pmin is a very large value while pmax is a small value. Thus the box is 'empty' and 'uninitialized'. See IsEmpty() and IsInitialized(). - - - - - Modifies this box such that half the side length is subtracted from pmin and added to pmax. This creates a cube with the specified center p and side length side. - Parameters: - & p - - Specifies the center point of the cube. - - float side - - Specifies the side length. - - - - - Returns the value of corner pmin. - - - - - Returns the value of corner pmax. - - - - - Returns the center of this as a . - - - - - Returns the width of the box as a . This is pmax-pmin. - - - - - Operator[] returns the 'i-th' corner point: - - Mapping : X Y Z - - [0] : (min,min,min) - - [1] : (max,min,min) - - [2] : (min,max,min) - - [3] : (max,max,min) - - [4] : (min,min,max) - - [5] : (max,min,max) - - [6] : (min,max,max) - - [7] : (max,max,max) - Parameters: - int i - - Specifies the corner to retrieve (0 <= i <= 7) - The 'i-th' corner point as a . - - - - - Expands this to include the p. - Parameters: - & p - - Specifies the point to expand the box to include. - - - - - Expands this to include the b. - Parameters: - & b - - Specifies the to expand this box to include. - - - - - Scales this box about its center by the specified scale. - Parameters: - float s - - Specifies the scale factor for this . - - - - - Translates this box by the distance specified. The point is added to each corner. - Parameters: - &p - - Specifies the distance to translate the box. - - - - - Enlarges this box. A is created from s as and added to pmax and subtracted from pmin. If the box is 'empty', the box is centered at (0,0,0) and then enlarged. - - - - - Returns a box that bounds the 8 transformed corners of the input box. - Parameters: - & tm - - Specifies the matrix to transform the box corners by. - - - - - Equality operator. Determines whether b is equal to this box. Returns nonzero if the boxes are equal; 0 otherwise. - - - - - Inequality operator. Determines whether b is different from this box. Returns true if the boxes are different. - - - - - Determines if the box is empty. A box is considered empty if any component value of pmin is greater than the corresponding component value of pmax. - true if the box is empty; otherwise false. - - - - - Determines if the box is initialized. This indicates the box has had specific values set by the developer. - true if the box is initialized; otherwise false. - - - - - Determines if the specified point p is contained in this box. - Parameters: - & p - - Specifies the point to check. - true if the specified point is contained in this box; otherwise false. - - - - - Determines if the specified is contained totally within this box. - Parameters: - & b - - Specifies the box to check. - true if the specified box is entirely contained within this box; otherwise false. - Operators: - - - - - Determines if the specified intersects this box. - Parameters: - & b - - Specifies the box to check. - true if the specified intersects this box; otherwise false. - Operators: - - - - - Determines if the triangle specified by the tree points vert0, vert1, vert2 is overlapping with this box. - true if the specified triangle overlaps with this box in some way; otherwise false. - - - - - Description: - This is a class developer can use to provide a box gizmo helper object for their plug-ins. It provides implementations of all the required methods. The following #defines are used to access the parameters from the pblock pointer of the base class . - - The ClassID for this class is defined as: BOXGIZMO_CLASSID - - - - - This class provides a bounding box and a matrix. It will compute a bounding box based on a set of points passed to it after these points have been transformed by the matrix. All methods of this class are implemented by the system. - - - - - - Returns the computed box. - - - - - Description: - This class provides methods that access properties of the IO module. All methods of this class are implemented by the system. - - - - - Returns the short description string for the IO module, and optionally sets it to d if it is not NULL. - Parameters: - const MCHAR *d = NULL - - The short description string to set. - - - - - Returns the long description string for the IO module, and optionally sets it to d if it is not NULL. - Parameters: - const MCHAR *d = NULL - - The long description string to set. - - - - - Returns the specified IO module file name extension, and optionally sets it to e if it is not NULL. - Parameters: - int index - - The index of the extension. - - const MCHAR *e = NULL - - The extension string. - - - - - Returns the number of file name extensions for the IO module. - - - - - Returns the class descriptor for the IO module. - - - - - Returns the capabilities flag for the IO module. - See BitmapIO Capability Flags - - - - - Tests the capability flags passed. - Parameters: - DWORD cap - - See BitmapIO Capability Flags. - TRUE if the flags were set; otherwise FALSE. - Operators: - - - - - Assignment operator. - - - - - This class is used for storing a linked list of Bitmap Manager objects. It provides methods for working with IO module devices derived from . All methods of this class are implemented by the system. - - - - - - - - Sets the state to indicate the list of IO modules has been built. - Parameters: - BOOL f - - TRUE to indicate the list exists; otherwise FALSE. - - - - - Indicates if the list of IO modules has been built. Returns TRUE if it has; otherwise FALSE. - - - - - Scans the list searching for a match for the description string passed. - Parameters: - const MCHAR *name - - The long description string of the device to find. - The index in the IO list of the device. If not found, -1 is returned. - - - - - This method scans the IO module list searching for a match for the extension in the filename passed. - Parameters: - const MCHAR *name - - The filename to check. - The index in the list of IO modules or -1 if not found. - - - - - Given a record, this method finds the device responsible for this image. If bi.Name() is empty, a device is listed in bi.Device(). In that case we simply use the FindDevice() function which returns an index to the device based on a given device name. - - If bi.Name() isn't empty, it means this is a file and we must search for a device based on a filename. For that we use FindDeviceFromFilename(). If we find a device, we take the opportunity to fill in the device name in the record (using SetDevice()). - Parameters: - *bi - - The for the image whose device you wish to find. - The index in the list of IO modules or -1 if not found. - - - - - Returns the capability flags of the device whose long description string is passed. - Parameters: - const MCHAR *name - - The long description flag. - See BitmapIO Capability Flags. - - - - - This creates an instance of the device plug-in class by calling Create() on the class descriptor. Make sure to delete the instance after use. - Parameters: - const MCHAR *d - - The long description string. - A pointer to an instance of the IO module. - - - - - This creates an instance of the device plug-in class by calling Create() on the class descriptor. Make sure to delete the instance after use. - Parameters: - int idx - - The index in the IO module list of the device. - A pointer to an instance of the IO module. - - - - - Exception thrown when calling a scripted function with less than 256k program call stack remaining. - - - - - Represents the projection matrix and common properties of a perspective or orthographic camera. - - - - - Initializes the camera with a perspective view given a field-of-view value and aspect ratio. - - - - - Initializes the camera with a orthographic view. - - - - - Sets the camera clipping hither and yon values. - - - - - Returns the type of camera whether it is a perspective camera (PERSP_CAM) or orthographic camera (ORTHO_CAM) - - - - - Returns the clipping hither value - - - - - Returns the clipping yon value - - - - - Resets the projection matrix. - - - - - This is a base class from which camera plug-ins may be derived. Methods of this class are used to get and set properties of the camera. All methods of this class are virtual. To ensure that the camera has a valid targDist during network rendering, be sure to call UpdateTargDistance( TimeValue t, INode* inode ); This call should be made PRIOR to cameraObj->EvalWorldState(). - - - - - This method is called to update the and validity interval at the specified time. - The view vector and 'up' vector for the camera are stored with the matrix transform for the node. Cameras can be multiple-instanced so it must work this way. To get at this matrix use the following method from Class : The scaling of this matrix may be removed by normalizing each of the rows. - REF_SUCCEED if the camera state was updated successfully; otherwise REF_FAIL. - - Specifies the time to evaluate the camera. - The plug-in computes the validity interval of the camera at the specified time and stores the result here. - The camera state to update. See Structure . - - - - Sets whether the camera is on ortho mode or not. - - Pass TRUE for ortho and FALSE for not ortho. - - - - Returns TRUE if the camera is in ortho mode and FALSE if it is not. - - - - - Sets the field-of-view of the camera at the specified time. - - The time at which to set the field-of-view. - The value to set in radians. - - - - Returns the field-of-view setting of the camera at the specified time and the validity interval passed is updated with the validity interval of this parameter. - The field-of-view of the camera in radians. - - The time to retrieve the field-of-view setting. - The validity interval to set. - - - - Returns the field-of-view setting of the camera at the specified time. - The field-of-view of the camera in radians. - - The time to retrieve the field-of-view setting. - - - - Sets the target distance setting (for free cameras) at the specified time. - - The time at which to set the target distance. - The value to set. - - - - Returns the target distance setting of the camera at the specified time and adjusts the validity interval of the camera to reflect the target distance parameter. - The target distance of the camera. - - The time to retrieve the target distance setting. - This validity interval is intersected with the validity interval of the target distance parameter. - - - - Returns the target distance setting of the camera at the specified time. - The target distance of the camera. - - The time to retrieve the target distance setting. target distance parameter. - - - - Returns the manual clip flag. This indicates the camera will perform clipping at its hither and yon distances. - Nonzero if manual clipping is enabled; otherwise 0. - - - - - Retrieves the clipping distance of the specified plane at the specified time and modifies the validity interval to reflect the setting of the clipping distance parameter. - The clipping distance. - - The time to retrieve the clipping distance. - Indicates which distance to return. One of the values in - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Retrieves the clipping distance of the specified plane at the specified time. - The clipping distance. - - The time to retrieve the clipping distance. - Indicates which distance to return. One of the values in - - - - Sets the clipping distance of the specified plane at the specified time. - - The time to set the clipping distance. - Indicates which distance to set. One of the values in - The distance to set. - - - - Sets the environment range distance at the specified time. - - The time to set the environment range. - Indicates which distance to set. One of the values in - The distance to set. - - - - Retrieves the environment range distance at the specified time and intersects the specified validity interval with the interval of the environment range parameter. - The environment range distance at the specified time. - - The time to retrieve the environment range. - Indicate which distance to set. One of the values in - The validity interval that this method will update to reflect the environment range setting. - - - - Retrieves the environment range distance at the specified time. - The environment range distance at the specified time. - - The time to retrieve the environment range. - Indicate which distance to set. One of the values in - - - - Sets the environment range display flag. This indicates if the camera will display its range settings. - - The flag state to set. - If notify is TRUE, dependents of this message are sent the message using NotifyDependents(FOREVER, PART_OBJ, REFMSG_CHANGE); Otherwise no notification is sent. - - - - Retrieves the environment range display setting. - TRUE if ranges are displayed; otherwise FALSE. - - - - - This method is called on all cameras when the render aperture width has changed. - - The time of the change. - - - - This method is called on all target cameras when the target distance has changed. For instance, a distance shown in the user interface may be updated in this method. - - The time of the change. - The camera node. - - - - Enables or disables the multi-pass effect. - - The time at which to enable the effect. - TRUE for enabled; FALSE for disabled. - - - - Returns the enabled or disabled state of the multi-pass effect setting for the camera. - TRUE for enabled; FALSE for disabled. - - The time at which to get the setting. - The validity interfal for the setting. - - - - Returns a pointer to the current multi-pass camera effect. See Class . - - - - - Compares this class instance to another one - - - - - Compares this class instance to another one - - - - - Description: - The purpose of this callback is to call INode::FlagForeground() for any nodes in the scene that are supposed to be in the foreground. - - - - - Description: - Implemented by the System (for Render plug-ins inside the Effect::Apply() method). - - The Check() method of this class may be called to check if the user did something to abort the application of the effect. - - - - - Returns TRUE if user has done something to cause an abort; otherwise FALSE. - - - - - This method is should be called by each plug-in as it proceeds through the image to update the progress bar. - Parameters: - int done - - The amount done, i.e. the current state of the image processsing. This is usually the number of scan lines processed so far. - - int total - - The total number of updates. This is usually the number of pixels in height of the image. - Returns TRUE if user has done something to cause an abort; otherwise FALSE. - - - - - This method is called internally by the calling code - plug-ins don't need to call this method. - - - - - Class descriptors provide the system with information about the plug-in classes in the DLL. The developer creates a class descriptor by deriving a class from (which derives from ) and implementing several of its methods. - - - - - 3ds Max calls this method when it needs a pointer to a new instance of the plug-in class. For example, if 3ds Max is loading a file from disk containing a previously used plug-in (procedural object, modifier, controller, etc...), it will call the plug-in's Animatable::Create() method. The plug-in responds by allocating a new instance of its plug-in class. See the Advanced Topic section on ~{ Memory Management }~ for more details. - - This parameter is a flag indicating if the class being created is going to be loaded from a disk file. If the flag is TRUE, the plug-in may not have to perform any initialization of the object because the loading process will take care of it. See the Advanced Topics section on ~{ Loading and Saving Plug-in Data }~ for more information. Note: If this parameter is TRUE, developers must initialize their references to NULL. Otherwise 3ds may crash. 3ds provides a default plug-in object creation process. Many plug-ins fit this form. When the system is about to create an instance of the plug-in object it calls a method .This method returns a callback object whose proc() method handles the mouse input during its creation phase. Most of the work is then handled by the system. The procedural sphere is an example of this type of plug-in. Certain plug-ins may have special creation needs however. The target camera is an example of such a plug-in. Because it needs to create two nodes in the scene (the camera and the target) it requires a custom creation process. To support these plug-ins the following two methods are provided. They allow the plug-in to manage the creation process themselves. See ~{ Creation Methods }~ for more details. - - - - The custom creation process of the plug-in object is handled by this method. For example, a plug-in can create a custom command mode and push it on the command stack to handle the creation process. - - Important Note: A plug-in that doesn't want to participate in the standard object creation mechanism using must push a on the stack in this method and remove it in EndCreate(). This is true even if the plug-in doesn't do anything inside the mode. A mode has to be pushed on the stack and then later popped off otherwise a crash will occur (if the default implementation of this method is not used). For more details on object creation see the Advanced Topics section ~{ Creation Methods }~. - To use the default creation process (the system implementation for this method) return 0; Return nonzero if the plug-in implements this method. - - An interface pointer the plug-in may use to call functions in 3ds . - - - - The termination of the custom creation process is managed by the implementation of this method. For example, the plug-in could remove a custom command mode from the command stack. See the Advanced Topics section on ~{ Creation Methods }~ for more details. - To use the system implementation for this method return 0; Return nonzero if the plug-in implements this method. - - An interface pointer the plug-in may use to call functions in 3ds . - - - - This method is used to enable or disable the button that allows the plug-ins class to be created. For example, at certain times it is not appropriate to for the object to be created. When there is not an object of the appropriate type selected the object cannot be created. At these times the button should be disabled (the button will appear as grayed out in the Create branch of the command panel). The button should be enabled if there is an object of the appropriate type selected. This method allows a plug-in to control the state of the button. - TRUE to enable the class creation button; FALSE to disable it. - Sample Code: - The following code from /MAXSDK/SAMPLES/OBJECTS/BOOLOBJ.CPP demonstrates an implementation of this method. If there is not a node selected, it is not OK to use the command so the button should appear disabled. To disable the button OkToCreate() returns FALSE. If the object that is selected is not of the appropriate type it the button is disabled as well - - An interface pointer the plug-in may use to call functions in 3ds . - - - - If a plug-in class has default parameters that it needs to allow the user to edit, TRUE should be returned and EditClassParams() and ResetClassParams() should be implemented. Otherwise return FALSE (the default). - - - - - If the user picks the class from the list this method is called. The plug-in should put up a modal dialog that allows the user to edit the plug-ins default parameters. The plug-in should not return until the user has finished editing the parameters. - - The parent window handle. - - - - When the user executes File / Reset or presses the 'Reset to Factory Settings...' button in the File / Preferences... / Animation tab / Controller Defaults section this method is called. The plug-in can respond by resetting itself to use its default values. - - When TRUE, the user has performed a File / Reset operation. When FALSE, the user is in the Preferences... dialog doing a reset controller defaults operation. - - - - 3ds Max calls this to get the number of action tables a plug-in has. If more than one class uses the table only one of the classes should export the table, but they can all use them. - - - - - Returns a pointer to the specified action table. - Ownership of the is transferred to 3ds Max when this function is called, and it should not be deleted by the plug-in. - - The zero based index of the table to return. - - - - Returns TRUE if the class implements a manipulator object; otherwise FALSE. - - - - - The method returns true if the class is a manipulator and it manipulates the given base object, modifier or controller. When starting "Manipulate" mode, this is called on selected nodes for the base object, all modifiers, the TM controller and the position, rotation and scale controllers, if the TM controller is a PRSController. - - A pointer to a reference target. - - - - Returns TRUE if the manipulator applies to the given node; otherwise FALSE. This method can be used to indicate that the manipulator works on a part of an object that is not covered by BOOL CanManipulate(ReferenceTarget* hTarget) such as the visibility controller of a node. - - The to check. - - - - Creates a manipulator object When a manipulator returns TRUE to CanManipulate(ReferenceTarget* hTarget), the system calls this version of CreateManipulator() to create an instance of the manipulator. - - Pointer to the newly created manipulator, or NULL if the creation failed. - - - The for which a manipulator is requested - - The node that the manipulator needs to manipulate (know about) - - - - Creates a manipulator object. When a manipulator returns TRUE to CanManipulateNode(INode* pNode), the system calls this version of CreateManipulator() to create an instance of the manipulator. - - Pointer to the newly created manipulator, or NULL if the creation failed. - - - The node that the manipulator needs to manipulate (know about) - - - - Returns TRUE if there is data associated with the class that needs to be saved in the 3ds Max file. If this is so, implement the Save() and Load() methods below. If there is no class data to save return FALSE. - - - - - If NeedsToSave() returns TRUE then this method should be implemented to save the data associated with the class. - IO_OK if the save was successful; otherwise IO_ERROR. - - A pointer that may be used to call methods to save data to disk. - - - - If NeedsToSave() returns TRUE then this method should be implemented to load the data associated with the class. - IO_OK if the load was successful; otherwise IO_ERROR. - - A pointer that may be used to load data from a file. - - - - Returns the number or ParamBlockDesc2s used by the plug-in. - - - - - Returns a pointer to the 'i-th' parameter block 2 descriptor. - - The zero based index of the descriptor to return. - - - - Implemented by the System. - - Returns a pointer to the specified parameter block 2 descriptor. - - The ID of the parameter block. - - - - Implemented by the System. - - Adds the specified parameter block 2 descriptor to the list of those maintained by the class. - - Points to the parameter block 2 descriptor to add. - - - - Implemented by the System. - - This method is called to handle the beginning of the automatic command panel user interface management provided by the param map 2 system. This method is called by the plug-in from its Animatable::BeginEditParams() method. The parameters passed to that method are simply passed along to this method. - - The interface pointer passed to the plug-in. - Points to the plug-in class calling this method. - The flags passed along to the plug-in in . - The pointer passed to the plug-in in . - - - - This method is called to handle the ending of the automatic command panel user interface management provided by the param map 2 system. This method is called by the plug-in from its Animatable::EndEditParams() method. The parameters passed to that method are simply passed along to this method. - - The interface pointer passed to the plug-in. - Points to the plug-in class calling this method. - The flags passed along to the plug-in in . - The pointer passed to the plug-in in . - - - - Invalidates the user interface for the rollup or dialog managed by the specified descriptor. This will cause the controls in that rollup to be redrawn. - - Points to the parameter block 2 descriptor whose corresponding is invalidated. - - - - Returns the number of parameter map2s used by the plug-in. - - - - - Returns a pointer to the nth parameter map2. - - The zero based index of the parameter map2 to return. - - - - Returns a pointer to the parameter map2 whose descriptor is passed. - - Points to the parameter block2 descriptor. - - - - Sets the parameter map 2 user dialog proc for the specified descriptor. Returns true if the proc was registered with a parameter map. If the proc was not registered with the parameter map, DeleteThis() will not be called on proc when the user dialog procs are cleared, potentially resulting in leakage of the proc. - - Points to the parameter block 2 descriptor. - This object manages user interface control that require special processing. - - - - Returns a pointer to the parameter map 2 user dialog proc (if any) for the specified descriptor. - See Class . - - Points to the parameter block 2 descriptor. - - - - Allows a plug-in to provide a custom image for display in Schematic . - TRUE if this class can draw an image to represent itself graphically; otherwise FALSE. - - The background color. See . - The handle for the device context. - The rectangle to draw in. - - - - Returns the number of function publishing interfaces maintained by the class descriptor. - - - - - Returns the nth function publishing interface. - - - - - Returns a pointer to the function publishing interface whose ID is specified. - - The inteface ID. - - - - Returns a pointer to the function publishing interface whose name is specified. - - The name of the interface. - - - - Adds the specified interface to the list maintained by this class descriptor. - - Points to the interface to add. - - - - Deletes all the interfaces maintained by the class descriptor. - - - - - This function is maintained so the 3ds Max SDK can be extended without breaking backwards compatibility. The behavior of this function depends on the cmd parameter: - - - - - Controls if the plug-in shows up in lists from the user to choose from. - If the plug-in can be picked and assigned by the user, as is usually the case, return TRUE. Certain plug-ins may be used privately by other plug-ins implemented in the same DLL and should not appear in lists for user to choose from. These plug-ins would return FALSE. - - - - - This method returns the name of the class. This name appears in the button for the plug-in in the 3ds Max user interface. - The name of the class. - - - - - This method returns the non-localized name of the class. This method was added in 3ds Max 2022 to provide more consistent scripting behavior in localized versions of 3ds Max. In versions of 3ds Max prior to 2022, MAXScript used the name returned from ClassName() (unless UseOnlyInternalNameForMAXScriptExposure() returns true) as (one of) the global variable name(s) holding the value which exposes this class. In 3ds Max 2022 and later, MAXScript uses the name returned from NonLocalizedClassName() (unless UseOnlyInternalNameForMAXScriptExposure() returns true) as (one of) the global variable name(s) holding the value which exposes this class. To maintain scripting compatibility with older versions of 3ds Max, the name returned should be the ClassName returned for locale en-US in versions of 3ds Max prior to 2022. - The non-localized name of the class. - - - - - Returns a string which provides a fixed, machine parsable internal name for the plug-in. This name is used by Scripting Engines. MAXScript uses this name (if not null) as (one of) the global variable name(s) holding the value which exposes this class. - - - - - This method returns a system defined constant describing the class this plug-in class was derived from. For example, the Bend modifier returns OSM_CLASS_ID. This super class ID is used by all object space modifiers. See Super Class IDs. - The SuperClassID of the plug-in. - - - - - This method must return the unique ID for the object. If two ClassIDs conflict, the system will only load the first one it finds. The ClassID consists of two unsigned 32-bit quantities. The constructor assigns a value to each of these, for example (0xA1C8E1D1, 0xE7AA2BE5). A developer should use the random generator to avoid conflicts (Generate a random ). See Class for more information. - The unique ClassID of the plug-in. - - - - - This methods returns a string describing the category a plug-in fits into. The category is usually selected in the drop down list in the create, or utility branch of the command panel. In the create branch, if this is set to be an existing category (i.e. "Standard Primitives", "Splines", ...) then the plug-in will appear in that category. If the category doesn't yet exists then it is created. If the plug-in does not need to appear in the list, it may simply return a null string as in _M(""). In the modify branch, the category determines which group it appears in the Configure Button Sets / Modifiers list. These are the categories such as "MAX STANDARD", "MAX EDIT", and "MAX SURFACE". - - This method is also used to distinguish between the various types of texture maps so they can be separated in the Material/Map Browser. The appropriate string should be returned by this method of the . For example: - The options for texture maps are: - - - - - This method returns a DWORD which is used to initialize the rollup state in both the create branch and the modify branch. The semantics are different, however for these two cases. Whenever the rollups are created in the create branch, their state will be that specified by this method. In the modify branch, the first time an object of this type is modified the state will be that of this method, but after that it will remain what it was last set to. - The bits of this DWORD set indicate the corrresponding rollup page is closed. The zero bit corresponds to the plug-ins first rollup, the first bit is the second rollup, etc. The value 0x7fffffff is returned by the default implementation so the command panel can detect this method is not being overridden, and just leave the rollups as is. - - - - - Returns true if only the InternalName is to be used for MAXScript exposure. For older plugins that did not previously implement InternalName but now do, MAXScript still needs to expose the plugin using the ClassName. But new plugins can be exposed using only the InternalName. - - - - - Returns the DLL instance handle of the plug-in. This is used so that string resources can be loaded by the ParamBlock2 system. - - - - - Returns a pointer to the string from the resource string table. - if the resource ID value is 0, a blank string is returned. If the resource ID value cannot be found, the string ">>> @!&*# <<<" is returned. - - The resource ID. - - - - This method creates the automatic parameter blocks for the specified plug-in. These are the ones with the P_AUTO_CONSTRUCT bit set on the ParamBlockDesc2::flags value. - - Points to the owner of the parameter block. - - - - This method can be used for further categorizing plugins. If a plugin has sub-plugins (like light > shadows, particles > operators), this method can be used to differentiate them. sub-plugins can be derived from but return a particular class ID published by the parent plugins SDK headers. Then parent plugin can get a list of all reference targets whose SubClassID matches the published SubClassID. - - - - - Description: - A subclass of which you specialize to provide a class descriptor for plug-in classes that will use the ParamBlock2 system. It contains a table of ParamBlockDesc2s for all the parameter blocks used in the plug-in and a number of sets of methods including access to the block descriptors, auto user interface management, auto param block2 construction, and access to any automatically-maintained ParamMap2s. - - - - - Returns a pointer to the parameter block2 descriptor as specified by the descriptor's internal name. - - The internal name of the parameter block descriptor. - - - - Implemented by the System. - - Removes all the parameter block 2 descriptors maintained by this plug-in. - - - - - Implemented by the System. - - This invalidates the entire UI for every parameter map of the plug-in. - - - - - Implemented by the System. - - This is called if a certain user interface parameter of the specified parameter map needs to be updated. The parameter ID of the control is passed. If the parameter is a <> then the index into the table of the parameter is passed. - - Points to the parameter block descriptor for the rollup. - The permanent parameter ID of the parameter. - If the parameter is a <> then this is the zero based index into the table. The default value of -1 indicates it is not a table. - - - - Implemented by the System. - - This is a method of the base class . This class provides an implementation of the method used by plug-ins using the ParamBlock2 system. - - Returns a pointer to the parameter map2 as specified by the parameter block2 pointer passed. - - Points to the parameter block descriptor2 associated with this parameter map. - This parameter specifies the ID of the map/rollout to get. - - - - This overload of SetUserDlgProc() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to set the user dialog proc for. See original function for the rest of the description. - - - - - Implemented by the System. - - This is a method of the base class . This class provides an implementation of the method used by plug-ins using the ParamBlock2 system. - - Returns a pointer to the user dialog proc associated with the parameter map as specified by the parameter block descriptor2 pointer. - - Points to the parameter block descriptor for the parameter map. - Specifies the ID of the map/rollout to get the user dialog proc for. - - - - Implemented by the System. - - This method creates and returns a pointer to the object which handles the automatic processing of the user interface in the materials editor. This method loops over all parameter blocks which specify AUTO_UI and makes the AutoMParamDlgs for them. The first one becomes the main and the others are added to it. - - The window handle of the materials editor. - The interface pointer provided for calling methods in 3ds . - Points to the plug-in class calling this method. - - - - Implemented by the System. - - This method creates and returns a pointer to the object which handles the automatic processing of the user interface in the materials editor. This method makes an AutoMParamDlg for the specified parameter block. - - The permanent ID of the parameter block. - The window handle of the materials editor. - The interface pointer provided for calling methods in 3ds . - Points to the plug-in class calling this method. - Specifies the ID of the map/rollout in the parameter block to create AutoMParamDlg for. - - - - Implemented by the System. - - This method creates and returns a pointer to the object which handles the automatic processing of the user interface in the rendering effects dialog. This method loops over all parameter blocks which specify AUTO_UI and makes the AutoMParamDlgs for them. The first one becomes the main and the others are added to it. - - The interface pointer provided for calling methods in 3ds . - Points to the plug-in class calling this method. See Class . - - - - Creates the automatically-managed parameter dialogs defined with the P_AUTO_UI or P_AUTO_UI_QT flags in the parameter block descriptors. - - - This method should generally be called from Renderer::CreateParamDialog(). - The newly created dialog. - - The interface passed to . - The renderer for which the dialogs are being created. - - - - Creates the automatically-managed parameter dialog for the given parameter block and parameter map only - - - - - Implemented by the System. - - This method creates and returns a pointer to the object which handles the automatic processing of the user interface in the rendering effects dialog. This method makes an AutoEParamDlg for the specified parameter block. - - The permanent ID of the parameter block. - The interface pointer provided for calling methods in 3ds . - Points to the plug-in class calling this method. See Class . - Specifies the ID of the map/rollout in the parameter block to create AutoEParamDlg for. - - - - Implemented by the System. - - This method is called when an AutoMParamDlg is deleted. - - Pointer to the object which handles the automatic processing of the user interface in the materials editor. - - - - Implemented by the System. - - This method is called when an AutoEParamDlg is deleted. - - Pointer to the object which handles the automatic processing of the user interface in the rendering effects dialog. - - - - Used internally. Called by the implementation of to un-register itself with the class descriptor. - - - - - Implemented by the System. - - Returns the main dialog processing routine for the materials editor plug-in. - - - - - Implemented by the System. - - Returns the main dialog processing routine for the rendering effects plug-in. - - - - - This method may be called to restore any saved rollout state (open/closed condition and scrolling position) for any parameter map maintained by the plug-in. - - - - - This method scans all the parameter blocks in the owner and returns the ParamID and parameter block making the most recent change notification. - The parameter ID of the parameter which made the most recent notification. - - The owner of the parameter blocks. - The parameter block which made the most recent notification. - - - - This method may be called to reset all the parameters of all known parameter blocks to their default values and optionally update the user interface. - - The owner of this . - If TRUE to user interface is updated. If FALSE it's not. - TRUE to call for all the parameters; otherwise FALSE. - - - - This method updates the validity interval passed with the cumulative validity interval of all the owner's parameter blocks. - - The owner of this . - The time about which to compute the interval. - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Implemented by the System. - - Removes a parameter block descriptor from the list of those maintained by this class descriptor, but does not delete it. This method would typically be used when a is dynamically created and its life cycle is controlled by the plugin. You would then be able to remove the parameter block descriptor from the class descriptor when no instances of the plug-in require it. - - A pointer to the parameter block descriptor to remove. - - - - This class represents the directory of all plug-in classes known to the system. The plug-in classes are grouped by super class id. The set of classes in each superclass group can be accessed. For each plug-in class, its can be then retrieved. All plug-in classes must have one of the super class ids pre-defined in the 3ds Max SDK. See Super Class IDs for a list of these super class ids. All methods of this class are implemented by the system. Clients can retrieve the sole instance of via DllDir::ClassDir() or via ClassDirectory::GetInstance() - - - - - Accesses a instance that corresponds to all plug-in classes of a certain super class id. - - - The super class ID - - - - Returns the number of instances in the class directory. - - - - - Accesses the i-th . - - - Specifies which sub class list to access. Must be in the range [0 and -1]. - - - - Returns a class descriptor that corresponds to a certain super and class id combination. - - - The super class id - - The class id - - - - Returns a class entry that corresponds to a certain super and class id combination. - - - The super class id - - The class id - - - - Allows for providing additional UI related information pertaining to a superclass. Currently this includes a descriptive string, a color, and a method which draws a representative image in a Windows DC. - - Returns true if successful or false if the superclass was not found. - - - The super class id the info pertains to - - A pointer to a object that carries the information - - - - Retrieves additional UI related information for a given superclass. - - Returns NULL if the superclass was not found or if no superclass information was assigned. - - - The super class id - - - - This class wraps a instance and maintains run-time related information about it. One class instance for each is created by 3ds Max and stored in the . The maintains information such as the usage count, rollout state etc. All methods of this class are implemented by the system. Client code can access instance via ClassDirectory::FindClassEntry() or various methods of class . - - - - - Returns the index of the plug-in dll that exposes the wrapped by this instance. - - - - - Returns nonzero if the class is public; otherwise zero. Non-public classes are those that are meant for private use by other plug-ins. - - - - - Returns the of the wrapped . - - - - - Returns the class name of the wrapped . - - - - - Returns the non-localized class name of the wrapped . - - - - - Returns the category for the wrapped . - - - - - Returns the number of instance of this class used in 3ds Max. - - - - - Returns nonzero if this entry matches the specified access type; otherwise zero. - - - One of the following values: ACC_PUBLIC - public classes, ACC_PRIVATE - non-public classes - - - - Returns true if the wrapped is loaded, false if it's defer loaded. - - - - - Returns the index of the wrapped class descriptor within the plug-in Dll - - - - - Returns a pointer to the wrapped class descriptor. If the class descriptor corresponds to a defer loaded plug-in, 3ds Max will load that plug-in automatically as soon as it's needed. Developers to not need to load the plug-in themselves. - - - - - Force the plug-in Dll that exposes the wrapped to load and returns a pointer to the wrapped and loaded class descriptor. As of 3ds Max 2012, FullCD() doesn't have to be called to ensure that the wrapped is loaded. 3ds Max loads the class descriptor on demand as soon as client code uses it. See ~{ Deferred Loading of Plug-Ins }~ for more details. - - - - - Assignment operator. - - - - - Equality operator. Always returns 0. - - - - - Description: - This class represents the unique class ID for a 3ds Max plug-in. A plug-ins must be unique. A program is provided with the SDK to generate these ClassIDs. It is VERY important you use this program to create the ClassIDs for your plug-ins. To generate a random and optionally copy it to the clipboard, run the gencid.exe program. A consists of two unsigned 32-bit quantities. The constructor assigns a value to each of these, for example . - - All the methods of this class are implemented by the system. - - - - - Returns the first unsigned 32-bit quantity. - - - - - Returns the second unsigned 32-bit quantity. - - - - - Checks for equality between two Class IDs. - - - - - Check for Inequality between two Class IDs. - - - - - Assignment operator. Note: In release 3.0 and later this method checks for self-assignment. - - - - - This operator is available in release 4.0 and later only. - - Less than operator. This returns true if the specified 's two parts are numerically less than this 's; false if not. - - - - - An animatable enumerator for clearing flags. - - - - - Description: - This class represents the planar collision object with the ClassID defined as MESH_COLLISION_ID. This class allows you to define a plane in space and determine if a particle hit it. - Data Members: - private: - - *node; - - The associated node. - - *pblock; - - The parameter block data. You can use the following enum parameter ID's: - - collisionmesh_hit_face_index - - collisionmesh_hit_bary - - collisionmesh_node - - validity; - - The validity interval. - - tm; - - The plane's TM. - - invtm; - - The inverse TM. - - tmPrev; - - The previous TM. - - prevInvTm; - - The cached previous inverse TM. - - float radius; - - The radius of the sphere. - - *dmesh; - - The mesh pointer. - - int nv, nf; - - The mesh number of vertices and number of faces. - - *vnorms; - - The collision vertex normals. - - *fnorms; - - The face normals. - - - - - Sets the node which drives the TM to put the plane in world space. - Parameters: - TimeValue t - - The time at which to set the node. - - *n - - The node to set. - Default Implementation: - { pblock->SetValue(collisionmesh_node,t,n); node = n; } - - - - - A collision object can be applied to a particle system by a Space Warp. The collision object checks a particle's position and velocity and determines if the particle will collide with it in the next dt amount of time. If so, it modifies the position and velocity. - - - - - - This method checks a particles position and velocity to determine if there was be a collision between the particle and this collision object. If there was a collision, the particles position and velocity should be modified. The plug-in may compute a line segment between where the particle is now, and where it will be in dt amount of time. The plug-in then checks if the line segment intersects the collision object. If so, it would compute the resulting position, and modify the velocity vector vel to point in the new direction (presumably reflected across the surface normal). 3ds Max 3.0 introduced interparticle collision (where particles may collide with other particles). In order to implement interparticle collision (IPC) in the presence of collision objects, it became necessary to generalize the operation of the deflectors so that they didn't always work in discrete time intervals. That is, in the general case of an unidentified number of particles interacting in an unspecified way, it was necessary to allow everything involved in that system to update to specified times without moving past that time. In the absence of IPC enabled, the particle system calls the bound collision objects with the parameter UpdatePastCollide == TRUE, and the deflector checks all collisions, updates particles based on their collisions with deflectors and the ensuing, remaining time intervals in dt subsequent to the collisions. In the presence of IPC that won't work. When IPC is active, all particles need to be updated to the time of the first collision in the system in dt, whether that collision be between particles or between particles and deflectors. Thus, in the presence of IPC, all particle updates to bound deflectors are called with UpdatePastCollide == FALSE. In that case, the collision objects return both the position and velocity of the updated particles and the time at which the collision occurred. All such times are compared, along with all possible internally calculated IPC event times. If there are any nonnegative times returned greater than or equal to zero, all particle states are reverted to their states at the beginning of the interval and then updated to the precise minimum time returned as the earliest collision. And then everything starts up again trying to update itself to the next integral time, when control can pass back to whatever is asking the particles to update themselves. If there are other collisions in that time, it happens again. This whole set of operations happens after any true returns from the trilinear sort/sweep correlator that looks for the possibility of collisions. If there are no possible collisions, everything proceeds through a complete interval normally. - TRUE if there was a collision and the position and velocity have been modified; otherwise FALSE. - - The time to check for collision. - The position of the particle to check and potentially modify. - The velocity vector of the particle to check and potentially modify. - This is an increment of time - the step size. The method checks if the particle will collide in this amount of time. - The index of the particle being collided. - An array of floating point times at which the collisions occurred. - This is a flag to tell the collision object to update the particle past the collision to the remainder of input dt or to output the state of the particle at the collision. In the presence of interparticle collision enable, we have to update to the times of collisions and then retest from there. See the Remarks. - - - - This method provides a way of identifying the 'parent' Deflector for a available to a particle system. This must be implemented by all Deflectors. It returns the object pointer to the Deflector from which the Collision object is derived. - - - - - Description: - This class represents the operation interface to the collision detection system. - - The interface ID is defined as COLLISION_FO_INTERFACE. To obtain a pointer to this interface you can use the macro GetCollisionOpsInterface(cd), which will return )(cd)->GetFPInterface(COLLISION_FO_INTERFACE). - - - - - This method returns the collision type supported by the engine. - - - Parameters: - *r - - A pointer to the reference target to check the collision type for. - One of the following; - - POINT_COLLISION for point collision, currently supported. - - SPHERE_COLLISION for spherical collision, currently not supported. - - BOX_COLLISION for box collision, currently not supported. - - EDGE_COLLISION for edge collision, currently not supported. - - - - - This method will be called once before the checkcollision is called for each frame which allows you to do any required initialization. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The time at which to initialize. - - TimeValue dt - - The delta of time the particle wil travel. - - - - - This method will be called at the end of each frame solve to allow you to destroy and deallocate any data you no longer need. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The time at which to initialize. - - TimeValue dt - - The delta of time the particle wil travel. - - - - - This method will be called to execute a point to surface collision and compute the time at which the particle hit the surface. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The end time of the particle. - - pos - - The position of the particle in world space. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute a sphere to surface collision and compute the time at which the particle hit the surface. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The end time of the particle. - - pos - - The position of the particle in world space. - - float radius - - The radius of the sphere. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute a box to surface collision and compute the time at which the particle hit the surface. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The end time of the particle. - - box - - The box itself. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute an edge to surface collision and compute the time at which the particle hit the surface. - Parameters: - *r - - A pointer to the reference target. - - TimeValue t - - The end time of the particle. - - edgeA - - The first edge. - - edgeB - - The second edge. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - Description: - This class represents the planar collision object with the ClassID defined as PLANAR_COLLISION_ID. This class allows you to define a plane in space and determine if a particle hit it. - Data Members: - private: - - *node; - - The associated node. - - *pblock; - - The parameter block data. You can use the following enum parameter ID's: - - collisionplane_width - - collisionplane_height - - collisionplane_quality - - collisionplane_node - - validity; - - The validity interval. - - tm; - - The plane's TM. - - invtm; - - The inverse TM. - - prevInvTm; - - The cached previous inverse TM. - - int initialTime; - - The initial time. - - > invTmList; - - The table of inverse TM's. - - float width, height; - - The width and height of the plane. - - int quality; - - The collision quality value. - - - - - Sets the width of the plane. - Parameters: - TimeValue t - - The time at which to set the width. - - float w - - The width. - Default Implementation: - { pblock->SetValue(collisionplane_width,t,w); } - - - - - Sets the height of the plane. - Parameters: - TimeValue t - - The time at which to set the height. - - float h - - The height. - Default Implementation: - { pblock->SetValue(collisionplane_height,t,h); } - - - - - Sets the quality of the solve. This is the maximum number of iterations the solver will take to find the hit point. The lower quality the mire likely a particle will leak through the surface but the faster the solver will be. - Parameters: - TimeValue t - - The time at which to set the quality. - - int q - - The quality value. - Default Implementation: - { pblock->SetValue(collisionplane_quality,t,q); } - - - - - Sets the node which drives the TM to put the plane in world space. - Parameters: - TimeValue t - - The time at which to set the node. - - *n - - The node to set. - Default Implementation: - { pblock->SetValue(collisionplane_node,t,n); node = n; } - - - - - Sets the controller for the plane width. - Parameters: - *c - - A pointer to the controller to set. - Default Implementation: - { pblock->SetControllerByID(collisionplane_width,0,c); } - - - - - Sets the controller for the plane height. - Parameters: - *c - - A pointer to the controller to set. - Default Implementation: - { pblock->SetControllerByID(collisionplane_height,0,c); } - - - - - Sets the quality of the solve. This is the maximum number of iterations the solver will take to find the hit point. The lower quality the mire likely a particle will leak through the surface but the faster the solver will be. - Parameters: - *c - - A pointer to the controller to set. - Default Implementation: - { pblock->SetControllerByID(collisionplane_quality,0,c); } - - - - - Description: - This class represents the planar collision object with the ClassID defined as SPHERICAL_COLLISION_ID. This class allows you to define a plane in space and determine if a particle hit it. - Data Members: - private: - - *node; - - The associated node. - - *pblock; - - The parameter block data. You can use the following enum parameter ID's: - - collisionsphere_radius - - collisionsphere_node - - validity; - - The validity interval. - - tm; - - The plane's TM. - - invtm; - - The inverse TM. - - prevInvTm; - - The cached previous inverse TM. - - float radius; - - The radius of the sphere. - - - - - Sets the radius of the sphere. - Parameters: - TimeValue t - - The time at which to set the radius. - - float r - - The radius. - Default Implementation: - { pblock->SetValue(collisionsphere_radius,t,r); } - - - - - Sets the node which drives the TM to put the plane in world space. - Parameters: - TimeValue t - - The time at which to set the node. - - *n - - The node to set. - Default Implementation: - { pblock->SetValue(collisionsphere_node,t,n); node = n; } - - - - - Sets the radius controller. - Parameters: - *c - - A pointer to the radius controller. - Default Implementation: - { pblock->SetControllerByID(collisionsphere_radius,0,c); } - - - - - Description: - This class represents a general list of collision vertex normals. - Data Members: - norm; - - The normal vector - - DWORD smooth; - - The smoothing flag. - - *next; - - A pointer to the next normal in the linked list. - - BOOL init; - - The initialization flag. - - - - - Description: - This class represents color as three floating point values: r, g, and b. All methods of this class are implemented by the system. - Data Members: - float r,g,b; - - These values are in the range 0.0 to 1.0. - - - - - Finds the kelvin temperature which, when converted to RGB, would generate the closest possible color to the current RGB value. For a color that was generated from a kelvin temperature, the returned value should match that temperature exactly. But for an arbitrary color, the returned value will only be an approximation (and may vary wildly if the color is very far from the set of valid black body colors). - The temperature, in kelvins, which would generate the closest matching color to 'this'. - This performs a search through the range of valid color temperatures, and may therefore be a bit expensive. - - - - - These values are in the range 0.0 to 1.0. - - - - - These values are in the range 0.0 to 1.0. - - - - - These values are in the range 0.0 to 1.0. - - - - - Sets the to black. r = g = b = 0.0f - - - - - Sets the to white. r = g = b = 1.0f - - - - - Makes all the components of the <= 1.0 - - - - - Makes all the components of the >= 0.0 - - - - - Makes all the components fall in the range [0,1] - - - - - Access operator. - Parameters: - int i - - The index of the component to return. - 0=r, 1=g, 2=b. - - - - - Unary - operator. - The with the components negated, i.e. - - (-r,-g,-b)); } - - - - - Unary + operator. - The itself. - - - - - Subtracts a from this . - A that is the difference between two Colors. - - - - - Adds a to this . - A that is the sum of two Colors. - - - - - Multiplies the components of this by a float. - A multiplied by a float. - - - - - Divides the components of a by a float. - A divided by a float. - - - - - Performs element-by-element multiplying between two Colors. - A element-by-element multiplied by another . - - - - - Test for equality between two Colors. - Nonzero if the Colors are equal; otherwise 0. - - - - - Tests for inequality between two Colors. - Nonzero if the Colors are not equal; otherwise 0. - - - - - Subtracts a from a . - A that is the difference between two Colors. - - - - - Adds a to a . - A that is the difference between two Colors. - - - - - Divides a by a . - A divided by a . r/r, g/g, b/b. - - - - - Multiplies a by a . - A multiplied by a . r*r, g*g, b*b. - - - - - Description: - Methods of this class are used for packing colors into a 256 color paletted representation. Create an instance of this class using BMMNewColorPacker() described below. All methods of this class are implemented by the system. - - - - - This method is used to enable dithering of the packed pixels. It defaults to the 3ds Max default. - Parameters: - BOOL onoff - - TRUE to enable dithering; FALSE to disable. - - - - - This method controls the propagation of error between lines. For static images this is best left to default to on. For animated images, it is better to set this to off and not propagate the error between lines. This defaults to ON. - Parameters: - BOOL onoff - - TRUE to enable error propagation between lines; FALSE to disable. - - - - - Packs the specified line of pixels into the 256 color representation. - Parameters: - BMM_Color_64* in - - The line of pixels to pack. - - BYTE *out - - The result, the output pixels. - - int w - - The number of pixels in the line. - - - - - Packs the specified line of pixels into the 256 color representation. - Parameters: - BMM_Color_48* in - - The line of pixels to pack. - - BYTE *out - - The result, the output pixels. - - int w - - The number of pixels in the line. - - - - - Description: - This class allows a plug-in to create a modeless color picker dialog box. - - Developers may also create a modal version of this dialog box. The function HSVDlg_Do is defined for this purpose. Note that this is not a class method but a global function. - - To use these APIs you need to #include "hsv.h". - - - - - - - This method changes the current color in the color picker, but does not change the "reset" color. - Parameters: - DWORD color - - The current color. - - - - - Sets a new color as current in the dialog. - Parameters: - DWORD color - - The color to set. - - MCHAR *name - - A new name to display in the title bar. - - - - - Returns the current color. - - - - - Returns the screen position of the upper left corner of the dialog as a . - - - - - This is called when the parent is going away. - - - - - This method is used to add a different callback, set a new initial color and update the title string. - Parameters: - DWORD col - - The new initial color. - - *pcb - - The new callback. - - MCHAR *name - - The new title string. - - - - - This method is available in release 4.0 and later only. - - This method is called when the display gamma changes. - - - - - This method changes the current color in the color picker, but does not change the "reset" color. - Parameters: - color - - The current color. - - - - - Sets a new color as current in the dialog. - Parameters: - color - - The color to set. - - MCHAR *name - - A new name to display in the title bar. - - - - - Returns the current color as an Acolor from the color picker. Default implementation returns . - - - - - This method is used to add a different callback, set a new initial color and update the title string. - Parameters: - Acolor col - - The new initial color. - - *pcb - - The new callback. - - MCHAR *name - - The new title string. - - - - - Call this function to get the rectangle of current dialog of color picker. - Default implementation returns RECT(0,0,0,0). - - - - - Is this picker in color sampling (eyedropper) mode. - - - Default implementation returns false. - true if this picker is in sampling mode, false otherwise. - - - - - Description: - This is the base class for the creation of plug-in color selectors. The list of available color pickers appear in the 3ds Max user interface in the General page of the Preferences dialog. The chosen picker will be called whenever a user clicks on a 3ds Max color swatch control. - Plug-In Information: - Class Defined In HSV.H - - Super Class ID COLPICK_CLASS_ID - - Standard File Extension DLU - - Extra Include File Needed HSV.H - - - - - This method is called to bring up the modal color picker. - Parameters: - HWND hwndOwner - - The owning window handle - - DWORD *lpc - - A pointer to the color to be edited. See . - - *spos - - The starting position of the dialog. This is set to ending position on return. - - *callBack - - This callback is called whenever color changes. - - MCHAR *name - - The name of color being edited - TRUE if the user pressed OK; FALSE on cancel. - - - - - This method is called to create and return a object for the modeless color picker. - Parameters: - HWND hwndOwner - - - The owning window handle. - - - DWORD initColor - - - The inital value of the color. See . - - - IPoint2* spos - - - The starting position of dialog. - - - *pcallback - - - This callback is called whenever color changes. - - - MCHAR *name - - - The name of color being edited. - - - BOOL isObjectColor=FALSE - - - This indicates the color picker is being used for the object color in the command panel, and the color picker then displays the Add button. - - The returned object is owned by the system and will be deleted when the user closes the picker window. pcallback's BeingDestroyed() function will be called before the object is deleted. - - - - - This method is called to create and return a object for the modeless color picker. - Parameters: - HWND hwndOwner - - - The owning window handle. - - - initColor - - - The inital value of the color. - - - IPoint2* spos - - - The starting position of dialog. - - - *pcallback - - - This callback is called whenever color changes. - - - MCHAR *name - - - The name of color being edited. - - - BOOL isObjectColor=FALSE - - - This indicates the color picker is being used for the object color in the command panel, and the color picker then displays the Add button. - - The returned object is owned by the system and will be deleted when the user closes the picker window. pcallback's BeingDestroyed() function will be called before the object is deleted. - - - - - Returns the name of the class. This name appears in the drop down list of color picker choices. - - - - - Returns the unique ClassID of this plug-in. The for the default color picker is . - - - - - This method is used for future expansion and is currently not used. - - - - - This base class allows the developer to create a command mode that handles processing user interaction using the mouse in the viewports. See the page on "Command Modes and Mouse Procs" and "Foreground / Background Planes". There are methods in 3ds Max's class to set and get the current command mode. - - - - - - Returns the Class of the command mode. The class describes the type of command mode this is. If the developer is defining a command mode to be used as part of the sub-object manipulation (Move, Rotate, and Scale) then one of the following pre-defined values in Command Classes should be used. - The Class of the command mode. - - - - - This method can be ignored. The default implementation should be used. - - - - - Returns the ID of the command mode. This value should be the constant CID_USER plus some random value chosen by the developer. As an example, this method could be implemented as: { CID_USER+0x1423; } In the special case of the developer implementing a custom command mode to be used as part of sub-object manipulation (Move, Rotate or Scale) the value for ID() should be one of the following values: - - - - - This method establishes the number of points required by the command mode and returns a pointer to the mouse callback object that is used to process the user input. - A pointer to the mouse callback object that is used to process the user input. - - This is where to store the number of points used by the . If the plug-in needs to use an undetermined number of points it can specify a large number for this value. When the mouse proc has finished processing points it returns FALSE to stop the point processing before the number of points specified here have been entered. - - - - Returns a pointer to a callback procedure that flags nodes that belong in the foreground plane. Plug-ins typically use a standard callback object provided by the system that flags all nodes dependent on the plug-in object. This ensures that when the plug-in object changes, any nodes that change as a result will be in the foreground plane, making redraw time faster. These constants may be specified to use one of the standard callback objects instead of an actual FG proc. For example {return CHANGE_FG_SELECTED;} CHANGE_FG_SELECTED Selected nodes are flagged. CHANGE_FG_ANIMATED Nodes that are animated are flagged. - A pointer to a callback procedure that flags nodes that belong in the foreground plane. - - - - - This method returns TRUE if the command mode needs to change the foreground proc (using ChangeFGProc()) and FALSE if it does not. A command mode that does not involve any redrawing of the viewports can just return FALSE. - Sample Code: - The sample code below checks to see if the command mode is already CHANGE_FG_SELECTED. If it is there is no reason to change to foreground proc to this mode so the method returns FALSE. If a different mode is in place TRUE is returned. - - This is the command mode that is currently in place. This may be used for comparison with a potential new mode. See the sample code below. - - - - This method is called when a command mode becomes active. Usually a developer responds by changing the state of a control to indicate to the user that they have entered the mode. Typically this means pushing in a tool button. When the mode is finished the button should be returned to normal (see ExitMode() below). - - - - - This method is called when the active command mode is replaced by a different mode. Typically a developer implements this method to set the state of the control that invoked the command mode to the 'out' state. See Class (specifically the method SetCheck(). - Sample Code: - - - - - Description: - This is the callback object for :: RegisterCommandModeChangedCallback(). - - - - - This method is called when the user changes command modes. - Parameters: - *oldM - - The command mode that was replaced. - - *newM - - The new command mode. - - - - - This is a base class used to create construction grid objects. It implements a few of the methods of and and provides a few for working with construction grids. - - - - - - This method returns the construction grid transformation matrix. This is the world space orientation and position of the construction plane. - - The time to retrieve the matrix. - The node in the scene corresponding to the construction grid object. - The viewport the TM is being returned for. Certain construction grid objects might have a different plane for different viewports. - The transform matrix for this view is returned here. - - - - This method is specific to construction grids. The system calls this method to retrieve the snap dimension of the grid. In the 3ds Max user interface for the construction grid helper object there is a spinner for 'Spacing'. This is the spacing for the grid. When GetSnaps() is called the returned will have this value in all three axes. This value is used, for example, when you create a box or other primitive and are setting the height dimension. - - The time to retrieve the snap values. - - - - Description: - is the class from which you may derived controller objects. Controllers are the objects in 3ds Max that control animation. Controllers come in different types based on the type of data they control. For example, Transform controllers control the 4x3 matrices used to define the position of nodes in the scene while float controllers control simple floating point values. - - Note: Many controller plug-ins may be able to subclass from rather than . This simplifies the developers job. handles the processing of Out of Range Types, Ease Curves, and Multiplier Curves. See Class for more information. - - Plug-In Information: - - Class Defined In CONTROL.H - - Super Class ID CTRL_FLOAT_CLASS_ID - Used by float controllers. - - CTRL_POINT3_CLASS_ID - Used by controllers. - - CTRL_MATRIX3_CLASS_ID - Used by controllers. - - CTRL_POSITION_CLASS_ID - Used by position controllers. - - CTRL_ROTATION_CLASS_ID - Used by rotation controllers. - - CTRL_SCALE_CLASS_ID - Used by scale controllers. - - CTRL_MORPH_CLASS_ID - Used by morph controllers. - - Standard File Extension DLC - - Extra Include File Needed None - Defines: - #define CONT_FLAGS_CHUNK 0x3003 - - - - - - When a controller is assigned to a track in the track view, the new controller is plugged into the parameter and this method is called on the new controller. A pointer to the old controller is passed in to this method. The new controller can attempt to copy any data that it can from the old controller. At the very least it should initialize itself to the value of the old controller at frame 0. - - A pointer to the previous controller. - - - - This method determines if another controller can replace this one. A controller can return FALSE from this method to not allow the user to assign a new controller in its place. This will also prevent the controller from being replaced by a paste controller operation. - TRUE to allow the controller to be replaced; otherwise FALSE. - Default Implementation: - {return TRUE;} - - - - - This method, along with RestoreValue(), comprise an "inner" hold and restore mechanism (see above). When the controller's SetValue() method is called, if the commit parameter is nonzero, then the controller should save the value of the controller at the current time into its cache and also 'commit' the value. For example, this stores a key in the case of a keyframe controller. If the set value was not committed then RestoreValue() may be called to restore the previous value. - Default Implementation: - {} - - Specifies the time to save the value. - - - - This method is the other half of the "inner" hold and restore mechanism. This method is called to restore a previously saved value. This method restores the current cache value to the value that was set before SetValue() was last called. They way the standard 3ds Max controllers handle this is as follows: When SetValue() is called a temporary hold mechanism ( define in CONTROL.H) is used to hold the current value. Then the new value is set. If RestoreValue() is later called then it restores the current value from the temporary storage. Note that in addition to restoring from the , another way a controller may restore the current value is to re-interpolate the keys. - Default Implementation: - {} - - Specifies the time to restore the value. - - - - This method retrieves a lookat controller's target. - The lookat controllers target node. - Default Implementation: - { return NULL; } - - - - - This method stores a lookat controller's target. - One of the following values: - - REF_SUCCEED - - Indicates the target was set. - - REF_FAIL - - Indicates the target was not set. - Default Implementation: - {return REF_SUCCEED;} - - The target node to store. - - - - Implemented by transform controllers that have a position controller that can be edited in the motion branch. This method returns a pointer to the position controller of the transform controller. - Default Implementation: - {return NULL;} - - - - - Implemented by transform controllers that have a rotation controller that can be edited in the motion branch. This method returns a pointer to the rotation controller of the transform controller. - Default Implementation: - {return NULL;} - - - - - Implemented by transform controllers that have a scale controller that can be edited in the motion branch. This method returns the a pointer to the scale controller of the transform controller. - Default Implementation: - {return NULL;} - - - - - This method assigns a new position controller. Plug-Ins don't need to be concerned with freeing the previous controller if this method is called. Any previous controller assigned will be deleted by 3ds Max if it is not used elsewhere in the scene. - Default Implementation: - {return FALSE;} - - - - - This method assigns a new rotation controller. Plug-Ins don't need to be concerned with freeing the previous controller if this method is called. Any previous controller assigned will be deleted by 3ds Max if it is not used elsewhere in the scene. - Default Implementation: - {return FALSE;} - - - - - This method assigns a new scale controller. Plug-Ins don't need to be concerned with freeing the previous controller if this method is called. Any previous controller assigned will be deleted by 3ds Max if it is not used elsewhere in the scene. - Default Implementation: - {return FALSE;} - - - - - Returns a pointer to the 'X' sub-controller of this controller. If a controller has an 'X', 'Y', or 'Z' controller, it can implement this set of methods so that its sub-controllers can respect track view filters. Examples of controllers that have XYZ sub-controllers are the Euler angle controller or the Position XYZ controller. - Default Implementation: - {return NULL;} - - - - - Returns a pointer to the 'Y' sub-controller of this controller. If a controller has an 'X', 'Y', or 'Z' controller, it can implement this set of methods so that its sub-controllers can respect track view filters. Examples of controllers that have XYZ sub-controllers are the Euler angle controller or the Position XYZ controller. - Default Implementation: - {return NULL;} - - - - - Returns a pointer to the 'Z' sub-controller of this controller. If a controller has an 'X', 'Y', or 'Z' controller, it can implement this set of methods so that its sub-controllers can respect track view filters. Examples of controllers that have XYZ sub-controllers are the Euler angle controller or the Position XYZ controller. - Default Implementation: - {return NULL;} - - - - - Implemented by lookat controllers that have a float valued roll controller so that the roll can be edited via the transform type-in. This method returns a pointer to the roll controller of the lookat controller. - Default Implementation: - {return NULL;} - - - - - This method assigns a new roll controller. Plug-Ins don't need to be concerned with freeing the previous controller if this method is called. Any previous controller assigned will be deleted by 3ds Max if it is not used elsewhere in the scene. - Default Implementation: - {return FALSE;} - - - - - This method should be implemented by TM controllers that support filtering out inheritance. It returns the state of the transform inheritance flags. These are the values that show up in the Hierarchy branch, under the Link Info section, in the Inheritance rollup. - One or more of the following values: - - Note: Each bit is used to represent a single inheritance. If the bit is CLEAR (OFF) it means inherit (checked in the 3ds MaxUI). If the bit is SET it means DON'T inherit (unchecked in the 3ds MaxUI). - - INHERIT_POS_X - - INHERIT_POS_Y - - INHERIT_POS_Z - - INHERIT_ROT_X - - INHERIT_ROT_Y - - INHERIT_ROT_Z - - INHERIT_SCL_X - - INHERIT_SCL_Y - - INHERIT_SCL_Z - - INHERIT_ALL - Default Implementation: - {return INHERIT_ALL;} - - - - - This method should be implemented by TM controllers that support filtering out inheritance. - - Note: Each bit is used to represent a single inheritance. This method expects the bits of the flags passed to be CLEAR (OFF) to mean DON'T inherit (unchecked in the 3ds MaxUI). If they are SET it means inherit (checked in the 3ds MaxUI). - Return TRUE if TM controller supports inheritance; otherwise FALSE. - Default Implementation: - {return FALSE;} - - The inheritance flags. One or more of the following values: - If TRUE the position of the node should remain the same; otherwise the node may move. - - - - This method is called on transform, position, rotation, and scale controllers when their input matrix is about to change. This happens when the user links an object (either from one object to another or when the user links an object for the first time). Because a controllers transformation is relative to its parent, when the user changes parents, the transform controller will need to change itself. If a plug-in returns FALSE the node will calculate a change and call SetValue() to make the necessary adjustments at the specific time passed. - - Consider the following example of a position controller: - - If a node in the scene that is NOT animated, is linked to another node, this method would be called. If the method returned FALSE then the node would calculate a change and call SetValue() to make the adjustment and this would be okay. If however the node was animated there would be a problem. Say for example that an unlinked node was bouncing up and down along the world Z axis. If this node is then linked to a node that was rotated such that its Z axis was pointed in the direction of the world X axis (so the object is flipped over on its side) the linked node (whose animation keys are stored relative to its previous parent (the world)) would then begin to bounce up and down along the world X axis instead. This is because it is still moving along its parent's Z axis, but its parents Z axis is really the world X axis. Thus the object needs to be counter-rotated to compensate. Additionally, all the animation keys for the object also need to be counter-rotated. A position keyframe controller would need to implement this method to handle the correction of the object and its keyframes. See the sample code below. - - NOTE: After this call, the controller and its subcontrollers may contain cached "instant" validity intervals of [t,t], and if immediately evaluated at time t they will reflect this interval, perhaps incorrectly. In order to avoid this problem, it is suggested that immediately after calling ChangeParents, you call GetValue on the controller with a time other than t to force a recompute of these cached validity intervals. - If FALSE the node will call SetValue() to make the necessary adjustments. - Default Implementation: - {return FALSE;} - Sample Code: - This is the code used inside 3ds Max' reactor controller (in MAXSDK/samples/controllers/reactor/reactor.cpp). - A plug-in could provide an implementation for this method using a similar concept. - - - - The time of the change. - The old parent matrix. - The new parent matrix. - The nodes current world transformation. - - - - If a node is pinned to another node, and the node gets a NotifyRefChanged() message that its pinned node has changed, then this method is called on the transform controller of the node. Otherwise the controller wouldn't get notified since the controller doesn't have a reference to the pin node (but the node does). Most controllers don't really care, but the IK controller does. - The return value from this method is of type RefResult. This is usually REF_SUCCEED indicating the message was processed. Sometimes, the return value may be REF_STOP. This return value is used to stop the message from being propagated to the dependents of the item. - Default Implementation: - {return REF_SUCCEED;} - - The message that was sent. - This is the interval of time over which the message is active. Currently, all controllers will receive for this interval. - This contains information specific to the message passed in. Some messages don't use the at all. See and for more information. - - - - Implemented by any controller that wishes to indicate that it is intended to control floating point RGB color values. Returns TRUE to indicate that it controls float color values; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - Indicates whether the controller is a leaf controller. If a controller is a leaf controller, then it MUST NOT BY DEFINITION have any sub-controllers or references. The controller should return TRUE if it has no sub-controllers. For example, a PRS controller is not a leaf controller (because it has sub-controllers for Position, Rotation and Scale), but a simple keyframed float controller is a leaf controller. - TRUE if the controller is a leaf controller; FALSE otherwise. - Default Implementation: - {return TRUE;} - - - - - Indicates if the controller is a keyframe controller. This means the controller stores keys at certain frames and interpolates between keys at other times. - Nonzero if the controller is a keyframe controller; zero otherwise. - Default Implementation: - {return 1;} - - - - - Retrieves the value of the controller at the specified time, and updates the validity interval passed in to reflect the interval of the controller. This method is responsible for handling Out of Range Types, Ease Curves and Multiplier Curves. See the sample code below. - val parameter Handling - float: - : - Position: - Rotation: - Scale: - Transform (Matrix3) - Sample Code: - The following code is from the BoolControl implementation of this method (see MAXSDK/samples/controllers/boolcntrl/boolcntrl.cpp). - - - Specifies the time to retrieve the value. - This points to a variable to hold the computed value of the controller at the specified time. What the plug-in needs to do to store the value of the controller depends on the controller type. There are six controller types: and . The way the value is stored also depends on the parameter . See "val parameter Handling" below for a list of the possible cases, and how the value should be stored in each case. - The interval into which the validity of the evaluated parameters is intersected. - One of the following values: Indicates the plug-in should apply the value of the controller to . See Above. Indicates the controller should simply store its value in . See Above. - - - - This method sets the value of the controller at the specified time. This method is responsible for handling Out of Range Types, Ease Curves and Multiplier Curves. See the sample code below. - - Note: Developers who want to create keys for a keyframe controller by calling SetValue() directly can do so, but the animate button should be turned on using the following code: - - SuspendAnimate(); - - AnimateOn(); - - SetValue() make sure commit=1 - - ResumeAnimate(); - Sample Code: - The following code is from the BoolControl implementation of this method (see MAXSDK/samples/controllers/boolcntrl/boolcntrl.cpp). - - - Specifies the time to save the value. - Points to an instance of a data type that corresponds with the controller type. These are the same as above with the following exceptions: For rotation controllers, if the is , points to an , while if it is it points to a . For controllers points to an instance of class . See Class . - When is called the controller should store it value (usually into a cache it maintains), and if this parameter is set, also 'commit' it's value (usually by calling ). For example, consider a 3ds keyframe controller: If and if the Animate button is on, then the cache should be updated and a key should be created. If the Animate button is off then the cache should be updated and the keys should all be offset. If then the cache value is set and its validity interval is set to the current time. If later then a key would be created from that cached value. If is never called with then the key is never set. For instance with Inverse Kinetmatics, is called many times over and over at the same with . The controller doesn't create a key, it just changes its cached value. When an IK solution is finally reached, is called with and a key is created. Note that calling with and then calling should have the same effect as calling with . See the methods and below. - One of the following values: Indicates the plug-in should add the value to the existing value (i.e. Move/Rotate/Scale) Indicates the plug-in should just set the value. When is called the parameter is ignored. The pointer passed to points to an instance of Class . See that class for more details on how it is used. - - - - This method returns the PRS components of the local matrix. In general, controller cannot decide on the local matrix without knowing the parent matrix. However, many controllers, such as default controllers, are well defined without the parent matrix. In these cases, it is more efficient to compute the local components directly without going through the world matrix. - - Therefore, the argument parentMatrix is a reference to . This would allow clients to supply a "delayed parent matrix," which will be computed only if it is necessary. It returns true for , Position, Rotation, or Scale controllers, and return false otherwise. - - The PRS components will be put in argument cmpts in the respective fields with corresponding validity intervals. NULL pointer, of TMComponentsArg::position for example, indicates that the client is not concerned about the component. When it is not NULL, the corresponding pointer to the validity interval MUST NOT be NULL. When it is not NULL, TMComponentsArg::rotation is a float[4]. rotRep tells what the numbers mean. - - Position, Rotation, or Scale, controllers will put results at the respective component when the corresponding pointer is not NULL. - - Upon entry, parentMatrix should represent the parent matrix up to the first requested components. For controllers, for example, if cmpts.position==NULL && cmpts.rotation!=NULL, then parentMatrix should be matrix that includes the parent node matrix plus the position of this node. Upon return, this matrix may be modified. - - The time at which to get the local TM components. - See Structure TMComponentsArgs. - The parent matrix. Note the definition: LocalMatrix = WorldMatrix * ParentWorldMatrix^(-1) - - - - Implemented by the System. - - Returns the specified Out of Range Type used by the controller. The system handles this method but the controller needs to process the ORT in its implementation of GetValue() and SetValue(). - One of the following values: - - See Out of Range Types. - - One of the following values: - leading up to the pattern - beyond the key pattern - - - - Implemented by the System. - - Sets the specified Out of Range Type to be used by the controller. The system handles this method but the controller needs to process the ORT in its implementation of GetValue() and SetValue(). - - See outOfRangeTypes. - One of the following values: - leading up to the pattern - beyond the key pattern - - - - Implemented by the System. - - Sets the enabled/disabled state for Out of Range Types. If disabled, this temporarily causes the Out of Range Types to behave as if set to constant. This can be used if you want to modify a controller but don't want ORT mapping for ORT_LOOP, ORT_CYCLE, or ORT_OSCILLATE. - - TRUE to enable ORTs; FALSE to disable. - - - - This tells the system how many parameters the controller has. A controller can have as many IK parameters as it wants. An IK parameter corresponds to a degree of freedom in IK. The parameter is a floating point scalar value. For example a position controller has three degrees of freedom (X, Y, Z) and thus three parameters that IK can vary in its solution. The path controller has only a single parameter (degree of freedom) - the position along the path. The 3ds Max user may set the number of degrees of freedom. For example, a user can specify that a rotation controller cannot rotate about one or more axes. These are then no longer degrees of freedom or IK parameters. - - This method is called by the system so the plug-in can specify how many IK parameters it has. It does this by calling the provided callback object proc() method once for each parameter it has. It passes a pointer to itself and the index of the IK parameter. For example a position controller with three degrees of freedom (and thus three IK parameters) would call the callback.proc() three time passing an index of 0, then 1, then 2. See the sample code below. - Default Implementation: - {} - Sample Code: - From MAXSDK/samples/controllers/layerctrl.cpp - - This callback is provided by the system and should be called by the plug-in once for each IK parameter the plug-in has. See Class . - - - - This method is used to determine what effect a change in the parameter has on the end effector. This is the derivative of the end effector with respect to the parameter. What the derivative means in this case is what happens to the end effector if the parameter is changed by some small delta. - - The plug-in provides the derivatives to the system calling derivs.DP() and derivs.DR(). It should call derivs.DP() and derivs.DR() in the same order as the callback.proc() was called in the NumIKParams() method implementation. - - When the controller computes the derivative it should apply itself to the parent matrix. For example a position controller would compute its derivative based on the parent and the position of the end effector and then apply itself to the parent matrix. If it does apply itself to the parent it should return TRUE. If it does not apply itself it should return FALSE. - If a controller isn't participating in IK then it should return FALSE and the client (usually PRS) will apply the controller's value to the parent TM. - Default Implementation: - {return FALSE;} - Sample Code: - The following sample code shows how the quaternion controller has implemented this method. Note that the method loops based on the number of end effectors, and calls derivs.NextDOF() after each iteration. - - - - Specifies the time to compute the derivative. - The parents transformation. - This class provides methods the plug-in calls to set the derivatives. See Class . - One of the following values: Indicates that should be called. Indicates that should be called. - - - - When the system has computed a change in the parameter it will call this method. The controller should increment the specified parameter by the specified delta. The controller can increment the parameter less than this delta if it needs to. This could be for several reasons: - - 1. Its parameter may be constrained to lie within a specific interval. It would not want to add a delta that took the parameter outside of this interval. - - 2. It was asked to calculate a constant partial derivative for a linkage that could be non-linear. Therefore the derivative may have only been an instantaneous approximation. Due to the locality of the IK solution, the controller might not want to allow a delta that was too large. - - After the controller has applied the delta, it needs to indicate to the system how much of the delta was used. - The amount the parameter was actually incremented. This allows the IK solver to know the value was not incremented the full amount. - Default Implementation: - {return 0.0f;} - Sample Code: - - The time of the increment. - Specifies the IK parameter to increment. - The delta to apply to the parameter. The controller can increment the parameter less than this delta if it needs to in order to accommodate a limit it has. This methods returns the amount that was actually incremented. - - - - This method is called to have the controller delete its keys. If the user has the 'Clear Keys' check box checked when they press the 'Apply IK' button, this method is called to have the controller deletes keys in the given interval for the specified degree of freedom. - Default Implementation: - {return;} - - The interval over which the keys should be deleted. - Specified the degree of freedom (parameter) that the keys should be deleted for. - - - - This is an optional method that can be implemented by controllers that support IK to initialize their joint parameters based on data loaded from 3D Studio R4/ DOS files. - Default Implementation: - {} - - The position data from the 3DS file. See Class . - The rotation data from the 3DS file. - - - - This method retrieves the IK joint parameter data from the UI. - TRUE if the data was retrieved; otherwise FALSE. - Default Implementation: - {return FALSE;} - - Points to the object to hold the position data. See Class . - Points to the object to hold the rotation data. - - - - The new IK system has some axes gizmos which show the degrees of freedom, etc. This method is called by the system. - TRUE if the method is implemented; FALSE otherwise. - Default Implementation: - {return FALSE;} - - The current time. - The parent matrix. - This is the structure to be filled in. See Class . - TRUE if the node is currently selected; otherwise FALSE. - - - - This method is called to create a locking key. This is a key that looks back to the previous key and creates a new key at the specified time which matches the previous key in value. It also adjusts the parameters for the key such that the value stays constant from the previous key to this key. For instance, the TCB controller will set the previous and new continuity to 0. The Bezier controller sets the out tangent type of the previous key to linear and the in tangent type of the new key to linear. - TRUE if the method is implemented; FALSE otherwise. - Default Implementation: - {return FALSE;} - - The time to create the key. - Specifies which type of key to create: for position, for rotation. - - - - This method is called to mirror the specified IK constraints about the specified axis. When IK constraints are mirrored they need to be updated to reflect the new orientation. For instance, if you set the constraints for a left arm to bend only +90 degrees along one axis and then copied these to a right arm the joint would bend backwards. What you need to do is provides the appropriate compensation so the orientation is kept proper. - Default Implementation: - {} - - Specifies the axis of reflection: for X, for Y, for Z. - Specifies which type of constraints are being mirrored: for position, for rotation. - TRUE if the mirror is being done as part of a paste operation; otherwise FALSE (for example if the mirror was being done with the mirror tool). - - - - User can specify a node as a terminator. This method gives the associated controller the chance to specify that it's terminated. - TRUE if the method is implemented; FALSE otherwise. - Default Implementation: - {return FALSE;} - - - - - This is an optional method that can be implemented by controllers that support IK to initialize their joint parameters based on data loaded from 3D Studio R4/ DOS files. - Default Implementation: - {} - - The position data from the 3DS file. See Class . - The rotation data from the 3DS file. - - - - This method retrieves the IK joint parameter data from the UI. - TRUE if the data was retrieved; otherwise FALSE. - Default Implementation: - {return FALSE;} - - Points to the object to hold the position data. See Class . - Points to the object to hold the rotation data. - - - - This method is called on a transform controller when one of the node level IK parameters has been changed. - Default Implementation: - {} - level IK parameters has been changed - Default Implementation: - {} - - - - - This method is called in a transform controller when a node invalidates its TM cache - Default Implementation: - {} - - - - - This method lets a TM controller determine if it's OK to IK bind to a particular node. - TRUE if it's okay to bind; FALSE if it's not. - Default Implementation: - {return TRUE;} - - Points to the node to check. - - - - This method returns TRUE if the controller has IK parameters it can copy and FALSE otherwise. - TRUE if the controller can copy the specified IK parameters; otherwise FALSE. - Default Implementation: - {return FALSE;} - - One of the following values: - - - - This method is called to have the controller copy the specified IK parameters to an and return a pointer to it. The plug-in should derive a class from the , put its data in the class, and return a new instance of it. See Class . - Default Implementation: - {return NULL;} - - One of the following values: - - - - Returns TRUE if the controller can paste the specified IK parameters; otherwise FALSE. - TRUE if the controller can paste the specified IK parameters; otherwise FALSE. - Default Implementation: - {return FALSE;} - - A pointer to the current in the clipboard. This class identifies the creator of the clip object. See Class . The plug-in should look at the IDs in the to make sure it matches this controller. If it does not, the plug-in should return FALSE. - One of the following values: - - - - This method is called to have the controller paste the specified IK parameters from the specified to itself. - Default Implementation: - {} - - A pointer to an . See Class . - One of the following values: - - - - This method determines if a controller may have ease or multiplier curves applied to it. This method defaults to returning TRUE, but can be implemented to return FALSE by a controller that does not wish to let ease or multiplier curves be applied to it. - TRUE to allow the application of ease and multiplier curves; otherwise FALSE. - Default Implementation: - {return TRUE;} - - - - - Implemented by the System. - - The controller calls this method to pipe the TimeValue passed through the ease curve to get the modified TimeValue. - The modified TimeValue. - - The time to have modified by the ease curve. - The interval into which the validity of the evaluated parameters is intersected. - - - - Implemented by the System. - - Adds an ease curve to the specified controller. - - The controller that the ease curve will be applied to. - - - - Implemented by the System. - - Deletes the 'i-th' ease curve from the controller. - - The index of the ease curve to delete. - - - - Implemented by the System. - - Returns the 'i-th' ease curve. - Parameters: - int i - - The index of the ease curve to return. - - - - - Implemented by the System. - - Returns the number of ease curves applied to the controller. - - - - - Implemented by the System. - - Retrieves a floating point value that is the product of all the multiplier curves at the specified time. - The product of all the multiplier curves applied to the controller. - - The time to retrieve the value. - The interval into which the validity of the evaluated parameters is intersected. - - - - Implemented by the System. - - Adds a multiplier curve to the specified controller. - - The controller to have the multiplier curve added. - - - - Implemented by the System. - - Deletes the 'i-th' multiplier curve from this controller. - - The index of the curve to delete. - - - - Implemented by the System. - - Returns the 'i-th' mult curve. - Parameters: - int i - - The index of the mult curve to return. - - - - - Implemented by the System. - - Returns the number of multiplier curves assigned to the controller. - - - - - This method is called on a transform controller after a node is cloned and the clone process has finished. This allows the controller to do any work it needs to after the clone is complete. - Default Implementation: - {} - - - - - This is called by the system to have the controller display its gizmo. When a controller is being edited in the Motion branch, this method is called to allow it to display any apparatus it may have in the scene. Note that Display() is only called on Transform Controllers. It is not called only any sub-controllers, for example it wouldn't be called on the position controller of a PRS transform controller. - - In R4 and higher however the display method WILL be called on Position, Rotation and scale controllers as well. - Nonzero if the item was displayed; otherwise 0. Default return value is -1, indicates this controller doesn't have display function. - Default Implementation: - { return 0; } - - The time to display the object. - The node to display. - An interface pointer that exposes methods the plug-in may call related to the viewports. - See . - - - - This method is called to determine if the specified screen point intersects the controller gizmo. The method returns nonzero if the gizmo was hit; otherwise 0. - Nonzero if the controller gizmo was hit; otherwise 0. - Default Implementation: - { return 0; } - - The time to perform the hit test. - A pointer to the node whose gizmo should be tested. - The type of hit testing to perform. See for details. - The state of the crossing setting. If TRUE crossing selection is on. - The hit test flags. See for details. - The screen point to test. - An interface pointer that may be used to call methods associated with the viewports. - - - - This is the world space bounding box of the controllers gizmo. - Default Implementation: - {} - - The time to retrieve the bounding box. - The node to calculate the bounding box for. - An interface pointer that exposes portions of View3D that are exported for use by plug-ins. - The returned bounding box. - - - - When the user changes the selection of the sub-object drop down, this method is called to notify the plug-in. This method should provide instances of a class derived from to support move, rotate, non-uniform scale, uniform scale, and squash modes. These modes replace their object mode counterparts however the user still uses the move/rotate/scale tool buttons in the toolbar to activate them. If a certain level of sub-object selection does not support one or more of the modes NULL may be passed. If NULL is specified the corresponding toolbar button will be grayed out. - Default Implementation: - {} - - The sub-object selection level the command modes should be set to support. A level of 0 indicates object level selection. If level is greater than or equal to 1 the index refers to the types registered by the object in the order they appeared in the list when registered by . See Class . - The command modes to support. See Class . - - - - This method is called to change the selection state of the component identified by hitRec. - Default Implementation: - {} - - Identifies the component whose selected state should be modified. See Class . - TRUE if the item should be selected; FALSE if the item should be de-selected. - TRUE if the entire object should be selected; FALSE if only the portion of the identified by . - This is set to TRUE when is also set to TRUE and the user is holding down the Shift key while region selecting in select mode. This indicates the items hit in the region should have their selection state inverted. - - - - This method is called to clear the selection for the given sub-object level. All sub-object elements of this type should be deselected. - Default Implementation: - {} - - Specifies the selection level to clear. - - - - Implemented by the System. - - Returns the index of the sub-object element identified by the hitRec. The sub-object index identifies a sub-object component. The relationship between the index and the component is established by the controller. For example a controller may allow the user to select a group of footprints and these groups may be identified as group 0, group 1, group 2, etc. Given a hit record that identifies a footstep, the controller's implementation of this method would return the group index that the footprint belonged to. - The index of the sub-object element. - Default Implementation: - {return 0;} - - Identifies the component whose index should be returned. See Class . - - - - This method is called to select every element of the given sub-object level. This will be called when the user chooses Select All from the 3ds Max Edit menu. - Default Implementation: - {} - - Specifies the selection level to select. - - - - This method is called to invert the specified sub-object level. If the element is selected it should be deselected. If it's deselected it should be selected. This will be called when the user chooses Select Invert from the 3ds Max Edit menu. - Default Implementation: - {} - - Specifies the selection level to invert. - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current controller being edited so that it can display the axes. This method specifies the position of the center. The plug-in enumerates its centers and calls the callback cb once for each. See ~{ Sub-Object Coordinate Systems }~. - Default Implementation: - {} - - The callback object whose methods may be called. See Class . - The time to enumerate the centers. - A pointer to the node. - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current controller being edited so that it can display the axes. This method returns the axis system of the reference coordinate system. The plug-in enumerates its TMs and calls the callback cb once for each. See ~{ Sub-Object Coordinate Systems }~. - Default Implementation: - {} - - - - The callback object whose methods may be called. See Class . - The time to enumerate the TMs. - A pointer to the node. - - - - When this method is called the plug-in should respond by moving its selected sub-object components. - Default Implementation: - {} - - The time of the transformation. - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the controller's space and convert them into world space points. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This value is a vector with X, Y, and Z representing the movement along each axis. - When TRUE the transformation is occurring about the sub-object's local origin. - - - - When this method is called the plug-in should respond by rotating its selected sub-object components. - Parameters: - TimeValue t - - The time of the transformation. - - & partm - - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the controller's space and convert them into world space points. - - & tmAxis - - The matrix that represents the axis system. This is the space in which the transformation is taking place. - - & val - - The amount to rotate the selected components. - - BOOL localOrigin=FALSE - - When TRUE the transformation is occurring about the sub-object's local origin. Note: This information may be passed onto a transform controller (if there is one) so they may avoid generating 0 valued position keys for rotation and scales. For example if the user is rotating an item about anything other than its local origin then it will have to translate in addition to rotating to achieve the result. If a user creates an object, turns on the animate button, and rotates the object about the world origin, and then plays back the animation, the object does not do what the was done interactively. The object ends up in the same position, but it does so by both moving and rotating. Therefore both a position and a rotation key are created. If the user performs a rotation about the local origin however there is no need to create a position key since the object didn't move (it only rotated). So a transform controller can use this information to avoid generating 0 valued position keys for rotation and scales. - - - - - When this method is called the plug-in should respond by scaling its selected sub-object components. - - The time of the transformation. - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the modifier's space and convert them into world space points. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This value is a vector with X, Y, and Z representing the scale along X, Y, and Z respectively. - When TRUE the transformation is occurring about the sub-object's local origin. See the note above in the Rotate method. - - - - This method is called when the user rescales time in the time configuration dialog. If FALSE is returned from this method then Animatable::MapKeys() will be used to perform the scaling. Controllers can override this method to handle things like rescaling tangents that MapKeys() won't affect and return TRUE if they don't want MapKeys() to be called. - Default Implementation: - {return FALSE;} - - The old time segment. - The new time segment. - - - - Prior to R4 TrackView was using static defines to determines the number samples/pixel it used to draw and compute curve extents. Now a controller can override these defaults by implementing GetDrawPixelStep() and GetExtentTimeStep(). - - This method allows a control to get sampled at a different rate than what trackview does by default so the controller can speed up redraws. It returns the pixel sample rate for when the curve is drawn. - Default Implementation: - {return 5;} - - - - - Prior to R4 TrackView was using static defines to determines the number samples/pixel it used to draw and compute curve extents. Now a controller can override these defaults by implementing GetDrawPixelStep() and GetExtentTimeStep(). - - This method returns the ticks sample rate used when the curve is checked for its Y extents. - Default Implementation: - {return 40;} - - - - - This method is only implemented by transform controllers. Transform controllers that do not inherit their parent's transform should override this method. - - When a transform controller is evaluated, the parent transform is passed in to the controller and the controller typically applies its value to the parent transform. However, some controllers (for example Biped) may choose to control the TM in an absolute manner and therefore ignore the incoming parent's TM. The system needs to know about this because normally if an object and its parent are selected and the user attempts to move them only the parent transform is modified because it is assumed that the child will inherit its parents TM. - TRUE if the controller inherits its parents TM; otherwise FALSE. Returning FALSE will cause SetValue() to be called even in the case when the parent is also being transformed. - This method may still return TRUE even if all the bits returned from GetInheritanceFlags() are SET to indicate that nothing is inherited from the parent. This is simply because these methods don't have the same level of 'granularity'. This method deals with the overall inheritance of the parent's transform whereas the inheritance flags relate to individual parts. - Default Implementation: - { return TRUE; } - - - - - This method is called on TM controllers so that system driven controllers can prevent the Interface::DeleteNode() API from deleting them. Note that DeleteNode()has an optional parameter to override this so driver controllers can easily delete driven nodes if they want to. - TRUE to prevent deletion; FALSE to allow it. - Default Implementation: - {return FALSE;} - - - - - The Level of Detail utility lets you construct an object that alters its geometric complexity (or level of detail) based on its size in the rendered image. You do this by creating several versions of the same object - each with different levels of detail, grouping them as one, and then assigning the Level of Detail utility, which automatically creates a special LOD controller as a Visibility track. The LOD controller then hides and unhides the various objects in the group, depending on their size in the rendered scene. - - This method is called on visibility float controllers with view related parameters. This is used by the Level of Detail controller to allow view dependent visibility. - The visibility of the object at the specified time. - Default Implementation: - The default implementation will simply call GetValue(). - - The time at which to evaluate. - This class contains information about the view being rendered. This includes information such as the image width and height, the projection type, and matrices to convert between world to view and world to camera. See Class . - The bounding box of the node that's being evaluated. - This interval should be updated to reflect the validity of the visibility controller. The interval into which the validity of the evaluated parameters is intersected. - - - - This method is called on visibility controllers. This gives them the option to completely hide an object in the viewports. - TRUE if the object is visible in the viewport; FALSE if invisible. - Default Implementation: - {return TRUE;} - - - - - Called on transform controllers or visibility controllers when a node is cloned and the user has chosen to instance - - Default Implementation: - {return TRUE;} - - - - - This method is implemented by the System. It should be called by any leaf controller's Clone() method so that ease and multiplier curves are cloned. - Sample Code: - - Points to the cloned controller (the new one). - The passed to this controller's method. - - - - interface class - In 3ds Max, subdivision surface creasing is set up around the concept of "Crease Sets" - Groups of edges or vertices which share common crease values. Establishing groups which share common crease values makes it easier for users to manage them and control creasing of various parts of their geometry in unison. - The Crease Explorer allows users to view all Crease Sets in all objects and manipulate them. For convenience in managing them, a hierarchy is created in which each Crease resides in a "Crease Set Container", which may contain any number of Crease Sets. A Crease Container can be anything in Max which defines a Crease . Presently, this includes the CreaseSet and Crease modifiers, as well as the SubdivBox primitive. - Any plugin which defines Crease Sets should derive from , implement all methods of the class and register each instance with the Crease Manager using the CreaseSetManager::RegisterCreaseSetContainer method. This will allow the system to access the Crease Sets it contains and display them in the Crease Explorer for the user to examine and/or alter. - When an instance of a is destroyed or removed from the scene, it should unregister itself by calling CreaseSetManager::UnregisterCreaseSetContainer. - When Crease Sets are created or destroyed in a , the should notify the via CreaseSetManager::NotifyStructureChanged so that the Crease Explorer, if active, may update to reflect the change. - Any time an existing Crease changes in any way, the should notify the via CreaseSetManager::NotifyComponentChanged. - A exposes the number of Crease Sets it contains (see CreaseSetContainer::GetNumberOfCreaseSets). Each Crease may be queried for its name, as well as its container's name (see CreaseSetContainer::GetCreaseName and CreaseSetContainer::GetCreaseContainerName). Usually, all Crease Sets within a will share the same container name (for example, a CreaseSet modifier in Max returns its name whenever any of the Crease Sets it contains are queried for their container's name), but this is up to the . The Crease Manager, which itself is a specialized , wraps all CreaseSetContainers in the system and will return the proper name for any Crease in the scene. - For an example of how to implement a , see the SubdivBox plugin in MaxSDK/Objects/PolyObjects/ - - - - - Get the for this Crease Container - that represents this Crease Container - - - - - Get the number of crease sets in this container - The number of crease sets - - - - - Get the name of the crease set container for a given crease set. Usually the same name for all sets contained by a given container (i.e. For Max's Crease , the container name for all crease sets is the modifier name) but the Crease Manager, which allows accessing all crease sets in the system, will return the appropriate container name for each crease set. - The name of the crease set - - - Index of the crease set - - - - Query whether the crease set container containing a given set can be renamed - true if the crease set container can be renamed - - - Index of the crease set - - - - the name of a crease set container which contains a given set - - - Index of the crease set - - Pointer to new name string - - - - Get the name of a given crease set - The name of the crease set - - - Index of the crease set - - - - Query whether a given crease set can be renamed - true if the crease set can be renamed - - - Index of the crease set - - - - the name of a given crease set - - - Index of the crease set - - Pointer to new name string - - - - Get the type of a crease set - The crease set type (CREASE_SET_TYPE_XXX, defined above) - - - Index of the crease set - - - - Get the number of entities in a crease set - The number of items in the set - - - Index of the crease set - - - - Get the crease value for a given set - The crease value, 0.0-1.0 - - - Index of the crease set - - The time at which to sample - - The interval into which the validity of the evaluated parameters is intersected. - - - - Query whether the crease value of a given set can be changed - true if the set value may be changed - - - Index of the crease set - - - - the crease value of a crease set - - - Index of the crease set - - The time at which to set the crease value - - The crease value to set - - - - Get the color used to represent a given crease set - The color used for the crease set - - - Index of the crease set - - - - Query whether the color of a given set can be changed - true if the color may be set - - - Index of the crease set - - - - Sets the color of a given crease set - - - Index of the crease set - - The color to set - - - - Get a list of nodes affected by this container - - - An that will receive the list of nodes - - - - Get a list of nodes affected by the given crease set - - - Index of the crease set - - An that will receive the list of nodes - - - - Container may contain animated Crease values. Get the validity interval. - The validity interval for the given time - - - The time at which to sample the validity - - - - Query whether the crease set color will be shown in the viewport - true if the visibility switch can be set - - - Index of the crease set - - - - Get the crease set color visibility switch for a given crease set - The state of the visibility switch (true = visible) - - - Index of the crease set - - - - the crease set color visibility switch for a given crease set - - - Index of the crease set - - The visibility state for the set (true = visible) - - - - Get the for a given crease set - A pointer to the - - - Index of the crease set - - - - Register a . All CreaseSetContainers must register themselves so that the can access them and their contents. - - - Pointer to the being registered - - - - Unregister a . All CreaseSetContainers must unregister themselves when they are destroyed so that the will no longer try to access them. - - - Pointer to the being registered - - - - Query whether a given is registered - true if the container is registered - - - Pointer to the being registered - - - - Notify the CreaseSetManaager that a container's structure has changed. Crease Containers should call this when the number of crease sets they contain has changed. - - - Pointer to the that has changed - - - - Notify the CreaseSetManaager that a set's content has changed. Crease Containers should call this when the any aspect of the crease sets they contain has changed. - - - Pointer to the that has changed - - Index of the crease set, or -1 if more than one has changed - - - - Description: - This is the callback object for handling the creation process of a plug-in object. - - - - - This is the method where the developer defines the user / mouse interaction that takes place during the creation phase of an object. - Parameters: - *vpt - - The viewport the creation process is taking place in. - - int msg - - This message describes the type of event that occurred. See Mouse Callback Messagesint point - - The point number. this is 0 for the first click, 1 for the second, etc. - - int flags - - These flags describe the state of the mouse button and keyboard Shift/Ctrl/Alt keys. See Mouse Call Back Flags m - - The 2D screen point that the user clicked on. Methods in the viewport interface allow this point to be converted into a world space ray or a 3D view space point. A world space ray can be intersected with the active construction plane which results in a point on the active construction plane. See Class . - - & mat - - This represents the transformation of the object relative to the construction plane. Typically the plug-in would get a point on the construction plane based on the screen point that the user clicked on and set the translation component of this matrix based on that point. - Return one of the following value to indicate the state of the creation process: - - CREATE_CONTINUE - - The creation process should continue. In this case the mouse is captured. - - CREATE_STOP - - The creation process has terminated normally. In this case the mouse is no longer captured and input is then allowed again from any viewport. - - CREATE_ABORT - - The creation process has been aborted. The system will delete the created object and node. - The Interface::StopCreating() method should not be called from a create call-back procedure, but instead the proper code should be returned to end the plugin creation process. - - - - - This method is used to override the default drag mode. Most plug-in will not need to replace the default implementation of this method. What this does is change the way the messages are sent relative to the mouse clicking. - - Normally the messages are sent as follows: When the user clicks down this generates a MOUSE_POINT message. Then the user drags the mouse with the button down and a series of MOUSE_MOVE messages are sent. When they let up on the mouse button a MOUSE_POINT messages is generated. Then as the mouse is moved a series of MOUSE_MOVE messages are sent. Then they click down on the mouse again, but this time a point message is not generated until the button is released. All future points are then only sent after the mouse button has been pressed and released. - Parameters: - int mode - - The current drag mode. See below. - One of the following drag modes should be returned: - - CLICK_MODE_DEFAULT - - Returned to indicate the use of the system mouse mode. - - CLICK_DRAG_CLICK - - This is the default behavior as described above. - - CLICK_MOVE_CLICK - - In this mode, the first point is entered by clicking the mouse button down and then letting it up. This generates point 0. In other words, a MOUSE_POINT message is only generated after the user has pressed and released the mouse button. - - CLICK_DOWN_POINT - - In this mode, point messages are sent on mouse-down only. CLICK_TWO_POINTS - - In this mode, each mouse click sends 2 MOUSE_POINT messages. One for button down, the other for button up. - Default Implementation: - { return mode; } - Sample Code: - A sample program that uses the override method is /MAXSDK/SAMPLES/OBJECTS/SPLINE.CPP.It uses CLICK_DOWN_POINT. - - - - - This gets called by the CreationManager to determine if the mouse proc is really starting a new object. The mouse proc for creating always returns CREATE_STOP, which is how it keeps the mouse from being captured, and this function tells the system if it is really ready to start a new object. Thus, this is called only if the mouse proc returned CREATE_STOP to see if the object is really in a state to start a new node. - TRUE if the mouse proc is ready to start a new object; otherwise FALSE. - Default Implementation: - { return TRUE; } - - - - - Called by the system to determine if ortho mode makes sense for this creation. Typically this only makes sense for splines and NURBS curves. - TRUE if ortho mode is okay; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - A callback object called for each sequence file created with Interface8::CreateRendImgSeq() - - - Pass an instance of this class to Interface8::CreateRendImgSeq(). For each sequence file created, the callback method will be called. The method can modify the name of the sequence file or return false to prevent creation of the file. - - - - - Method called for each sequence file to create. - - - Return FALSE to prevent creation of the sequence file, TRUE otherwise. - - - Full path and name of the sequence file; may be modified by the callee - - 0 for the main render output, or 1 for render elements - - NULL for the main render output, or IRenderElement* for render elements - - - - Description: - This class is a callback for interactive adjustment of bitmap "Croppingrectangle", passed in as an argument to the Bitmap::Display() method. See /MAXSDK/SAMPLES/MATERIALS/BMTEX.CPP for sample code. - - All methods of this class are virtual. - - - - - Returns the initial U value. - - - - - Returns the initial V value. - - - - - Returns the initial W value. - - - - - Returns the initial H value. - - - - - Returns TRUE for place mode; FALSE for crop mode. In crop mode the image is clipped at the edges. In place mode, the image is resized or moved. - - - - - This method is called to set the values as the user is making adjustments. If the parameters may be animated, use Interface::GetTime() to retrieve the time they are being set for. - Parameters: - float u - - The U parameter to set. - - float v - - The V parameter to set. - - float w - - The W parameter to set. - - float h - - The H parameter to set. - - BOOL md - - The mode being set. TRUE is place mode; FALSE is crop. - - - - - This method is called when the cropping adjustment window is closed. - - - - - class - Description: - This class provides a data structure for keeping a log of hits during controller gizmo hit-testing. It provides a list of CtrlHitRecords that may be added to and cleared. A developer may also request the 'closest' hit record in the list. All methods are implemented by the system. - - - - - Clears the list of hits. - - - - - Returns the first hit record in the list. - - - - - Returns the that was 'closest' to the mouse position when hit testing was performed. - - - - - This method is called to log a hit. It creates a new object using the data passed and adds it to the hit log. - Parameters: - *nr - - The node whose gizmo was hit. - - DWORD dist - - The 'distance' of the hit. What the distance actually represents depends on the rendering level of the viewport. For wireframe modes, it refers to the distance in the screen XY plane from the mouse to the sub-object component. In a shaded mode, it refers to the Z depth of the sub-object component. In both cases, smaller values indicate that the sub-object component is 'closer' to the mouse cursor. - - ulong hitInfo; - - A general unsigned long value. Most controllers will just need this to identity the sub-object element. The meaning of this value (how it is used to identify the element) is up to the plug-in. - - DWORD infoExtra; - - If the above hitInfo data member is not sufficient to describe the sub-object element this data member may be used as well. - - - - - class - Description: - This class provides a data structure used during controller gizmo hit-testing. All methods are implemented by the system. - Data Members: - *nodeRef; - - This identifies the node the user has clicked on. - - DWORD distance; - - The 'distance' of the hit. What the distance actually represents depends on the rendering level of the viewport. For wireframe modes, it refers to the distance in the screen XY plane from the mouse to the sub-object component. In a shaded mode, it refers to the Z depth of the sub-object component. In both cases, smaller values indicate that the sub-object component is 'closer' to the mouse cursor. - - ulong hitInfo; - - A general unsigned long value. Most controllers will just need this to identity the sub-object element. The meaning of this value (how it is used to identify the element) is up to the plug-in. - - DWORD infoExtra; - - If the above hitInfo data member is not sufficient to describe the sub-object element this data member may be used as well. - - - - - Each maintains a pointer to another . This method returns the next hit record. - - - - - Description: - This class stores data about a single point on a curve used by the custom curve control. - Data Members: - p; - - The curve point. - - in; - - The in tangent, relative to p. - - out; - - The out tangent, relative to p. - - int flags; - - One or more of the following values which describes the type of curve point: - - CURVEP_BEZIER - - Indicates the point is a bezier smooth point. - - CURVEP_CORNER - - Indicates the point is a corner point. - - To get a Bezier Corner use: - - CURVEP_CORNER & CURVEP_BEZIER - - CURVEP_LOCKED_Y - - Indicates the point is locked in Y. - - CURVEP_LOCKED_X - - Indicates the point is locked in X. - - CURVEP_SELECTED - - Indicates the point is selected. - - CURVEP_ENDPOINT - - Indicates a constrained endpoint on the curve. - - CURVEP_NO_X_CONSTRAINT - - Indicates a point should not be constrained to X. - - - - - Description: - This class allow a plug-in particle system to provide its own custom drawing routine. Implement the DrawParticle() method of this class and register this callback with the SetCustomDraw() method of class . - - - - - Draws the 'i-th' particle of the specified particle system. - Parameters: - *gw - - The window into which to draw the particle. - - &parts - - The particle system whose 'i-th' particle is to be drawn. - - int i - - The index of the particle to draw. - - - - - Description: - This class represents the Custom Attributes. - - A sample on how to use this class is located in /MAXSDK/SAMPLES/HOWTO/CUSTATTRIBUTIL - - - - - A plugin can implement this method in order to provide the name that gets displayed in the TrackView and the name that is used internally. - Parameters: - bool localized - - If true, then the name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - - - Default Implementation: - { return "Custom Attribute";} - - - - - This method gets called when the material or texture is to be displayed in the material editor parameters area. The plug-in should allocate a new instance of a class derived from to manage the user interface. - Parameters: - HWND hwMtlEdit - - The window handle of the materials editor. - - *imp - - The interface pointer for calling methods in 3ds Max. - A pointer to the created instance of a class derived from . - Default Implementation: - {return NULL;} - - - - - This method will check if it possible to copy the current custom attributes to the specified custom attributes container. - Parameters: - *to - - A pointer to the custom attributes container you wish to check for possible reception of the custom attributes.. - TRUE if it is possible to copy, otherwise FALSE. - Default Implementation: - { return true; } - - - - - Description: - This is a class developer can use to provide a cylindrical gizmo helper object for their plug-ins. It provides implementations of all the required methods. The following #defines are used to access the parameters from the pblock pointer of the base class . - - The ClassID for this class is defined as: CYLGIZMO_CLASSID - - - - - Callback class that allows for hooking into 3ds Max's assertion mechanism. - - - Plugins can derive from this class and overwrite the CAssertCB::AssertEx method if they wish to execute a custom action, such as logging, when an assertion fails during execution of 3ds Max. See CAssertCB::AssertResult for more information on the customization options this callback mechanism offers. - - - - - Callback method invoked when an assertion fails. - - - One of the possible AssertResult values. - - - the line number where the assertion occurred - - the file path and name where the assertion occurred - - the non-decorated name of the function in which the assertion occurred - - the expression that was asserted - - - - The class stores job information which is of a dynamic nature or of variable length. - - - - - - - This method return the number of buffers in the list. Note: Developers should use Job.jobtextcount to find out how many elements there are. - - - - - This method will add another buffer. - The number of buffers. - - A pointer to the buffer to add. - - - - This method will delete one or a sequence of buffers. - - The position of the first index to be deleted. - The number of entries to delete. - - - - This method will reset and deallocate the buffers. - - - - - This method will return a pointer to the actual buffer. - - - - - This method returns the total size of the buffer. - - - - - This access operator returns a reference to a entry. - - The index of the buffer to return. - - - - This method allows you to search for a entry by its type. Refer to the list of Text types for details. - The index of the entry which was found, or -1 if not found. - - The Text type you wish to find. - The start position from which to initiate the search process. - - - - This method retrieves an index based on it's Text Type. Refer to JOB_TEXT_TYPE for details. - TRUE if the method was successful, otherwise FALSE. - - A pointer to the text buffer which will be filled in by the method. - The size in characters of the text buffer which will be filled in by the method. If the text buffer is not big enough to hold the output (including a null terminator), the result is truncated. - The Text type you wish to find. - The start position from which to retrieve the text item. - A pointer to the index found. - - - - This method will retrieve the user name associated with a job. - TRUE if the user name was retrieved, otherwise FALSE. - - The user name which was retrieved. - The size in characters of the user buffer which will be filled in by the method. If the user buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - - - This method will retrieve the computer name associated with a job. - TRUE if the computer name was retrieved, otherwise FALSE. - - The computer name which was retrieved. - The size in characters of the computer buffer which will be filled in by the method. If the computer buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - - - This method will retrieve the frame sequence (such as the "1,2,4,5-40" types). - TRUE if the frame sequence string was retrieved, otherwise FALSE. - - The frames retrieved. - The size in characters of the frames buffer which will be filled in by the method. If the frames buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - - - This method will retrieve the Manager's network share associated with a job. - TRUE if the network share was retrieved, otherwise FALSE. - - The network share which was retrieved. - The size in characters of the share buffer which will be filled in by the method. If the share buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - - - Description: - reflect changes with MAXBMPFileIcon class*** - - This object controls the overall operation of the individual CUI Frames (the name given to the windows that contain toolbars, menus, the command panel, etc.). There is one instance of this class (obtained by calling the global function GetCUIFrameMgr()). Methods of this class are available to do things like get pointers to button and status controls, and bring up the standard toolbar right click menu . - - Note: Developers may use their own images on icon buttons that are managed by this class but the following guidelines must be followed: - - BMP files must be put in the /UI/icons folder. This is the UI directory under the 3ds Max EXE directory. This is hard coded because it must be retrieved before 3ds Max is fully started and thus there is no configurable path for it. There is a command line option however, (-c), which specifies for 3ds Max to look in an alternate directory for the CUI file. In that case the bitmap files should be located in the same directory. - - For more information on the new icon image system refer to the chapter on ~{ Icons }~. - - - - - Returns the directory name of the custom user interface (CUI) file location. - - - - - This is a very important method. It redraws all the visible CUI buttons in 3ds Max, calling the "IsEnabled" and - "IsChecked" handlers on the ActionItems associated with each button (if it has one). If a the "IsEnabled" handler returns FALSE, the button is grayed out. If the "IsChecked" handler return TRUE, the button is draw pressed in. - - This method is called internally by the system on selection changes and command mode changes. This handles the majority of the cases where buttons need to be redrawn. However, if a 3rd party plug-in changes some sort of internal state that might affect the return value of an 's IsEnables or IsChecked handler, then the plug-in should call this method to update the button states. If this method isn't called, buttons may look disabled or pressed (or visa versa) when they shouldn't be. See Class . - - This parameter, if TRUE, tells the system to redraw the button even if its state hasn't changed since the last time it was redrawn. Normally this argument is FALSE so it only redraws the buttons that changed state. - - - - This method is for internal use only. - - - - - Returns the window handle for the item whose ID is passed. This correspond to the method in but which should no longer be called for Tool Palettes. It is now also a method of this class because the CUI system doesn't know which toolbar a particular button is on. For example, a 3ds Max user in 3.0 can drag a button from one tool palette to another. No longer then can one use the previous GetItemHwnd() method since the button has moved to a different toolbar. - - The ID of the control. - - - - Returns a pointer to the custom button whose ID is passed (or NULL if not found). In the implementation of this method it loops through each toolbar that it has control over and calls ICustToolbar::GetICustButton() on it. That method returns NULL if it doesn't find the specified ID. The keeps looping through the toolbars until it gets a non-NULL value. When it finds it it returns the pointer. - - The ID of the control. - - - - Returns a pointer to the custom status control whose ID is passed. - - Returns a pointer to the custom status control whose ID is passed (or NULL if not found). In the implementation of this method it loops through each toolbar that it has control over and calls ICustToolbar::GetICustStatus() on it. That method returns NULL if it doesn't find the specified ID. The keeps looping through the toolbars until it gets a non-NULL value. When it finds it it returns the pointer. - - The ID of the control. - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This returns the path to the CUI file in use. This may be a UNC name. - - - - - This method is for internal use only. - - - - - Returns the bitmap button image height for the specified size. - - The size to check. If 0 is passed then the current icon size is checked. One of the following values: - - - - Returns the bitmap button image width for the specified size. - - The size to check. One of the following values: - - - - This method is used internally to create a for a given object type. These methods retrieve the file name and base index in the file of the icon for the given object class. They are used in the constructor for that takes a class ID and super class ID. This method is for internal use only. - - - - - This method is used internally to create a for a given object type. These methods retrieve the file name and base index in the file of the icon for the given object class. They are used in the constructor for that takes a class ID and super class ID. This method is for internal use only. - - - - - This method is for internal use only. It is used to add images to the icon manager. The icon manager, which is used to implement the class, reads all the .bmp files in the UI/Icons directory at startup time. These icons are specified by an image file and an alpha mask. The icons support two sizes. Large, which is 24 by 24 and small, which is 15 by 16. The icon manager stores the unprocessed image and alpha masks (the "raw" images). Whenever an instance of needs to draw itself, it gets the image list and index of the icon in the imagelist using GetSmallImageIndex or GetLargeImageIndex. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - Plug-In developers should not call this method - it is for internal use only. - - - - - Plug-In developers should not call this method - it is for internal use only. - - - - - Returns TRUE if the layout is locker; FALSE if unlocked. - - - - - Given a configuration filename, will attempt to find the best match. - - - If the application is configured to use User Profiles, this function will attempt to match the filename in the user profile UI directory. If this fails, it will check the system directory. - - true if a match is found, false otherwise - - [in] the filename to match, with extension - [out] the resulting absolute path for the matched file, if found - - - - Given a configuration filename, will resolve the correct write absolute path. - - - If the application is configured to use User Profiles, this function map this configuration file to a user profile directory. Otherwise, the configuration file will be resolved to the legacy system UI directory. - true if resolved correctly, false if any error is encountered - - [in] the filename to match, with extension - [out] the resulting absolute path to which a client should write a config file - - - - A proxy for a class descriptor. Plug-ins do not need to work directly with this class. When a plug-in DLL is defer loaded, the plug-in classes it exposes are represented by instances of this class. When the instance does not have enough information to query out a request from client code, it will load the plug-in DLL which exposes the actual the is a proxy for. From that point on, the actual instance is used. When a instance is replaced by a full class descriptor, inside of ClassDirectory::AddClass then a notification is sent: - - - - - The category string. - - - - - The first ulong of the . - - - - - The second ulong of the . - - - - - The SuperClassID of the class. - - - - - The class name. - - - - - The non-localized class name. - - - - - If this plugin is public or not. - - - - - If it is OK to create. - - - - - Returns the number of file name extensions supported if this class descriptor represents a import or export plug-in. - - - - - The file name extension. - - - - - The short ASCII description. - - - - - The long ASCII description. - - - - - The export options. - - - - - The module capability flags. - - - - - For Modifiers. The first ulong of theModifier::InputType() . - - - - - For Modifiers. The second ulong of the Modifier::InputType(). - - - - - The scripter exposed non-localized internal name. - - - - - Description: - This mouse proc allows drawing in multiple viewports, offsetting from the contruction plane, and orthogonal and angle snapping. This allows developers to support orthogonal snapping and angle snapping on creation (as the Bezier line tool does). If the user presses Shift while dragging the mouse, the point is snapped to the nearest quadrant (ortho snapping). If the Alt key is held, the point is snapped using the setting of the angle snap system. - - The typical control flow of this class is that the OnPointSelected() method is called every time the user clicks in the viewport, and OnMouseAbort() is called when the user right clicks to finish the curve. RemoveLastPoint() is called when backspace is pressed, and & p) is called every time the mouse moves (this lets the developer update the curve continuously). - - This class is a sub-class of , but it can also be used as a to create curves from the creation panel. To do this you embed a in a as show below. Notice the implementation of the virtual member StartNewCreation(). This is a new virtual method on that tells the system whether the mouse proc is in a state ready to create a new object. This was required, becase the "proc" function now always returns "CREATE_STOP" in order to implement multi-viewport input. - - - Data Members: - protected: - - Object* mpObject; - - This a pointer to the object that is using the mouse proc. - - int mMouseClick; - - The number of clicks (i.e. selected points) the user has entered in creating this object. It is like the "point" parameter to "proc". - - > mPoints; - - These are the 3D values of the points the user has selected. - - > mClickPoints; - - These are the 2D viewport coordinates the user selected. - - BOOL mLiftOffCP; - - TRUE when in the mode where we lift off the construction plane - - - - - This method is called every time the user clicks in the viewport to enter data. This is the method in NURBS curves, for example, that adds a new CV or point to the curve. The method can query the mMouseClick member to see which point this is in the sequence (like the "point" parameter to traditional MouseCallback classes), and the 3D value of the point can be determined from mPoints[mMouseClick]. The data member mPoints contains all the 3D points selected, and mClickPoints is a table of the 2d points where the user clicked in the viewport. - The return value is used to determine whether the creation should continue or not. If it returns TRUE, more points are selected. If it returns FALSE, then the creation is done. In the case of NURBS, this is used to implement the feature that asks users if they want to close a curve when they click on the same point where they started the curve. If the answer is yes, this method returns FALSE, otherwise it always return TRUE. - Default Implementation: - {return TRUE; } - - - - - This method is called on every mouse move event. - Parameters: - & p - - The current point in world space of the mouse position. - Default Implementation: - {} - - - - - This method tells the system when to allow drawing in multiple viewports. - TRUE to allow drawing between viewports; FALSE to not allow drawing between viewports. - Default Implementation: - { return TRUE; } - - - - - This method is called when the backspace key is pressed. Typically this deletes the last point entered by the user so they may correct its entry. - Default Implementation: - {} - - - - - This method is called when the creation is finished. - Return one of the following value to indicate the state of the creation process: - - CREATE_CONTINUE - - The creation process should continue. - - CREATE_STOP - - The creation process has terminated normally. - - CREATE_ABORT - - The creation process has been aborted. The system will delete the created object and node. - Default Implementation: - { return CREATE_ABORT; } - - - - - This method indicates whether the mouse proc should perform redraws. When used in a , this should return FALSE. - TRUE to have the mouse proc perform redraws; otherwise FALSE. - Default Implementation: - { return TRUE; } - - - - - This method is called to tell the object to draw offset lines. This is called passing TRUE when the system enters the mode where points are lifted off the construction plane. It is telling the object that it needs to draw a line between the points supplied by p). It is called passing FALSE when the offset procedure is complete. - - To see an example of how this is used, create a NURBS Point curve, and press the key while laying down a point. It enters a mode that lets you lift the point off the construction plane, and draws a red dotted line back to the CP to give some visual feedback. - Parameters: - BOOL useLine - - TRUE if the mode is beginning; FALSE if it is ending. - - - - - These methods need to be implemented to get the offset line drawn - - This method is called with i==0 for the start point and with i==1 for the end point. - Parameters: - int i - - The point index: 0 for the start or 1 for the end. - - p - - The point to draw to or from. - - - - - Implemented by the System. - - This method clears the creation parameters. The data members are reset as follows: - - mMouseClick = 0; - - mPoints.SetCount(0); - - mClickPoints.SetCount(0); - - mLiftOffCP = FALSE; - - mPreviousFlags = 0; - - - - - Implemented by the System. - - This method sets the parameters as follows: - - mpObject = pObj; - - mCursor = cursor; - - mInstance = hInst; - - - - - Implemented by the System. - - This method sets the parameters as follows: - - mpObject = pObj; - - mCursorEnum = cursor; - - - - - - - The Default Action System interface. - - - This interface allows for associating default actions to be taken by the system (3ds Max) when certain predefined events occur, and managing these associations. Note that the default actions are carried out only when the system is runing in quiet mode, i.e. no dialogs are displayed. - - - - - Retrieves the action associated with an event. - - - - TRUE if an action was specified for the given event, otherwise FALSE. - - Identifier of a or a user defined one. - If an action was specified for the given event, it is returned through this argument. The default action value for events which have not had an action set is DEFAULTACTIONS_LOGTOFILE The returned value can be a combination of the following - - - - Sets the default action and descriptive title for an event. - - - Returns TRUE if a default action was previously associated with the event - - Identifier of a or a user defined one. - The to be taken when the specified event occurs. - The event's title. Appears in the log file or dialog displaying the messages associated with the event. - The old value can be returned via this argument - - - - Deletes the specified default action event. - - - Returns TRUE if the event was found and deleted - - Identifier of a or a user defined one. - - - - Retrieves the number of events registered with the Default Action System. - - - The number of events registered with the Default Action System. - - - - - Retrieves the title of the specified event. - - - The title of the specified event, or an empty string if the event is not found. - - Identifier of a or a user defined one. - - - - Retrieves the title of an event specified by its index in the Default Action System. - - - The title of the event at the specified index, or an empty string if there's no event with the specified index. - - The index of an event registered with the Default Action System - - - - Retrieves the id of an event specified by its index in the Default Action System. - - - The id of the event at the specified index. - - The index of an event registered with the Default Action System - - - - Logs a message for the specified event. - - - Returns TRUE if message was successfully logged. - - Identifier of a or a user defined one - The message to log for the specified event. The message is kept within the Defautl Action System. Use GetMsgLogMsg to retrieve messages logged for an event. - - - - Clears logged messages. - - - - Identifier of a or a user defined event. If eventID is 0, all messages are deleted, otherwise only messages for the specific event are deleted. - - - - Retrieves the number of logged messages. - - - The number of messages - - Identifier of a or a user defined event. If eventID is 0, all messages are counted, otherwise only messages for the specific event are counted. - - - - Retrives a specified logged message. - - - The message logged for the specified event, found at the specified index. - - Identifier of a or a user defined event. - The index of a logged message to be retrieved. - - - - Retrieves the event for a logged message. - - - The id of the event for which the message at the specified index was logged. - - The index of a message logged with the Default Action System. - - - - Sets the total maximum number of messages that can be logged with the Default Action Sustem. - - - The previous maximum number of messages. - - The maximum number of messages that can be logged. - - - - Describes a default light. An array of these default lights is passed into the method Renderer::Open(). - - Note: In 3ds Max 3.0 the production renderer has been modified so that if a is passed into Renderer::Open() with a transformation matrix that is all zeros, the renderer will interpret this to mean that on each frame it should create a light located at the view point, pointing in the view direction. This allows the implementation of the new viewport 1-light option so that it tracks the camera during an animated camera move. - - - - - Describes the properties of the light. - - - - - The transformation of the light that controls its position in the scene. - - - - - Implements a default version of a . - - - First clear the A_WORK2 flag on all objects being cloned. - Flag is set on all entries in remap directory. - - - used to set this flag on all entries in the remap directory. - - - - The callback object used by modifiers to deform "Deformable" objects. - - - - - DEPRECATED : See const version for help. REASON : Deformer::Map should have always been const, now it will be. This will allow us to accelerate the deformers using more aggressive threading. - - - - - Override this function and return true if your deformer implements Deformer::Map() const. - - - - - This is the method that is called to deform or alter a point normal. Note that this method needs to be thread safe, that is why it is const. If you absolutely must modify state inside of MapNormal, use a mutex. - By default, this will call your Map() implementation. Override this if you need different behavior when deforming normals. - The altered normal. - - The index of the normal to be altered. Note: An index of -1 may be passed. This indicates that the deformer is not being applied to a regular object but instead normals that are generated on the fly for display purposes. - The normal to be altered. - - - - Description: - This class is 3ds Max's implementation of Note Tracks. It provides implementation for the methods that let the keys work in Track . Developers use this class to access the table of keys associated with a track. Methods of class are available to get access to this class. - - - - - A to remove custom attribute containers and note tracks from a RefMaker and its references. - - - An instance of this class should be used if a session static RefMaker instance adds itself to TrackView, and re-adds itself to TrackView on a file reset. If this occurs, any custom attributes or note tracks that were applied to the static instance will still be present after the file reset. An instance of this class can be used to remove custom attributes or note tracks from the instance and its references. Example: - - - - - Description: - This class enables implementing undo of Gizmo deletion in Atmosphere and Effects classes. This class provides implementations of the methods. An instance of this class can be put on the when a Gizmo is deleted. For example: - All methods of this class are implemented by the System. - Data Members: - *fx; - - Points to the Atmosphere of . - - *node; - - Points to the gizmo node. - - int num; - - The index of the gizmo which is being deleted. - - - - - A callback class for enumerating dependents. - - - This class is a callback object for the ReferenceMaker::DoEnumDependentsImpl() and ReferenceMaker::DoEnumDependents() methods. The proc() method is called by the system. - - - - - This is the method called by system from ReferenceTarget::DoEnumDependentsImpl(). - - - One of the following values: - - - A pointer to the reference maker - - - - This method sets and checks whether a was visited. - - - This method is used to check whether a was previously visited by this callback object, and registers it as having been visited if not. This is used to only call the proc on each once. If you override ReferenceTarget::EnumDependentsImp, you should use this method to process your instance only if it was not previously visited. - Returns true of the rmaker was previously visited, false if not. - - - A pointer to the reference maker - - - - This is the method called by system from ReferenceTarget::DoEnumDependents() when entering enumerating dependents for an object. - - - - - A pointer to the reference maker - - - - This is the method called by system from ReferenceTarget::DoEnumDependents() when exitting enumerating dependents for an object. - - - - - A pointer to the reference maker - - - - Iterates through all direct dependents of a given . - - - Client code can simply instantiate an object of this type with the instance whose direct dependents need to be iterated on. Calling method DependentIterator::Next() will return the next that depends on the given . For instance, you can count the number of ReferenceMakers that depend on a using the following code: All methods of this class are implemented by the system. - Adding or deleting dependents to the after the instance has been created can invalidate the iterator and lead to undefined behaviour. - - - - - Returns a pointer to the next or NULL when there are no more. - - - - - Resets the iterator object so it starts at the beginning again with the original passed. - - - - - Represents a viewport rectangle, but with coordinates in the range [0..1] instead of in pixels. - - - - - Dialog resizing and positioning. A generic class for resizing a dialog. Includes functions to save and restore the initial size and position of the dialog. - - - This class makes it easy to add resizability to a dialog. You'll need one instance of this class for each instance of a dialog. up various parameters during your dialog's WM_INITDIALOG processing, then let this class handle all WM_SIZE events. - Include library: core.lib - HOW TO USE THIS CLASS: - - - - - Description: - This is a call-back class for the display filter list in the Hide by Category rollup of the Display command panel. This allows plug-ins to add additional filters to this list. - Data Members: - BOOL on; - - Determines if the callback is on or off. If a callback is selected in the list in the Display Panel list it is on; else it's off. - - - - - Returns the name that will appear in the drop down list in the display panel when the callback is registered. - - - - - This is the method that does the filtering of the node. It returns TRUE if the node is to be hidden; FALSE if it is not hidden. - - - Parameters: - SClass_ID sid - - The Super Class ID of the node. - - cid - - The Class ID of the node. - - *node - - Points to the node to check. - - - - - Called when the callback is registered via Interface::RegisterDisplayFilterCallback. - - - - - Called when the callback is unregistered via Interface.UnRegisterDisplayFilterCallback. Note that the instance can safely be deleted in this method. - - - - - A class for Dlls to use for info that will be sent back to them at load time. - - - - - This class models a plug-in DLL. 3ds Max creates an instance of this class for each plugin dlls that it loads. This class allows for querying a number of plug-in DLL properties and the plug-in classes that expose. - Plugins must be built with support for RTTI, and must export all of the following functions in order for them to be loaded into 3ds Max. Plugins may implement the following functions for added flexibility: Class represents the plug-in Dll "registry" and offers various way to get to instances. - - - - - Returns true if the corresponding plug-in has been successfully loaded and initialized, false otherwise or if the plug-in has been defer-loaded. - - - - - Returns the Description defined in the LibDescription function. - - - - - Returns the number of classes implemented in the DLL. This is the value returned by the library function LibNumberClasses. - - - - - Returns a pointer to the 'i-th' class descriptor. - Pointer to a class descriptor. - - - The zero based index of the to return. - - - - Returns a pointer to the 'i-th' class descriptor. This method is identical to DllDesc::operator[](int). - Pointer to a class descriptor. - - - The zero based index of the to return. - - - - Equality operator. Always returns zero. - - - - - Checks if this plugins dll was built with run-time type information (RTTI). - NumberOfClasses must return a positive non-zero value for the check to be performed - Returns true if the dll was built with RTTI, otherwise false. In the later case, the plugin dll will not be loaded into 3ds Max and DllDesc::IsLoaded() will return false. - - - - - Returns true if the plug-in DLL is binary compatible with the version of 3ds Max where it's being loaded into, false otherwise. If it return false the plugin dll will not be loaded into 3ds Max and DllDesc::IsLoaded() will return false. - - - - - Returns the value reported by the LibVersion() function implemented by the plug-in DLL. - - - - - Returns whether the corresponding plug-in DLL can be defer loaded or not. - - - - - Returns whether the corresponding plug-in DLL implements the CanAutoDefer function or not. - - - - - Returns the full path of the plug-in DLL file this instance of represents - - - - - Returns the file name and extension of the plug-in DLL this instance of represents - - - - - Returns the folder name with a trailing backslash of the plug-in DLL this instance of represents - - - - - Returns the module handle of the plug-in DLL represented by this instance. The module handle should not be used to load or unload the plug-in DLL. - - - - - Returns the size of the linear space that the plug-in DLL occupies in memory, in bytes, or 0 if the plug-in DLL is not loaded. - - - - - Represents the plug-in DLL "directory", which is a registry of every plug-in DLL loaded by 3ds Max. It also encapsulates the which is a registry of all classes implemented in the plug-in DLLs. The following diagram shows the relationship between the classes that make up the structure. The lines in the diagram indicate how the objects are accessed. Class provides access to a list of objects. Each of these has a list of objects. Class provides access to the a table of objects which are grouped by super class ID. Each has a series of objects. The object provides information about the plug-in classes (some of the same information as the class descriptor, usage counts, etc.). - - - is a singleton; its sole instance can be retrieved by DllDir::GetInstance() or Interface::GetDllDir(). All methods of this class are implemented by the system. - - - - - - Loads the specified plug-in dlls from all the plug-in folders that 3ds Max knows about. This method loads the specified plug-ins from the "stdplugs" and all the other folders specified in the Configure System Paths > 3rd Party Plug-ins list. - Nonzero if successful; zero on error. - - - that specifies via wildcard characters (* and ?) which plug-in dlls to load. - - If true the plug-in dll is guaranteed not to be defer loaded, otherwise the loading of the plug-in dll might be deferred to a later time. For more information see the topic called "Defer loading of plug-ins" in the 3ds SDK Programmer's Guide - - - - Loads plug-in DLLs from the specified directory. The default behaviour of this method is to defer the loading of a plug-in if possible. - Nonzero if successful; zero on error. - - - that specifies a valid path to load plug-in DLLs from. - - that specifies via wildcard characters (* and ?) which plug-in dlls to load. - - If true the plug-in dll is guaranteed not to be defer loaded, otherwise the loading of the plug-in dll might be deferred to a later time. For more information see the topic called "Defer loading of plug-ins" in the 3ds SDK Programmer's Guide - - - - Loads a given plug-in DLL. - - true if the plug-in was loaded successfully - - - The path and name of the plug-in dll to load - - If true the plug-in dll is guaranteed not to be defer loaded, otherwise the loading of the plug-in dll might be deferred to a later time. For more information see the topic called "Defer loading of plug-ins" in the 3ds SDK Programmer's Guide - - - - Returns the number of plug-in DLLs currently loaded. - - - - - Returns a reference to the i-th that represents a loaded plug-in dll - - - Zero based index of the loaded plug-in dll descriptors - - - - Returns a reference to the i-th that represents a loaded plug-in dll - - - Zero based index of the loaded plug-in dll descriptors - - - - Returns a reference to the . - - - - - Returns the that contains the definition of a class with the specified class and superclass IDs. - The object that owns the associated with this ID pairing, or NULL if no such exists. - - The super class ID. - The class ID. - - - - Returns the index within the DLL Directory () for a given full path. - the index to the or -1 if not found - - A fully-qualified path object to the dll represented by the desired object - - - - The base class from which specialized drag-and-drop handlers should be derived. - - - - - This method handles the process of the drag operation leaving the drop target window. - Parameters: - HWND window - - The specified handle to the window in which the drag and drop event is occurring. This is one of the windows that was enabled via a IDragAndDropMgr::EnabledDnD() call, so it may be the parent of the lowest-level window that the mouse is actually over. - Standard return values of E_OUTOFMEMORY, E_INVALIDARG, F_UNEXPECTED, and E_FAIL, S_OK. - Default Implementation: - { return E_FAIL; } - - - - - This is the high-level method called to handle drag and drop events with already recognized and parsed data object. Override the above methods as needed in your subclass to handle drag and drop events. - Parameters: - HWND window - - The specified handle to the window in which the drag and drop event is occurring. This is one of the windows that was enabled via a IDragAndDropMgr::EnabledDnD() call, so it may be the parent of the lowest-level window that the mouse is actually over. - - DropType* type - - The specified Pointer to the instance that corresponds to the data in the dropped IDataObject. You can use DropType::TypeCode()the method to determine the droptype (see the built-in codes in the section). Each subclass instance has utility methods and public data members containing the parsed drop data. See each subclass definition for details. - - DWORD grfKeyState - - The specified current state of the keyboard modifier keys on the keyboard. Valid values can be a combination of any of the flags MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON. - - POINT& pt - - The specified current cursor coordinates in the coordinate space of the drop-target window. - - DWORD* pdwEffect - - On entry, pointer to the value of the pdwEffect parameter of the DoDragDrop function. On return, must contain one of the effect flags from the Win32 DROPEFFECT enumeration, which indicates what the result of the drop operation would be. - Standard return values of E_OUTOFMEMORY, E_INVALIDARG, F_UNEXPECTED, and E_FAIL, S_OK. - Default Implementation: - { return E_FAIL; } - - - - - This method will parse the dropped dataObject. - - Here's an example implementation of Drop() in the default handler: - - - Parameters: - HWND window - - The specified handle to the window in which the drag and drop event is occurring. This is one of the windows that was enabled via a IDragAndDropMgr::EnabledDnD() call, so it may be the parent of the lowest-level window that the mouse is actually over. - - DropType* type - - The specified Pointer to the instance that corresponds to the data in the dropped IDataObject. You can use DropType::TypeCode()the method to determine the droptype (see the built-in codes in the section). Each subclass instance has utility methods and public data members containing the parsed drop data. See each subclass definition for details. - - DWORD grfKeyState - - The specified current state of the keyboard modifier keys on the keyboard. Valid values can be a combination of any of the flags MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON. - - POINT& pt - - The specified current cursor coordinates in the coordinate space of the drop-target window. - - DWORD* pdwEffect - - On entry, pointer to the value of the pdwEffect parameter of the DoDragDrop function. On return, must contain one of the effect flags from the Win32 DROPEFFECT enumeration, which indicates what the result of the drop operation would be. - Standard return values of E_OUTOFMEMORY, E_INVALIDARG, F_UNEXPECTED, and E_FAIL, S_OK. - Default Implementation: - { return E_FAIL; } - - - - - This method handles the process of dragging over a drop target. - Parameters: - HWND window - - The specified handle to the window in which the drag and drop event is occuring. This is one of the windows that was enabled via a IDragAndDropMgr::EnabledDnD() call, so it may be the parent of the lowest-level window that the mouse is actually over. - - DWORD grfKeyState - - The specified current state of the keyboard modifier keys on the keyboard. Valid values can be a combination of any of the flags MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON. - - POINT& pt - - The specified current cursor coordinates in the coordinate space of the drop-target window. - - DWORD* pdwEffect - - On entry, pointer to the value of the pdwEffect parameter of the DoDragDrop function. On return, must contain one of the effect flags from the Win32 DROPEFFECT enumeration, which indicates what the result of the drop operation would be. - - - Standard return values of E_OUTOFMEMORY, E_INVALIDARG, F_UNEXPECTED, and E_FAIL, S_OK. - Default Implementation: - { return E_FAIL; } - - - - - This method is called when the drag and drop manager starts managing a window for this handler. managing drag and drop events for a particular window for this handler. You can provide an implementation if you need to keep track of extant uses of the handler (say, by ref-counting) or to do handler-specific cleanup. - Default Implementation: - { } - - - - - This method is called called during a when the drag and drop manager stops managing drag and drop events for a particular window for this handler. - - - By default, the drag and drop manager will call this method on all registered 's during a NOTIFY_SYSTEM_SHUTDOWN broadcast. You should provide an implementation if you need to keep track of extant uses of the handler (say, by ref-counting) or to do handler-specific cleanup. - Default Implementation: - { } - - - - - This class provides a simplified way to draw a connected series of lines to the passed to the class constructor. - - - - - - Description: - is the base class for the various supported clipboard formats contained in a dropped IDataObject. Subclasses represent particular IDataObject clip format or package of related formats that can be accepted by various windows in 3ds Max. The prime responsibility of each is to recognize its presence in a dropped IDataObject and to parse the data object into one of the supported DropTypes. Each subclass should have a singleton instance created. This is automatically registered with the drag and drop system for use in the clipform recognition routines. - Data Members: - protected: - - <DropClipFormat*> clipFmts; - - The table of supported clip formats. - - - - - This method should be implemented by each subclass to detect the presence of its clipformat(s) in the given IDataObject. See ParseDataObject() below for a detailed example. - Parameters: - IDataObject* pDataObject - - The data object. - TRUE if the data was queries successfully, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method should be implemented by each subclass to parse its clipformat(s) in the given IDataObject into the corresponding subclass instance. For example, the DropClipFormats that accept dropped files will typically return one of the subclasses depending on the filename suffix. A list of built-in clipformats: - - iDrop XML package - VIZable file URL - internal dropScript - - Here's an example (simplified) implementation, which accepts a custom CF_MAXURL clip format containing the URL of a file. CheckClipFormat() returns true if it finds the CF_MAXURL clipboard format present in the given IDataObject. Because this is a dropping file, ParseDataObject() clears the current droptype data (the FileDropType::Init(), extracts the file name from the IDataObject and installs it into the current_package variable. It then asks the class to recognize the actual file type being dropped and return the corresponding subclass instance (using FileDropType::FindDropType()). - - - Parameters: - IDataObject* pDataObject - - The data object. - A pointer to the drop-type. - Default Implementation: - { return NULL; } - - - - - Description: - This class represents the internal drop script format. - - - - - Description: - This class is an intermediate base class for drop content that comes in the form of a dropScript. This is a special kind of macroScript that implements dropScript event handlers (see the DropScript documentation for details.) The prime subclass is which recognizes files of type .ds. The parsed data for this type is a single parsed macroScript, represented as a pointer. The class provides utility methods for compiling a .ds file into the current_dropscript slot and for running the drag and drop-associated handlers in the current dropScript. - - The methods RunDropScriptDragEnter(FPParams* params), RunDropScriptDragOver(FPParams* params) and RunDropScriptDrop(FPParams* params) take care of the 'on droppable' handler in the current_dropscript, if supplied. The DragAndDropHandler::DragEnter call is usualy made once on initial entry to a registered drag and drop target window and DragAndDropHandler::DragOver is usually called as the mouse moves over this window. In both cases, the handler returns true or false to indicate whether the dropping dropScript will be accepted. If a handler is not supplied, the dropScript is always deemed droppable. If the handler returns false, the not-droppable cursor is shown. - - The handler is called with a set of arguments, supplied by the , that usually depends on the window currently under the mouse pointer. For example, over a viewport, the current mouse coordinates, scene node under the mouse, slot number in a list window, etc. By convention, the first argument is positional and always a window type name, such as "Viewport" or "MaterialEditor", and all the others are keyword arguments, since they will vary from window to window. They are delivered to the RunDropScriptXXX methods in a ~{ Function Publishing }~ FPParam object, so that handler code needs to deal as little as possible with the MAXScript SDK. Here's an example code fragment from the default drop handler: - - - In the above code, the handler is called with 3 actual arguments, one position and two keyword. They are loaded into the 'params' instance with the varargs constructor. The first is the positional window name, in this case either #viewport or #max, then comes a special TYPE_KEYARG_MARKER signalling that the following arguments are keyword. The keyword args are given in pairs, name then value, in this case node: and point:. See the ~{ Function Publishing }~ system documentation for full details on using the class for passing parameter blocks. An example droppable handler might be as follows: - - on droppable window node: do - - return window == #viewport and superclassOf node == Shape - - This handler effectively makes the dropScript droppable if the mouse is over a Shape object in a viewport window. Notice that the function only looks at the node: keyword argument in this definition; arguments delivered as keyword arguments can vary from call to call and the called function can choose to look at only subset of them. - Data Members: - public - - static MacroEntry* current_dropscript; - - Cache for current macroScript. See /MAXSDK/INCLUDE/iMacroScript.h for the MacroScript manager public API. There are also utility methods in that do all the necessary drag and drop compiling & running of macroScripts, so you only have to deal with the MacroScript manager for special processing. - - - - - This method parses the given file, looking for a single macroScript definition. If successful, interns the macroScript and places its corresponding MacroEntry* in the current_dropscript static data member. Note that if there is more code than just a single macroScript in the file, only the last macroScript definition is taken; the other code is NOT executed, so you cannot include auxiliary global functions and other prep code in the file. These should be inside the body of the macroScript, as local data and functions. - Parameters: - MCHAR* filename - - The filename of the script. - TRUE if successfully compiled, otherwise FALSE. - - - - - This methods takes care of the 'on droppable' handler in the current_dropscript, if supplied. If the handler returns false, the not-droppable cursor is shown. - Parameters: - FPParams* params - - The set of arguments for the handler. - TRUE if droppable script will be accepted, otherwise FALSE. - - - - - This methods takes care of the 'on droppable' handler in the current_dropscript, if supplied, during the process of dragging contents over the drop target. If the handler returns false, the not-droppable cursor is shown. - Parameters: - FPParams* params - - The set of arguments for the handler. - TRUE if droppable script will be accepted, otherwise FALSE. - - - - - This methods takes care of the 'on droppable' handler in the current_dropscript, if supplied and handles the parsing of the dropped script. If the handler returns false, the not-droppable cursor is shown. - Parameters: - FPParams* params - - The set of arguments for the handler. - TRUE if droppable script will be accepted, otherwise FALSE. - - - - - This method will initialize a drag and drop check. - Parameters: - MacroEntry* dropscript - - The drop script macro entry. - - LPARAM mousePt - - The initial mouse cursor position. - - WPARAM keyState - - They initial state of the keyboard. - - HWND hwnd - - The handle to the initial start window. - - - - - Description: - This class represents the drop script file (*.ds, *.dse) and is available through the built-in type instance dropScriptFileDropType. - - - - - Description: - This is the base class for droppable content types. Distinguished instances of subclasses represent different types of drop content, such as a file distinguished by file suffix or a scene object The active parses dropped IDataObject into one of these dropped types, filling its data members with appropriate guff from the data object. - - Each can encompass multiple possible types of dropped data. For example, the iDrop package can drop max files, image files, script files, etc. The classes parse raw dropped clipboard data into one of the family of classes. These contain recognizer predicates, extracted data from the current drop, and utilities for working with the data, such as URL downloads, script compile & execution, etc. Custom drop-types can be created by subclassing one of the base classes. The built-in DropTypes are listed in DropTypes - Data Members: - protected: - - static IDragAndDropMgr* dndMgr; - - Cached pointer to the drag and drop manager. - - static bool dragging; - - The drop source state. - - static POINT startPt; - - The drag and drop starting point. - - static WPARAM startKeyState; - - They starting state of the keyboard. - - static HWND startWnd; - - The handle to the starting window. - - static bool loaded; - - Flags if the current packages is already downloaded. - - static IDataObject* current_dataobject; - - Currently dropping IDataObject. Filled in by the low-level DragEnter() code. - - - - - This method returns the typecode of the . - - - - - This method returns TRUE if the is of the specified code, otherwise FALSE. - - Each subclass is given a unique integer code that can be used for type-testing, switching, etc. The TypeCode() method must be implemented to return this code and isDropType() to test against the given code (this is provided to that intermediate base classes with codes can effectively support superclass testing). The codes for the built-in DropTypes are given by the following defined symbols which are listed in DropTypes - Parameters: - int code - - The code. - Default Implementation: - TypeCode(); } - - - - - Subclasses should implement this method if they need to perform any droptype-specific loading prior to clipformat data use. For example, the URL package types all download any web-resident files in this method. any implemented progress dialog with the showProgress parameter. - Parameters: - bool showProgress = true - - The download progress dialog can be displayed by passing true. - Default Implementation: - { return true; } - - - - - This method returns the dropeffect currently supported by the accepted dropping type. - Default Implementation: - { return DROPEFFECT_MOVE; } - - - - - Description: - This class represents a dummy helper object. There are several methods plug-ins may call to get and set the size, and set the color of the dummy object. These are used when a plug-in needs to create a dummy object in the scene. This class provides implementations of all the required methods of , , , , , and . All methods of this class are implemented by the system. - - - - - Returns the size of the dummy object box representation. - - - - - Sets the display color of the dummy object in its normal state (not selected or frozen). - - - - - Enables the dummy object so it may be displayed, hit tested, snapped, etc. - - - - - Prevents the dummy object from being displayed, hit tested, snapped, etc. - - - - - Description: - It is used to provide drag and drop functionality for Bitmaps. See the following global function for getting a pointer to the instances of this class. - - All methods of this class are implemented by the system. - - - - - Returns the name of the bitmap carrier. - - - - - Description: - Drag and drop functionality has been expanded to include all map and material buttons - including those in the non-standard materials, plus most cases of bitmap buttons. As a result, whenever you see a button representing a material or map you can drag the button over a like button to display the Swap/Copy/Cancel dialog. Likewise, you can drag any materials or maps from the modeless version of the Materials/Maps Browser. - - The drag-and-drop functions distinguish between material maps and bitmaps. A bitmap is an image file, such as a .tga, or .jpg. A map is an image used by the Materials Editor. It might consist of an image file, but could just as easily be a parametric image, such as Checkers or Noise, or it could be a map tree consisting of several different types of maps or bitmaps. Users can drag any map slot or button to any other map slot or button - including the sample slots. Users can drag the button in the Parameters rollout to the button in the Image area of the Displace modifier, and vice-versa. - - Users can drag from: - - Sample slots - - Browser lists (text or iconic) - - The sample-sphere preview window in the Browser. - - map buttons, including: - - The buttons in the Maps rollout - - The shortcut map buttons - - Any map buttons at any level - - Submaterial buttons, such as those found in the Multi/Subobject material - - Projector light map button - - Environment background map button - - Fog and Opacity maps buttons - - Users can drag to: - - Objects in the viewports - - The Type button in the Materials Editor from the Browser. - - All of the items in the FROM list, with this exception: You can only drag to the Browser when it displays the material library. - - All methods of this class are virtual. For developers of plug-in textures and materials see Class , Class . These classes provide implementations of these methods and the objects can simply be used. - - - - - This method is called on the item that supports drag and drop to see what (if anything) can be dragged from the point p. This method returns a super class id to indicate the type of item that can be dragged away. If it does not support anything being dragged from the specified point a SClass_ID of 0 should be returned. - Parameters: - HWND hwnd - - The source window handle - - POINT p - - The screen point (relative to the window upper left as 0,0). - - - - - If the method GetInstance() creates a new instance every time it is called, then the this method should return TRUE. Otherwise it should return FALSE. This prevents GetInstance() from being called repeatedly as the drag progresses. - Parameters: - HWND hwnd - - The source window handle. - - POINT p - - The point to drag from. - - SClass_ID type - - The super class ID to create. - Default Implementation: - { return FALSE; } - - - - - This method is called on potential dropee to see if can accept the specified type at the specified point. - Parameters: - *dropThis - - A pointer to the item to check. - - HWND hfrom - - The window handle of the source. - - HWND hto - - The window handle of the destination. - - POINT p - - The point to check. - - SClass_ID type - - The super class ID of dropThis. - - BOOL isNew = FALSE - - TRUE if the item is a new instance; otherwise FALSE. - TRUE if the specified item can be dropped; otherwise FALSE. - - - - - This method is called on a potential target to allow it to substitute custom cursors. It returns the handle for the custom cursor to use (or NULL to ignore). - Parameters: - *dropThis - - The pointer to the item to check. - - HWND hfrom - - The window handle of the source. - - HWND hto - - The window handle of the destination. - - POINT p - - The point to check. - - SClass_ID type - - The super class ID of dropThis. - - BOOL isNew = FALSE - - TRUE if the item is a new instance; otherwise FALSE. - Default Implementation: - { return NULL;} - - - - - Returns a predefined value to indicate the source of the drag. - One of the following values: - - OWNER_MEDIT_SAMPLE - - From a materials editor sample slot. - - OWNER_NODE - - From a node in the scene. - - OWNER_MTL_TEX - - From a button in a material or texture. - - OWNER_SCENE - - From a button in a light, modifier, atmospheric effect, etc. - - OWNER_BROWSE_NEW - - From the browser in the new category. - - OWNER_BROWSE_LIB - - From the browser in the library category. - - OWNER_BROWSE_MEDIT - - From the browser in the materials editor category. - - OWNER_BROWSE_SCENE - - From the browser in the scene category. OWNER_MATERIAL_EXPLORER - - From the material explorer. - Default Implementation: - { return OWNER_MTL_TEX; } - - - - - Return a pointer to the drag source. - Parameters: - HWND hwnd - - The source window where the mouse down occurred. - - POINT p - - The point to drag from (position within hwnd). - - SClass_ID type - - The super class ID of the item to create. - - - - - Return a pointer to the drag destination. For window which won't scroll automatically during drag and drop, just use the default implementation. - Parameters: - HWND hwnd - - The destination window where the mouse up occurred. - - POINT p - - The point to drop to (position within hwnd). - - SClass_ID type - - The super class ID of the item. - Default Implementation: - { return GetInstance(hwnd, p, type); } - - - - - This is the method called to actually process the drop operation. This routine is called on the target with the pointer returned by the source's GetInstance(), or possibly a clone of it as the dropThis. - Parameters: - *dropThis - - A pointer to the item to drop. - - HWND hwnd - - The destination window handle (where the mouse was released). - - POINT p - - The destination point (within hwnd). - - SClass_ID type - - The type of object being dropped - the super class ID of dropThis. - - DADMgr* srcMgr - - The source pointer. NULL by default. - - BOOL bSrcClone - - TRUE if the dropThis is a clone of the drag source object, FALSE otherwise. FALSE by default - - - - - This method is called when the source and target WINDOW are the same. - Parameters: - HWND h1 - - The source/target window handle. - - POINT p1 - - The source point. - - POINT p2 - - The target point. - Default Implementation: - {} - - - - - This lets the manager know whether to call LocalDragAndDrop() if the same is handling both the source and target windows, or just ignore this condition. Return TRUE if LocalDragAndDrop() should be called; otherwise FALSE. - Default Implementation: - { return 0; } - - - - - This is called if the same is handling both the source and target windows, if LetMeHandleLocalDAD() returned TRUE. - Parameters: - HWND h1 - - The window handle. - - HWND h2 - - The window handle. - - POINT p1 - - The drag source point. - - POINT p2 - - The drop destination point. - Default Implementation: - {} - - - - - If this method returns TRUE, then Custom Buttons that use this DAD Manager will automatically support a tooltip that matches the button text. Note that this method will only show a tooltip when the button text is too long and thus exceeds the button size. - Default Implementation: - { return FALSE; } - - - - - If a drag source doesn't want any references being made to the instance returned, then this method should return TRUE: it will force a copy to be made; otherwise return FALSE. - Parameters: - HWND hwnd - - The source window handle. - - POINT p - - The source point (within hwnd). - - SClass_ID type - - The type of object being dragged. - - - Default Implementation: - { return FALSE; } - - - - - Normally the mouse down and mouse up messages are not sent to the source window when doing drag and drop, but if you need them, return TRUE. - Default Implementation: - { return FALSE; } - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - Parameters: - int cmd - - The command to execute. - - ULONG arg1=0 - - Optional argument 1 (defined uniquely for each cmd). - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - - - - This method is called on potential target to see if can instance "dropThis" at the specified point. Returns TRUE if it is okay to drop the specified item and FALSE if not. - Parameters: - *dropThis - - The pointer to the item to check. - - HWND hfrom - - The window handle of the source. - - HWND hto - - The window handle of the destination. - - POINT p - - The point to check. - - SClass_ID type - - The super class ID of dropThis. - Default Implementation: - { return TRUE; } - - - - - This class represents a 2D box described by two double-precision 2D corner coordinates. provides methods that return individual coordinates of the box, scale and translate it, retrieve its center, modify its size, expand it to include points or other boxes, and determine if points are inside the box. All methods are implemented by the system. - - - - - The minimum 2D point in this box - - - - - The maximum 2D point in this box - - - - - Initializes this box such that pmin is a very large value while pmax is a small value. Thus the box is 'empty'. See - - - - - Returns the minimum corner value. - the value of corner pmin - - - - - Returns the maximum corner value. - the value of corner pmax. - - - - - Returns the center of this as a . - the center of the box - - - - - Returns the width of the box as a . This is pmax-pmin. - the width of the box - - - - - Expands this to include the p. - the resulting box - - the to include in the new size - - - - Expands this to include the specified . - the resulting box - - the box to include in the new size - - - - Scales this box about its center by the specified scale. - - Specifies the scale factor for this . - - - - Translates this box by the distance specified. The point is added to each corner. - - Specifies the distance to translate the box. - - - - Enlarges this box. A is created from s as and added to pmax and subtracted from pmin. If the box is 'empty', the box is centered at (0,0) and then enlarged. - - the amount to enlarge the box on all sides - - - - Determines if the box is empty. This indicates the box has not had specific values set by the developer. - Nonzero if the box is empty; otherwise 0. - - - - - Determines if the specified point p is contained in this box. - Nonzero if the specified point is contained in this box, otherwise 0. - - Specifies the point to check. - - - - Determines if the specified is contained totally within this box. - Nonzero if the specified box is entirely contained within this box; otherwise 0. - - Specifies the box to check. - - - - Determines if the specified overlaps this box. - Nonzero if the specified box overlaps this box; otherwise 0. - - Specifies the box to check. - - - - - - - - This clears the MAT_IDENT flag to indicate the matrix is not the identity. Non-const GetAddr() calls this for you. - - - - - Returns the identity flags. - - - - - Returns TRUE if the matrix is the identity matrix (based on the flags); otherwise FALSE. - - - - - This method may be used to recompute the *_IDENT flags for this matrix. For instance, if you call a method, such as INode::GetObjTMAfterWSM(), and it returns a matrix, you cannot use the IsIdentity() method to check if the matrix is indeed the identity. This is because the flags that method checks are not initialized by the method. What you can do however is call this method first. This will validate the flags in the matrix so they accuratly reflect the properties of the matrix. If after calling this method, and then calling IsIdentity(), the proper result would be returned. - - - - - Initializes the matrix with the row data passed and validates the matrix flags. - A reference to this matrix. - - The data for row 0. - The data for row 1. - The data for row 2. - The data for row 3. - - - - Compares the elements of this matrix and the one specified element by element for exact equality. Returns nonzero if they are equal; otherwise zero. - - The matrix to compare against. - - - - Compares the elements of this matrix and the one specified element by element for equality within the specified tolerance epsilon. Returns nonzero if they are 'equal'; otherwise zero. - - The matrix to compare against. - The tolerance for comparison. If the values in the matrix are within this value (+ epsilon or - epsilon) they are considered equal. - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Multiplies this by the specified (*this = (*this)*M;). - Multiply this matrix on the right by Matrix m. - A reference to this matrix - - The matrix multiplied to the right of this matrix - - - - Multiplies each element of this by a double. - a reference to this matrix - - The scale to apply to each element of this matrix - - - - this matrix to the Identity Matrix. - - - - - This method sets all elements of the matrix to 0.0f - - - - - Returns the specified row of this matrix. - - Specifies the row to retrieve. - - - - Sets the specified row of this matrix to the specified values. - - Specifies the row to set. - The values to set. - - - - Returns the 'i-th' column of this matrix. - - Specifies the column to get (0-2). - - - - Sets the 'i-th' column of this matrix to the specified values. Note : Clears the matrix flags. - - Specifies the column to set (0-2). - The values to set. - - - - Returns the upper three entries in the specified column. - - Specifies the partial column to get (0-2). - - - - This method zeros the translation portion of this matrix. - - - - - This method zeros the rotation and scale portion of this matrix. - - - - - This method zeros the scale portion of this matrix without orthogonalization. If the matrix was sheared (skewed) then this method is not able to remove the scale component completely. In that case, use the Orthogonalize() method instead to remove the scale component entirely. Read the SCL_IDENT flag to check whether the NoScale() method was enough to make the matrix to be orthogonal (with perpendicular axes of unit length). - - - - - Ortho-normalize the matrix. This ensures that each axis of the basis is of length 1 and at right angles to the other. This is an "unbiased" orthogonalization, which means that no single axis is used as the basis for the other axis, and all axis will be modified equally. - - This is an iterative process, and should not be used in high-performance situations. It seems to take a maximum of 4 iterations to converge. - - - - - A version of Orthogonalize() that uses the previous less-accurate version of the DPoint::operator + - - - - - Sets the specified component of the translation row of this matrix to the specified value. The POS_IDENT flag is cleared. - - Specifies the component of the translation row of this matrix to set. - The value to set. - - - - Returns the translation row of this matrix. - The translation row of this matrix. - - - - - Apply an incremental translation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the translation. - - - - Apply an incremental X rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the X rotation in radians. - - - - Apply an incremental Y rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the Y rotation in radians. - - - - Apply an incremental Z rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the Z rotation in radians. - - - - Apply an incremental scaling transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - The scale values. - If set to TRUE, the translation component is scaled. If trans = FALSE the translation component is unaffected. When 3ds was originally written there was a bug in the code for this method where the translation portion of the matrix was not being scaled. This meant that when a matrix was scaled the bottom row was not scaled. Thus it would always scale about the local origin of the object, but it would scale the world axes. When this bug was discovered, dependencies existed in the code upon this bug. Thus it could not simply be fixed because it would break the existing code that depended upon it working the incorrect way. To correct this the trans parameter was added. If this is set to TRUE, the translation component will be scaled correctly. The existing plug-ins don't use this parameter, it defaults to FALSE, and the code behaves the old way. - - - - Apply an incremental translation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. param p Specifies the translation distance. - - - - - Apply an incremental X rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the X rotation in radians. - - - - Apply an incremental Y rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the Y rotation in radians. - - - - Apply an incremental Z rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the Z rotation in radians. - - - - Apply an incremental scaling transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - The scale values. The translation component is unaffected. - - - - Sets this matrix to the identity and the translation components to the specified values. - - The translation values to store. - - - - Sets this matrix to the identity and the rotation components to the specified X rotation. - - The angle for X rotation (in radians). - - - - Sets this matrix to the identity and the rotation components to the specified Y rotation. - - The angle for Y rotation (in radians). - - - - Sets this matrix to the identity and the rotation components to the specified Z rotation. - - The angle for Z rotation (in radians). - - - - Sets the rotation components of the matrix as specified by the quaternion. The translation and scale components will match the identity matrix. - - Specifies the rotation to use for the matrix. - - - - Sets the rotation components of the matrix as specified by the . The translation and scale components will match the identity matrix. - - Specifies the rotation to use for the matrix. - - - - Sets the rotation components of this matrix using yaw, pitch and roll angles. There are many different conventions for specifying a rotation by means of three Euler angles. This function uses the convention of rotating around the world Z axis, then the X axis, then the Y axis; the three arguments are given in the order Y, X, Z. - - This one is equivalent to: - - M.IdentityMatrix(); - - M.RotateZ(roll); - - M.RotateX(pitch); - - M.RotateY(yaw); - - - Which presupposes Y is vertical, X is sideways, Z is forward - - The yaw angle in radians. - The pitch angle in radians. - The roll angle in radians. - - - - Sets the rotation portion of the matrix to the rotation specified by the angle and axis and sets the translation portion to zeros. - - The axis of rotation. - The angle of rotation about the axis in radians. - - - - Sets the scale components of this matrix to the specified values. The other components to this matrix will match the identity. - - The scale factors for the matrix. - - - - This creates a matrix describing a viewpoint which is at the 'from' location, looking toward the 'to' location; the viewpoint is tilted so that the 'up' vector points to the top of the view. - - This specifies the viewpoint source location. - This vector specifies the direction of view. - This vector points to the top of the view. - - - - This method performs an in-place inversion on this matrix. An inverted matrix, when multiplied by the original, yields the identity. - - - - - Perform matrix multiplication. - - - - - Perform matrix addition. - - - - - Perform matrix subtraction. - - - - - Returns the specified point transformed by this matrix. - - The point to transform by this matrix. - - - - Returns the specified vector transformed by this matrix. - - The vector to transform by this matrix. - - - - Transforms the specified list of points with this matrix. - - The array of points to transform with this matrix. - The number of points in the array. - The size of the increment used when moving to the next point. If you wish to transform an array of data objects which contain x, y, and z coordinates in order (such as a , or a structure containing a as a member) you can specify a 'stride' value (for instance sizeof(data_object)). - - - - Transforms the specified list of points with this matrix and stores the resulting transformed points in the storage passed. - - The array of points to transform (the source). - The array to store the transformed points (the destination). - The number of points in the source array. - The size increment used when moving to the next source location. - The size increment used when moving to the next storage location. - - - - Transforms the specified list of vectors with this matrix. - - The array of vectors to transform with this matrix. - The number of vectors in the array. - The size of the increment used when moving to the next vector. If you wish to transform an array of data objects which contain x, y, and z coordinates in order (such as a , or a structure containing a as a member) you can specify a 'stride' value (for instance sizeof(data_object)). - - - - Transforms the specified list of vectors with this matrix and stores the resulting transformed vectors in the storage passed. - - The array of vectors to transform (the source). - The array to store the transformed vectors (the destination). - The number of vectors in the source array. - The size increment used when moving to the next source location. - The size increment used when moving to the next storage location. - - - - Retrieves the yaw, pitch and roll angles represented by the rotation in this matrix. - - The yaw rotation angle is stored here (in radians). - The pitch rotation angle is stored here (in radians). - The roll rotation angle is stored here (in radians). - - - - Save this to disk - IO_OK on success, or a failure code - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - The interface responsible for actually saving the data - - - - Load the data for this . - IO_OK on success, or a failure code - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - The interface responsible for actually loading the data - - - - Returns the 'parity' of the matrix. Scaling one axis of the matrix negatively switches the 'parity'. However if you scale two axis the parity will flip back. Scaling three axis switches the parity again. - - When rendering a mesh, if you scale something along one axis, it turns 'inside out'. That is the direction when the normals are reversed. This method may be used to detect that case and then reverse the normals. The 3ds Max renderer does this - if this method returns TRUE it flips all the normals so it won't turn inside out. - - - - - Converts to a - the concersion to - - - - - Copies a matrix3 into the - - - - - Description: - This structure is passed to the method Control::GetDOFParams(). Controllers that support IK can provide information about their Degree Of Freedoms (DOFs) so that bones can display this information. The first 3 DOFs are assumed to be position and the next 3 are assumed to be rotation - Data Members: - BOOL display[6]; - - Indicates if this DOF should be displayed. - - axis[6]; - - Specifies the DOF axis. - - pos[6]; - - Specifies the base of the axis. - - BOOL limit[6]; - - Indicates if the joint is limited at all. - - float min[6]; - - Specifies the minimum limit. - - float max[6]; - - Specifies the maximum limit. - - float curval[6]; - - Specifies the current value of the parameter. - - BOOL sel[6]; - - Indicates if the DOF should be highlighted. - - BOOL endEffector; - - Indicates if there is an end effector for this controller. - - eeTM; - - Specifies the world transformation matrix of the end effector (if present). - - - - - Description: This class describes a 2D point using double precision x and y coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, and element by element multiply and divide two points. All methods are implemented by the system. - - - - - Assign a to this - - - - - const for (0,1) - - An index of 0 will return x, 1 will return y. - - - - - Unary - operator. Negates both x and y - - - - - Unary +. Returns this point unaltered. - - - - - Subtracts a from this . - the resulting - - the value to subtract from this - - - - Adds a to this . - the resulting - - the value to add to this - - - - Member-wise multiplication of two vectors: (x*x, y*y) - the resulting - - the multiplier - - - - Member-wise division of two vectors - the resulting - - the multiplier - - - - Each element of this is increased by the specified double. - - - - - Each element of this is decreased by the specified double. - - - - - Each element of this is multiplied by the specified double. - the resulting - - the multiplier - - - - Each element of this is divided by the specified double. - the resulting - - the divisor - - - - Subtracts a from a . - the resulting - - the value to subtract from this - - - - Adds a to a . - the resulting - - the value to add to this - - - - Member-wise multiplication of two vectors: (x*x, y*y) - the resulting - - the multiplier - - - - Member-wise division of two vectors: - the resulting - - the multiplier - - - - Returns the dot product of two DPoint2s. - - - - - Returns the dot product of two DPoint2s. - - - - - The 'Length' squared of this point. This is v.x*v.x+v.y*v.y. - the length value - - - - - Returns the 'Length' of this point (vector). This is: - - sqrt(v.x*v.x+v.y*v.y). - the length value - - - - - In place normalize - the normalized value - - - - - Returns the component with the maximum abs value. 0=x, 1=y. - - - - - Returns the component with the minimum abs value. 0=x, 1=y. - - - - - Returns a unit vector. This is a with each component divided by the point Length(). - the unit vector for the specified - - - - - Equality operator. Compares two 's. - - - - - Returns true if the absolute difference between point components is less or equal to the given epsilon for each component - - - - - class Description: This class describes a 3D point using double precision x, y and z coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, and element by element multiply and divide two points. All methods are implemented by the system. Data Members: double x,y,z; - - - - - const for (0,0,1) - - An index of 0 will return x, 1 will return y, 2 will return z. - - - - - Unary - operator. Negates both x, y and z. - - - - - Unary +. Returns the point unaltered. - - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Member-wise multiplication of two vectors. - - - - - Member-wise, in-place division of this vector. - - - - - Adds floating point value to this . - - - - - Subtracts floating point value from this . - - - - - Each element of this is multiplied by the specified double. - - - - - Each element of this is divided by the specified double. - - - - - Subtracts a from a . - - - - - Adds a to a . - - - - - Divides a by a element by element. - - - - - Member-wise multiplication of two vectors: (x*x, y*y, z*z) - - - - - The 'Length' squared of this point. - - - - - Returns the 'Length' of this point (vector) - - - - - Returns unit vector in the same direction as this point - - - - - in place normalize - - - - - The largest axis - - - - - The smallest axis - - - - - Equality operator. Test for equality between two 's. - true if the 's are equal. - - - - - Equality operator. Test for nonequality between two 's. - true if the 's are not equal. - - - - - Returns true if the absolute difference between point components is less or equal to the given epsilon for each component - - - - - The dot product of two 's (vectors). - - - - - Computes the cross product of this and the specified . - - - - - - - - - This class describes a vector in space using an origin point p, and a unit direction vector in double precision. - - - - - Description: - This class is simply a table of DWORDs (32-bit values.) - - - - - Description: - This class represents a list of ease curves. - - The macro used to access this class is defined as follows: This may be used to access the methods of this class as follows: - - All methods of this class are implemented by the system. - - - - - Returns a TimeValue that reflects the TimeValue passed modified by each of the enabled ease curves in the list. - - - The base time which is eased by the curves. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Adds the specified ease curve to the end of the ease curve list. - Parameters: - *cont - - Points to the ease curve to append. - - - - - Deletes the 'i-th' ease curve in the list. - Parameters: - int i - - The index of the ease curve to delete. - - - - - Disables the 'i-th' ease curve in the list. - Parameters: - int i - - The index of the ease curve to disable. - - - - - Enables the 'i-th' ease curve in the list. - Parameters: - int i - - The index of the ease curve to enable. - - - - - Returns TRUE if the 'i-th' ease curve is enabled; otherwise FALSE. - Parameters: - int i - - The index of the ease curve to check. - - - - - Returns the 'i-th' ease curve. - Parameters: - int i - - The index of the ease curve to return. - - - - - Returns the number of ease curves in the list. - - - - - Description: - This is a list of edge "clusters" for a given mesh. A typical application would be in Edit(able) , where the user has selected a two separate groups of edges on different parts of the mesh and wants to extrude them both, or rotate both around their local centers. Each "cluster" is a contiguous group of selected edges. Like AdjEdgeLists and AdjFaceLists, this class is only defined in relation to some mesh. - - Note: for construction of this list, an edge is considered selected on both sides if it's selected on either. If you select the diagonal on top of a box, you probably only selected one of (face 2, edge 2 = 8) or (face 3, edge 2 = 11). But edges 8 and 11 will both be in the same cluster. - Data Members: - clust; - - The cluster IDs of all the edges - this table has size mesh::numFaces*3. clust[i] is UNDEFINED if edge i is not in any cluster (ie is totally unselected). - - DWORD count; - - The number of clusters. - - - - - Returns the cluster ID for face f, edge e. - Parameters: - int f - - The index of the face in the mesh. - - int e - - The index of the edge in the mesh. - - - - - Access operator. Returns the cluster ID for edge i (indexed as 3*face+edge). - - - - - This method extracts normal and center information for the various clusters of the mesh. - Parameters: - &mesh - - The mesh to evaluate. - - > & norm - - This table has its sizes set to the number of clusters in the cluster list. Normals are computed as the normalized average of the area-normal vectors of all faces in the cluster. - - > & ctr - - This table has its sizes set to the number of clusters in the cluster list. Centers are the average location of the face centers or edge centers - thus a point on three faces or edges in the same cluster has more weight than a point on one face in the cluster. - - - - - Edit Soft Selection Callback used to control the new Edit Soft Selection Command Mode. - - - New to 3ds max 2009, the new pure virtual base class, , is to be used to interact with the new Edit Soft Selection which let's you interactively set soft selection's falloff, pinch and bubble parameters. The normal use will be to create a subclass of this class which implements the given pure virtual functions and then pass this object it in as a parameter to the constructor. - - - - - Accept an operation. - - - This operation will be called whenever an operation is finished and the client needs to perform some acceptance operation. - - The current time. - - - - the falloff. - - - This operation will be called whenever the falloff needs to be set. - - The current time. - The soft selection falloff value that should get saved locally. - - - - the bubble parameter. - - - the internal, current soft selection bubble value. - - The current time. - The soft selection bubble value that should get saved locally. - - - - Get the falloff parameter. - - - Get the internal, current soft selection falloff value. - - The current time. - - - - Get the pinch parameter. - - - Get the internal, current soft selection pinch value. - - The current time. - - - - Get the bubble parameter. - - - Get the internal, current soft selection bubble value. - - The current time. - - - - Edit Soft Selection Command Mode for interactively setting soft selection parameters. - - - This Edit Soft Selection is a new command mode that lets the user interactive set a soft selections fallout, pinch and bubble parameters. To use this class the client needs to implement the virtual base class - - - - - Description: - This is the base class used in the creation of Rendering plug-ins. In 3ds Max 3.0 these plug-in are added in sequence after a rendering is complete without the use of Video Post. A developer creates a sub-class of this class and implements or calls the methods shown below. - - Plug-In Information: - - Class Defined In RENDER.H - - Super Class ID RENDER_EFFECT_CLASS_ID - - Standard File Extension DLV - - Extra Include File Needed None - - There are also methods in the class for manipulating the Effects List: - - virtual int NumEffects()=0; - - *GetEffect(int i)=0; - - virtual void SetEffect(int i,Effect *e)=0; - - virtual void AddEffect(Effect *eff)=0; - - virtual void DeleteEffect(int i)=0; - - - - - Returns a DWORD that indicates the channels that this requires in the output bitmap. - Parameters: - TimeValue t - - The time at which the channels are required. - The required channels. See Image (G-Buffer) Channels. - Default Implementation: - { return 0; } - - - - - This is the method that is called to apply the effect to the bitmap passed. - Parameters: - TimeValue t - - The time at which to apply the effect. - - *bm - - The bitmap the effect modifies and stores the result in. - - *gc - - This can be used to retireve information about the global rendering enviornment. - - *cb - - Points to an object whose Check() method may be called to determine if the user wants to abort. See Class . - - - - - Extension to class , new to 3ds max 8. - This class extends the class through the addition of new methods. - All new plugins should derive from the class. All existing should ideally be re-compiled and derived from this class. - An Effect8* can easily be retrieved from an & by calling: Effect8::GetEffect8(Effect& effect) - - - - - Returns wether the given bitmap is supported by the effect. The implementation should usualy check the bitmap type (bitmap.Storage()->Type()) to determine whether it supports that type. - Usage example: An effect plugin which uses the version of Bitmap::GetPixels() will work with 32bit floating-point bitmaps, but will clamp the colors and should therefore be considered incompatible. An effect plugin which uses the version of Bitmap::GetPixels() can be considered as compatible with all bitmap types. - To check whether an effect supports a given bitmap, it is advised to call the static method Effect8::SupportsBitmap(Effect&, Bitmap&) instead of this. The static method handles class as well as and implements appropriate default behaviour for class . - true if the bitmap is supported by this render effect, false otherwise. - - - The bitmap to be tested for compatibility. - - - - A mini Max class descriptor. This is purely to instantiate multiple objects, and query the ID for the DLL. - - - - - Called by the system to create an instance of the parser. - - - A valid pointer to the parser - - - - - The unique ID that is used in the effect file. - - - The system will look at the effect file and then will get the ID. it will then use this ID to query for a parser - The ID of this parser - - - - - The string to go along with the extension supported to be displayed in the Open Dialog box. - - - This should be in the form "Microsoft Direct3D Effects" - - - - - Get the support file extension for the parser. - - - The system will filter "like" extensions. This is only used for the open dialog box. The ParamID is still used to define the actual parser to use. THe string should be in the form "*.fx" - - - - - Description: - Event router functionality. All methods of this class are implemented by the system. - - - - - Register and activate an event user. - Parameters: - *user - - The to activate. - - - - - Remove an event user from the list (automatically re-activates the previous user). - Parameters: - *user - - The to remove. - - - - - Process the event. - TRUE if the event was handed off to a user. - - - - - Description: - This is a generic event notification system. The only two places this is currently used are for when the Delete key is pressed or the Delete menu item is selected, and when the Backspace key is pressed. The usage can be seen in /MAXSDK/SAMPLES/MODIFIERS/EDITPAT.CPP, where the Edit modifier sets up for notification of Delete operations. It is also used in EDITSPL.CPP where it deals with deletion of selected items. - - To use it: - - 1. Create an object. - - 2. Register the object with the appropriate router. - - 3. The will call the 's Notify() method when the event occurs. - - 4. When you're done with the object, call the 's UnRegister() method. This will delete the from the router's notification system. - - 5. If your code is part of a window proc, call the router's Register and UnRegister methods when the window receives WM_ACTIVATE messages. This will properly uncouple the notification system when the window is deactivated. - - - - - - This is the proc called by the when the event occurs. - - - - - Description: - This class represents an exclusion list and is a direct parallel to the , and converting from using one to the other is fairly simple. - - - - - Sets the specified flag to the specified value. - Parameters: - ULONG f - - The flag(s) to set. One or more of the following values: - - NT_INCLUDE - - This bit is used to indicate "Include" mode. - - NT_AFFECT_ILLUM - - This bit is used to indicate the "Illumination" check box in the exclusion list dialog. - - NT_AFFECT_SHADOWCAST - - This bit is used to indicate the "Shadow Casting" check box in the exclusion list dialog. - - BOOL b=1 - - The value to set. - - - - - Returns TRUE if the specified flag(s) are set; otherwise FALSE. - Parameters: - ULONG f - - The flag(s) to set. One or more of the following values: - - NT_INCLUDE - - This bit is used to indicate "Include" mode. - - NT_AFFECT_ILLUM - - This bit is used to indicate the "Illumination" check box in the exclusion list dialog. - - NT_AFFECT_SHADOWCAST - - This bit is used to indicate the "Shadow Casting" check box in the exclusion list dialog. - - - - - This method returns the number of handles in the table. - - - - - Index operator. - - - - - This method allows you to set a specified entry in the table to the specified node. - Parameters: - int i - - The index in the table. - - *node - - The node to set. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - Returns the index of the node passed; otherwise returns -1. - Parameters: - *node - - The node to find. - - - - - Appends the specified node to the end of the list. - Parameters: - *node - - The node to add. - Returns the number of items in the list prior to appending. - - - - - Removes thes node from the list. - Parameters: - *node - - The node to remove. - - - - - Removes the 'i-th' name from the list. - Parameters: - int i - - Specifies the index of the node to remove. - - - - - Sets the size of the list. If the new size is smaller than the current size entries are deleted. - Parameters: - int num - - Specifies the size of the list. - - - - - Loads this from disk. - Parameters: - *iload - - This class provides methods to load data from disk. - - - - - Saves this to disk. - Parameters: - *isave - - This class provides methods to save data to disk. - - - - - This method takes care of setting the merge manager interface. - Parameters: - IMergeManager* imm - - A pointer to the merge manager interface. - - - - - A callback object that will get called before the program exits. - - - Register an instance of this class with Interface::RegisterExitMAXCallback. During normal shutdowns, the Exit method will be called. The Exit method is not called during shutdown after crash recovery. - - - - - Method called on normal shutdown - FALSE to abort the exit, TRUE otherwise. - - - MAX main window handle is passed in. - - - - A callback object that will get called before the program exits. - - - Register an instance of this class with Interface8::RegisterExitMAXCallback. During normal shutdowns, the ExitMAXCallback::Exit method will be called. During shutdown after crash recovery, the CrashRecoverExit method will be called. Since it is being called after crash recovery, the scene may or may not be in a stable state, do only absolutely necessary actions here. - - - - - Method called on shutdown after crash recovery. - - - - - MAX main window handle is passed in. - - - - This is the inteface class to implement in order to support exposure controls. - - - Description: - This class is an extension to allow maxscript to determine whether a material's shaded output is to be processed by a tone operator and whether the self-illumination, reflection or refraction channels are to be inverted by the tone operator so the actual rgb values will appear in the display. - - This class is added to materials that want to expose control over the results of the exposure control on the shaded output of the material. This is useful when a material knows the specific RGB value to appear in the rendered image, and does not want this color to be adjusted. For example, a material might already perform its own physically-based lighting calculations with handling for image exposure. Or, in the case of specialty "non-physical" materials, it might be inappropriate to perform exposure adjustments on the color. - - You determine whether a material allows this control by asking for the interface. If the interface is present, then you can set values. This is how you ask for the interface: A material can support this interface by deriving from this class and handling the GetInterface() method as follows: There are four properties in the interface, each with a get and a set method. Use the get method to get the current value and set to set a new value for the property. - - The properties are: - Also, if you want your material's methods to be exposed to MAXScript, you can derive from . - - - - - Returns the NoExposure property. If this returns true, the shaded output of the material is NOT processed by the exposure control. When the property is false the shaded output is processed by the exposure control. This is useful for materials that aren't interacting with lighting that want specific RGB values to end up in the rendered image. - true if the material should NOT be processed by the exposure control. - - - - - Gets the InvertSelfIllum property: When this property is true, the self-illumination portion of the shaded output is converted from RGB to a physical value, so that the physical value gives the original RGB value when processed by the exposure control. When the property is false the self-illumination value is converted by multiplying by the physical scale. This is useful if the self-illumination value is a RGB value that you want preserved, but you also want lighting to interact with the material. - the value of Invert Self Illumination property - - - - - Gets the InvertReflect property: When this property is true, the reflection map portion of the shaded output is converted from RGB to a physical value so that the physical value gives the original RGB value when processed by the exposure control. When the property is false the reflection map value is converted by multiplying by the physical scale. This is useful if the reflection value is not being calculated by the renderer from the scene. - the state of the InvertReflect property - - - - - Gets the InvertRefract property: When this property is true, the refraction map portion of the shaded output is converted from RGB to a physical value so that the physical value gives the original RGB value when processed by the exposure control. When the property is false the refraction map value is converted by multiplying by the physical scale. This is useful if the reflection value is not being calculated by the renderer from the scene. - the state of the InvertRefract property - - - - - Save the plugin parameters to disk. - This is implemented by the system to save the exposure parameters, any child classes that override this function should explicitly call the parent classes Save. An example of how to do this is as follows The implementation is as follows - - - - - Load the plugin parameters. - This is implemented by the system to load the exposure parameters, any child classes that override this function should explicitly call the parent classes Load. An example of how to do this is as follows The implementation is as follows - - - - - This implementation of is to be used to implement the interface. - - - - - Description: - This class may be used by developers to parse mathematical expressions. The expression is created as a character string using a straightforward syntax. Expressions consist of operators (+, -, *, /, etc.), literal constants (numbers like 180, 2.718, etc.), variables (single floating point values or vector () values), and functions (mathematical functions that take one ore more arguments and return a result). The return value from the expression may be a floating point value or a vector. There are many built in functions, operators and constants available for use. - - All methods of this class are implemented by the system. - - Developers wishing to use these APIs should #include /MAXSDK/INCLUDE/EXPRLIB.H and should link to /MAXSDK/LIB/EXPR.LIB. - - Sample code using these APIs is shown below, and is also available as part of the expression controller in /MAXSDK/SAMPLES/CONTROLLERS/EXPRCTRL.CPP. - - Variables may be defined and used in expressions. Variable names are case sensitive, and must begin with a letter of the alphabet, but may include numbers. They may be any length. To create a named variable, you use the method defVar(). This takes a name and returns a register number. Defining the variable creates storage space in a list of variables maintained by the parser, and the register number is used as an array index into the variable value arrays passed into the expression evaluation method (eval()). - - To use the variable in an expression just use its name. For example if you define a variable named radius, you can use it in an expression like: 2*pi*radius. To give the variable a value, you define two arrays of variables and pass them to the evaluation method (eval()). There is one array for scalar variables, and one for vector variables. You pass these arrays along with the number of variables in each list. See the sample code below for an example. - - The order of calling the methods of this class to evaluate an expression is as follows: - - Declare an expression instance ( expr;) - - Define the expression (char e1[] = "2*pi*radius";). - - Define any variables (expr.defVar(SCALAR_VAR, _M("radius"));) - - Load the expression (expr.load(e1);) - - Evaluate the expression (expr.eval(...);) - - There are no restrictions on the use of white space in expressions - it may be used freely to make expressions more readable. In certain instances, white space should be used to ensure non-ambiguous parsing. For example, the x operator is used for to compute the cross product of two vectors. If a developer has several vectors: Vec, Axis and xAxis and wanted to compute the cross product, VecxAxis is ambiguous while Vec x Axis is not. - - All the necessary information to evaluate an expression is completely stored within an expression object. For example, if you are passed a pointer to an expression object for which some variables have been defined that you knew the value of, you could get all the information you needed from the expression object to completely evaluate the expression. This includes the expression string, variable names, variable types, and variable register indices. - - For complete documentation of the built in functions please refer to the 3ds Max User's Guide under Using Expression Controllers. Below is an overview of the operators, constants and functions that are available: - Expression Operators: - Scalar Operators - - Operator Use Meaning - - + p+q addition - - - p-q subtraction - - - -p additive inverse - - * p*q multiplication - - / p/q division - - ^ p^q power (p to the power of q) - - ** p**q same as p^q - - Operators - - = p=q equal to - - < p<q less than - - > p>q greater than - - <= p<=q less than or equal to - - >= p>=q greater than or equal to - - | p|q logical OR - - & p&q logical AND - - Vector Operators - - + V+W addition - - - V-W subtraction - - * p*V scalar multiplication - - V*p " - - * V*W dot product - - x VxW cross product - - / V/p scalar division - - . V.x first component (X) - - . V.y second component (Y) - - . V.z third component (Z) - Built-In Constants: - pi 3.1415... - - e 2.7182... - - TPS 4800 (ticks per second) - Expression Functions: - Trigonometric Functions - - The angles are specified and returned in degrees. - - sin(p) sine - - cos(p) cosine - - tan(p) tangent - - asin(p) arc sine - - acos(p) arc cosine - - atan(p) arc tangent - - Hyperbolic Functions - - sinh(p) hyperbolic sine - - cosh(p) hyperbolic cosine - - tanh(p) hyperbolic tangent - - Conversion between Radians and Degrees - - radToDeg(p) takes p in radians and returns the same angle in degrees - - degToRad(p) takes p in degrees and returns the same angle in radians - - Rounding Functions - - ceil(p) smallest integer greater than or equal to p. - - floor(p) largest integer less than or equal to p. - - Standard Calculations - - ln(p) natural (base e) logarithm - - log(p) common (base 10) logarithm - - exp(p) exponential function - exp(e) = e^p - - pow(p, q) p to the power of q - p^q - - sqrt(p) square root - - abs(p) absolute value - - min(p, q) minimum - returns p or q depending on which is smaller - - max(p, q) maximum - returns p or q depending on which is larger - - mod(p, q) remainder of p divided by q - - Conditional - - if (p, q, r) works like the common spreadsheet "if" - if p is nonzero - - then "if" returns q, otherwise r. - - Vector Handling - - length(V) the length of V - - unit(V) returns a unit vector in the same direction as V. - - comp(V, I) i-th component, where I=0, 1, or 2. - - comp([5,6,7],1) = 6 - - Special Animation Functions - - noise(p, q, r) 3D noise - returns a randomly generated position. - - p, q, and r are random values used as a seed. - Sample Code: - The following code shows how the expression parser can be used. This code evaluates several expressions and displays the results in a dialog box. Both scalar and vector variables are used. One expression contains an error to show how error handling is done. - - - - - - - This method is used to load an expression for parsing. An error code is returned indicating if the expression was loaded. A successfully loaded expression is then ready for evaluation with the eval() method. - Parameters: - char *s - - The expression to load. - See Expression Return Codes - - - - - This method is used to evaluate the expression loaded using load(). It returns either a scalar or vector result. - Parameters: - float *ans - - The numeric result of the expression is returned here, i.e. the answer . For scalar values this is a pointer to a single float. For vector values, ans[0] is x, ans[1] = y, ans[2] = z. You can determine which type of result is returned using the method getExprType(). - - int sRegCt - - The number of items in the sRegs array of scalar variables. - - float *sRegs - - of scalar variables. - - int vRegCt=0 - - The number of items in the vRegs array of vector variables. - - *vRegs=NULL - - of vector variables. - See Expression Return Codes - - - - - Returns the type of expression. See Expression Types - - - - - Returns a pointer to the currently loaded expression string. - - - - - If there was an error parsing the expression, this method returns a string showing what portion of the expression was parsed before the error occurred. - - - - - Defines a named variable that may be used in an expression. - Parameters: - int type - - The type of variable. See Expression Variable TypesMCHAR *name - - The name of the variable. This name must begin with a letter, may include numbers and may be any length. - The register number (into the sRegs or vRegs array passed to eval()) of the variable. - - - - - This method returns the number of variables defined of the specified type. When you call eval() on an expression, you must make sure that the variable arrays (sRegs and vRegs) are at least the size returned from this method. - Parameters: - int type - - See Expression Variable Types - - - - - Returns the name of the variable whose index is passed, or NULL if the variable could not be found. - Parameters: - int type - - The type the variable. See Expression Variable Typesint i - - The register number of the variable. - - - - - When you define a variable with defVar(), you get a back a register number. If your code is set up in such a way that saving that register number is not convenient in the block of code that defines it, you can use this method later on to find out what that return value had been. For example, one piece of code might have: - - expr->defVar(SCALAR_VAR, "a"); // not saving return value... - - expr->defVar(SCALAR_VAR, "b"); - - and then right before evaluating the expression, you might have some code such as: - - for(i = 0; i < expr->getVarCount(SCALAR_VAR); i++) - - if(_tcscmp("a", expr->getVarName(SCALAR_VAR, i) == 0) - - aRegNum = expr->getVarRegNum(SCALAR_VAR, i); - - Of course, this is a bit contrived - most real examples would probably have tables to store the variable names, register numbers, etc. and thus would not need to call this method. It is available however, and this makes the expression object self-contained in that everything you need to evaluate an expression with variables (other than the variable values themselves) is stored by the expression object. - Parameters: - int type - - See Expression Variable Typesint i - - The variable index returned from the method defVar(). - The register index for the variable whose type and index are passed. - - - - - Deletes all the variables from the list maintained by the expression. - TRUE if the variables were deleted; otherwise FALSE. - - - - - Deletes the variable whose name is passed from the list maintained by the expression. Register numbers never get reassigned, even if a variable gets deleted. For example, if you delete variables 0-9, and keep variable 10, you're going to need to pass in an array of size at least 11 to the eval() method, even though the first 10 slots are unused. - Parameters: - MCHAR *name - - The name of the variable to delete. - TRUE if the variable was deleted; otherwise FALSE (the name was not found). - - - - - Compares this class instance to another one - - - - - Description: - Export class. A data member of this class allows the plug-in to enumerate all nodes in the scene. - Data Members: - *theScene; - - A pointer to the scene. See Class . - - - - - Compares this class instance to another one - - - - - Description: - The class is the main interface to the Editable Poly . This class is a virtual class with no data members. More details can be found in the SDK samples under /MAXSDK/SAMPLES/MESH/EDITABLEPOLY. - - - - - This method is used to indicate to the that some parts of its mesh have changed. This is automatically handled by most methods; you only need to use it if you're directly manipulating the mesh yourself. - Parameters: - ChannelMask channels - - Parts of the mesh that have been changed, such as GEOM_CHANNEL, TOPO_CHANNEL, etc. - Default Implementation: - { } - - - - - This method invalidates soft selection values in the mesh and in any cached data. - Default Implementation: - { } - - - - - This method invalidates pre-computed distances on which soft selection values are based (as well as soft selection values) - note this is automatically done when you call LocalDataChanged(GEOM_CHANNEL). This should also be done if the soft selection parameters are changed. - Default Implementation: - { } - - - - - This is a handy method that does a simple call to ip->RedrawViewports. Also updates the named selection dropdown list. Also, if the project has been compiled as a debug build, it will verify that the is free of errors using the MNMesh::CheckAllData method. - Default Implementation: - { } - - - - - This method indicates if the Editable Poly object is currently being edited in the modifier panel (and has its UI present). - Default Implementation: - { return FALSE; } - - - - - - - This method returns the selection level, as defined by the ePolySelLevel enum: One of the following values; EP_SL_OBJECT, EP_SL_VERTEX, EP_SL_EDGE, EP_SL_BORDER, EP_SL_FACE, EP_SL_ELEMENT. - Default Implementation: - { return EP_SL_OBJECT; } - - - - - This method returns the 's selection level, as defined by the PMeshSelLevel enum in MNMesh.h: one of the following; MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, MNM_SL_FACE. (Note that the Editable Poly selection levels EP_SL_BORDER and EP_SL_ELEMENT are considered varieties of MNM_SL_EDGE and MNM_SL_FACE selection types, respectively.) - Default Implementation: - { return MNM_SL_OBJECT; } - - - - - This method fills in a depending on whether or not each in the has a particular flag or set of flags set or cleared. - - Example: for instance to set the according to selected vertices, you'd just call EpGetVerticesByFlag (vset, MN_SEL). But to find vertices which do not have the MN_DEAD flag set, but which do have the MN_WHATEVER flag set, you'd call EpGetVerticesByFlag (vset, MN_WHATEVER, MN_WHATEVER|MN_DEAD). - Parameters: - & vset - - The array for output to be stored in. The vset will be set to size of the number of verts in the mesh. - - DWORD flags - - The flags we're looking for in the vertices - - DWORD fmask=0x0 - - The mask of flags we're checking. This is automatically or'd with "flags". - TRUE if successful, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method fills in a depending on whether or not each in the has a particular flag or set of flags set or cleared. - - Example: for instance to set the according to selected edges, you'd just call EpGetEdgesByFlag (eset, MN_SEL). But to find edges which do not have the MN_DEAD flag set, but which do have the MN_WHATEVER flag set, you'd call EpGetEdgesByFlag (eset, MN_WHATEVER, MN_WHATEVER|MN_DEAD). - Parameters: - & vset - - The array for output to be stored in. eset will be set to size of the number of edges in the mesh. - - DWORD flags - - The flags we're looking for in the edges - - DWORD fmask=0x0 - - The mask of flags we're checking. This is automatically or'd with "flags". - TRUE if successful, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method fills in a depending on whether or not each in the has a particular flag or set of flags set or cleared. - - Example: for instance to set the according to selected faces, you'd just call EpGetFacesByFlag (fset, MN_SEL). But to find faces which do not have the MN_DEAD flag set, but which do have the MN_WHATEVER flag set, you'd call EpGetFacesByFlag (fset, MN_WHATEVER, MN_WHATEVER|MN_DEAD). - Parameters: - & vset - - The array for output to be stored in. fset will be set to size of the number of faces in the mesh. - - DWORD flags - - The flags we're looking for in the faces - - DWORD fmask=0x0 - - The mask of flags we're checking. This is automatically or'd with "flags". - TRUE if successful, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method sets flags based on a . - - Example: to hide vertices specified by the , you'd just call EpSetVertexFlags (vset, MN_HIDE). To unhide the vertices, you'd use EpSetVertexFlags (vset, 0, MN_HIDE). - Parameters: - & vset - - This bitarray indicates which vertices should have their flags modified. - - DWORD flags - - The flags to set. - - DWORD fmask=0x0 - - The flag mask - if it includes bits not in "flags", those bits are cleared in the specified vertices. - - bool undoable=true - - If (undoable && theHold.Holding()), a restore object for this flag change will be added to the current undo stack. - Default Implementation: - { return; } - - - - - This method sets flags based on a . - - Example: to select edges specified by the , you'd just call EpSetEdgeFlags (eset, MN_SEL). To clear selection on the edges, you'd use EpSetEdgeFlags (eset, 0, MN_SEL). - Parameters: - & vset - - This bitarray indicates which edges should have their flags modified. - - DWORD flags - - The flags to set. - - DWORD fmask=0x0 - - The flag mask - if it includes bits not in "flags", those bits are cleared in the specified edges. - - bool undoable=true - - If (undoable && theHold.Holding()), a restore object for this flag change will be added to the current undo stack. - Default Implementation: - { return; } - - - - - This method sets flags based on a . - - Example: to hide faces specified by the , you'd just call EpSetFaceFlags (fset, MN_HIDE). To unhide the faes, you'd use EpSetFaceFlags (fset, 0, MN_HIDE). - Parameters: - & vset - - This bitarray indicates which faces should have their flags modified. - - DWORD flags - - The flags to set. - - DWORD fmask=0x0 - - The flag mask - if it includes bits not in "flags", those bits are cleared in the specified faces. - - bool undoable=true - - If (undoable && theHold.Holding()), a restore object for this flag change will be added to the current undo stack. - Default Implementation: - { return; } - - - - - - - Completes the action corresponding to the specified UI button. - Parameters: - int opcode - - The list of "button operations" is defined by the epolyButtonOp enum. - - Select dialog button operations: - - epop_hide: Hide current selection - - epop_unhide: Unhide current selection - - epop_ns_copy: Copy named selection (brings up UI) - - epop_ns_paste: Paste named selection (may bring up UI) - - Edit Geometry dialog button operations: - - epop_cap: Cap currently selected borders - - epop_delete: Delete current selection. - - epop_detach: Detach current selection. - - epop_attach_list: Attach any number of nodes using the attach by name dialog. - - epop_split: Split currently selected edges. - - epop_break: Break currently selected vertices - - epop_collapse: Collapse current selection - - epop_reset_plane: Reset the slice plane - - epop_slice: Slice - - epop_weld_sel: Weld current vertex or edge selection - - epop_create_shape: Create a shape from current edge selection (brings up UI) - - epop_make_planar: Make current selection planar - - epop_align_grid: Align current selection to construction grid - - epop_align_view: Align current selection at right angles to view. - - epop_remove_iso_verts: Remove isolated vertices - - Subdivide dialog button operations: - - epop_meshsmooth: Subdivide by MeshSmooth (NURMS Style) - - epop_tessellate: Subdivide by Tessellation - - Surface Properties dialog button operations: - - Level: - - epop_update: Update MeshSmooth subdivision - - Vertex Level: - - epop_selby_vc: Select by vertex color - - Level: - - epop_retriangulate: Retriangulate currently selected faces - - epop_flip_normals: Flip normals on currently selected elements - - epop_selby_matid: Select faces by ID (brings up UI) - - epop_selby_smg: Select faces by smoothing groups (brings up UI) - - epop_autosmooth: Autosmooth currently selected faces - - epop_clear_smg: Clear all smoothing groups on currently selected faces. - - - Default Implementation: - { } - - - - - If the user is currently in the specified command mode, this method causes them to exit it. If the user is not, this method will enter it. - Parameters: - int mode - - The list of command modes is defined by the epolyCommandMode enum and is given here for reference. (Their names are self-explanatory.) - - epmode_create_vertex - - epmode_create_edge - - epmode_create_face - - epmode_divide_edge - - epmode_divide_face - - epmode_extrude_vertex (note: currently inactive) - - epmode_extrude_edge (note: currently inactive) - - epmode_extrude_face - - epmode_chamfer_vertex - - epmode_chamfer_edge - - epmode_bevel - - epmode_sliceplane - - epmode_cut_vertex - - epmode_cut_edge - - epmode_cut_face - - epmode_weld - - epmode_edit_tri - - - Default Implementation: - { } - - - - - This method enters the specified pick mode, which is like a command mode but relates to picking nodes. - Parameters: - int mode - - Currently there is only one pick mode supported by , which is defined in the epolyPickMode enum: epmode_attach, which allows the user to pick a node to attach to this Editable Poly object. - Default Implementation: - { } - - - - - This method exits from any command mode the system currently may be in. - Default Implementation: - { } - - - - - - - This method moves the current selection (including any soft selection) by the specified amount in the specified coordinate system. - Parameters: - int level - - The enum ePolySelLevel, being one of the following values; EP_SL_OBJECT, EP_SL_VERTEX, EP_SL_EDGE, EP_SL_BORDER, EP_SL_FACE, EP_SL_ELEMENT. - - TimeValue t - - The time at which to apply the move operation. - - & partm - - The parent transformation matrix. - - & tmAxis - - The transformation axis. - - & val - - The vector describing the translation. - - BOOL localOrigin - - TRUE to move based on the local origin, otherwise FALSE. - Default Implementation: - { } - - - - - This method rotates the current selection (including any soft selection) by the specified amount in the specified coordinate system. - Parameters: - int level - - The enum ePolySelLevel, being one of the following values; EP_SL_OBJECT, EP_SL_VERTEX, EP_SL_EDGE, EP_SL_BORDER, EP_SL_FACE, EP_SL_ELEMENT. - - TimeValue t - - The time at which to apply the rotate operation. - - & partm - - The parent transformation matrix. - - & tmAxis - - The transformation axis. - - & val - - The rotation quaternion. - - BOOL localOrigin - - TRUE to rotate based on the local origin, otherwise FALSE. - Default Implementation: - { } - - - - - This method scales the current selection (including any soft selection) by the specified amount in the specified coordinate system. - Parameters: - int level - - The enum ePolySelLevel, being one of the following values; EP_SL_OBJECT, EP_SL_VERTEX, EP_SL_EDGE, EP_SL_BORDER, EP_SL_FACE, EP_SL_ELEMENT. - - TimeValue t - - The time at which to apply the rotate operation. - - & partm - - The parent transformation matrix. - - & tmAxis - - The transformation axis. - - & val - - The scaling value. - - BOOL localOrigin - - TRUE to scale based on the local origin, otherwise FALSE. - Default Implementation: - { } - - - - - This method applies a geometric "delta" vector to the current mesh at the specified time. (Note: if t!=0 and the system's animate feature is on, this will set keys.) - Parameters: - > & delta - - The table of geometry delta vectors. - - *epol - - A pointer to the editable poly object to apply to. - - TimeValue t - - The time at which to apply the geometric delta. - Default Implementation: - { } - - - - - - - This method resets the slice plane. - Default Implementation: - { } - - - - - This method returns the slice plane, as defined by its normal, center, and size. (Size is irrelevant for slicing, but defines the size of the slice gizmo the user sees.) - Parameters: - & planeNormal - - The plane normal vector. - - & planeCenter - - The plane center. - - float *planeSize=NULL - - The size of the plane. - Default Implementation: - { } - - - - - This method sets the slice plane to have the specified normal, center, and size. (Unlike in EpGetSlicePlane(), size is not an optional argument here.) - Parameters: - & planeNormal - - The plane normal vector. - - & planeCenter - - The plane center. - - float planeSize - - The size of the plane. - Default Implementation: - { } - - - - - - - This method obtains the vertex color for the flagged vertices in the indicated map channel. - Parameters: - bool *uniform=NULL - - If non-NULL, the bool this pointer points to is set to true if all flagged vertices have the identical color, and false otherwise. (It's set to true if there are 0 vertices.) - - int *num=NULL - - If non-NULL, the number of vertices currently flagged is computed and stored here. - - int mp=0 - - The map channel we're using. Most vertex color applications use the standard vertex color channel, 0. However, you can also use this method with the Illumination channel (MAP_SHADING = -1) or the alpha channel (MAP_ALPHA = -2) - or even with a regular UVW map channel (1-99). - - DWORD flag=MN_SEL - - This indicates the vertices we look at. If left at the default, selected vertices' colors are analyzed. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors analyzed. - - TimeValue t=0 - - This is not currently used. - The color of the flagged vertices, or black (0,0,0) if the vertices' colors are not the same. - Default Implementation: - ; } - - - - - This method sets the vertex color for the flagged vertices in the indicated map channel. - Parameters: - clr - - The color to set the vertices to. - - int mp=0 - - The map channel we're using. Most vertex color applications use the standard vertex color channel, 0. However, you can also use this method with the Illumination channel (MAP_SHADING = -1) or the alpha channel (MAP_ALPHA = -2) - or even with a regular UVW map channel (1-99). - - DWORD flag=MN_SEL - - This indicates which vertices we set. If left at the default, selected vertices' colors are set. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors set. - - TimeValue t=0 - - This is not currently used. - Default Implementation: - { } - - - - - This method obtains the face color for the flagged faces in the indicated map channel. - Parameters: - bool *uniform=NULL - - If non-NULL, the bool this pointer points to is set to true if all flagged faces have the identical color, and false otherwise. (It's set to true if there are 0 flagged faces.) - - int *num=NULL - - If non-NULL, the number of faces currently flagged is computed and stored here. - - int mp=0 - - The map channel we're using. Most vertex color applications use the standard vertex color channel, 0. However, you can also use this method with the Illumination channel (MAP_SHADING = -1) or the alpha channel (MAP_ALPHA = -2) - or even with a regular UVW map channel (1-99). - - DWORD flag=MN_SEL - - This indicates which vertices we set. If left at the default, selected vertices' colors are set. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors set. - - TimeValue t=0 - - This is not currently used. - The color of the flagged faces, or black (0,0,0) if the faces' colors are not the same. - Default Implementation: - ; } - - - - - This method sets the vertex color for the flagged faces in the indicated map channel. - Parameters: - clr - - The color to set the faces to. - - int mp=0 - - The map channel we're using. Most vertex color applications use the standard vertex color channel, 0. However, you can also use this method with the Illumination channel (MAP_SHADING = -1) or the alpha channel (MAP_ALPHA = -2) - or even with a regular UVW map channel (1-99). - - DWORD flag=MN_SEL - - This indicates which vertices we set. If left at the default, selected vertices' colors are set. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors set. - - TimeValue t=0 - - This is not currently used. - Default Implementation: - { } - - - - - This method obtains floating-point vertex data from the flagged vertices in the specified vertex data channel. - Parameters: - int channel - - The vertex data channel we're querying. See the Vertex Data Index Options (which are defined in mesh.h). - - int *numSel - - If non-NULL, this is filled in with the current number of flagged vertices. - - bool *uniform - - If non-NULL, this is set to indicate whether the currently flagged vertices have uniform values or not. - - DWORD vertexFlags - - Indicates which vertices to evaluate. (Use MN_SEL to get vertex data from selected vertices.) - - TimeValue t - - This is not currently used. - The vertex data value for the flagged vertices. If the vertices' values vary, the first value found is returned. - Default Implementation: - { return 1.0f; } - - - - - This method obtains floating-point edge data from the flagged edges in the specified edge data channel. - Parameters: - int channel - - The edge data channel we're querying. See the Edge data channel index values (which are defined in mnmesh.h). - - int *numSel - - If non-NULL, this is filled in with the current number of flagged edges. - - bool *uniform - - If non-NULL, this is set to indicate whether the currently flagged edges have uniform values or not. - - DWORD edgeFlags - - Indicates which edges to evaluate. (Use MN_SEL to get vertex data from selected vertices.) - - TimeValue t - - This is not currently used. - The edge data value for the flagged edges. If the edges' values vary, the first value found is returned. - Default Implementation: - { return 1.0f; } - - - - - This method sets floating-point vertex data for the flagged vertices in the specified vertex data channel. - Parameters: - int channel - - The vertex data channel we're modifying. See the Vertex Data Index Options (which are defined in mesh.h). - - float w - - The value to set the flagged vertices to. - - DWORD vertexFlags - - Indicates which vertices to modify. (Use MN_SEL to set vertex data in selected vertices.) - - TimeValue t - - This is not currently used. - Default Implementation: - { } - - - - - This method sets floating-point edge data for the flagged edges in the specified edge data channel. - Parameters: - int channel - - The edge data channel we're modifying. See the Edge data channel index values (which are defined in mnmesh.h). - - float w - - The value to set the flagged edges to. - - DWORD edgeFlags - - Indicates which edges to modify. (Use MN_SEL to set edge data in selected edges.) - - TimeValue t - - This is not currently used. - Default Implementation: - { } - - - - - This method resets all vertex data in the specified channel. For instance, ResetEdgeData (VDATA_WEIGHT) would reset all vertex weights to 1. - Parameters: - int channel - - The vertex data. See the Vertex Data Index Options - Default Implementation: - { } - - - - - This method resets all edge data in the specified channel. For instance, ResetEdgeData (EDATA_CREASE) would reset all edge crease values to 0. - Parameters: - int channel - - The edge data channel. See the Edge data channel index values - Default Implementation: - { } - - - - - This method is used in combination with EndPerDataModify to store undo information for any vertex or edge data modification. - Parameters: - int mnSelLevel - - to one of MNM_SL_VERTEX or MNM_SL_EDGE for vertex or edge data respectively. - - int channel - - Indicates the channel of vertex or edge data we're modifying. For instance, BeginPerDataModify (MNM_SL_EDGE, EDATA_CREASE) would be used before modifying edge crease information. - Default Implementation: - { } - - - - - This method returns true if we're between BeginPerDataModify and EndPerDataModify calls. - Default Implementation: - { return false; } - - - - - This method completes the undo object corresponding to the vertex or edge data modifications made since the related BeginPerDataModify call. - Parameters: - bool success - - If FALSE, the system restores the original vertex colors and throws away the undo object. - Default Implementation: - { } - - - - - This method is used in combination with EndVertexColorModify to store undo information for any vertex or edge data modification. - Parameters: - int mp=0 - - The map channel we're using. Most vertex color applications use the standard vertex color channel, 0. However, you can also use this method with the Illumination channel (MAP_SHADING = -1) or the alpha channel (MAP_ALPHA = -2) - or even with a regular UVW map channel (1-99). DWORD flag =MN_SEL - - The flag used to mark the vertices to be moved (only applies in MN_SEL_VERTEX mode) - Default Implementation: - { } - - - - - This method returns true if we're between BeginVertexColorModify and EndVertexColorModify calls. - Default Implementation: - { return false; } - - - - - This method completes the undo object corresponding to the vertex color modifications made since the related BeginVertexColorModify call. - Parameters: - bool success - - If FALSE, the system restores the original vertex colors and throws away the undo object. - Default Implementation: - { } - - - - - This method obtains the material index for the selected faces. - determined - The bool this points to (which should not be NULL) is filled with: - FALSE if there are no selected faces or if selected faces have different material indices. TRUE if at least one face is selected and all selected faces have the same material ID. - - - - - This method sets the material index for the flagged faces. - Parameters: - int index - - The material index to set flagged faces to. - - DWORD flag=MN_SEL - - Indicates which faces should have their material IDs set. - Default Implementation: - { } - - - - - This method obtains smoothing group information for the specified faces. - Parameters: - DWORD faceFlag - - Indicates which faces to read smoothing group information from. If this value is 0, all faces are read. - - DWORD *anyFaces - - DWORD *allFaces=NULL - - These two parameters are where the output is stored. "<b>anyFaces</b>" has bits set that are present in any of the faces' smoothing groups. "<b>allFaces</b>", if non-NULL, has bits set that are present in all of the faces' smoothing groups. In other words, anyFaces or's together the faces' groups, while allFaces and's them together. - Default Implementation: - { if (anyFaces) *anyFaces = 0; if (allFaces) *allFaces = 0; } - - - - - This method sets (or clears) smoothing group bits in the specified faces. - Parameters: - DWORD bits - - The smoothing group bits to set in flagged faces. - - DWORD bitmask - - The smoothing group bits to clear in flagged faces - - DWORD flag - - Indicates which faces to set smoothing group information in. If this value is 0, all faces are modified. - Default Implementation: - { } - - - - - - - This method copies displacement parameters from pblock to polyobject. - Default Implementation: - { } - - - - - This method copies displacement parameters from polyobject to pblock. - Default Implementation: - { } - - - - - This method engages a displacement approximation preset. - Parameters: - int presetNumber - - The presetNumber values are either 0 (low), 1 (medium), or 2 (high). - Default Implementation: - { } - - - - - - - This method is called at the beginning of an interactive extrusion operation. Performs the topological extrusion. - Parameters: - int msl - - Indicates the MNMesh-based selection level we're extruding. (Currently, this must be MNM_SL_FACE.) - - DWORD flag - - Indicates the faces we're extruding. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is called at the end of an interactive extrusion operation. Completes the RestoreObjects and finalizes the geometric edit. - Parameters: - bool accept - - If TRUE, end extrude normally. If FALSE, cancel the extrusion completely (undoing the original topological extrusion). - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is used to drag the current extrusion to the amount specified. May be called multiple times in one session between EpfnBeginExtrude and EpfnEndExtrude. - Parameters: - float amount - - The (absolute) amount of the extrusion - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is called at the beginning of an interactive bevel or outline operation. Performs the topological extrusion if necessary, and prepares certain cached data. - Parameters: - int msl - - Indicates the MNMesh-based selection level we're beveling. (Currently, this must be MNM_SL_FACE.) - - DWORD flag - - Indicates the faces we're extruding. - - bool doExtrude - - Indicates whether or not a topological extrusion should be done for this bevel. (For instance, leaving this at false you to do "outlining", or to adjust a previous bevel.) - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is called at the end of an interactive bevel. Completes the RestoreObjects and finalizes the geometric edit. - Parameters: - bool accept - - If TRUE, end bevel normally. If FALSE, cancel the bevel completely (undoing any earlier topological extrusion). - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is used to drag the current bevel to the outline and height specified. May be called multiple times in one session between EpfnBeginBevel and EpfnEndBevel. - Parameters: - float outline - - The (positive or negative) outline amount for the bevel. - - float height - - The (positive or negative) height of the bevel. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is called at the beginning of an interactive chamfer operation. Performs the topological changes and prepares certain cached data. - Parameters: - int msl - - Indicates the MNMesh-based selection level we're chamfering. (Either MNM_SL_VERTEX or MNM_SL_EDGE.) - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is called at the end of an interactive chamfer. Completes the RestoreObjects and finalizes the geometric edits. - Parameters: - bool accept - - If TRUE, end chamfer normally. If FALSE, cancel the chamfer completely (undoing the earlier topological changes). - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method is used to drag the current chamfer to the amount specified. May be called multiple times in one session between EpfnBeginChamfer and EpfnEndChamfer. - Parameters: - float amount - - The amount of the chamfer. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - - - This method Hides flagged components. - Parameters: - int msl - - selection level - should be either MNM_SL_VERTEX or MNM_SL_FACE. - - DWORD flags - - Indicates which components to hide. For instance, MN_SEL would cause it to hide selected vertices or faces. - TRUE if components were hidden, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method unhides all components at the specified level. - Parameters: - int msl - - selection level - should be either MNM_SL_VERTEX or MNM_SL_FACE. - TRUE if components were unhidden, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method copies the named selection specified to the named selection copy/paste buffer. - Parameters: - MSTR setName - - The name of the selection set. - Default Implementation: - { } - - - - - This method pastes selection from named selection copy/paste buffer. - Parameters: - bool useDlgToRename - - Only matters if there is a name conflict with an existing named selection. If true, the system should throw up an interactive dialog for the user to rename the selection. If false, 3ds Max should use string techniques to rename the selection (by adding or increasing a number, etc.) - Default Implementation: - { } - - - - - This method creates a new vertex in the mesh. - Parameters: - pt - - The location of the new vertex in object or world space. - - bool pt_local=false - - If true, the point passed is assumed to be in object space. If false, the point is assumed to represent world space, and the object space location must be computed by the method. - - bool select=true - - Indicates if the new vertex should be selected (have its MN_SEL flag set). - The index of the new vertex, or -1 to indicate failure to create the vertex. - Default Implementation: - { return -1; } - - - - - This method creates a new edge, dividing a polygon into two smaller polygons. - Parameters: - int v1, v2 - - The endpoint vertices for this edge. These vertices must have at least one face in common, or the creation will fail. - - bool select=true - - Indicates if the new edge should be selected (have its MN_SEL flag set). - The index of the edge created. - Default Implementation: - { return -1; } - - - - - This method creates a new face on a set of vertices. - Parameters: - int *v - - An array of vertices for this new face. Note that each vertex must be an "open" vertex - it either must be on no edges or faces, or it must be part of a border (i.e. it's on more edges than faces). - - int deg - - The degree of the new face - and the size of the "<b>v</b>" array. - - bool select=true - - Indicates if the new face should be selected (have its MN_SEL flag set). - The index of the face created. - Default Implementation: - { return -1; } - - - - - This method caps the indicated holes. - Parameters: - int msl=MNM_SL_EDGE - - MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. The holes are border loops which can be identified by containing selected edges, using selected vertices, or being touched by selected faces. - - DWORD targetFlags=MN_SEL - - The flags we're looking for (in the vertex, edge, or face levels, according to msl) to identify the holes we should cap. - TRUE if any hole was successfully capped, otherwise FALSE - Default Implementation: - { return false; } - - - - - This method deletes the specified components (and any other components dependent on them). - Parameters: - int msl - - MNMesh-based selection level for deletion to occur on; one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. Note that edge deletion joins, rather than removes, the neighboring faces. Border edges cannot be deleted. Deleting an edge between two quads makes a hexagon. Etc. - - DWORD delFlag=MN_SEL - - The flag indicating components to delete. - - bool delIsoVerts=false - - If deleting faces, this indicates whether vertices that are left isolated by the face deletion should also be deleted. (Note that in the reverse situation, faces dependent on deleted vertices are always deleted.) - TRUE if components were deleted, otherwise FALSE. - Default Implementation: - { return false; } - - - - - Attach button: - - - - - This method attaches a bunch of nodes to this mesh. The objects in the nodes are converted to polymeshes if needed, then attached as elements in this Editable Poly. (Then the originals are deleted.) - Parameters: - &nodeTab - - A table of nodes we want to attach. - - *myNode - - A pointer to this Editable Poly's node (used to match the attached objects to our object space). - - TimeValue t - - The current time. - Default Implementation: - {} - - - - - This method detaches part of PolyMesh to a separate element. - Parameters: - int msl - - Indicates the MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag - - Flag indicates which components should be detached. For instance, MNM_SL_VERTEX and MN_SEL means selected vertices. - - bool keepOriginal - - If TRUE, the original components are left intact and a new element is cloned instead. - TRUE if elements are detached, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method detaches part of PolyMesh to a separate object. - Parameters: - MSTR name - - The desired name for the new node. - - int msl - - Indicates the MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag - - Flag indicates which components should be detached. For instance, MNM_SL_VERTEX and MN_SEL means selected vertices. - - bool keepOriginal - - If TRUE, the original components are left intact and the new object is cloned from them. - - *myNode - - A pointer to this 's node (for transform and other node property access). - - TimeValue t - - The current time. - TRUE if parts were detached, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method "splits" edges by breaking vertices on two or more flagged edges into as many copies as needed. In this way, any path of flagged edges becomes two open seams. - Parameters: - DWORD flag=MN_SEL - - Indicates which edges should be split. (Left at the default, selected edges are split.) - TRUE if any topological changes happened, FALSE if nothing happened. - Default Implementation: - { return false; } - - - - - This method breaks vertices into separate copies for each face using them. For example, breaking one corner of a box polymesh turns it into 3 vertices, one for each side that met at that vertex. - Parameters: - DWORD flag=MN_SEL - - Indicates which vertices should be broken. (Left at the default, selected vertices are broken.) - TRUE if any topological changes happened, FALSE if nothing happened. - Default Implementation: - { return false; } - - - - - This method divides the face into triangles meeting at a point described by generalized barycentric coordinates on the face. An n-sided polygon will become n triangles using this technique. - Parameters: - int face - - The face to divide. - - <float> &bary - - A table of floats, of the same size as the face's degree, indicating the contribution of each of the face's vertices to the division point. They should all sum to 1, indicating that the division point is a linear combination of the vertices. If they are all equal (1/n), the center of the face will be used. - - bool select=true - - Indicates whether the new triangles should have the MN_SEL flag set or not. - The index of the new vertex, or -1 for failure. - Default Implementation: - { return -1; } - - - - - This method divides an edge in two, creating a new vertex. - Parameters: - int edge - - The edge to divide. - - float prop - - The proportion along the edge for the new vertex, going from 0 at the v1 end to 1 at the v2 end. For instance, a prop of .35 means that the new point will be located at; - - .65*(v[e[edge].v1].p) + .35*(v[e[edge].v2].p) - - bool select=true - - Indicates if the new vertex should be selected. (The new edge picks up its selection flag from the old edge.) - The index of the new vertex, or -1 for failure. - Default Implementation: - { return -1; } - - - - - This method will collapse the current selection, turning each cluster (in edge or face level) or all selected points into a single point. Some restrictions inherent in a 3ds Max polygon-based mesh may prevent a complete collapse, if the result would have an illegal geometry. - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag - - The flag on the components we wish to collapse. - TRUE if any changes occurred, FALSE if nothing happened. - Default Implementation: - { return false; } - - - - - This method extrudes the flagged faces by the specified amount. Note that this method uses the parameter block value for ep_extrusion_type. Values can be: - - 0: Extrude by group (cluster) - - 1: Extrude by local normals - - 2: Extrude by polygon - each polygon extrudes separately. - Parameters: - float amount - - The height of the extrusion. Can be positive or negative. - - DWORD flag - - Indicates which faces should be beveled. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method bevels the flagged faces by the specified height and outline. Note that this method uses the parameter block value for ep_extrusion_type in making the extrusion component. Values can be: - - 0: Extrude by group (cluster) - - 1: Extrude by local normals - - 2: Extrude by polygon - each polygon extrudes separately. - Parameters: - float height - - The height of the desired bevel. Can be positive or negative. - - float outline - - The amount of the outlining in the bevel. Positive amounts make the selected region larger; negative amounts make it smaller. - - DWORD flag - - Indicates which faces should be beveled. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method chamfers the flagged vertices by the specified amount. - Parameters: - float amount - - The amount of the chamfer. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method chamfers the flagged edges by the specified amount. - Parameters: - float amount - - The amount of the chamfer. - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method slices the mesh with the specified plane. - Parameters: - planeNormal - - planeCenter - - The definition of the plane, by the normal and the "center" (which can be any point in the plane). - - bool flaggedFacesOnly=false - - If set, only the flagged faces should be sliced. If false, all faces should be sliced. - - DWORD faceFlags=MN_SEL - - Indicates which faces should be sliced, if flaggedFacesOnly is TRUE. - TRUE if something has been sliced, or FALSE if nothing happened. - Default Implementation: - { return false; } - - - - - This method indicates whether the Editable Poly is currently in Slice mode. - Default Implementation: - { return false; } - - - - - This method cuts from one vertex to another. Note that this algorithm uses the parameter block value for ep_split, which controls whether the cut algorithm splits the mesh open. - Parameters: - int startv - - The starting vertex for the cut - - destination - - The location of the ending vertex for the cut. - - projDir - - The direction of the "view". (projDir and the vector between the two vertices define the plane that the cut occurs in.) - The destination vertex, or -1 if the cut was unable to be completed for some reason. - Default Implementation: - { return -1; } - - - - - This method cuts from one edge to another. Note that this algorithm uses the parameter block value for ep_split, which controls whether the cut algorithm splits the mesh open. - Parameters: - int el - - The edge index along that edge for the start of the cut. - - float propl - - The edge proportion along that edge for the start of the cut. - - int e2 - - The edge index along that edge for the end of the cut. - - float prop2 - - The edge proportion along that edge for the end of the cut. - - projDir - - The direction of the "view". (projDir and the vector between the two endpoints define the plane that the cut occurs in.) - The vertex created at the end of the cut, or -1 if the cut was unable to be completed for some reason. - Default Implementation: - { return -1; } - - - - - This method cuts from one face to another, subdividing the start and end faces as needed for precisely matching the given start and end points. Note that this algorithm uses the parameter block value for ep_split, which controls whether the cut algorithm splits the mesh open. - Parameters: - int f1 - - The face we should start on. - - p1 - - The point (on face f1) for the start of the cut. - - p2 - - The point at the end of the cut. - - projDir - - The direction of the "view". (projDir and the vector between the two endpoints define the plane that the cut occurs in.) - The vertex created at the end of the cut, or -1 if the cut was unable to be completed for some reason. - Default Implementation: - { return -1; } - - - - - This method welds the specified vertices together (if possible), and puts the result at the location specified. - Parameters: - int vert1, vert2 - - The two vertices we wish to weld. Note that these vertices must be "border" vertices, that is, they must be used by some open (one-sided) edges. - - destination - - The desired location for the result. Usually this is v[vert1].p, v[vert2].p, or the average of the two. - Indicates if any welding successfully occurred. If FALSE, nothing happened. - Default Implementation: - { return false; } - - - - - This method welds the first edge to the second edge, leaving the result at the location of the second edge. - Parameters: - int edge1, edge2 - - The two edges we wish to weld. Note that these must be open (one-sided) edges. - Indicates if any welding successfully occurred. (If false, nothing happened.) - Default Implementation: - { return false; } - - - - - This method welds all flagged vertices together to their average location. - Parameters: - DWORD flag - - Indicates which vertices should be welded. Note that these vertices must be "border" vertices, that is, they must be used by some open (one-sided) edges. - Indicates if any welding successfully occurred. If FALSE, nothing happened.) - Default Implementation: - { return false; } - - - - - This method welds flagged edges together. - Parameters: - DWORD flag - - Indicates which edges should be welded. Note that these edges must be open (one-sided). - Indicates if any welding successfully occurred. (If false, nothing happened.) - Default Implementation: - { return false; } - - - - - This method creates a new shape object from flagged edges in the polymesh. - Parameters: - MSTR name - - The desired name for the new node containing the shape. - - bool smooth - - If TRUE, the new shape should be a smooth curve. If FALSE, it should be a linear shape which exactly follows the edges. - - *myNode - - A pointer to the node of the PolyMesh (used to obtain transform and other node level information for the new shape node). - - DWORD edgeFlag=MN_SEL - - Indicates which faces should be used in creating this shape. - TRUE if successful, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method moves the flagged area into its "average plane". ( computed using average vertex positions and normals.) - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT. - - TimeValue t=0 - - The current time. (This action can be used to set a key for animation.) - Indicates whether anything was moved. - Default Implementation: - { return false; } - - - - - This method moved flagged region to the plane given (by orthogonal projection into the plane). - Parameters: - planeNormal - - float planeOffset - - The definition of the plane. The plane is that region of points X for which DotProd (planeNormal, X) = planeOffset. - - int msl - - MNMesh-based selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT. - - TimeValue t=0 - - The current time. (This action can be used to set a key for animation.) - Indicates whether anything was moved. - Default Implementation: - { return false; } - - - - - This method aligns flagged parts to be on the current construction plane (in the current viewport). - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT. - Indicates whether anything was aligned. - Default Implementation: - { return false; } - - - - - This method aligns flagged parts to be at right angles to the current view (through the active viewport). - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT. - Indicates whether anything was aligned. - Default Implementation: - { return false; } - - - - - This method deletes isolated vertices, those that aren't used by any faces. - Indicates whether any vertices were deleted. - Default Implementation: - { return false; } - - - - - This method applies the NURMS style MeshSmooth algorithm to the flagged area of the mesh. Uses parameter block parameters: - - ep_ms_smoothness: Smoothness value for MeshSmooth type subdivision (float spinner, range 0-1) - - ep_ms_smooth: Currently unused. - - ep_ms_sep_smooth: Separate by smoothing groups for MeshSmooth type subdivision (checkbox) - - ep_ms_sep_mat: Separate by material IDs for MeshSmooth type subdivision (checkbox) - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to meshsmooth. Ignored if msl is set to MNM_SL_OBJECT. - TRUE if applied, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method tessellates flagged area of the mesh. Uses ep_tess_type and ep_tess_tension from the param block. - Parameters: - int msl - - MNMesh-based selection level, one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flag=MN_SEL - - The flag that indicates which components to tessellate. Ignored if msl is set to MNM_SL_OBJECT. - TRUE is tessellated, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method will cue an update of the subdivision surface based on this Editable Poly. (See the Editable Poly documentation on the Object-level Surface Properties dialog for information on this surface.) Equivalent to the user pressing the "Update" button. - Default Implementation: - { } - - - - - This method selects (or deselects) vertices based on their color. Note that the color to compare to is part of the parameter block - see ep_vert_sel_color and related parameters for details. - Parameters: - BOOL add - - If TRUE, this selection should be in addition to the current selection. If FALSE, only the vertices within the color range should be selected. - - BOOL sub - - If TRUE, then instead of the options under "add" above, the vertices within the specified color range are deselected (while other selections are unmodified). - - int mp=0 - - The map channel used for vertex colors. Use 0 for the traditional vertex color channel, 1-99 for a texture map channel, MAP_SHADING for the vertex illumination channel, or MAP_ALPHA for the vertex alpha channel. - - TimeValue t=0 - - The current time. - Default Implementation: - { } - - - - - This method modifies a polygon's triangulation so that the specified diagonal is part of it. - Parameters: - int face - - The face whose triangulation we want to modify - - int corner1, corner2 - - The endpoints of the new diagonal. They should be indices into the vertex list. So for instance corner values of (0,3) would refer to vertices f[face].vtx[0] and f[face].vtx[3]. Note that if (corner1+1)deg == corner2 (or vice versa), or if corner1==corner2, nothing will happen. - Default Implementation: - { } - - - - - This method will automatically re-triangulate flagged faces, using the standard polygon triangulation algorithm. Note that this algorithm is designed to work well on a single face, but not necessarily to produce the best results on groups of faces. - Parameters: - DWORD flag=MN_SEL - - Indicates which faces should be affected. - Indicates whether anything happened. (If nothing was in fact flagged, it returns false.) - Default Implementation: - { return false; } - - - - - This method flips the normals in selected elements. (Note that because of topological rules for the PolyMesh, there is no way to flip a single face - whole elements must be flipped at once.) - Parameters: - DWORD flag=MN_SEL - - Indicates which elements should be flipped. An element is considered flagged if any of its faces have that flag set. - Indicates which elements should be flipped. An element is considered flagged if any of its faces have that flag set. - Default Implementation: - { return false; } - - - - - This method selects or deselects faces by material ID. - Parameters: - int index - - The material ID that indicates a face should be affected. - - bool clear - - If TRUE, these faces should have their selection cleared. (If FALSE, their selection is set.) - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method selects or deselects faces by smoothing group. - Parameters: - DWORD bits - - The smoothing group bits that indicate a face should be affected. - - BOOL clear - - If TRUE, these faces should have their selection cleared. (If FALSE, the selection is set.) - - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method autosmooths the current face selection, using the autosmooth threshold set in the parameter block. - Parameters: - TimeValue t - - The current time. - Default Implementation: - { } - - - - - This method deletes all the components in all the levels that have the MN_DEAD flag set. Note that this causes a renumbering of affected component levels. If you're deleting faces in the middle of a complex operation, it's usually best to just set their MN_DEAD flags, then call CollapseDeadStructs at the end, so that you don't have to worry about other faces' indices changing before you're done. - Default Implementation: - { } - - - - - This method is used for setting flags in the components based on flags of other components that they touch. This is very versatile. For instance, to hide all faces that use selected vertices, you would call EpfnPropegateComponentFlags (MNM_SL_FACE, MN_HIDE, MNM_SL_VERTEX, MN_SEL, false, true, true). (Hiding faces should be undoable.) To set the MN_WHATEVER flag on all vertices that are used only by selected edges, you'd call EpfnPropegateComponentFlags (MNM_SL_VERTEX, MN_WHATEVER, MNM_SL_EDGE, MN_SEL, true); - Parameters: - int slTo - - The selection level we wish to modify. (One of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE.) - - DWORD flTo - - The flags we wish to change in that selection level. - - int slFromt - - The selection level we wish to base the changes on. - - DWORD flFrom - - The flags that indicate a change should happen. - - bool ampersand=FALSE - - When slFrom and slTo are different, this indicates whether the flags of the nearby components should be "or'd" or "and'd". If it's false, then any flagged components in the "from" level will cause the component in the "to" level to be affected. If true, then all the components in the "from" level that touch a component in the "to" level must be flagged in order for the "to" level component to be affected. (i.e., if from is faces and to is vertices, a vertex would only be modified if all faces that use it have the flFrom flag set.) - - bool set=TRUE - - If TRUE, this parameter indicates that the flTo flags should be set on targeted components. If false, it indicates that the flags should be cleared. For instance, to clear MN_HIDE flags on vertices that are used by selected edges, you'd call EpfnPropegateComponentFlags (MNM_SL_VERTEX, MN_HIDE, MNM_SL_EDGE, MN_SEL, false, false, true); - - bool undoable=FALSE - - Indicates if this action should create an entry for the undo system. Changes to MN_SEL, MN_HIDE, and MN_DEAD flags should generally be undoable, but changes to more minor flags like MN_WHATEVER that are used to set up for other operations generally don't have to be. - The number of components in the slTo level that were affected by the call. (If 0, nothing happened.) - Default Implementation: - { return 0; } - - - - - This method returns a pointer to the Editable Poly's . See Class for fun things to do with an . - Default Implementation: - { return NULL; } - - - - - Gets a pointer to the Editable Poly's parameter block, which can be used to get or set Editable Poly UI parameters. (See class for more information on access methods.) Here is a list of the available parameters, as defined in the epolyParameters enum near the top of iEPoly.h. (Please see the Editable Poly documentation in the normal 3ds Max User Reference file for more information on these parameters.) - - Selection dialog parameters: - - ep_by_vertex: select by vertex (checkbox) - - ep_ignore_backfacing: Ignore backfacing (checkbox) - - ep_show_normals: Currently unused. - - ep_normal_size: Currently unused. - - Soft Selection dialog parameters: - - ep_ss_use: Use soft selection (checkbox) - - ep_ss_retro: Currently unused - - ep_ss_edist_use: Use edge-based distances to compute soft selection (checkbox) - - ep_ss_edist: Maximum number of edges to traverse in computing edge-based distances (int spinner - range: 1-999999) - - ep_ss_affect_back: Affect backfacing in soft selection (checkbox) - - ep_ss_falloff: Falloff value for soft selection (float spinner) - - ep_ss_pinch: Pinch value for soft selection (float spinner) - - ep_ss_bubble: Bubble value for soft selection (float spinner) - - Edit Geometry dialog parameters: - - ep_extrusion_type: Type of face extrusion. (Radio.) Values: - - 0: Extrude by group (cluster) - - 1: Extrude by local normals - - 2: Extrude by polygon - each polygon extrudes separately. - - ep_split: Controls whether the Cut algorithm splits the mesh open. (Checkbox) - - ep_refine_ends: Currently unused - - ep_weld_threshold: Threshold for welding selected vertices. (float spinner) - - ep_weld_pixels: Pixel threshold for Target welding (int spinner) - - Subdivide dialog parameters: - - ep_ms_smoothness: Smoothness value for MeshSmooth type subdivision (float spinner, range 0-1) - - ep_ms_smooth: Currently unused. - - ep_ms_sep_smooth: Separate by smoothing groups for MeshSmooth type subdivision (checkbox) - - ep_ms_sep_mat: Separate by material IDs for MeshSmooth type subdivision (checkbox) - - ep_tess_type: Tessellation type (Radio) Values: - - 0: by edge - - 1: by face. - - ep_tess_tension: Tessellation tension (float spinner) - - Surface Properties dialog parameters (object level): - - ep_surf_subdivide: Apply NURMS-style MeshSmooth subdivision to polymesh. (checkbox) - - ep_surf_subdiv_smooth: Apply MeshSmooth smoothing group algorithm after subdividing (checkbox) - - ep_surf_ig_sel: Currently unused. - - ep_surf_iter: of iterations of subdivision (int spinner) - - ep_surf_thresh: "Smoothness" threshold for adaptive subdivision (float spinner, range 0-1) - - ep_surf_riter: Render value of iterations (int spinner) - - ep_surf_rthresh: Render value of smoothness threshold (float spinner, range 0-1) - - ep_surf_use_riter: Use Render iterations value when rendering (checkbox) - - ep_surf_use_rthresh: Use Render smoothness threshold when rendering (checkbox) - - ep_surf_sep_smooth: Separate by smoothing groups in subdivision (checkbox) - - ep_surf_sep_mat: Separate by materials in subdivision (checkbox) - - ep_surf_update: Update type for subdivision (radio). Values: - - 0: Update always - - 1: Update when rendering - - 2: Update manually - - Surface Properties dialog parameters (vertex level): - - ep_vert_sel_color: Target color for select-by-color (color swatch) - - ep_vert_selc_r: Tolerance of red values in select-by-color. (int spinner, range 0-255) - - ep_vert_selc_g: Tolerance of green values in select-by-color. (int spinner, range 0-255) - - ep_vert_selc_b: Tolerance of blue values in select-by-color. (int spinner, range 0-255) - - ep_vert_color_selby: Which kind of color to select by in select-by-color. Radio values: - - 0: Select by regular vertex color - - 1: Select by vertex illumination - - Surface Properties dialog parameters (face level): - - ep_face_smooth_thresh: Autosmooth threshold (float spinner, angle units). - - Subdivision Displacement parameters (object level): - - ep_sd_use: Apply subdivision displacement (checkbox) - - ep_sd_split_mesh: Split the mesh (checkbox) - - ep_sd_method: Subdivision displacement method (radio). Values: - - 0: Regular method - - 1: Spatial method - - 2: Curvature method - - 3: Use both spatial & curvature methods. - - ep_sd_tess_steps: Tessellation steps (for regular method) (int spinner) - - ep_sd_tess_edge: size (for spatial method) (float spinner) - - ep_sd_tess_distance: Distance (for curvature method) (float spinner) - - ep_sd_tess_angle: Angle value (for curvature method) (float spinner) - - ep_sd_view_dependent: dependency (checkbox) - - Advanced Subdivision Displacement parameters: - - ep_asd_style: Subdivision style. Radio values: - - 0: Grid-based - - 1: Tree-based - - 2: Delauney algorithm. - - ep_asd_min_iters: Minimum number of iterations (grid or tree style) (int spinner) - - ep_asd_max_iters: Maximum number of iterations (grid or tree style) (int spinner) - - ep_asd_max_tris: Maximum number of triangles (Delauney style) (int spinner) - Default Implementation: - { return NULL; } - - - - - - - Retrieves the current command mode in use, if any. - - - The current command mode from the EpActionToggleCommandMode above, or -1 if the current command mode is not any of the command modes. - - - - - Retrieves the current pick mode in use, if any. - - - The current pick mode (from the EpActionEnterPickMode above), or -1 if the current pick mode is not any of the pick modes. - - - - - Chamfer vertices, creating a whole between the chamfered vertices. - - - - Chamfer distance between new vertices, must be positive - If true, newly created faces are removed - The time at which to chamfer the vertices - - - - Chamfer edges, creating a whole between the chamfered edges. - - - - Chamfer distance between new edges, must be positive - If true, newly created faces are removed - The time at which to chamfer the edges - - - - Changes the edge selection , in the ring direction. - - - This method adds ( move or remove ) edges from the current selection. - n the 'positive' ( or negative ) ring direction,using the 3 existing parameters. The ring direction is vertical for a plane. - If in_newPos == -3 , in_moveOnly == false and in_add == true, it adds 3 edges from the current selection, - in the negative ring direction. this is equivalent to the MaxScript: $.setRingShift -3 false true - - If > 0 will change the edge selection the 'positive' ring direction, if < 0 in the 'negative' direction. - If true, edges are moved, if false, edges are added or removed from selection - If true edges are added, if false, edges are removed from current selection - - - - Changes the edge selection , in the loop direction. - - - This method adds ( move or remove ) edges from the current selection. - n the 'positive' ( or negative ) loop direction,using the 3 existing parameters. The loop direction is horizontal for a plane. - If in_newPos == -3 , in_moveOnly == false and in_add == true, it adds 3 edges from the current selection, - in the negative ring direction. this is equivalent to the MaxScript: $.setLoopShift -3 false true - - If > 0 will change the edge selection the 'positive' ring direction, if < 0 in the 'negative' direction. - If true, edges are moved, if false, edges are added or removed from selection - If true edges are added, if false, edges are removed from current selection - - - - Converts current sub-object selection to the specified sub-object border. - - - It converts for instance selected faces into their border edges and selects it - if you call EpfnConvertSelectionToBorder( EP_SL_FACE, EP_SL_EDGE); - - Can be EP_SL_EDGE, EP_SL_FACE or EP_SL_VERTEX - Can be EP_SL_EDGE, EP_SL_FACE or EP_SL_VERTEX - - - - Commits any Paint Deformation as if pressing the Commit button. - - - Has no effect when the Commit button is disabled - - - - - Cancels any Paint Deformation as if pressing the Cancel button. - - - Has no effect when the Cancel button is disabled - - - - - Closes the Smooth Group Floater Floater dialog. - - - - - Closes the ID Floater dialog. - - - - - Returns the ID Floater dialog handle. - - - - - Returns the Smooth Group Floater dialog handle. - - - - - Brings up the Smooting Group floater dialog. If it is already up it closes it. - - - - - Brings up the ID floater dialog. If it is already up it closes it. - - - - - Returns whether the ID floater dialog is up. - - - - - Returns whether the Smooting Group floater dialog is up. - - - - - This new class extends with new functionality, in particular the ability for epoly to support manipulate grips. - - - - - Turns the manipulate grip item on or off. When at least one grip item is on and select and manipulate mode is on a grip will show up for each item that's on. - - - - - Whether or not the specified item will be turned on or off - - Which grip item that will be turned on or off. - - - - Get whether or not this manipulator item is on or not. - - - Whether or not the item is on or not. Note that it doesn't take into account whether or not the correct subobject mode is also active, it just checks to see if it would be on if we were in the right mode. - - - Which grip item we are checking to see if it's on or off. - - - - This new class extends with new functionality, for new hard/smooth edge workflow. - - - - - Make the edges marked with the specified flag hard (unsmoothed) - true if any faces had smooothing groups altered - - - Edges marked with this flag () will be set to hard if possible by setting appropriate smoothing groups in adjacent faces. - - - - Make the edges marked with the specified flag smooth - true if any faces had smooothing groups altered - - - Edges marked with this flag () will be set to smooth if possible by setting appropriate smoothing groups in adjacent faces. - - - - Select hard (unsmoothed) edges. This operation selects edges between any faces which do not share any smoothing groups. - - - - - Select smoothed edges. This operation selects edges between any faces which share any smoothing groups. - - - - - Get the current Edit Poly Chamfer type (obsolete). - - - The current Edit Poly Chamfer type, or -1 if the current type is not any of the Edit Poly Chamfer types. - - - - - the current Edit Poly Chamfer type (obsolete). - - - - - Standard = 0, Quad = 1. - - - - Get the current Edit Poly Chamfer quad intersections (obsolete). - - - The current Edit Poly Chamfer quadIntersections - - - - - the current Edit Poly Chamfer quad intersections (obsolete). - - - - - - - - This class is the published interface for Edit Poly modifiers. - - - You can use it to manipulate Edit Poly modifiers directly. / Implementations of all of these methods can be found in the source for the Edit Poly modifier. / usages for most of them can be found there as well. - - - - - These methods retrieve the parts of the object that match the specified flags and mask passed in. - - - Retrieves the vertices specified the flag and mask, and updates the bitarray passed in - This is based on the mesh after all committed operations, but before the current operation, if any. - - The passed by reference - the bits will be updated to show the specified vertices - The flags that are to be checked for - The results will use the bitwise-AND of fmask and flags if it is specified - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves the edges specified the flag and mask, and updates the bitarray passed in. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The passed by reference - the bits will be updated to show the specified edges - The flags that are to be checked for - The results will use the bitwise-AND of fmask and flags if it is specified - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves the faces specified the flag and mask, and updates the bitarray passed in. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The passed by reference - the bits will be updated to show the specified faces - The flags that are to be checked for - The results will use the bitwise-AND of fmask and flags if it is specified - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - These methods set the flags on the specified subobjects to match the flags and mask passed in. - - - Sets the specified vertices flags to the specified value - - The list of vertices to have their flag changed - The flags that are to be set - The results will use the bitwise-AND of fmask and flags if it is specified - Can the results of this operation be undone through the normal method - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Sets the specified vertices flags to the specified value. - - - - The list of edges to have their flag changed - The flags that are to be set - The results will use the bitwise-AND of fmask and flags if it is specified - Can the results of this operation be undone through the normal method - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Sets the specified faces flags to the specified value. - - - - The list of faces to have their flag changed - The flags that are to be set - The results will use the bitwise-AND of fmask and flags if it is specified - Can the results of this operation be undone through the normal method - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - These methods get the flags on the specified subobjects. - - - Retrieves the flags from the specified vertex - This is based on the mesh after all committed operations, but before the current operation, if any. - - The vertex to retrieve the flags from - between 0 and EpMeshGetNumVertices - 1 - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves the flags from the specified edge. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The edge to retrieve the flags from - between 0 and EpMeshGetNumEdges - 1 - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves the flags from the specified face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The face to retrieve the flags from - between 0 and EpMeshGetNumFaces - 1 - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - These methods retrieve all subobjects of the specified type that are connected to the second list of subobjects passed in . - - - Retrieves list of verts that are used by the edges specified - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of vertices that will be updated with the vertices used by the edges - - List of edges used for finding the vertices - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves list of edges that are used by the vertices specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of edges that will be updated with the edges used by the vertices - - List of vertices used for finding the edges - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves list of faces that are used by the edges specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of faces that will be updated with the faces used by the edges - - List of edges used for finding the faces - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves list of elements that are used by the faces specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of elements that will be updated with the elements used by the faces - - List of faces used for finding the elements - - List for calculating elements from the face - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves list of faces that are used by the vertices specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of faces that will be updated with the faces used by the vertices - - List of vertices used for finding the faces - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Retrieves list of verts that are used by the faces specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of vertices that will be updated with the vertices used by the faces - - List of faces used for finding the vertices - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Returns the Edit Poly selection level - one of the ePolyModSelLevel enum defined above, such as EPM_SL_VERTEX. - - - - - Returns the selection level - one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - - - - Converts selection between two Edit Poly selection levels, by selecting adjacent subobjects, such as edges using selected vertices, or vertices used by selected faces, etc. - - - The number of subobjects this method selected in the "To" level. - - Example: This could be used to convert the current vertex selection to a selection of all border loops containing only selected vertices by calling EpModConvertSelection (EPM_SL_VERTEX, EPM_SL_BORDER, true); - - The selection level to convert from. - The selection level to convert to - subobjects in this selection level will have their selection set or cleared based on this algorithm. - Indicates if subobjects in the "to" level should be selected if subobjects in the "from" level are selected (false) or if subobjects in the "from" level are selected (true). - - - - Returns the "current" Edit Poly operation. If there is no current operation ep_op_null is returned. (Values are from the epolyModButtonOp enum above.) - - - - - Returns the parameter block for the Edit Poly modifier. (Clients can use this to control the individual parameters of the modifier. Parameters are listed above in the epolyModParameters enum.) - - - - - Returns the Preserve settings for all map channels. (Does not reflect the epm_preserve_maps parameter, however.) - - - - - Sets whether a particular map channel will be "preserved" in geometric operations. (Note: This does not affect the epm_preserve_maps parameter, it just changes the setting for this particular map channel.) - - - - - Indicates whether a particular map channel is set to be "preserved" in geometric operations. (Note: This does not indicate whether the epm_preserve_maps parameter is set to true, it only indicates the setting for this particular map channel.) - - - - - Invalidates the computed distances from selected vertices that are used to generate soft selections. - - - - - Invalidates the computed soft selections (but not the distances from selected vertices that the soft selections are based on). - - - - - Sets the current operation. - - - - Indicates the desired operation, from the epolyModButtonOp enum above - - - - Sets the operation to the one given, and then pops up the operation dialog, if one exists. - - - - - Applies the operation given, and commits to it immediately. - - - - - Indicates to the EditPolyMod that some channels of its mesh have changed. Forces an update of UI elements based on the mesh, such as the Selected display and the Smoothing Group buttons, and also notifies the Edit Poly's dependents of the change. - - - - - Triggers a redraw of the viewports at the current time. - - - - - Commits to the current operation unless we're set to "animation mode" (epm_animation_mode parameter is true) and the current operation supports animation. - - - - - Commits to the current operation, and clears any animation. - - - - - Commits to the current operation, but maintains it as the current operation with the same settings (and any animation in those parameters). - - - - - Cancels the current operation. - - - - - Toggles a given command mode - if it's not currently in this mode it will enter it, otherwise it will exit it. - - - - The command mode, from the epolyModCommandMode enum above. - - - - Exits any previous Edit Poly command modes, and enters the command mode given. - - - - The command mode, from the epolyModCommandMode enum above. - - - - Enters the pick mode given. - - - - The pick mode, from the epolyModPickMode enum above. - - - - Retrieves the current Edit Poly command mode in use, if any. - - - The current command mode from the epolyModCommandMode above, or -1 if the current command mode is not any of the Edit Poly command modes. - - - - - Retrieves the current Edit Poly pick mode in use, if any. - - - The current pick mode (from the epolyModPickMode above), or -1 if the current pick mode is not any of the Edit Poly pick modes. - - - - - Returns a containing the subobject selection in the desired selection level. - - - A pointer to an internal containing the selection. This should not be altered! It is available for read only. - - The selection level, such as MNM_SL_VERTEX for vertex or MNM_SL_CURRENT for "the current level". - If this Edit Poly modifier is instanced across multiple nodes, this parameter specifies which node we're inquiring about. - - - - Sets the subobject selection explicitly. - - - - The selection level, such as MNM_SL_VERTEX for vertex or MNM_SL_CURRENT for "the current level". - A containing the desired selection. - If this Edit Poly modifier is instanced across multiple nodes, this parameter specifies which node we want to set selection in. - - - - Change the selection state of a subset of subobjects - select them, invert their selection, or deselect them. - - - - The selection level, such as MNM_SL_VERTEX for vertex or MNM_SL_CURRENT for "the current level". - A indicating which subobjects we want to change the selection state of. - If true, the selection state of the subobjects should be inverted. Otherwise, it should be set or cleared depending on "select" - If true, the subobjects indicated should be selected; if false, the subobjects indicated should be deselected. Ignored if "invert" is true. - If this Edit Poly modifier is instanced across multiple nodes, this parameter specifies which node we want to set selection in. - - - - Clear any hit level override, and let hit-testing fall back on the normal hit level for subobject selection. - - - - - Returns the current hit level override, or 0 if there is none. - - - The Hit Level - one of SUBHIT_MNVERTS, SUBHIT_MNEDGES, SUBHIT_MNFACES, or SUBHIT_MNDIAGONALS, along with SUBHIT_OPENONLY if hit-testing is restricted to "open" vertices or edges (ie those on borders) - - - - - Indicates the current hit level. If there's a HitLevelOverride in place, that's returned; otherwise this method returns the regular hit level, which is typically the hit level for the current selection level. If "Select by vertex" is turned on, SUBHIT_MNVERTS will be returned. - - - The Hit Level - one of SUBHIT_MNVERTS, SUBHIT_MNEDGES, SUBHIT_MNFACES, or SUBHIT_MNDIAGONALS, along with SUBHIT_OPENONLY if hit-testing is restricted to "open" vertices or edges (ie those on borders) - - If you specifically want to know whether "Select by vertex" is being used currently, pass a pointer to an int here. The int pointed to will be set to true if select by vertex is on, or false if not. - - - - Normally, all hit-testing on Edit Poly meshes is done on the mesh before the "currentoperation". (This makes it possible to change selections underneath a Bevel or Extrude or Vertex Weld.) If you want to hit-test on the result of the current operation, you need to call this method. - - - This is typically used in Edit Poly command modes, such as Chamfer or Extrude, after the user has entered the mode, but while the last operation might still be the "current" one, so that we can hit-test as though the current operation had already been committed. It's also used in command modes like Create so that we can hit-test on the freshly created vertices. - - Controls whether subobjects that are newly created by the current operation can be hit-tested. For instance, if the current operation is an Extrude, this controls whether or not the sides of the extrusion can generate hits. - - - - Clears any HitTestResult settings, and falls back on hit-testing before the current operation. (See SetHitTestResult for more details.) - - - - - Clear any display level override, and let hit-testing fall back on the normal display for the current selection level. - - - - - Returns any current DisplayLevelOverride. See SetDisplayLevelOverride for more details. - - - The set of display flags to show, or 0 for no override currently set. These are MNDISP flags, such as MNDISP_VERTTICKS, that are defined in MNMesh.h. - - - - - Indicates whether or not the Edit Poly is currently set to force ignoring backfacing subobjects. See ForceIgnoreBackfacing for details. - - - - - Move the current subobject selection. This method uses the current selection and soft selection, and respects the settings for Constraints and for Preserving texture maps. - - - - The representing the move. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This parameter is ignored - The time at which to move the points. This time is used to generate vertex animation keys, if appropriate, as well as to obtain the current soft selection parameters. - - - - Rotate the current subobject selection. This method uses the current selection and soft selection, and respects the settings for Constraints and for Preserving texture maps. - - - - The Quaternion representing the rotation. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This parameter is ignored - The time at which to rotate the points. This time is used to generate vertex animation keys, if appropriate, as well as to obtain the current soft selection parameters. - - - - Scale the current subobject selection. This method uses the current selection and soft selection, and respects the settings for Constraints and for Preserving texture maps. - - - - A representing the scale in each dimension. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - This parameter is ignored - The time at which to scale the points. This time is used to generate vertex animation keys, if appropriate, as well as to obtain the current soft selection parameters. - - - - Move the Slice that's used in the ep_op_slice and ep_op_slice_face operations. - - - - The representing the move. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - The time at which to move the plane. This time is used to generate animation keys, if appropriate. - - - - Rotate the Slice that's used in the ep_op_slice and ep_op_slice_face operations. - - - - The Quaternion representing the rotation. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - When TRUE the transformation is occurring about the sub-object's local origin; otherwise, the rotation occurs in object space. - The time at which to move the plane. This time is used to generate animation keys, if appropriate. - - - - Scale the Slice that's used in the ep_op_slice and ep_op_slice_face operations. Note that scaling the slice plane with localOrigin == true has no effect on the actual slice effect; it only affects the way the slice plane is displayed. - - - - The representing the scale in each dimension. - The 'parent' transformation matrix. - The matrix that represents the axis system. This is the space in which the transformation is taking place. - When TRUE the transformation is occurring about the sub-object's local origin; otherwise, the scale occurs in object space. - The time at which to move the plane. This time is used to generate animation keys, if appropriate. - - - - Resets the slice plane used in the slice operations so that it lies in the XY plane in object space. - - - - - Returns the current transform of the slice plane. - - - - - Retrieves the current slice plane, by its normal and center. - - - - - Sets the slice plane to use the normal and center given. - - - - - Indicates if we're currently in the "Slice Plane" mode, which is not a command mode, but rather a different way of handling the regular (move, rotate, scale) command modes. - - - - - Indicates if we're currently in a Slice operation (ep_op_slice or ep_op_slice_face). - - - - - Returns the Edit Poly cast as a modifier. - - - - - Returns NULL if the Edit Poly is not currently up in the modifier panel, or the interface pointer otherwise. - - - - - Returns the handle of the dialog specified. - - - - Example: The Edit Poly command modes use this method to access the buttons for their command mode, to set them to checked when entering the command mode and unchecked when leaving. - - This is an int representing the ID of the dialog. This enum should be moved to this header, but currently it resides in maxsdk/samples/mesh/EditPoly/EditPoly.h. Here are the IDs: 0 - ep_animate - The dialog displaying the current operation, and controlling whether we're in model or animate mode 1 - ep_select - The subobject selection dialog 2 - ep_softsel - The soft selection dialog 3 - ep_geom - The dialog with general Edit Geometry operations, such as Create, Collapse, and Attach. 4 - ep_subobj - The subobject level specific Edit dialog, such as "Edit Vertex" or "Edit Borders", 5 - ep_surface - The face-level dialog for editing surface material surface features 6 - ep_settings - The popup dialog with settings for the current operation 7 - ep_paintdeform - the Paint Deformation dialog. 8 - ep_face_smooth - The face-level dialog for editing smoothing groups. If the dialog you're requesting is not currently displayed, NULL will be returned. - - - - Updates the Align normal and offset parameters based on the current viewport and on the ep_align_type parameter. If there's no viewport available, method does nothing. - - - - - Makes sure that all the used by the Edit Poly modifiers has an up to date cache. This should be called before trying to obtain information about the mesh. - - - - - Show the popup dialog associated with the current operation. Does nothing if there is no current operation, or if the current operation has no associated popup dialog. - - - True if we succeeded in displaying a popup dialog, false if we couldn't find one to display. - - - - - Indicates whether or not there is currently a popup dialog being displayed with parameters for the current operation. - - - - - Close the popup dialog which shows the current operation's parameters, if it's currently being displayed. - - - - - Repeat the last operation. If there is a "current" operation, it will be committed and repeated, without changing any parameters or removing any animations. If there is not, the last recorded operation, if any, will be applied and committed. (In Max 7.0, unfortunately, the identity of this last operation is not exposed in the SDK. You can examine it in the Edit Poly source, maxsdk/samples/mesh/EditPoly, the EditPolyMod::mLastOperation data member. - - - - - Get the current "Primary" node, which is used by default when node-specific commands are given and the node given is NULL. - - - - - the current "Primary" node, which is used by default when node-specific commands are given and the node given is NULL. - - - - - Retrieve the transform of the Edit Poly's node. - - - If the node is given, we just return node->GetObjectTM (t). This method is more interesting when you just want to know what the TM is of the primary node, without bothering to retrive it. - - The time at which to retrieve the node's TM. - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Create a new vertex in the mesh. - - - The (0-based) index of the newly created vertex - - The location of the vertex in object space - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Create a new face in the mesh. - - - The (0-based) index of the newly created face - - A table of the vertices to use as the corners of the face - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Create a new edge in the mesh. The vertices which we're creating a new edge between must be on the same polygon, but not have an existing edge between them. The polygon is split in two by the new edge. - - - The (0-based) index of the newly created edge - - The start vertex of the new edge. - The end vertex of the new edge. - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Change the triangulation of a polygon such that there will be a diagonal between the two vertices given. (The two vertices must obviously be used by the same polygon.) - - - - Example: This is used in the Edit Poly "Edit Triangulation" command mode - - The start vertex of the new diagonal. - The end vertex of the new diagonal. - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - up a Cut operation, starting at a specific subobject and at a specific point. (Use EpModSetCutEnd to finish the cut.) - - - - The starting subobject level, which should be an level such as MNM_SL_VERTEX for vertex or MNM_SL_FACE for face. - The index of the starting subobject. For instance, if startLevel==MNM_SL_EDGE, and startIndex==4, the Cut should start on edge 4. - The location (in object space) of the start of the cut. The end of the cut is also initialized to this value, and can be further modified by using EpModSetCutEnd. - The normal direction for the Cut. In the Cut command mode, this is generally set to the viewport direction. Cuts should occur where the plane defined by the start point, the end point, and this normal intersects the mesh. - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - the end point of a cut. - - - - The location of the end of the Cut, in object space - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - If the last Cut we made finished successfully, this method will return the index of the vertex at the end of the cut. If there was no previous Cut or if it couldn't reach all the way to the desired end point, this method will return -1. - - - - Example: The Cut mode uses this method to generate a series of sequential cuts, where each cut begins exactly on the vertex at the end of the last cut. - - - - - Resets the "last cut end" data to -1. (See EpModGetLastCutEnd for more details.) - - - - - Please ignore - this method was never implemented, it does nothing. At some point in the future, it may be used to cancel out of a cut, but this probably isn't necessary since EpModCancel does that effectively. - - - - - Divides edge, inserting a vertex partway along its length. Used in the Edit Poly "Insert Vertex" mode in the subobject level. - - - - The edge to divide - The proportion along the edge for the location of the new vertex. This should be in the range 0-1, where 0 is on top of the edge's v1 vertex, 1 is on top of the v2 vertex, and .5 is exactly in the middle. - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Divides the face, inserting a vertex in it and splitting the face up into triangles connecting the new vertex with all the face's original edges. - - - - The face to divide - A set of weights for the corners of the face. This table should have Count equal to the face's degree, and its values should add up to 1. NULL is not permitted. If you want a vertex in the center of the polygon, set all values to 1.0f / (face degree). - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Weld two vertices. In order for the operation to succeed, the vertices must either share an edge, or both be on borders. Success can be detected by checking vertex v2's MN_DEAD flag after the operation - if it's set, the weld succeeded. - - - - index of the first vertex - index of the second vertex - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Weld two edges (by welding the vertex endpoints). In order for the operation to succeed, both edges must be on borders - their "f2" face should be empty (-1). Success can be detected by checking edge e2's MN_DEAD flag after the operation - if it's set, the weld succeeded. - - - - index of the first edge - index of the second edge - The specific node to use, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Attach another mesh to this one. - - - Note that this method deletes the original node which is being attached. - - The node containing the mesh to attach. (If the object contained is not a mesh, it will be converted to a mesh.) - The specific node to attach to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - The time at which to attach it. (This is the time at which the other node is evaluated, which may be important if the other node is animated.) - - - - Attach a bunch of other meshes to this one. - - - Note that this method deletes the original nodes which are being attached. - - The table of nodes containing the meshes to attach. (If the object contained is not a mesh, it will be converted to a mesh.) - The specific node to attach to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - The time at which to attach it. (This is the time at which the other nodes are evaluated, which may be important if the other nodes are animated.) - - - - Detaches the current selection to a new Editable Poly object. - - - If this Edit Poly modifier is instanced across multiple nodes, a new Editable Poly object will be created for each node. - - - - - Creates a shape object based on the current set of selected edges. - - - Note that control over whether the resulting shape is curved or linear is not currently exposed in the SDK. It's controlled by the static EditPolyMod variable "mCreateShapeType", which you can find in the Edit Poly source in maxsdk/samples/mesh/EditPoly. - - - - - Sets the Hinge from operation to use the hinge edge given. - - - - The edge to use as a hinge - The mod context TM for the node containing the edge. This is important when the Edit Poly is instanced across multiple nodes, because the coordinates of the edge are used to hinge the faces in the other nodes as well. We need to get these coordinates in some common reference frame, which is what the mod context tm is used for. - The specific node which contains the hinge, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Retrieves the current Hinge , or -1 if no hinge edge is set (or if it's set on a different node). Note that if the Edit Poly is instanced across multiple nodes, only one node should contain a hinge edge. - - - - The specific node which we're referring to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Create a Bridge between two border loops. - - - - An edge on the first border loop - An edge on the second border loop - The specific node which we're referring to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - - index of the first face to bridge - index of the second face to bridge - The specific node which we're referring to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The index of the diagonal - between 0 and EpMeshGetFaceDegree(faceIndex, pNode)-4. (There are always n-3 diagonals in a polygon of degree n.) - The specific node which we're referring to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Lists the entire history of applied operations to the Scripting window. This is not quite adequate for recreating the Edit Poly in a script, because some information is omitted; but it'. - - - - The specific node which we're referring to, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Get a pointer to the Edit Poly's cached mesh. This is the mesh after all the committed operations, but before the current operation, if any. The mesh returned from this method should not be modified! - - - - The specific node which we want the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Get a pointer to the Edit Poly's cached output mesh. This is the mesh after all committed operations as well as the current operation, if any. The mesh returned from this method should not be modified! - - - - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of vertices in the mesh. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the position (in object space) of a particular vertex in the mesh. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the vertex - between 0 and EpMeshGetNumVertices(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of faces using a particular vertex. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the vertex - between 0 and EpMeshGetNumVertices(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns a face that uses the vertex given. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the vertex - between 0 and EpMeshGetNumVertices(pNode)-1. - The index of the face - between 0 and EpMeshGetVertexFaceCount(vertIndex, pNode)-1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of edges using a particualr vertex. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the vertex - between 0 and EpMeshGetNumVertices(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns one of the edges using the vertex given. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the vertex - between 0 and EpMeshGetNumVertices(pNode)-1. - The index of the edge - between 0 and EpMeshGetVertexEdgeCount(vertIndex, pNode)-1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of edges in the mesh. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the vertex at one end of the edge given. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the edge - between 0 and EpMeshGetNumEdges(pNode)-1. - The end of the edge - 0 or 1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the face on one side of the edge given. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the edge - between 0 and EpMeshGetNumEdges(pNode)-1. - The side of the edge. Edges are guaranteed to have a face on side 0, but "border" edges have no face on side 1. "No face" is indicated by a return value of -1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of faces in the mesh. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the degree of the indicated face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the vertex in a particular corner of a particular face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. The relationship between sides and corners of the polygon is: side i goes from corner i to corner (i+1)degree. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The corner of the face - between 0 and EpMeshGetFaceDegree(faceIndex,pNode)-1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the edge on a particular side of a particular face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. The relationship between sides and corners of the polygon is: side i goes from corner i to corner (i+1)degree. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The side of the face - between 0 and EpMeshGetFaceDegree(faceIndex,pNode)-1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the index of the corner used at an end of a face diagonal. - - - The index of the corner of the face. To get the index of the vertex at that corner, call EpMeshGetFaceVertex on this result. - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The index of the diagonal - between 0 and EpMeshGetFaceDegree(faceIndex, pNode)-4. (There are always n-3 diagonals in a polygon of degree n.) - 0 for the start of the diagonal, 1 for the end. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the material ID used by a particular face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the smoothing groups used by a particular face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of positive map channels in the mesh. This number depends on the map channels that are active, or have been in the past. Default is 2, typically it's in the single digits, but it can range as high as MAX_MESHMAPS. (These channels need not all be active - this method just gives an upper bound on the index of active map channels.) - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Indicates if the specified map channel is "active", that is, if it contains a set of map coordinates and map faces. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the map channel, which can range from -NUM_HIDDENMAPS to EpMeshGetNumMapChannels(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the number of map vertices in the specified map. This is typically larger than the number of regular vertices in the mesh, though it can be the same or lower. Returns 0 for inactive maps. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the map channel, which can range from -NUM_HIDDENMAPS to EpMeshGetNumMapChannels(pNode)-1. - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the UVVert map vertex position for a given map channel and map vertex index. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the map channel, which can range from -NUM_HIDDENMAPS to EpMeshGetNumMapChannels(pNode)-1. - The index of the map vertex, in the range of 0 to EpMeshGetNumMapVertices(mapChannel,pNode)-1 - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Returns the index of the map vertex used in a particular corner of a particular map face (in a particular map). - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the map channel, which can range from -NUM_HIDDENMAPS to EpMeshGetNumMapChannels(pNode)-1. - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. (All map channels have the same number of faces as the mesh.) - The corner of the face - between 0 and EpMeshGetFaceDegree(faceIndex,pNode)-1. (Each map face has the same degree as the corresponding mesh face.) - The specific node to get the mesh from, in cases where the Edit Poly is instanced across multiple nodes. If left at NULL, the Primary node is used. (See EpModSetPrimaryNode.) If no primary node has yet been established, one is picked arbitrarily. If the Edit Poly is only used by one node, you may safely leave this at NULL. - - - - Bridges individual edges, will use current parameters. - - - - The source of the bridge operation - The target of the bridge operation - The node to which the bridge is applied - - - - Changea the edge selection in the ring direction. - - - - - Changes the edge selection in the loop direction. - - - - Specifies which way the current edge selection is changed. it can take the values : - The node to which the bridge is applied - - - - Changes the edge selection , in the ring direction. - - - This method adds ( move or remove ) edges from the current selection. - n the 'positive' ( or negative ) ring direction,using the 3 existing parameters. The ring direction is vertical for a plane. - If in_newPos == -3 , in_moveOnly == false and in_add == true, it adds 3 edges from the current selection, - in the negative ring direction. this is equivalent to the MaxScript: $.setRingShift -3 false true - - If > 0 will change the edge selection the 'positive' ring direction, if < 0 in the 'negative' direction. - If true, edges are moved, if false, edges are added or removed from selection - If true edges are added, if false, edges are removed from current selection - - - - Changes the edge selection , in the loop direction. - - - This method adds ( move or remove ) edges from the current selection. - n the 'positive' ( or negative ) loop direction,using the 3 existing parameters. The loop direction is horizontal for a plane. - If in_newPos == -3 , in_moveOnly == false and in_add == true, it adds 3 edges from the current selection, - in the negative ring direction. this is equivalent to the MaxScript: $.setLoopShift -3 false true - - If > 0 will change the edge selection the 'positive' ring direction, if < 0 in the 'negative' direction. - If true, edges are moved, if false, edges are added or removed from selection - If true edges are added, if false, edges are removed from current selection - - - - Converts current sub-object selection to the specified sub-object border. - - - It converts for instance selected faces into their border edges and selects it, - if you call EpModConvertSelectionToBorder( EPM_SL_FACE, EPM_SL_EDGE); - - Can be EPM_SL_EDGE, EPM_SL_FACE or EPM_SL_VERTEX - Can be EPM_SL_EDGE, EPM_SL_FACE or EPM_SL_VERTEX - - - - Commits any Paint Deformation as if pressing the Commit button. - - - Has no effect when the Commit button is disabled - - - - - Reverts any Paint Deformation as if pressing the Revert button. - - - Has no effect when the Revert button is disabled - - - - - Returns the normal of the face specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Returns the center of the face specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Returns the area of the face specified. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - The index of the face - between 0 and EpMeshGetNumFaces(pNode)-1. - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Returns a list of edges that are adjacent to at least one empty face. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Moves the specified vertices to the specified point. Requires a commit for other functions to return the proper data. - - - This is based on the mesh after all committed operations, but before the current operation, if any. - - - List of vertices that will be moved - - Point in the current coordinate system that the vertices will be moved to - - Optional node to run the check on. If the node is not specified, we will use the currently selected noe - - - - Brings up the Smooting Group floater dialog. If it is already up it closes it. - - - - - Brings up the ID floater dialog. If it is already up it closes it. - - - - - Returns whether the ID floater dialog is up. - - - - - Returns whether the Smooting Group floater dialog is up. - - - - - Closes the Smoothing Group Floater Dialog. - - - - - Returns the ID Floater Dialog Handle. - - - - - Returns the SmGrp Floater Dialog Handle. - - - - - Prints the delta operations to script window. - - - - - Returns the last operation used or -1 if none. - - - - - This new class extends EPolyMode, in particular adds a more efficient way for setting several vertex positions, and the ability for to support manipulate grips. - - - - - Prepares the Edit Poly modifier for setting several vertex positions in a row. - - - - - Sets the posititon of a single vertex. Should only be used inbetween. - - - - - Finishes setting vertex positions and applies undo functionality. - - - - - Turns the manipulate grip item on or off. When at least one grip item is on and select and manpulate mode is active a grip will show up for each item that's on. - - - - - Whether or not the specified item will be turned on or off - - Which grip item that will be turned on or off. - - - - Get whether or not this manipulator item is on or not. - - - Whether or not the item is on or not. Note that it doesn't take into account whether or not the correct subobject mode is also active, it just checks to see if it would be on if in the right mode. - - - Which grip item we are checking to see if it's on or off. - - - - This new class for Phoenix extends for altering vertex and edge Crease/Weight/etc. values. - - - - - Gets float data and other information from the specified float vertex channel. - value in common for all flagged vertices if 'numSel' is nonzero and 'uniform' is true - - - See for vertex channel numbers (VDATA_XXX). - - Returns number of vertices in the group (indicated by vertexFlags, below) - - True if all vertices flagged have the same value in the specified channel - - Specifies flags for vertices to be checked (i.e. MN_SEL: all selected vertices) - - The node that is used by the modifier. - - - - Gets float data and other information from the specified float edge channel. - value in common for all flagged edges if 'numSel' is nonzero and 'uniform' is true - - - See for edge channel numbers (EDATA_XXX). - - Returns number of edges in the group (indicated by edgeFlags, below) - - True if all edges flagged have the same value in the specified channel - - Specifies flags for edges to be checked (i.e. MN_SEL: all selected edges) - - The node that is used by the modifier. - - - - Removes data for the specified float vertex channel. - - - See for vertex channel numbers (VDATA_XXX). - - The node that is used by the modifier. - - - - Removes data for the specified float edge channel. - - - See for edge channel numbers (EDATA_XXX). - - The node that is used by the modifier. - - - - Starts the modification process for per-vertex or per-edge data, creates restore objects in case they're needed for undo Call this prior to calling DoPerDataModify. - - - See for selection level numbers (MNM_SL_VERTEX and MNM_SL_EDGE are supported). - - See for vertex channel numbers (VDATA_XXX) and for edge channel numbers (EDATA_XXX). - - - - Does the actual modification for per-vertex or per-edge data. Should only be used inbetween calls to BeginPerDataModify and EndPerDataModify. - - - See for selection level numbers (MNM_SL_VERTEX and MNM_SL_EDGE are supported). - - See for vertex channel numbers (VDATA_XXX) and for edge channel numbers (EDATA_XXX). - - float value to set - - - - Checks to see if the per-data modification process for per-vertex or per-edge data is underway - True (in progress) or false (not in progress) - - - - - Ends a per-data modify operation. Call this after all DoPerDataModify calls are complete. - - - If true, this commits the operation and puts the restore objects to the undo system. If false, the restore objects are destroyed. - - - - This class represents a single triangular face. The class maintains three indices into the vertex list for the face, a 32-bit smoothing group for the face, and 32-bits of face flags. The flags also store information about the visibility of the face, the visibility of the three edges, and whether or not the face has texture vertices present. The most significant 16-bits of the face flags store the material index. All methods of this class are implemented by the system. - - - - - These are zero-based indices into a mesh object's array of vertices. - - - - - Smoothing group bits for the face. Each bit of this 32 bit value represents membership in a smoothing group. The least significant bit represents smoothing group #1 while the most significant bit represents group #32. If two adjacent faces are assigned the same smoothing group bit, the edge between them is rendered smoothly. - - - - - The Flags: Can be from the following list: - - - - - Retrieves the zero based material ID for this face. Note: typedef unsigned short MtlID; - - - - - Returns the smoothing group bits for this face. - - - - - Sets the vertices of this face. - - An array of the 3 vertices to store. These are zero based indices into the mesh object's array of vertices. - - - - Sets the vertices of this face. The specified indexes are zero based indices into the mesh object's array of vertices. - - Specifies the first vertex. - Specifies the second vertex. - Specifies the third vertex. - - - - Sets the visibility of the specified edge. - - Specifies the edge to set the visibility of. You may use 0, 1, or 2. - One of the following values: - - - - Sets the visibility of the all the edges. - - Specifies the visibility for edge 0. Use either EDGE_VIS or EDGE_INVIS. - Specifies the visibility for edge 1. Use either EDGE_VIS or EDGE_INVIS. - Specifies the visibility for edge 2. Use either EDGE_VIS or EDGE_INVIS. - - - - Retrieves the edge visibility for the specified edge. - Nonzero if the edge is visible, zero if the edge is invisible. - - Specifies the edge. - - - - Returns the index into the mesh vertex array of the specified vertex. - - Specifies the vertex to retrieve. You may use 0, 1 or 2. - - - - Retrieves a pointer to the vertex array. - A pointer to the vertex array. - - - - - Determines if the face is hidden or visible. - TRUE if the face is hidden; otherwise FALSE. - - - - - Hides this face (makes it invisible in the viewports). - - - - - Shows this face (makes it visible in the viewports). - - - - - Sets the hidden state of this face. - - Specifies the hidden state for the face. Pass TRUE to hide the face; FALSE to show it. - - - - Returns the first vertex in the face that isn't v0 or v1. - The zero based index of the vertex found in the 's vertex list. - - The zero based index of one of the vertices to check. - The zero based index of the other vertex to check. - - - - Returns the index of the edge in the face that goes from v0 to v1, or v1 to v0. - The zero based index of the edge found in the 's edge list. - - The zero based index of the vertex at one end of the edge. - The zero based index of the vertex at the other end of the edge. - - - - Indicates order in which vertices v0 and v1 appear in the face. - 1 if v1 follows v0 in sequence (This includes e.g. when Face::v[2] == v0 and Face::v[0] == v1.) -1 if v0 follows v1 in sequence 0 if v0 or v1 are not on the face. - - One vertex on this face. - Another vertex on this face. - - - - Returns the index of the specified vertex in this face's vertex list (0, 1 or 2). If not found 3 is returned. - - The zero based index of the vertex to check. - - - - This method switches v0,v1 if needed to put them in face-order. If v0 and v1 are in the order in which they appear in the face, or if one or both of them are not actually on the face, nothing happens. If however v0 follows v1, the values of the parameters are switched, so that they are then in the correct order for this face. Sample Code: - - One vertex on this face. - Another vertex on this face. - - - - This class represents the notion of a mesh edit Change, which changes the visibility of the face's edges, its hidden state and/or its material ID. - - - - - The face to change. This is a zero based index into the Mesh::faces array. - - - - - Specifies which attributes to change. One or more of the following values: ATTRIB_EDGE_A - Alter edge between v0 and v1 ATTRIB_EDGE_B - Alter edge between v1 and v2 ATTRIB_EDGE_C - Alter edge between v2 and v0 ATTRIB_EDGE_ALL - Alter all the edges. ATTRIB_HIDE_FACE - Alter the face hidden state. ATTRIB_MATID - Alter the material ID. - - - - - The value containing the face change information. Bits 0, 1, 2 hold the edge visibility, bit 3 holds the hidden state, and bits 5-21 hold the material ID. - - - - - Applies the face change to the passed using the flags of this object to control what's altered. - Parameters: - &ff The face to change. - - - - - Updates the flags and val to the passed using this and its flags. - Parameters: - &fa The object to alter. - - - - - Description: - This is a list of face "clusters" for a given mesh. A typical application would be in Edit(able) , where the user has selected two separate groups of faces on different parts of the mesh and wants to extrude them both, or rotate both around their local centers. Each "cluster" is a contiguous group of selected faces. Like AdjEdgeLists and AdjFaceLists, this class is only defined in relation to some mesh. - - This class may be used to group faces together based on the angle between their normals or by their selection status. - - All methods of this class are implemented by the system. Note that the functionality provided by this class is not available in the 1.0 release of the SDK. Later releases (1.1, 1.2, etc) do support it. - Data Members: - clust; - - The cluster number (id), one for each face. Non-selected faces have UNDEFINED for their id. - - The cluster IDs of all the faces - this table has size mesh::numFaces. clust[i] is UNDEFINED if face i is not in any cluster (ie is unselected). - - DWORD count; - - The number of clusters. - - - - - Access operator. Returns the cluster ID for face i. - - - - - Computes average normals and centers for all face clusters. Within a cluster, normals are weighted by the area of the face - a face twice as big contributes twice as much to the cluster normal. (Mathematically, we just total up the non-normalized cross-products of each face, which are equivalent to 2*(area)*(face normal). Then we normalize the cluster total.) centers are directly averaged, without weighting. - Parameters: - &mesh - - The mesh associated with this . - - > &norm - - The average normal table to store the results in. This is set to size FaceClusterList::count, the number of clusters. - - > &ctr - - The average center table to store the results in. This is set to size FaceClusterList::count, the number of clusters. - - - - - This creates "outline" directions for the vertices on the edge of the clusters. These are used in Edit(able) 's new "Bevel" operation (when you Bevel by "Group"). These vectors, which are all perpendicular to the cluster normals, point in the direction and speed vertices must travel in order to move the edges out at a consistent rate without changing the shape of the outline of the cluster. - - To see how this works, create a Prism in 3ds Max ("Extended Primitives") with dimensions like 20 x 40 x 40 x 40, and apply an Edit . Select all the faces on the top of the prism, and spin the Bevel spinner up and down. Notice that the vertex at the sharpest point moves faster than the other 2, but that the edges all remain parallel to their original positions. The essence of Outlining is that the edges move at a constant rate, and the vertices move faster or slower to make this happen. (This strategy is also used in the Bevel and Path Bevel modifiers.) - Parameters: - & m - - The mesh associated with this - - &af - - The adjacent face list associated with this - - > &cnorms - - The cluster normals, as computed by GetNormalsCenters - - > &odir - - A table to put the outline direction result in. This is set to size mesh.numVerts. Entries for vertices that are not on a cluster border are all (0,0,0). Entries for cluster border vertices are scaled, such that if you move all vertices the specified amount, each cluster's border edges will move by one 3ds Max unit. - Operators: - - - - - This class represents the notion of a face create within a . The public data members provide the index of any original face the new face may be based on as well as the new face itself. The virtue of providing the original face information is that we may use it to track per-face data that isn't contained within the face itself. Note that this class relates closely to the new custom per-face data channels. For details on the implementations see Class , Class . - - - - - The face in the input mesh this new face should copy properties from. If UNDEFINED, this face is assumed to be totally original and should not copy properties from any faces in the input mesh. - - - - - The new face. - - - - - Assignment operator. Sets all data members to be equal to those in fc. - Default Implementation: - { original = fc.original; face=fc.face; return *this; } - - - - - Description: - This is a class that lets you go from mesh space to patch space basically the painter only paints on meshes you can create an array of this type so you can look up a hit face and then get a patch index from it and the UVW of the hit space on the patch - - - - - the patch that own this face - - - - - the UVW space of the corners of the patch - - - - - Description: - This class may be used to access the various elements that compose a mesh. Given a object mesh, the calls below allow a developer to access the element number for a particular face, and the total number of elements in the mesh. - - ae(mesh); - - af(mesh, ae); - - elem(mesh, af); - - All methods of this class are implemented by the system. - Data Members: - elem; - - This gives the element number for a particular face, i.e. elem[i] gives the element number for face i. - - DWORD count; - - The total number of elements. - - - - - Accesses the i-th element of the table. - - - - - Simple extension to the 3ds Max class. - - - Simple class to store extended data about the face. The indexing works as a regular 3ds Max but mirroring has been taken account of, in the construction. - - - - - Index into the vertex array. - - - - - Index into the standard mapping channel. - - - - - Index into the normal array. - - - - - Index into the vertex color array. - - - - - Index into the vertex illumination array. - - - - - Index into the vertex alpha array. - - - - - The smoothing group. - - - - - The material ID of the face. - - - - - Additional flags. - - - - - Index of corresponding face in the original mesh. - - - - - Index into edge visibility array. - - - 1 for visible, 0 if the edge is invisible. - - - - - This class represents the notion of a mesh edit Remap, which changes one or more of the vertices a face uses. It can also alter the visibility of the face's edge, its hidden state and its material ID. - - - - - being remapped. This is a zero based index into the 's faces array. - - - - - Specifies which vertices to remap. One or more of the following values: FR_V0 - Remap the 0th vertex. FR_V1 - Remap the 1st vertex. FR_V2 - Remap the 2nd vertex. FR_ALL - Remap all the vertices. - - - - - of vertex indices. These indicate which vertex is used by each specified corner of the face being remapped. - - - - - Applies the vertex remapping to the given face based on the flags of this object. - - - The face whose vertices are remapped. - - - - Applies the vertex remapping to the given map face based on the flags of this object. - - - The texture face whose tVerts are remapped by the verts of this object. The data member used contains indices into the mesh object's array. - - - - Assigns the flags and verts of this object to the passed. - - - The whose flags and verts are assigned. - - - - Returns a new with the applied. - - - - - Returns a new with the applied. - - - - - This class represents the notion of the edit mesh Smooth operation. This updates the smoothing group information in the face. - - - - - The face to change. This is a zero based index into the Mesh::faces array. - - - - - The mask into the face of the smoothing groups. - - - - - The smoothing group information to store. - - - - - Applies this smoothing change to the given face. - Parameters: - &ff The face to update. - - - - - Assigns the flags and val to the given object from this one. - Parameters: - &fs The object to alter. - - - - - Description: - This is an intermediate base class for drop content that comes in the form of a package of filenames or URLS. This class maintains a list of all its subclass singleton instances and provides utility methods for finding an appropriate subclass instance, based on the dropped filename, and for download URL packages. - Data Members: - protected: - - <FileDropType*> fileDropTypes; - - The table of FileDropTypes. - - static MSTR download_directory; - - Cache for current default URL package download directory . - - public - - current_package; - - Currently dropping URL package. Filled in by the active in its ParseDataObject() method . - - - - - Subclasses should implement this method to recognize the file types associated with this drop type. This is used by FindDropType(). - Parameters: - MCHAR* filename - - The filename suffix. - TRUE if the filename suffix checks out, otherwise FALSE. - Default Implementation: - { return false; } - - - - - Open an encrypted text file for read. - The instance itself if max is able to open the file or undefined if it fails. - - The file name. - The seed encryption value. - The encoding to use if if can not be determined from the file contents, If -1, a default encoding based on the file language settings in Preference /Files (exposed through ) will be used. - - - - Open a text file - The instance itself if max is able to open the file or undefined if it fails. - - The file name. - The file open mode. See the Help file, topic Values, for a description of the mode string values. - The encoding to use if if can not be determined from the file contents, If -1, a default encoding based on the file language settings in Preference /Files (exposed through ) will be used. - - - - Description: - This is the plug-in class from which developers sub-class their Anti-aliasing filters. These filters appear in the Render Scene dialog in the Anti-Aliasing section in the Filter dropdown list. - - Filter are a very simple plug-in as there are only a few methods that define them. The KernelFn() method is the one that does the filtering. The other methods are simply informational. - - A filter kernel is nothing but a curve that starts (usually at 0) at some distance R from a center pole. This curve is swept around the center pole forming a volume that is centered at the center of a pixel (0.5,0.5) and extends to cover some of the near neighboring pixels. The height of this filter "hat" gives the weight for each pixel under the filter. To achieve high resolution and good quality this convolution is done at full 8x8 sub-pixel resolution: each subpixel is weighted by the height of the curve above it. This is what the KernelFn() method returns. It is given the distance from the center pole and it returns the weight. This is the only method that computes anything. - - Note: When things get rasterized in 3ds Max it is done so at a resolution higher than that of the final output raster. 3ds Max actually rasterizes the geometry to an 8x8 raster within each pixel. This mask is used do hiding and shading operations properly inside each pixel. Each of these 64 inside-a-pixel pixels is called a subpixel. - - Theoretically, the KernelFn() function could get called once for each sub-pixel with the distance of the center of that subpix to the center pole. Of course that would take a great deal of time. Instead 3ds Max builds a table at the beginning of a render. This table is slow to build (it requires many calls to KernelFn()) but fast to use and gives exactly the same answer as doing the computationly intense approach at the sub-pixel level. Thus the KernelFn() function can be fairly slow yet the render still happens relatively fast. - Plug-In Information: - Class Defined In RENDER.H - - Super Class ID FILTER_KERNEL_CLASS_ID - - Standard File Extension DLK - - Extra Include File Needed None - - - - - This is the function that is called to sample the kernel values. This returns the weight of the filtering curve at the specified distance from the center pole of the curve. - Parameters: - double x - - The distance from the center pole of the curve. - - double y = 0.0 - - The distance from the center pole of the curve in y (for 2D filters). - - - - - This method returns the kernel 'support'. Support is the integer number of pixels beyond the center pixel that are touch in some part by the kernel. Support of 0 is 1x1: the area filter. A support value of 1 is a 3x3 filter, one pixel on all sides of the center. A support of 2 is 5x5. The size of a side of the block is always 2*Support+1. Support confides how many pixels might be touched, but not the exact size of the filter. - - - - - For 2D kernels returns the Y support. See GetKernelSupport() above. - - - - - Most kernels are 1D and hence circularly symmetric about the center pole, but some are 2D like a box or diamond. This method returns true if the filter is 2D and false if 1D. - - A 2D kernel uses both parameters of the methods GetKernelSz() and SetKernelSz(). A 1D kernel only uses x; y need not be included in the set. Note that GetKernelSz() always requires both x & y since they are return parameters while a 1D kernel ignores y. Also note that a 2D filter provides a filter function that uses both the x and y parameters. - - - - - Returns true if the filter is variable size; otherwise false. Size means the distance from the center pole where the filter function becomes essentially 0. In non-variable size filters this width is returned in GetKernelSz() and is usually displayed in the greyed out Size box in the user interface. In variable size filters get & set size control the bluriness. - - - - - Stores the kernel size. A 2D kernel stores both parameters of this method. A 1D kernel stores only x. - Parameters: - double x - - The x value to store. - - double y = 0.0 - - The y value to store. - - - - - Retrieves the kernel size. A 2D kernel uses both parameters of this method. A 1D kernel only uses x (y is set to 0). - Parameters: - double& x - - The x size is returned here. - - double& y - - The y size is returned here. - - - - - Returning true from this method will disable the built-in normalizer. Normalized means that if you have some solid color and you filter it, you get the same color out;. it is not brighter or darker than the original. With positive only filters this is always possible, but with some negative lobe filters the colors overflow, so they are toned down (produce a slightly darker image, but don't overflow). - - The normalizer computes the positive and negative volumes of an arbitrary filter and scales all the filter values by 1/volume where volume is (posVolume - abs( negVolume )). This whole process is turned off and the filter values direct from the plug-in have already been scaled internally when this method returns true. - Default Implementation: - { return FALSE; } - - - - - This method tells the filtering code that it can speed things up potentially by dealing with the positive common only case. Currently this is not taken advantage of. - - - - - Returns a pointer to a string which describes the filter. This string is displayed in the static text box in the user interface. - - - - - There are two optional parameters that may be used by the filter (besides Filter Size). This method returns the number used. If two parameters are used both hidden spinners appear in the Anti-aliasing section of the Render Scene dialog. If only one parameter is used just the top spinner appears. If this method returns nonzero then the methods below are used to supply the names for the parameter(s) and to provide and receive the values. - - - - - Returns a pointer to the string containing the name of the specified parameter. - Parameters: - long nParam - - The index of the parameter (0 or 1). - - - - - Returns the specified parameter value. - Parameters: - long nParam - - The index of the parameter (0 or 1). - - - - - Stores the value passed for the specified parameter. - Parameters: - long nParam - - The index of the parameter (0 or 1). - - double val - - The value to set. - - - - - class - Description: - A class whose sole purpose is for building up a filter list to pass to the Windows API functions GetSaveFileName() and GetOpenFileName(). It automatically puts in the embedded nulls and two terminating nulls. All methods are implemented by the system. - - Example usage: - - filterList; - - filterList.Append(_M("MAX files(*.max)")); - - filterList.Append(_M("*.max")); - - ofn.lpstrFilter = filterList; - - GetSaveFileName(&ofn) - - persistent filter support is supported by this class. The index can be used by OPENFILENAME structure. - The default value is 1 and both DoMaxSaveAsDialog and DoMaxOpenDialog have been updated to honour these settings. The developer has to simply store the new index and set it as the actual index the next time these functions are used. - CAUTION: The resulting filter list string is used as-is in the Windows file selector, and expects pairs of entries (a description entry and a wildcard entry, as shown in the example usage above). Providing an odd number of Appended strings can result in a crash. - An example is shown below, and assumes filterIndex is a global variable. - - - - - Appends the string passed to buf. - - - - - Returns the current filter index that will be used in OPENFILENAME structure - The current index - - - - - Returns the new filter index reflecting the users choice of filter. Currently DoMaxSaveAsDialog and DoMaxOpenDialog store this value when they successfully run. - It allows a developer to set the new index correctly using SetFilterIndex() - The new index as chosen by the user. - - - - - Returns the file description string identified by an index into the filter list. - - - Pointer to the string representing the file filter description - - - 1 based index into the filter list - - - - Returns the file extension string identified by an index into the filter list. - - - Pointer to the string representing the file filter extension. The returned extension is exactly in the form in which it's been recorded in the instance. - - - 1 based index into the filter list - - - - Description: - This is a handy class to subclass off of when you're designing a class with flags. It contains one private data member, a DWORD, with the flag info. It then implements a bunch of handy flag-related functions. All methods of this class are implemented by the system. - Data Members: - private: - - DWORD FlagUserFlags; - - Stores the flags. - - - - - Sets flags. Each bit that is set in fl is assigned the value val. - - - - - Clears flags. Each bit that is set in fl is cleared. - - - - - Checks if flags are set. - TRUE if any of the bits set in fl are set in this . FALSE if none of them are. - - - - - Sets FlagUserFlags to 0, clearing all flag bits. - - - - - Copies all flag bits over from fl. - - - - - Copies all flag bits over from fu. - - - - - Copies all flag bits over from *fu. - - - - - Copies from fl only those bits set in mask. - - - - - Copies from fu only those bits set in mask. - - - - - Copies from *fu only those bits set in mask. - - - - - Sets all flags that are set in fu. - - - - - Sets all flags that are set in *fu. - - - - - Clears all flags that are clear in fu. - - - - - Clears all flags that are clear in *fu. - - - - - Checks whether all the bits that are set in fmask are the same in this and in fl. - - - - - Checks whether all the bits that are set in fmask are the same in this and in fu. - - - - - Checks whether all the bits that are set in fmask are the same in this and in *fu. - - - - - Returns a DWORD equal to FlagUserFlags. - - - - - Sets FlagUserFlags equal to fl. Same as CopyFlags (fl), but it's included for "linguistic completeness". - - - - - Description: - This class uses four indices into the image list to describe the button in each of the possible states: Out&Enabled, In&Enabled, Out&Disabled and In&Disabled. An array of instances of this class are passed into the method ICustButton::SetFlyOff(). - Data Members: - These four data members are indices into the image list. They indicate which images to use for each of the four possible button states: - - You may specify a unique image for each one of these states by passing a different index for each state. Or you may supply a single image to be used for all the states by specifying the same index four times. - - int iOutEn; - - Out&Enabled. - - int iInEn; - - In&Enabled - - int iOutDis; - - Out&Disabled. - - int iInDis; - - In&Disabled. - - - - - A class for providing access to required 3ds Max internals - - - - - A Space Warp modifier usually uses an instance of this class and implements the Force() method. The force field is then applied to the particle system when the particle system is bound to the Space Warp. This class is similar in some respects to the class as used by a modifier. The difference is that a deformer modifies the points of the object. A force field is really an acceleration - it modifies velocity rather than position. The force field provides a function of position in space, velocity and time that gives a force. The force is then used to compute an acceleration on a particle which modifies its velocity. Typically, particles are assumed to have a normalized uniform mass equal to 1 so the acceleration is F/M = F. - - - - - - This method is called to compute a force on the particle based on its position, velocity and the current time. - The force vector as a . This vector is added to the velocity. - - The time to compute the force. - The current position of the particle. - The current velocity of the particle. - The index of the particle being forced. - - - - Description: - This class describes a range of frames and provides methods to access the first, last, current and number of frames in the range. All methods of this class are implemented by the system. - - - - - Returns the first frame number of this range. - - - - - Returns the last frame number of this range. - - - - - Returns the number of frames in this range. - - - - - Returns the current frame of this range. - - - - - Returns the elapsed time of this range. - - - - - This is passed to the renderer on every frame. This provides information about the ambient light color, the background color, the duration of one frame, etc. - Data Members: - ambient; - - The ambient light color. - - background; - - The background color. - - globalLightLevel; - - This is a multiplier that scales the brightness of all scene lights: it doesn't affect the ambient light level. - - float frameDuration; - - The duration of one frame in units of current frames. This describes how much scene time is used by one (video) frame time. For instance, in Video Post, you can scale time so it's stretched out or compressed. In this case, you may be rendering one frame to video, but because the scene is being run at a faster speed than normal, you in fact see say 2.5 frames of the scene. Things such as field rendering or motion blur must know about this so they know how long a frame is in terms of the time of the scene. - - float relSubFrameDuration; - - This is the relative fraction of frameDuration used by a subframe. Within the frameDuration, if you're sub-dividing the rendering up into multiple frames for scene motion blur, this may be used. - - For instance, say the duration (frames) is set to 0.5 and the duration subdivisions is 5, then this data member would be 0.1. This means that each subframe is effectively covering only 1/10th of the frame duration. - - This value is always less than 1.0. - - int regxmin, regxmax; - - The x min and max boundary values for render region or render blowup in device coordinates. - - int regymin, regymax; - - The y min and max boundary values for render region or render blowup in device coordinates. - - blowupCenter; - - The 2D point at the center of the render blowup region. - - blowupFactor; - - The X and Y scale factors for render blowup. - - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Description: - This class provides methods that access properties of the image filter plug-in. All methods of this class are implemented by the system. - - - - - Returns a pointer to the class descriptor. - - - - - Returns the capability flags. - - - - - Tests the flags passed to see if they are set in the capability flags. - Parameters: - DWORD cap - - The flags to test. - TRUE if the flags are set; otherwise FALSE. - - - - - Compares this class instance to another one - - - - - Description: - This class provides methods to access the table of image filters. Methods are provided to find the index in the table of the filter using it description string, check the capabilities of any filter in the table, and to create instances of any filters in the table. All methods of this class are implemented by the system. - - - - - Sets the state to indicate the list of filter plug-ins has been built. - Parameters: - BOOL f - - TRUE indicates the list has been built; FALSE indicates this list has not been built. - The state that was set is returned. - - - - - Returns TRUE if the list of filter plug-ins has been built; otherwise FALSE. - - - - - Returns the index in the filter table of the image filter whose description string is passed. - Parameters: - const MCHAR *name - - The Description string of the filter to find. - If found, the index in the table is returned; otherwise -1. - - - - - Returns the capability flags associated with the image filter whose description is passed. - Parameters: - const MCHAR *name - - The Description string of the filter. - The capability flags. If not found, 0 is returned. - - - - - This method creates an instance of the class. This method will call Create() on the class descriptor. Make sure to delete this instance after use. - Parameters: - const MCHAR *d - - The Description string of the filter to create. - An instance of the class. The developer is responsible for deleting this instance. - - - - - Description: - , contains extra descriptor info for Action interface functions. - Data Members: - MSTR internal_cat; - - The fixed, internal category name. - - StringResID category; - - The localizable category string resource ID. - - FunctionID isEnabled_id; - - The interface function IDs for the isEnabled predicate for this action. - - FunctionID isChecked_id; - - The interface function IDs for the isChecked predicate for this action. - - FunctionID isVisible_id; - - The interface function IDs for the isVisible predicate for this action. - - ResID icon_resID; - - The icon as resource ID. - - MSTR icon_file; - - The icon as UI .bmp filename, index pair, as per CUI icon specifications. - - short icon_index; - - The index of the icon associated with the action. - - MaxIcon* icon; - - The class data associated with this action. - - StringResID button_text; - - The button text string resource ID, defaults to function description. - - StringResID tool_tip; - - The tooltip string resource ID, defaults to function description. - - StringResID menu_text; - - The menu item text string resource ID, defaults to buttonText or function description. - - ControlType2 ctrl_type; - - The type of UI control, if f_ui specified. - - ResID ctrl_pbID; - - The control's host parammap pblock ID. - - MapID ctrl_mapID; - - The control's host parammap map ID within the block. - - int ctrl_id; - - The control dialog item ID. - - COLORREF ctrl_hiCol; - - The highlight color if check button. - - ACCEL shortcut; - - The default keyboard shortcut. - - - - - Description: - This class contains an ID for the enumeration and a table of structures which contains a name and an integer code for each item. This is used by metadata clients to support symbolic values for TYPE_ENUM types (ints). - - One or more symbolic enums, similar to C++ enums, can now be added to an 's metadata, and individual int parameters and/or results for functions in that interface can be defined as TYPE_ENUM and associated with one of the enum lists. Working in a similar manner as MAXScript, this allows metadata clients to support symbolic encodings for these parameters and results. - - Enums are defined in the descriptor following the function and property definitions as sets of string/code pairs. Each enum list is identified by a unique integer, similar to function IDs, which is used to associated a TYPE_ENUM parameter or result with its enum. IDs for these would normally be defined somewhere near the function IDs for an interface. For example: might be some of the IDs for a possible bitmap manager interface. The two enums provide symbolic codes for the bitmap type and copyImage quality defines in the "bitmap.h" SDK header, such as BMM_PALETTED, BMM_TRUE_32, COPY_IMAGE_RESIZE_LO_QUALITY, etc. In the descriptor for the interface, any enum lists follow the function and property definitions. They are introduced by the special tag, 'enums', as in the following example: In the above example, the enums are listed following the function and property definitions. They are introduced by the 'enums' tag and consist of an enum ID followed by a count of items, followed by that many string and code pairs. By attaching them to the interface like this, any number of functions and properties in the interface can use them. - - The above example also has function and property definitions showing the use of TYPE_ENUM. The copyImage function takes a copyType parameter which uses the bmm_copy_quality enum and the type property uses the bmm_type enum. In all situations where TYPE_xxx types can be supplied in a descriptor, including the new property definitions, TYPE_ENUM can be used to indicate an int by-value type. TYPE_ENUM's must always be followed by an enum ID. This is the only case in which the type is specified as a pair of values. TYPE_ENUM parameters and results show up in MAXScript as # names. For example, if a bmm interface was in the variable 'bm1' and the bitmap type was BMM_GRAY_16: the integer TYPE_ENUM codes are translated back-and-forth to symbolic # names by MAXScript using the definitions in the descriptor's enums. If you need to access the enum metadata in an , it is available in the 'enumerations' data member. This is a <> of pointers to class instances which themselves contain a <> of name, code pairs. See class in /MAXSDK/INCLUDE/FnPub.h for details. - - - - - ID for this enumeration. - - - - - The table of enumeration codes. - - - - - Description: - This class stores data about a single function of an . A table of pointers to these objects is a data member of Class . - Data Members: - FunctionID ID; - - The interface-local ID (unique to the interface only) used to identify the function in calls. - - MSTR internal_name; - - The fixed internal name for the function. - - StringResID description; - - The description string resource. - - USHORT flags; - - The internal flag bits. One of more of the following values: - - FP_ACTION - - Indicates this is an action function. - - FP_HAS_UI - - Indicates the action has UI specified. - - FP_ICONRES - - Indicates icon via resource ID. - - FP_ICONFILE - - Indicates icon via bmp file + index. - - FP_HAS_SHORTCUT - - Indicates has default keyboard shortcut. - - FP_HAS_KEYARGS - - Indicates function has some optional keyword args defined. - - FP_VAR_ARGS - - Indicates a variable number of args, pass args directly in a instance. - - FP_NO_REDRAW - - Do not flag need for viewport redraw when function is invoked, MAXScript defaults to flag redraw. - - ParamType2 result_type; - - The type of value returned by the function. - - EnumID enumID; - - The ID of symbolic enumeration in owning interface if any. - - FPActionDef* action_def; - - The extra metadata if function in an Action interface. - - <FPParamDef*> params; - - The descriptors for parameters to this function. - - - - - Description: - The Function Publishing system makes use of this class. Functions are published in one or more Interfaces by a plug-in. Each interface is represented by an instance of a class derived from this base class. - - Note that the Function Publishing class hierarchy is as follows: - - : This is the base class for all interfaces, the prime client type for using interfaces. - - : This is the class which contains interface metadata. - - : This is the class to use as the base class for defining static or core virtual interface classes. - - : This is for use as the base class for defining object-based mixin interface classes, in this case you also use for mixin interface descriptors. - - - - - Returns a pointer to the class which contains the interface metadata. - - - - - Parameters: - FunctionID fid - - The function ID of the function to invoke. - - TimeValue t=0 - - The timevalue at which to invoke the function. - - FPParams* params=NULL - - The to pass. - The FPStatus. See FPStatus values for details - - - - - This method will invoke the specified function. - Parameters: - FunctionID fid - - The function ID of the function to invoke. - - FPParams* params - - The to pass. - The FPStatus. See FPStatus values for details - - - - - This method will invoke the specified function. - Parameters: - FunctionID fid - - The function ID of the function to invoke. - - TimeValue t - - The timevalue at which to invoke the function. - - & result - - A reference to the resulting . - - FPParams* params=NULL - - The to pass. - The FPStatus. See FPStatus values for details - - - - - This method will invoke the specified function. - Parameters: - FunctionID fid - - The function ID of the function to invoke. - - & result - - A reference to the resulting . - - FPParams* params=NULL - - The to pass. - The FPStatus. See FPStatus values for details - - - - - This method returns a function ID based on the name of the function specified. - Parameters: - MCHAR* name - - The name of the function to retrieve the ID for. - - - - - This method allows you to check whether a specific action function is enabled, in which case the method will return TRUE. If the action function is not enabled FALSE will be returned. - Parameters: - FunctionID actionID - - The function ID of the action you wish to check the enabled state for. - - - - - This method allows you to check whether a specific action function is checked, in which case the method will return TRUE. If the action function is not checked FALSE will be returned. - Parameters: - FunctionID actionID - - The function ID of the action you wish to check the checked state for. - - - - - This method allows you to check whether a specific action function is visible, in which case the method will return TRUE. If the action function is not visible FALSE will be returned. - Parameters: - FunctionID actionID - - The function ID of the action you wish to check the visibility state for. - - - - - This method will return the isEnabled ID for the specified action function. - Parameters: - FunctionID actionID - - The function ID of the action you wish to get the isEnabled ID for. - - - - - This method will return the isChecked ID for the specified action function. - Parameters: - FunctionID actionID - - The function ID of the action you wish to get the isChecked ID for. - - - - - This method will return the isVisible ID for the specified action function. - Parameters: - FunctionID actionID - - The function ID of the action you wish to get the isVisible ID for. - - - - - This method returns a pointer to the . - Default Implementation: - { return NULL; } - - - - - This method allows you to enable or disable the entire set of actions in the interface You might want to use this method if the actions are only to be active during certain periods in the running of 3ds Max. Usually, this control is achieved via contexts. - Parameters: - BOOL onOff - - TRUE to enable actions, FALSE to disable them. - Default Implementation: - { } - - - - - Description: - This is the Function Publishing interface descriptor. This is usually a static instance of the implementation interface. The constructor for this class uses the same var-args technique used by the constructor, enabling descriptive information for all the functions in the interface to be supplied in one constructor call. - - The class, an that contains the metadata for an interface, is a distinguished singleton instance per interface kept in a <> in . This class is subclassed typically by static and core interfaces and instantiated by mixins to provide their metadata. - - Note the following typedef: typedef - Data Members: - ID; - - The unique ID of the interface. - - MSTR internal_name; - - The fixed internal name for the interface. - - StringResID description; - - The description string resource ID. - - ClassDesc* cd; - - Points to the publishing plug-in's . - - USHORT flags; - - The flag bits. One or more of the following values: - - FP_ACTIONS - - Marks this as an Action , holding only UI modal, zero parameter action functions. - - FP_MIXIN - - Marks this as a Mixin , it is implemented directly by the plug-in class, so the methods in it are virtual on the plugin's objects. - - FP_CORE - - Marks this as a 3ds Max Core , available through GetCOREInterface(Interface_ID). - - FP_STATIC_METHODS - - This interface is used as a static method interface in MAXScript, properties are not directly callable - - FP_SCRIPTED_CLASS - - Internal use only: Belongs to a scripted plug-in class. - - FP_TEMPORARY - - Internal use only: Temporary descriptor built during scene load. - - <FPFunctionDef*> functions; - - A table of descriptors for individual functions in this interface. - - <FPPropDef*> props; - - A Table of descriptors for individual properties in this interface. - - <FPEnum*> enumerations; - - A table of any symbolic enums for the interface. This is a <> of pointers to class instances which themselves contain a <> of name, code pairs. - - The following data members are for scripted plug-ins if this interface belongs to a scripted plug-in class. - - MSPluginClass* pc; - - The scripted class if non-NULL (gc-protected by the scripted plugin class). - - Rollout* rollout; - - The rollout if specified (gc-protected by the scripted plugin class). - - ActionTable* action_table; - - The table published for this action interface. - - For more information, see Class . - - - - - This is a virtual method called by the varargs-based constructors for interface descriptors and static interfaces, so that they have an opportunity to do runtime initialization of any extra state data you add to these interfaces (usually to static interfaces). Since such interfaces are usually constructed with the built-in varargs constructor, there is no way to do custom initialization without a hook like the Init() call. Your static interface would provide an implementation of Init() to do any special initialization. - Default Implementation: - { } - - - - - This method relates to Init(). In some cases, you really do need to provide your own constructor or set of constructors for a static interface or descriptor, but you still want to be able to load it with all the interface metadata that the built-in varargs constructor does. You can do this by calling the LoadDescriptor() method at any point in your own constructors and it takes the same arguments as the built-in varargs constructor. - Parameters: - id - - The unique ID of the interface. - - MCHAR* int_name - - The fixed internal name for the interface. - - StringResID descr - - A string resource ID containing the description for this interface class. - - ClassDesc* pCD - - A pointer to a class descriptor of the publishing plug-in. - - ULONG flag - - The flag bits. One or more of the following values: FP_ACTIONS, FP_MIXIN, FP_CORE, FP_STATIC_METHODS, FP_SCRIPTED_CLASS, FP_TEMPORARY. For a description see the data members descriptions. - - ... - - This method takes a variable number of arguments representing the 'properties' sections and function definitions. For more information see the advanced topics on ~{ Function Publishing }~. - - - - - Add a new function to this interface descriptor. - - - Uses the same parameter syntax as LoadDescriptor and the Constructor. Note that it is mandatory to mark the end of the variable arguments list with end. Failure to do so will result in undefined behaviour. - - - - - Add a new property to this interface descriptor. - - - Uses the same parameter syntax as LoadDescriptor and the Constructor. Note that it is mandatory to mark the end of the variable arguments list with end. Failure to do so will result in undefined behaviour. - - - - - Add a new enum to this interface descriptor. - - - Uses the same parameter syntax as LoadDescriptor and the Constructor. Note that it is mandatory to mark the end of the variable arguments list with end. Failure to do so will result in undefined behaviour. - - - - - This method sets the pointer associated class. You can only call this method once on a descriptor and then only if it has been constructed initially with a NULL cd. See the notes in the constructor. - - - Parameters: - ClassDesc* i_cd - - This points to the class descriptor to set. - - - - - This method returns a pointer to the function definition of a specific function identified by its ID. Calls to this method, given an FPInterface*, can be made indirectly through FPInterface::GetDesc(). For example; GetDesc()->GetFnDef(foo_move); - Parameters: - FunctionID fid - - The unique function ID used to identify the function. - - - - - This method will return a handle to the owning instance. - - - - - This method returns the string associated with a specified Resource ID - Parameters: - StringResD id - - The string resource ID for which you want to obtain the string. - - - - - Description: - A "Mixin" interface provides a way for a plug-in to expose some of its functionality for use by other plug-ins or MAXScript. The notion of "Mixin" refers to the idea that the interface is a sub-class of the plug-in class and thus "mixed in" with it. Many classes in the SDK now inherit from in order to expose some of their functionality. - - Developers should see the documentation for Class for reference on this class as well. - - For an overview of the function publishing system as a whole, see ~{ Function Publishing }~. - - - - - This method is used to directly implement FPInterface::GetDesc() in your public virtual base mixin class, like this; - - GetDesc() { return GetDescByID(THIS_INTERFACE_ID); } - - Then implement a GetDescByID() in the implementing class to avoid link export issues. - Parameters: - id - - The unique interface ID by which to get the . - Default Implementation: - { return &nullInterface; } - - - - - This parameters class contains a 's. is the actual parameter for an FP call. - - - - - The table of 's contained in this class. - - - - - This method loads a number of parameter values using variable args. This method takes a variable number of arguments representing the parameter values that will be stored in the params table. - - - The number of parameter values to add. - - - - Gets the number of parameters in the params member array. - - - - - Getter function to get the . Note there is no Setter function. - - - - - Description: - This class contains a descriptor for each published function, found in <> in . - Data Members: - MSTR internal_name; - - The internal name. - - StringResID description; - - The string resource ID of the description. - - ParamType2 type; - - The parameter type. See ParamType2 for details. - - EnumID enumID; - - ID of symbolic enumeration in owning interface if any. - - USHORT flags; - - The parameter definition flags; - - FPP_HAS_RANGE - - Indicates that the parameter definition contains a range. - - FPP_HAS_VALIDATOR - - Indicates that the parameter has a validator. - - FPP_IN_PARAM - - In flag used by _BR ref types to decide when to pass in source values or hand back returns. - - FPP_OUT_PARAM - - Out flag used by _BR ref types to decide when to pass in source values or hand back returns. - - FPP_IN_OUT_PARAM - - In-Out flag used by _BR ref types to decide when to pass in source values or hand back returns. - - FPP_KEYARG - - If p_keyArgDefault supplied, the client can use keyword args if supported for this param. If the parameter type is a _BR type, the default value must be specified as a pointer to the default value. - - FPParamOptions* options; - - Present if non-NULL, a pointer to the parameter options object. - - - - - Description: - This class contains the optional parameters holding specific descriptor information. - Data Members: - range_low; - - The low range if specified. - - range_high; - - The high range if specified. - - FPValidator* validator; - - The validator if specified. - - keyarg_default; - - The default if value is optional keyword arg - - BYTE pos_param_count; - - The count of positional params in event of keyword arg presence - - - - - Description: - The 'properties' section follows the function definitions. Each propery has a single entry defining the function IDs for the getter and setter functions, a fixed internal property name, a descriptor string resource ID and the property type. If the property is read-only and there is no setter function, specify FP_NO_FUNCTION for the setter ID. - Data Members: - FunctionID getter_ID; - - The interface-local ID for getter method. - - FunctionID setter_ID; - - The interface-local ID for setter method. - - MSTR internal_name; - - The fixed, internal name. - - StringResID description; - - The description string resource ID. - - USHORT flags; - - The flag bits. - - ParamType2 prop_type; - - The property type. - - EnumID enumID; - - The ID of symbolic enumeration in owning interface if any. - - FPParamOptions* options; - - Present if non-NULL, used for setter param. - - - - - Description: - This class is currently the same as as per the following typedef: - - typedef - - See Class for details. - - - - - Description: - An interface descriptor may contain validation information for individual parameters, so that clients (such as MAXScript) can validate values given as parameters to calls, prior to making the call. The validation information can be in the form of a range of values for int and float types, or more generally, a validator object that is called to the validate a parameter value. - - The validation info is specified in the descriptor in optional tagged entries following the parameters to be validated. The two possible tags are f_range and f_validator. An instance of this class is used when f_validator is specified. - - Here's an example from a possible mixin interface to Cylinder: - - cylfpi ( - - CYL_INTERFACE, _M("cylMixin"), 0, &cylinderDesc, FP_MIXIN, - - ... - - cyl_setRadius, _M("setRadius"), 0, TYPE_VOID, 0, 1, - - _M("radius"), 0, TYPE_FLOAT, - - f_range, 0.0, 10000.0, - - cyl_setDirection, _M("setDirection"), 0, TYPE_VOID, 0, 1, - - _M("vector"), 0, TYPE_POINT3, - - f_validator, &cylValidator, - - ... - - end - - ); - - The "vector" parameter in the above example has a validator object specified. This must be a pointer to an instance of a class derived from the new class, , defined in I/MAXSDK/INCLUDE/iFnPub.h. This is a virtual base class, containing a single method, Validate(), that is called to validate a prospective value for a parameter. You would typically subclass in your code and provide an implementation of Validate() to do the validation. - - - - - This method is called to validate the value val passed for the given parameter in the function whose ID is passed in the specified interface passed. If there are many parameters to validate this way, developers can choose to provide a separate subclass for each parameter or a single subclass and switch on the parameter identification supplied. - Parameters: - FPInterface* fpi - - Points to the interface the function is a part of. - - FunctionID fid - - The ID of the function within the interface above. - - int paramNum - - Identifies which parameter within the function above to validate. - - & val - - The value to validate. - - MSTR& msg - - Update this string with an error message if needed. The user of the Validator can then display this string. - Returns true if the value was valid; false if invalid. - - - - - Description: - This class contains a single value used as part of the ~{ Function Publishing }~ system. It's capable of holding any of the FnPub supported types. This value is used as a parameter and as a return value. - Data Members: - ParamType2 type; - - This data member identifies which type of value is stored in the union below. - - The following union contains a single value, pointer to a single value, or a pointer to a single table (<>) of values. - - - - - - - This method will free up all memory used by the class. - - - - - - - This method will Initialize class. - Default Implementation: - { type = (ParamType2)TYPE_INT; s = NULL; } - - - - - Allocates and initializes the in the for TAB types. - - - - - The ParamType2 type to set the to. - - The size of the tab - - - - Assignment operator. - - - - - This method will load the class with the provided data. - Parameters: - int paramType - - The parameter type to load. - - ... - - This method takes a variable number of arguments. - Default Implementation: - {va_list ap; va_start(ap, type); ap = Loadva(type, ap); va_end(ap);} - - - - - This method will load the class with the provided data. - Parameters: - int paramType - - The parameter type to load. - - ... - - This method takes a variable number of arguments. - - - - - Saves the . - - - Note that raw pointers are not saved. FPValues that contain a raw pointer (TYPE_IOBJECT, TYPE_INTERFACE, TYPE_VOID, TYPE_HWND) will store a pointer value of NULL. - For TYPE_VALUE values, only the following singleton values are saved and loaded: undefined, unsupplied, emptyVal, ok. - All other value types are saved as undefined. - IOResult - One of the following values: IO_OK - The result was acceptable - no errors. IO_ERROR - This is returned if an error occurred. FPValues that contain a raw pointer (TYPE_IOBJECT, TYPE_INTERFACE, TYPE_VOID, TYPE_HWND) will store a pointer value of NULL. For TYPE_VALUE values, only the following singleton values are saved and loaded: undefined, unsupplied, emptyVal, ok. All other value types are saved as undefined. - Parameters: - isave - - This class provides methods to save data to disk. - IOResult - One of the following values: - - IO_OK - The result was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - - - - This class provides methods to save data to disk. - - - - Loads the . - - - IOResult - One of the following values: IO_OK - The result was acceptable - no errors. IO_ERROR - This is returned if an error occurred. - - - This class provides methods to load data from disk. - - - - Compares this class instance to another one - - - - - Description: - Deprecated gamma manager class: Please use which provides better color management functionality. Methods of this class are used to gamma correct and de-gamma colors in various formats. Various settings from the 3ds Max user interface are also accessible via data members of this class (for example the display, and file gamma settings). These settings may be read but should not be set by a plug-in developer. All methods of this class are implemented by the system. - - There is a global instance of this class (defined in /MAXSDK/INCLUDE/GAMMA.H): - - gammaMgr; - - Note the following #defines. These are used to reduce the size of the gamma tables for correcting 16 bit values. - - This class provides a set of commonly used gamma tables. This class does not provide tables for all types of conversion however. For example if you have a different gamma setting that you are using, or if you are going in a different conversion direction than the tables provided here you may use the classes and to build gamma tables. - Data Members: - BOOL enable; - - Indicates if gamma correction is enabled or disabled. - - BOOL dithTrue; - - Indicates if output dithering is to be used for true color images. - - BOOL dithPaletted; - - Indicates if output dithering is to be used for paletted images. - - float dispGamma; - - The display gamma setting. - - float fileInGamma; - - The file input gamma setting. - - float fileOutGamma; - - The file output gamma setting. - - UBYTE disp_gamtabw[RCOLN]; - - Display gamma table (RCBITS->8). - - UWORD file_in_degamtab[256]; - - For de-gamifying bitmaps on input. (8->16) - - UWORD file_out_gamtab[RCOLN]; - - Gamma correct for file output, before dither (RCBITS->16). - - - - - Gamma corrects the specified color using the display gamma setting. - Parameters: - c - - The color to gamma correct. - The gamma corrected color. - - - - - Returns the gamma correction enabled setting; TRUE if enabled; FALSE if disabled. - - - - - Returns the display gamma setting. - - - - - Returns the file input gamma setting. - - - - - Returns the file output gamma setting. - - - - - Description: - A temporary table for converting 16->16. A developer may define an instance of this class and it will build a gamma correction table. The constructor will build the table with the specified gamma setting and the destructor will free the table. All methods of this class are implemented by the system. - - - - - Gamma corrects the specified color. - Parameters: - UWORD v - - The color to gamma correct. - The gamma corrected value. - - - - - Description: - A temporary table for converting 8->16. A developer may define an instance of this class and it will build a gamma correction table. The constructor will build the table with the specified gamma setting and the destructor will free the table. All methods of this class are implemented by the system. - - - - - Gamma corrects the specified color. - Parameters: - UBYTE v - - The color to gamma correct. - The gamma corrected value. - - - - - Description: - This is a utility class for describing hierarchies of shapes. All methods of this class are implemented by the system. - - This is used in generating mesh objects from shapes. In order for a mesh object to be generated correctly, nested shapes must be oriented clockwise or counter-clockwise depending on their level of nesting. For example, a donut shape with two circular curves will have the outer shape going counter-clockwise and the inner shape going clockwise. If a third shape was nested inside both of these, its points would be going counter-clockwise. - - - - - - This method adds one entry given its parent. - Parameters: - int data - - The polygon index of the entry to add. - - int parent = -1 - - The index of the parent of the entry. - - - - - Returns the total number of members in the hierarchy. - - - - - Retrieves the first item under the root. - The first under the root. - - - - - Finds the specified entry in the hierarchy. - Parameters: - int data - - The polygon index of the entry to find. - - HierarchyEntry* start = NULL - - The entry at which to begin the search. If NULL is specified the search starts at the root. - A pointer to the of the found entry. If not found, NULL is returned. - - - - - Returns the number of children for this item. - Parameters: - int data - - The index of the polygon to return the number of children of. - - - - - Returns the specified child of the specified entry. - Parameters: - int data - - The index of the polygon whose child is to be returned. - - int index - - Specifies which child to return. - The specified child of the entry. - - - - - Clear out the hierarchy tree. - - - - - Sorts the hierarchy tree by children / siblings. This is used internally as all the sorting is done automatically as the hierarchy is generated. - - - - - Determines if this hierarchy and the specified hierarchy are compatible. - Parameters: - & hier - - The hierarchy to check for compatibility. - TRUE if the hierarchies are compatible; otherwise FALSE. - - - - - This method is used internally to DebugPrint() the tree. See ~{ Troubleshooting }~. - - - - - Copy operator. - Parameters: - & from - - The hierarchy to copy from. - - - - - Returns the sort key for the hierarchy. This is used internally. - Operators: - - - - - Description: - This class is a tool for manipulating lists of named selection sets. This class is used by modifiers such as the edit mesh, mesh select, spline select and edit patch. - - All methods of this class are implemented by the system. - Data Members: - <MSTR*> names; - - A table of names, one for each selection set. - - <BitArray*> sets; - - The bit array pointers for the selection sets. - - <DWORD> ids; - - A table of Ids, one for each selection set. - - - - - Returns a pointer to the bit array corresponding to the specified name. If the set is not found NULL is returned. - Parameters: - MSTR name - - The name of the selection set to retrieve. - - - - - Returns a poniter to the bit array corresponding to the specified ID. If the set is not found NULL is returned. - Parameters: - DWORD id - - The id of the selection set to retrieve. - - - - - Returns a pointer to the bit array corresponding to the specified index in the list. If the set is not found NULL is returned. - Parameters: - int index - - The zero based index of the selection set to retrieve (>= 0 and < sets.Count()). - - - - - Returns the number of selection sets. - - - - - Appends the named selection set data to the list of sets maintained by this class. - Parameters: - &nset - - The selection set data to append. - - DWORD id=0 - - An ID for the selection set. - - MSTR name - - The name for the selection set. - - - - - Inserts the named selection set data into the list of sets maintained by this class. - Parameters: - int pos - - The position in the list where this named selection set should be inserted. If pos >= Count(), AppendSet() is automatically used instead. - - &nset - - The selection set data to insert. - - DWORD id=0 - - An ID for the selection set. - - MSTR &name=MSTR("") - - The name for the selection set. - - - - - This method is similar to InsertSet() above, however instead of accepting an explicit location this method inserts the new set alphabetically in the list. (Of course, this requires an alphabetized list to work properly, although there's no problem if the list is not alphabetized.) - Parameters: - &nset - - The selection set data to insert. - - DWORD id=0 - - An ID for the selection set. - - MSTR &name=MSTR("") - - The name for the selection set. - The position where the set was inserted. - - - - - Removes the selection set whose name is passed. - Parameters: - MSTR name - - The name of the selection set to remove. - TRUE on success; otherwise FALSE. - - - - - Removes the selection set whose ID is passed. - Parameters: - DWORD id - - The id of the selection set to retrieve. - TRUE on success; otherwise FALSE. - - - - - This method is used internally to load the selection sets from disk. - - - - - This method is used internally to save the selection sets to disk. - - - - - Resizes the selectin set bit arrays to the specified number of bits. The old selection set data is preserved. - Parameters: - int size - - The new size for the bit arrays in bits. - - - - - Assignment operator. This list of sets is emptied and then copied from the list passed. - Parameters: - & from - - The list of selection sets to copy. - - - - - This method is not currently used. What it does however, is go through all of the named selection sets and deletes array elements according to which bits are set in the given bit array. It could be used to keep the named selection set bit arrays in line with the vertex array (for example). - - - - - Deletes the named selection set whose index is passed. - Parameters: - int i - - The zero based index of the set to delete (>=0 and < sets.Count()). - - - - - This locates the named selection set oldName and renames it to newName. - Parameters: - MSTR &oldName - - The old name of the set. - - MSTR &newName - - The new name for the set. - TRUE if the operation succeeded; otherwise FALSE. It will only fail if the oldName set is not present. - - - - - Alphabetizes the list of names. - - - - - Returns a reference to the 'i-th' selection set. - Parameters: - int i - - The zero based index of the selection set to return. - - - - - Description: - This class provides a method that is used to set the parameters of a box object. This allows the object to be created programmatically. All methods of this class are implemented by the system. - - - - - This method is used to set the parameter of the box object. - Parameters: - float width - - The width of the box. - - float height - - The height of the box. - - float length - - The length of the box. - - int wsegs=1 - - The number of width segments. - - int lsegs=1 - - The number of length segments. - - int hsegs=1 - - The number of height segments. - - BOOL genUV=TRUE - - Generate UV coordinates flag. - Sample Code: - The following code demonstrates the creation of the box object and the setting of its parameters: - - *)CreateInstance(GEOMOBJECT_CLASS_ID,BOXOBJ_CLASS_ID); - - gb->SetParams(10.0f, 10.0f, 10.0f, 1, 1, 1, TRUE); - - - - - Description: - This class describes a generic camera object. It is used as a base class for creating plug-in cameras. Methods of this class are used to get and set properties of the camera. All methods of this class are virtual. - - - - - Creates a new generic camera object. - Parameters: - int type - - Nonzero if the camera has a target; otherwise 0. - A pointer to a new instance of the specified light type. - - - - - Returns TRUE if the camera cone is displayed in the viewports; otherwise FALSE. - - - - - Returns TRUE if the camera has a horizon line displayed; otherwise FALSE. - - - - - Enables or disables the camera. If enabled the camera may be displayed, hit tested, etc. - Parameters: - int enab - - Nonzero to enable; zero to disable. - - - - - Sets the controller for the field-of-view parameter. - Parameters: - *c - - Points to the controller to set. - Returns TRUE if set; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Returns the Field-Of-View type of the camera. One of the following values: - - FOV_W - - Width-related FOV - - FOV_H - - Height-related FOV - - FOV_D - - Diagonal-related FOV - - - - - Returns the controller for the field-of-view parameter. - - - - - This method is available in release 3.0 and later only. - - Returns one of the following values to indicate the camera type: - - FREE_CAMERA (No Target) - - TARGETED_CAMERA (Target / Look At Controller) - - PARALLEL_CAMERA (Orthographic ) - - - - - Description: - This class provides a method that is used to set the parameters of a cylinder object. This allows the object to be created programmatically. All methods of this class are implemented by the system. - - - - - This method is used to set the parameter of the cylinder object. - Parameters: - float rad - - The radius. - - float height - - The height. - - int segs - - The number of segments. - - int sides - - The number of sides. - - int capsegs=1 - - The number of segments in the cylinder cap. - - BOOL smooth=TRUE - - Smoothing flag. - - BOOL genUV=TRUE - - Generate UV coordinates flag. - - BOOL sliceOn= FALSE - - Slice the cylinder flag. - - float slice1 = 0.0f - - Slice angle1 in radians. - - float slice2 = 0.0f - - Slice angle2 in radians. - Sample Code: - The following code demonstrates the creation of the object and the setting of its parameters: - - *)CreateInstance(GEOMOBJECT_CLASS_ID,CYLINDER_CLASS_ID); - - gc->SetParams(10.0f, 50.0f, 1, 1); - - - - - Description: - This class describes a generic light object. It is used as a base class for creating plug-in lights. Methods of this class are used to get and set properties of the light. All methods of this class are virtual. - - - - - Creates a new light object of the specified type. - Parameters: - int type - - One of the following values: - - OMNI_LIGHT - Omnidirectional light. - - TSPOT_LIGHT - Targeted spot light. - - DIR_LIGHT - Directional light. - - FSPOT_LIGHT - Free spot light. - - TDIR_LIGHT - Targeted directional light. - A pointer to a new instance of the specified light type. - - - - - Returns the type of light this is. - One of the following values: - - OMNI_LIGHT - Omnidirectional light. - - TSPOT_LIGHT - Targeted spot light. - - DIR_LIGHT - Directional light. - - FSPOT_LIGHT - Free spot light. - - TDIR_LIGHT - Targeted directional light. - - - - - Returns TRUE if the light is a spotlight; otherwise FALSE. - - - - - Returns TRUE if the light is directional; otherwise FALSE. - - - - - Retrieves the shape used for a spotlight. - One of the following values: - - RECT_LIGHT - - CIRCLE_LIGHT - - - - - - - Sets the HSV color of the light at the specified time. - Parameters: - TimeValue t - - The time to set the color. - - & hsv - - The color. - Sample Code: - The following sample shows how the RGB value can be converted to HSV. - - { - - int h, s, v; - - rgbf = GetRGBColor(t, valid); - - DWORD rgb = RGB((int)(rgbf[0]*255.0f), - - (int)(rgbf[1]*255.0f), (int)(rgbf[2]*255.0f)); - - RGBtoHSV (rgb, &h, &s, &v); - - (h/255.0f, s/255.0f, v/255.0f); - - } - - - - - Retrieves the HSV color of the light at the specified time and updates the validity interval to reflect the color parameter. - The color of the light (as a ). - - - The time to retrieve the value at. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Retrieves the HSV color of the light at the specified time. - Parameters: - TimeValue t - - The time to retrieve the color. - - - The color of the light (as a ). - - - - - Sets the light's contrast setting. - Parameters: - TimeValue time - - The time to set the contrast value. - - float f - - The new contrast value in the range of 0.0 to 100.0. - - - - - Returns the light's contrast setting in the range 0.0 to 100.0. - - - The time to get the light's contrast setting. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the light's contrast setting in the range 0.0 to 100.0. - Parameters: - TimeValue t - - The time to get the light's contrast setting. - - - - - - - Sets if the light uses near attenuation. - Parameters: - int s - - Nonzero to use near attenuation; otherwise zero. - - - - - Returns TRUE if the light has near attenuation on; otherwise FALSE. - - - - - Establishes if the light near attenuation range is displayed in the viewports. - Parameters: - int s - - TRUE to turn on the display; otherwise FALSE. - - - - - Returns TRUE if the light near attenuation range is displayed in the viewports; otherwise FALSE. - - - - - Returns a pointer to the shadow generator plug-in in use by the light. See Class . - Default Implementation: - { return NULL; } - - - - - Sets the atmospheric shadow flag to on or off at the specified time. - Parameters: - TimeValue t - - The time at which to set the value. - - int onOff - - TRUE for on; FALSE for off. - Default Implementation: - {} - - - - - Returns the atmospheric shadow setting at the specified time. - Parameters: - TimeValue t - Default Implementation: - { return 0; } - - - - - Sets the atmospheric opacity value at the time passed. - Parameters: - TimeValue t - - The time to set the value. - - float f - - The value to set. - Default Implementation: - {} - - - - - Returns the atmospheric opacity value at the specified time and updates the validity interval to reflect the validity of the opacity controller. - - - The time to get the value. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the atmospheric opacity value at the specified time. - Parameters: - TimeValue t - - The time to get the value. - - - - - - - Sets the atmospheric shadow color amount at the specified time. - Parameters: - TimeValue t - - The time to set the value. - - float f - - The value to set. - Default Implementation: - {} - - - - - Returns the atmospheric shadow color amount at the specified time and updates the interval passed to reflect the validity of the amount. - - - The time to get the value at. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the atmospheric shadow color amount - Parameters: - TimeValue t - - The time to get. - - - - - - - Returns the exclusion list for the light. - - - - - Sets the controller for the hot spot parameter. - Parameters: - *c - - The controller to set. - TRUE if the controller was set; otherwise FALSE. - - - - - Sets the controller for the falloff parameter. - Parameters: - *c - - The controller to set. - TRUE if the controller was set; otherwise FALSE. - - - - - Sets the controller for the color parameter. - Parameters: - *c - - The controller to set. - TRUE if the controller was set; otherwise FALSE. - - - - - Returns the controller for the hot spot parameter. - - - - - Returns the controller for the falloff parameter. - - - - - Returns the controller for the color parameter. - - - - - Returns TRUE if the light affects the diffuse color of objects; otherwise FALSE. - - - - - Returns TRUE if the light affects the specular color of objects; otherwise FALSE. - - - - - Returns the decay state of the light. - This boolean works as an integer where 0 is None, 1 is Inverse and 2 is Inverse Square. - Default Implementation: - {return 0;} - - - - - Sets the decay radius (i.e. falloff) of the light. - Parameters: - TimeValue time - - The time at which to set the radius. - - float f - - The radius to set. - - - - - Returns the decay radius of the light and updates the validity interval to reflect the validity of the radius controller. - - - The time at which to return the radius. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the decay radius of the light. - Parameters: - TimeValue t - - The time at which to return the radius. - - - - - - - Sets the state of the 'Soften Diffuse ' parameter. - Parameters: - TimeValue time - - The time at which to set the value. - - float f - - The value to set in the range of 0.0 to 100.0. - Default Implementation: - {} - - - - - Returns the state of the 'Soften Diffuse ' parameter. - - - The time at which to return the value. - - TThe interval into which the validity of the evaluated parameters is intersected. - - - - Returns the state of the 'Soften Diffuse ' parameter. - Parameters: - TimeValue t - - The time at which to return the value. - - - - - - - Sets the shadow color to the specified value at the time passed. - Parameters: - TimeValue t - - The time at which to set the shadow color. - - & rgb - - The color to set. - Default Implementation: - {} - - - - - Returns the shadow color at the time passed and updates the validity interval passed to reflect the validity of the shadow color controller. - - - The time at which to return the shadow color. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the shadow color at the time passed. - Parameters: - TimeValue t - - The time at which to return the shadow color. - - ; } - - - - - Returns TRUE if the Affects Shadow flag is set; otherwise FALSE. - Default Implementation: - { return 0; } - - - - - Sets the shadow color multiplier (density) to the value passed at the specified time. - Parameters: - TimeValue t - - The time at which to set the value. - - float m - - The value to set. - Default Implementation: - {} - - - - - Returns the shadow color multiplier (density) at the specified time and updates the interval passed to reflect the validity of the multiplier controller. - Default Implementation: - - - The time at which to return the value. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the shadow color multiplier (density) at the specified time. - Parameters: - TimeValue t - - The time at which to return the value. - - - - - - - Returns a pointer to the texmap used as the shadow projector or NULL if not set. - Default Implementation: - { return NULL; } - - - - - Returns the state of the ambient only flag. TRUE is on; FALSE is off. - Default Implementation: - { return FALSE; } - - - - - Description: - This class provides a method that is used to set the parameters of a sphere object. This allows the object to be created programmatically. All methods of this class are implemented by the system. - - - - - This method is used to set the parameter of the sphere object. - Parameters: - float rad - - The radius. - - int segs - - The number of segments. - - BOOL smooth=TRUE - - Smoothing flag. - - BOOL genUV=TRUE - - Generate UV coordinates flag. - - float hemi=0.0f - - The hemisphere setting where 0.0 is a full sphere, 0.5 is a half sphere and 1.0 is nonexistent. - - BOOL squash=FALSE - - If TRUE the number of segments is kept constant when the sphere is a hemisphere. If FALSE the number of segments is truncated based on the hemisphere setting. - - BOOL recenter=FALSE - - If FALSE, the 'Base To Pivot' setting if off; otherwise it is on. - Sample Code: - The following code demonstrates the creation of the object and the setting of its parameters: - - - - - - - This class provides a generic implementation for sub-object types. Instead of having to create a sub-class of the constructors of this class may be used to initialize private data members of the class. Then implementations of the GetName() and GetIcon() methods of are provided which simply return the data members. This SubObjectType will either use the subObjectIcons_16i.bmp and SubObjectIcons_16a.bmp bitmaps in the UI/icons directory (for the GenSubObjType(int idx) constructor), or any other bmp file that is specified in the (const MCHAR nm, const MCHAR pFilePrefix, int idx) constructor. The bitmap files have to reside in the UI/icons directory. All methods of this class are implemented by the System. - - - - - Sets the name for this sub-object type. - - The name to set. - - - - This is the base class for the creation of Geometric plug-ins. This class represents an object that has geometry and is renderable. - - - - - - If an object creates different meshes depending on the particular instance (view-dependent) it should return nonzero; otherwise 0. - - - - - This method should be implemented by all renderable GeomObjects. It provides a mesh representation of the object for use by the renderer. Primitives that already have a mesh cached can just return a pointer to it (and set needDelete to FALSE). Implementations of this method which take a long time should periodically call View::CheckForRenderAbort() to see if the user has canceled the render. If canceled, the function can either return NULL, or return a non null pointer with the appropriate value for needDelete. (If needDelete is TRUE a non-null mesh will be deleted.) - A pointer to the mesh object. - - The time to get the mesh. - The node in the scene. - If the renderer calls this method it will pass the view information here. See Class . - to TRUE if the renderer should delete the mesh, FALSE otherwise. - - - - Objects may supply multiple render meshes ( e.g. particle systems). If this method returns a positive number, then GetMultipleRenderMesh and GetMultipleRenderMeshTM will be called for each mesh, instead of calling GetRenderMesh. - The number of render meshes, or 0 to indicate that multiple meshes aren't supported. - - - - - For multiple render meshes, this method must be implemented. set needDelete to TRUE if the render should delete the mesh, FALSE otherwise. - - The time at which to obtain the mesh. - The pointer to the node. - A reference to the view. - TRUE if the mesh needs to be deleted, otherwise FALSE. - Specifies which of the multiplie meshes is being asked for. - - - - For multiple render meshes, this method must be implemented. - - The time at which to obtain the mesh. - The pointer to the node. - A reference to the view. - Specifies which of the multiplie meshes is being asked for. - Should be returned with the transform defining the offset of the particular mesh in object space. - Should contain the validity interval of meshTM. - - - - This method provides a patch mesh representation of the object for use by the renderer. If this method returns NULL, then GetRenderMesh() will be called. - A pointer to the patch mesh. See Class . - - The time to get the patch mesh. - The node in the scene. - If the renderer calls this method it will pass the view information here. See Class . - to TRUE if the renderer should delete the patch mesh, FALSE otherwise. - - - - Returns TRUE if this object can do displacement mapping; otherwise FALSE. - - - - - Description: - This class and its associated global functions are available in release 4.0 and later only. - - This is the callback object for the global geometry pipeline enumeration functions. The single proc() method of this class is called as the enumeration takes place. - - The following functions are not methods of this class but are available for use with it to begin the enumeration: - - These all start a pipeline enumeration down the pipeline towards the baseobject and over the baseobjects' branches in case it is a compound object. A pipleine enumeration can be started from a Node, an or from a . - - - - - This is the callback procedure for pipeline enumeration. The passed to the proc can be a Node, or . In case it is a the parameter derObj contains the DerivedObject and the index is the index of this modifier in the DerivedObject. In all other cases derObj is NULL and index is 0. - Parameters: - *object - - Points to the item in the geometry pipeline. This can be a Node, or . - - *derObj - - If object above is a this points to the derived object. - - int index - - If object aive is a this is the index of this modifier in the DerivedObject. - One of the following values which determines how the enumeration proceeds: - - PIPE_ENUM_CONTINUE - - Specifies to continue the enumeration. - - PIPE_ENUM_STOP - - Specifies to halt the enumeration. - - - - - Description: - This class is used to store a parameter dimension. When a client of a parameter block receives the REFMSG_GET_PARAM_DIM message, the PartID (PartID) field is set to point at one of these structures. The client should set dim to point at its dim descriptor. - Data Members: - *dim; - - Assign the dimension to this variable. - - int index; - - Index of the parameter in the parameter block. - - - - - Description: - This class is used to hold a parameter name. When a client of a parameter block receives the REFMSG_GET_PARAM_NAME_LOCALIZED message or the REFMSG_GET_PARAM_NAME_NONLOCALIZED message, the partID field is set to point at one of these structures. The client should fill in the parameter name. - Data Members: - MSTR name; - - Assign the parameter name to this variable. - - int index; - - Index of the parameter in the parameter block. - - - - - Description: - This is a simple reference class for plugin gizmos for the skin modifier. This allows developers to create plugin deformers for skin. This class is of super object type REFTARGET and must use the category BonesDefGizmoDeformer for skin to detect it. - - If the client of maintains several parameter blocks then the client must implement the methods NumSubs(), SubAnim(i), SubAnimName(i), NumRefs(), GetReference(i) and SetReference(i) and call the methods when 'i' refers to the parameters maintained by . - Data Members: - cid; - - The Class ID of the gizmo. - - *bonesMod; - - The pointer back to the skin modifier so the gizmo can ask for basic information about the modifier. - - *pblock_gizmo_data; - - The param block provided for the gizmo to store its data. - - - - - This method returns whether or not this gizmo is active or not. - Default Implementation: - { return TRUE; } - - - - - This method returns whether or not this gizmo is volume based or not. If it is volume based IsInVolume is used to check to see if a point is deformed otherwise a tab list of points is used to determine if a point is affected. - Default Implementation: - { return FALSE; } - - - - - If IsVolumBased returns TRUE his function is called to determine if the point is deformed. - Parameters: - p - - The point to be checked in the skinned objects local space. - - tm - - This matrix will transform the point into world space. - Default Implementation: - { return FALSE; } - - - - - This method does the actual deformation of the points. Both initial and current point positions are passed in so the deformer has a chance to start from scratch minus the weighted transformation deformation. For instance a joint lattice deformer would want to work with the initial position while a bulge deformer would use the current point position. - Parameters: - TimeValue t - - The time of the modification. - - int index - - Te index of the point into the object. - - initialP - - The initial position of the point. - - p - - The current deformed position of the point. - - tm - - The matrix to convert p and initialP into world space. - Default Implementation: - { return p; } - - - - - This method is called to let the gizmo name it self after creation. - Default Implementation: - { } - - - - - This method returns the name of he gizmo. - Default Implementation: - { return NULL; } - - - - - This method is called when the gizmo is created. A list of points that where selected are passed in world space coordinates. This allows the gizmo to setup whatever initial parameters are needed when it is created. This should return TRUE if it was successful, else FALSE. - Parameters: - int count - - The number of points that are to be affected. - - *p - - The list of points that where selected when the gizmo was created in world space. - - int numbeOfInstances - - The number of times that the modifier has been instanced. - - int *mapTable - - An index list of back into the original point list for the object for *p. This is used so the gizmo can map the points back into the original point list from the object so you can figure out later on where the points are. - Default Implementation: - { return TRUE; } - - - - - This method is called before the actual deformation loop to allow the plug-in to create any temporary data it may need. - Parameters: - TimeValue t - - The time of the modification. - Default Implementation: - { } - - - - - This method is called after the actual deformation loop to allow the plug-in to create any temporary data it may need. - Parameters: - TimeValue t - - The time of the modification. - Default Implementation: - { } - - - - - This method will ask the plugin to create a copy buffer of its current parameters. The plugin needs to allocate the memory for this buffer. The skin modifier will take care of the destruction of this memory. - Default Implementation: - { return NULL; } - - - - - This method is called when the user paste data to the gizmo. The gizmo needs to cast his pointer into its copy class and the use the data to paste into it. - Parameters: - *buffer - - The buffer to paste from. - Default Implementation: - { } - - - - - This sets the current to gizmo to be enabled or disabled. - Parameters: - BOOL enable - - TRUE to enable; FALSE to disable. - Default Implementation: - { } - - - - - This method returns whether the user is in the edit mode for the gizmo. When this is TRUE the gizmo will get its HitTest, SelectSubComponents, Move, SetSubObjectCenters, SetObjectTMs, ClearSelection, SelectAll, and InvertSelections will be passed from skin to the gizmo. - Default Implementation: - { return FALSE; } - - - - - This is called when the system wants the gizmo to stop editing. - Default Implementation: - { } - - - - - When the skin modifier wants the gizmo to disable any controls that are not used outside the sub object mode this function is called. This gives the gizmo a chance to disable/hide any UI elements that it does not want the user to manipulate when out of the subobject mode. - Parameters: - BOOL enable - - TRUE to enable; FALSE to disable. - Default Implementation: - { } - - - - - This method is called to determine if the specified screen point intersects the item. The method returns nonzero if the item was hit; otherwise 0. This method differs from its version in that this is based a TM which is the matrix that transfroms the skin modifier into world space. - Parameters: - TimeValue t - - The time to perform the hit test. - - INode* inode - - A pointer to the node to test. - - int type - - The type of hit testing to perform. See Scene and Node Hit Test Types. for details. - - int crossing - - The state of the crossing setting. If TRUE crossing selection is on. - - int flags - - The hit test flags. See Scene and Node Hit Testing Flags for details. - - *p - - The screen point to test. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. - - ModContext* mc - - A pointer to the modifier context. - - tm - - The transform matrix to transform the skin into world space. - Nonzero if the item was hit; otherwise 0. - Default Implementation: - { return 0; } - - - - - This method is called to change the selection state of the component identified by hitRec. - Parameters: - *hitRec - - Identifies the component whose selected state should be set. See Class . - - BOOL selected - - TRUE if the item should be selected; FALSE if the item should be de-selected. - - BOOL all - - TRUE if all components in the chain should be selected; FALSE if only the top-level should be selected. (A contains a Next() pointer; typically you want to do whatever you're doing to all the Next()'s until Next() returns NULL). - - BOOL invert=FALSE - - This is set to TRUE when all is also set to TRUE and the user is holding down the Shift key while region selecting in select mode. This indicates the items hit in the region should have their selection state inverted. - Default Implementation: - { } - - - - - When this method is called the plug-in should respond by moving its selected sub-object components. - Parameters: - TimeValue t - - The time of the transformation. - - & partm - - The 'parent' transformation matrix. This matrix represents a transformation that would take points in the modifier's space and convert them into world space points. This is constructed as the node's transformation matrix times the inverse of the 's transformation matrix. The node whose transformation is used is the node the user clicked on in the scene - modifiers can be instanced so there could be more than one node. - - & tmAxis - - The matrix that represents the axis system. This is the space in which the transformation is taking place. - - & val - - This value is a vector with X, Y, and Z representing the movement along each axis. - - tm - - The transform matrix. - - BOOL localOrigin=FALSE - - When TRUE the transformation is occurring about the sub-object's local origin. - Default Implementation: - { } - - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current modifier being edited so that it can display the axis. This method specifies the position of the center. The plug-in enumerates its centers and calls the callback cb once for each. This method differs from its version in that this is based a TM which is the matrix that transfroms the skin modifier into world space. - Parameters: - *cb - - The callback object whose methods may be called. See Class . - - TimeValue t - - The time to enumerate the centers. - - *node - - A pointer to the node. - - tm - - The transform matrix to transform the skin into world space. - Default Implementation: - { } - - - - - When the user is in a sub-object selection level, the system needs to get the reference coordinate system definition from the current modifier being edited so that it can display the axis. This method returns the axis system of the reference coordinate system. The plug-in enumerates its TMs and calls the callback cb once for each. See ~{ Sub-Object Coordinate Systems }~. This method differs from its version in that this is based a TM which is the matrix that transfroms the skin modifier into world space. - Parameters: - *cb - - The callback object whose methods may be called. - - TimeValue t - - The time to enumerate the TMs. - - *node - - A pointer to the node. - - tm - - The transform matrix to transform the skin into world space. - Default Implementation: - { } - - - - - This method is called to clear the selection for the given sub-object level. All sub-object elements of this type should be deselected. This will be called when the user chooses Select None from the 3ds Max Edit menu. - Parameters: - int selLevel - - Specifies the selection level to clear. - Default Implementation: - {} - - - - - This method is called to select every element of the given sub-object level. This will be called when the user chooses Select All from the Edit menu. - Parameters: - int selLevel - - Specifies the selection level to select. - Default Implementation: - {} - - - - - This method is called to invert the specified sub-object level. If the element is selected it should be deselected. If it's deselected it should be selected. This will be called when the user chooses Select Invert from the Edit menu. - Parameters: - int selLevel - - Specifies the selection level to invert. - Default Implementation: - {} - - - - - Description: - This is the base class for the creation of atmospheric gizmo objects. It provides implementations of most of the methods needed. Developers will probably want to provide their own implementations of BeginEditParams() and EndEditParams() and call the implementations from within their implementation. See the source code for in /MAXSDK/SAMPLES/HOWTO/MISC/GIZMO.CPP to see how the base class methods are implemented. - - Note that developers must use the data members below as the base class code relies on these being used. - Data Members: - *pblock; - - This is a pointer to the parameter block that should be used to manage the animated parameters of the gizmo object. - - *pmapParam; - - This is a pointer to the parameter map that should be used to manage the user interface for the gizmo object. - - *ip; - - This is the interface pointer for the gizmo object. - - *editOb; - - This is a pointer to the current gizmo object being edited in the command panel. When BeginEditParams() is called, this pointer is set to the this pointer of the being edited. - - - - - Invalidates the user interface for the gizmo so it will get redrawn on the next screen update. - Default Implementation: - {} - Sample Code: - This is the code from the Sphere implementation of this method. Note that it simply calls Invalidate() on the parameter map. - - - - - Returns the dimension of the parameter whose parameter block index is passed. - Parameters: - int pbIndex - - Specifies which parameter name to return. - Default Implementation: - {return defaultDim;} - Sample Code: - - - - - Returns the name of the parameter whose parameter block index is passed. - Parameters: - int pbIndex - - Specifies which parameter name to return. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - Default Implementation: - {return MSTR(_M("Parameter"));} - - - - - This method is called to draw the gizmo at the specified time into the specified viewport. - Parameters: - TimeValue t - - The time to draw the gizmo. - - *gw - - The associated with the viewport in which to draw the gizmo. - Default Implementation: - {} - - - - - Returns the wire frame color for the gizmo in the viewports. - Default Implementation: - ;} - - - - - Returns the bounding box for the gizmo, as transformed by the matrix passed, at the time passed. - Parameters: - &mat - - The points of the gizmo object should be transformed by this matrix before the bounding box is computed from them. - - TimeValue t - - The time to compute the bounding box. - - &box - - The result is stored here. - Default Implementation: - {} - Sample Code: - - - - - Description: - This class represents the main gizmo shape. - - The Function Publishing interface to SimpleManipulators is defined as: - - #define MANIP_GIZMO_INTERFACE - - - Data Members: - private: - - mPolyShape; - - The gizmo polyshape. - - mLine; - - A poly line. - - - - - This method instructs the gizmo shape to start (append) a new line segment. - - - - - This method instructs the gizmo shape to append a new point to the line segment. - Parameters: - & p - - The vertex point to add. - - - - - This method returns a pointer to the gizmo's poly shape. - - - - - This method allows you to transform the gizmo shape. - Parameters: - & tm - - The transformation matrix. - - - - - This class lets you tap in to ALL reference messages in the entire system. - - - Once registered, the NotifyRefChanged() method will be called once for every time NotifyRefChanged() is called on a regular effectively allowing you to wire tap the entire reference network. - WARNING This should be used with extreme care. NotifyRefChange() will be called MANY MANY times so it is important to do very little processing within this method. This most that should probably be done is to set a dirty bit. - - - - - Callback function to receive messages. - - - This method is implemented to receive and respond to messages broadcast by all the Dependants in the entire system. - The return value from this method is of type RefResult. This is usually REF_SUCCEED indicating the message was processed. Sometimes, the return value may be REF_STOP. This return value is used to stop the message from being propagated to the dependents of the item. - - - This is the interval of time over which the message is active. Currently, all plugins will receive FOREVER for this interval. - - This is the handle of the reference target the message was sent by. The reference maker uses this handle to know specifically which reference target sent the message. - - This contains information specific to the message passed in. Some messages don't use the partID at all. - - The msg parameters passed into this method is the specific message which needs to be handled. - - If called through , the value of 'propagate' passed to it. Used if calling NotifyDependents() from within . - - - - Description: - This class provides access to the 3ds Max Gradient texture. All methods of this class are implemented by the system. - - - - - Retrieves a pointer to the interface for this texture. This allows access to the mapping parameters such as UV offsets, blur, angle, noise level, etc. - - - - - Retrieves a pointer to the for this texture. This allows access to the RGB level and output and the output amount. - - - - - Sets the ' 2 Position' setting at the time passed. - Parameters: - float m - - The value to set in the range of 0.0 to 1.0. - - TimeValue t=0 - - The time to set the value. - - - - - Description: - The abstract graphics window class. The methods here provide low-level access to 3ds Max's graphics system. These methods are available for plug-ins to do any graphics work not possible using the standard high-level graphics methods of 3ds Max. - - These methods are for use in the existing 3ds Max viewports. Note that these APIs are not for casual use, as they are not intended to be a high level graphics library. For example, many steps are required to display a single lit polygon. These APIs are optimized for speed, and not at all for plug-in programmer ease of use. - - These methods are provided, however, so that developers can do things that are otherwise impossible using the high-level methods. - - Max be considered an "ordinary" 2D/3D API. (That's what OpenGL, D3D, and HEIDI are for.) - - One final note of warning: most graphics windows methods execute in a separate thread (or in multiple separate threads) that are owned by the graphics window. Thus, due to thread scheduling, when a bad argument or incorrect sequencing of graphics windows calls causes 3ds Max to crash, it is not at all easy to figure out where the problem is. In particular, the location of the main 3ds Max thread is not relevant. - - All the methods of this class are implemented by the system. - - - - - This is called after all four GraphicsWindows used by 3ds Max are created. SDK users shouldn't need this call - - - - - This is used to tell the driver that it is shutting down. - - - - - This returns "0x200" to indicate R2.0 - - - - - This identifies the driver (and includes manufacturer info if available) - - - - - This is called to put up the config dialog if the driver supports GW_SPT_CAN_CONFIG - Parameters: - HWND hWnd - - The parent window handle for the dialog. - - - - - Determines if the driver supports the specified feature. - Parameters: - int what - - One of the following values: - - GW_SPT_TXT_CORRECT - - This is used to enable or gray-out the perspective correction right-click viewport menu option. - - GW_SPT_GEOM_ACCEL - - This is used to indicate to 3ds Max (and the mesh class in particular) that the driver wants to handle all of the 3D data natively. In this case, meshes are rendered by passing 3D world space data and letting the driver transform, clip, and light the vertices. If this returns FALSE, then the mesh class handles all xforms/clip/lighting calculations (using a lazy evaluation algorithm) and then calls the hPolygon or hPolyline 2 1/2D calls for the driver to rasterize. (Primitives that are actually clipped are still sent to the polygon/polyline methods.) - - Right now, only the OpenGL driver returns TRUE to this query, but other drivers have been developed that return TRUE, and the HEIDI and D3D drivers may change in the future. - - GW_SPT_TRI_STRIPS - - If this returns TRUE, then 3ds Max will try to stripify meshes before calling the rendering methods. Right now, the drivers just return the user preference that is set in the driver config dialog. It defaults to TRUE. - - GW_SPT_DUAL_PLANES - - If a driver has dual-planes support it returns TRUE. Our OpenGL display driver only returns TRUE for this if the underlying display driver has implemented a custom OpenGL extension that allows us to handle this efficiently. - - GW_SPT_SWAP_MODEL - - This returns TRUE if 3ds Max has to redraw the whole scene any time the viewports are exposed. - - GW_SPT_INCR_UPDATE - - This returns TRUE if the driver can update a rectangular subset of the viewport without trashing the image outside that rectangle. This is TRUE for most drivers that blit the viewport region and FALSE for those that do page-flipping in the hardware. For OpenGL, this is TRUE if the display driver implements the Microsoft glSwapRectHintWIN extension. - - GW_SPT_1_PASS_DECAL - - This is TRUE if the driver can handle decalling with only one pass. Right now, this is TRUE for OpenGL, but FALSE for HEIDI and D3D. (And as with all of these options, it may change in a given driver any time in the future.) - - GW_SPT_DRIVER_CONFIG - - This is TRUE if the driver has a configuration dialog box. This is TRUE for all three of our standard drivers. - - GW_SPT_TEXTURED_BKG - - This is TRUE if the viewport background is implemented as a textured rectangle, and FALSE if it is a blitted bitmap. - - GW_SPT_VIRTUAL_VPTS - - This is TRUE if the driver allows viewports to be made larger than the physical window they are attached to. Right now this is ony TRUE for OGL. - - GW_SPT_PAINT_DOES_BLIT - - This is TRUE if WM_PAINT messages result in a blit of the backbuffer (as opposed to a page-flipping swap). This allows 3ds Max to do quick damage region repair, and works together with the GW_SPT_SWAP_MODEL flag. - - GW_SPT_WIREFRAME_STRIPS - - This is TRUE if the driver wants 3ds Max to send down wireframe models using triangle strips instead of a bundle of 2-pt segments. This is only used by the OGL driver, and it is there as a user-choosable performance-accuracy tradeoff (since the strips are faster and are back-culled, but they display hidden edges as though they are visible). - - - - - This returns the "output" window handle. (Input goes to an invisible window above the viewport. The invisible window is owned by 3ds Max.) - - - - - This method returns the size (in pixels) that the specified text string will occupy - Parameters: - MCHAR *text - - The string to check. - - SIZE *sp - - The size is returned here. - - - - - If a developer is working with an existing 3ds Max instance of (one of 3ds Max's viewports) this method should NOT be called. - - - - - As above, if a developer is working with an existing 3ds Max instance of (one of 3ds Max's viewports) this method should NOT be called. - - - - - This method sets the clipping boundaries within a viewport within the graphics window. This allows more than one viewport to appear within a single graphics window. It has the side-effect of building a 4x4 viewport matrix. This routine should be called any time the graphics window is resized, or else rendering will still occur to the old window size. (And since most drivers do not do range-checking since it is too time-costly, this could cause a system crash.) - Parameters: - Note: all coordinates are in Windows format, with the origin in the upper left - - int x - - Specifies the left viewport origin. - - int y - - Specifies the top viewport origin. - - int w - - Specifies the viewport width. - - int h - - Specifies the viewport height. - - - - - This method is used to set up a virtual viewport. Note that this is a no-op unless GW_SPT_VIRTUAL_VPTS is TRUE. Plug-in developers should not call this method - it's for internal use only. - - - - - This method is used to set a virtual viewport as active. Note that this is a no-op unless GW_SPT_VIRTUAL_VPTS is TRUE. Plug-in developers should not call this method - it's for internal use only. - Parameters: - int onOff - - TRUE to set the virtual viewport active; FALSE to make it inactive. - - - - - This is used internally. It returns if the determinant of the current transform is positive or negative. If it's positive, 0 is returned; if it's negative, 1 is returned. - - - - - Returns TRUE if the view is in perspective projection; otherwise FALSE (orthographic projection). - - - - - Sets the size and position of the . The coordinates are all Windows coordinates in the space of the GraphicsWindows' parent window. (The origin is the upper left.) - Parameters: - int x - - Window x origin. - - int y - - Window y origin. - - int w - - Window width. - - int h - - Window height. - - - - - This method returns the current state. One of the following values: - - GW_DISPLAY_MAXIMIZED - - GW_DISPLAY_WINDOWED - - GW_DISPLAY_INVISIBLE - - - - - This method gets the current window size in X. - - - - - This method gets the current window size in Y. - - - - - This method returns the z-buffer depth (in bits) - - - - - This method returns the largest device Z value. - - - - - This method returns the smallest device Z value. - - - - - This method returns the largest number of triangles that can be in a strip - - - - - This method resets the update rectangle. The update rectangle is the region of the screen that needs to be updated to reflect items that have changed. When the system is done rendering items, the goal is to only update the region that has actually been altered. This method sets the update rectangle (the region that will be blitted to the display) to invalid. In this way when enlargeUpdateRect() is later called, the RECT passed will be used as the region. - - - - - This method enlarges the update rectangle to include the RECT passed. If rp is NULL, then the whole window will later be updated. - Parameters: - RECT *rp - - Pointer to a rectangle (or NULL). - - - - - This method retrieves the current update rectangle. - Parameters: - RECT *rp - - The current update rectangle. - Zero if the update rectangle is invalid; otherwise nonzero. - - - - - Call to begin or end a pass when doing multiple passes for the purpose of drawing wireframe edges over solid geometry. - - - indicates which pass: - - TRUE indicates the start of a pass, FALSE indicates the end of a pass - - not used - - - - Returns the current skip count setting. - - - - - Retrieves the rendering limits used by primitive calls. See ~{ Rendering Modes and Rendering Limits }~. - - - - - Returns the current rendering mode used by the viewport. This is a subset of the rendering limit, in that any limits imposed by the rendering limit are forced onto the current mode. See ~{ Rendering Modes and Rendering Limits }~. - - - - - For internal use only. - - - - - This method is used internally. Most drivers control two image buffers. One is displayed on the screen, and the other is used to rasterize geometric primitives. When rasterization of a complete frame is done, the off-screen buffer is blitted onto the display screen. This is referred to as dual-plane mode. This method will turn dual-plane mode on or off. This is used internally by the File/Preferences... Viewport page Use Dual Planes toggle. - Parameters: - int which - - Specifies which buffer should use dual-planes. - - BUF_F_BUFFER - - The image (Framebuffer) buffer. - - BUF_Z_BUFFER - - The Z buffer. - - int b - - Nonzero to enable access (toggle on); 0 to toggle off. - TRUE if the graphics window has access to the specified buffer; otherwise FALSE. - - - - - This method is used internally. It returns a boolean value indicating if dual plane mode is on or off for the specified buffer. - Parameters: - The buffer whose dual-planes setting will be returned. - - int which - - The buffer whose dual-planes setting will be returned. One of the following values: - - BUF_F_BUFFER - - The Framebuffer. - - BUF_Z_BUFFER - - The Z buffer. - TRUE if the dual-plane mode is on; otherwise FALSE. - - - - - This method is used internally. It retrieves the size of the specified buffer in bytes. - Parameters: - int which - - One of the following values: - - int *size - - The size of the buffer in bytes. - - Note the following concerning the HEIDI driver. For HEIDI getBufSize() always returns 10 if dual-planes are on (and 0 otherwise). This is because HEIDI actually never returns the image - it keeps its own copy stored away. Thus the "logical" way to think is that we actually get a copy of the buffer by calling getBuf, and that we give it back by calling setBuf. But in reality (with the HEIDI driver) getBuf and setBuf only tell HEIDI to do some internal buffer manipulation. - TRUE if the size was returned; otherwise FALSE. - - - - - This method is used internally. It retrieves the specified buffer. - Parameters: - int which - - The buffer to retrieve. One of the following values: - - BUF_F_BUFFER - The image Framebuffer. - - BUF_Z_BUFFER - The Z buffer. - - int size - - The number of bytes to retrieve. This must be at least the size returned from getBufSize(). - - void *buf - - Storage for the buffer data. - TRUE if the buffer was retrieved; otherwise FALSE. - - - - - Stores the specified buffer. - Parameters: - int which - - The buffer to store. One of the following values: - - BUF_F_BUFFER - The image Framebuffer. - - BUF_Z_BUFFER - The Z buffer. - - int size - - The number of bytes to store. - - void *buf - - The buffer data. - - RECT *rp - - This allows only a subset of the saved image rect to be blitted back to the screen. - TRUE if the buffer was stored; otherwise FALSE. - - - - - This method is used internally to pan the viewport. - - - - - This method returns the size of the texture bitmap that the driver wants sent in to the getTextureHandle() call (if bkg is FALSE). If bkg is TRUE, this returns the size of the texture that 3ds Max should send to the setBackgroundDIB() call. In general, the return value needs to be a power of 2, though that could be driver-specific - Parameters: - int bkg=FALSE - - TRUE to get the size for setBackgroundDIB(); FALSE to get the size for getTextureHandle(). - - - - - When you are finished with the texture handle, call this method to free it. - Parameters: - DWORD_PTR handle - - The texture handle to free. - - - - - This sets the current texture to the image whose handle is passed (see getTextureHandle()). The texture dimensions must be a power of 2. - Parameters: - DWORD_PTR handle - - The handle of the texture to make current. - - - - - Sets the way in which textures are tiled across the surface of the object. - Parameters: - The following parameters may use one of these values: - - GW_TEX_NO_TILING - - The texture clamped - Any UVW that is bigger than 1 is interpreted as being 1. - - GW_TEX_REPEAT - - As the UVW numbers keep getting larger than 1 the image is repeated. - - GW_TEX_MIRROR - - If UVW goes beyond 1, the numbers are interpreted as going backwards. So if you had 0 to 2 it would actually go 0 to 1 then 1 down to 0. - - int u - - The type of texturing in the U direction. - - int v - - The type of texturing in the V direction. - - int w=GW_TEX_NO_TILING - - The type of texturing in the W direction. - TRUE if the tiling mode was set; otherwise FALSE. - - - - - Returns the type of texture tiling set for the particular direction. - - For example, if setTextureTiling(GW_TEX_NO_TILING, GW_TEX_REPEAT, GW_TEX_MIRROR) were called first, then - - getTextureTiling(0) would yield GW_TEX_NO_TILING, and - - getTextureTiling(1) would yield GW_TEX_REPEAT. - Parameters: - int which - - This value is 0 or 1 and it represents the U or V direction respectively. The value 2 is not yet implemented. - GW_TEX_NO_TILING - - The texture clamped - Any UVW that is bigger than 1 is interpreted as being 1. - - GW_TEX_REPEAT - - As the UVW numbers keep getting larger than 1 the image is repeated. - - GW_TEX_MIRROR - - If UVW goes beyond 1, the numbers are interpreted as going backwards. So if you had 0 to 2 it would actually go 0 to 1 then 1 down to 0. - - - - - This method allows one to put an affine transformation on a texture. This allows you to translate, rotate or scale a texture on an object. - Parameters: - &m - - The texture transformation matrix. - - - - - Returns the maximum number of lights that may be used by the interactive renderer. - - - - - Turns a light on or off, and sets the light parameters. The light's position is set through the current transformation matrix at the time of this call. A particular light is specified by its light number (-1 through getMaxLights()-1). number -1 is reserved for ambient light. If a particular field in the class is not needed for a particular type of light, that field's value is ignored (for example, only the color field is used for ambient light.) - Parameters: - int num - - The light number of the light to set. This is a value in the range -1 to getMaxLights()-1. - - *l - - The light class instance used to set the light parameters. If this is NULL, the light is turned off. - - - - - This allows a developer to control if a light is used to render an object. There is one bit per light (bits 0 through getMaxLights()). If the bit is set the light is NOT used to render the object. If the bit is off, the light IS used. This method allows you to set the exclusion vector controlling the lights. - Parameters: - DWORD exclVec - - The exclusion vector controlling the lights. - - - - - This method is no longer used. - - - - - Sets the properties of the current camera used by the . - Parameters: - float mat[4][4] - - The transformation matrix times the projection matrix. - - *invTM - - This is the inverse of the affine part of the camera transformation matrix (not the inverse of the projection part). - - int persp - - Nonzero indicates this is a perspective view; 0 is orthogonal. - - float hither - - Near clip value. - - float yon - - Far clip value. - - - - - Retrieves the properties of the current camera. - Parameters: - float mat[4][4] - - The transformation matrix times the projection matrix. - - *invTM - - This is the inverse of the affine part of the camera transformation matrix (not the inverse of the projection part). - - int *persp - - Nonzero indicates this is a perspective view; 0 is orthogonal. - - float *hither - - Near clip value. - - float *yon - - Far clip value. - - - - - Sets the current transparency flags for the current pass. - - - Parameters: - DWORD settings - - This can be a combination if GW_TRANSPARENCY and GW_TRANSPARENT_PASS See ~{ Rendering Modes and Rendering Limits }~. You also use these settings in the Render limits as well. - - - - - Sets the current rendering material, and modifies the rendering mode parameter for controlling the rasterizer driver. Note: You must have your rendering limit set BEFORE you set the material because the material setting may lower the rendering mode based on the material limits. - Parameters: - &m - - The new material to instantiate - - int index=0 - - Indicates which material index refers to the material which gets set. - - - - - Returns the current rendering material. - - - - - - - This method converts coordinates to "<b>h</b>" format device coordinates. Note: This method maps points from the 's current transform to device space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *in - - The input point. - - *out - - The output point in integer format values in the native device coords for the device. For HEIDI and OpenGL the origin at the lower left. For Direct3D the origin is at the upper left. - DWORD containing the clipping flags for the point. If a flag is set it indicates the transformed point lies outside the view volume. See View Volume Clip Flags. - - - - - This method converts coordinates to "<b>h</b>" format device coordinates, without integer rounding. Note: This method maps points from the 's current transform to device space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - & in - - The input point. - - & out - - The output point in floating point values in the native device coords for the device. For HEIDI and OpenGL the origin at the lower left. For Direct3D the origin is at the upper left. - DWORD containing the clipping flags for the point. If a flag is set it indicates the transformed point lies outside the view volume. See View Volume Clip Flags. - - - - - This method is used to convert coordinates to "<b>w</b>" format device coordinates. Note: This method maps points from the 's current transform to device space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - - - Parameters: - *in - - The input point. - - *out - - The output point in integer format with the origin at the upper left. - DWORD containing the clipping flags for the point. If a flag is set it indicates the transformed point lies outside the view volume. See View Volume Clip Flags. - - - - - This method is used to convert coordinates to "<b>w</b>" floating point coordinates. This is just a helper routine to avoid building up round-off error. 3ds Max uses it just for IK. Note: This method maps points from the 's current transform to device space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *in - - The input point. - - *out - - The output point in floating point format with the origin at the lower left. - DWORD containing the clipping flags for the point. If a flag is set it indicates the transformed point lies outside the view volume. See View Volume Clip Flags. - - - - - This method is used internally and should not be called by plug-in developers. - - - - - Clears the specified rectangular region of the screen. - Parameters: - RECT *rp - - Specifies the rectangular region to clear. - - int useBkg = FALSE - - Specifies if the background should be used to fill the cleared area. Nonzero indicate the background should be used; 0 indicates the 'clear' color should be used (see setColor() above). - - - - - Sets the RGB color used for the specified drawing type (line, fill, text, clear). - Parameters: - ColorType t - - One of the following values: - - LINE_COLOR - - Line drawing color. - - FILL_COLOR - - Polygon fill color. - - TEXT_COLOR - - Text drawing color. - - CLEAR_COLOR - - The color that the viewport is cleared to when you call clearScreen(). - - GRADIENT_BOTTOM_COLOR - - The bottom color of the gradient viewport ground. - - NOTE: Only Nitrous and DirectX driver support this now. - - GRADIENT_TOP_COLOR - - The top color of the gradient viewport ground. - - NOTE: Only Nitrous and DirectX driver support this now. - - float r - - Specifies the red amount 0.0 - 1.0. - - float g - - Specifies the green amount 0.0 - 1.0. - - float b - - Specifies the blue amount 0.0 - 1.0. - - - - - Lights a vertex, using all the current lights. The vertex appears to be transformed using the current transformation matrix, although actually the calculations are done using back-transformed light coordinates (for speed). The vertex position and normal are passed in, and a color is returned. The rendering uses the current material. - Parameters: - &pos - - Vertex position. - - &nor - - Vertex normal. - - &rgb - - Returned color. - - - - - Draws 2D fixed font annotation text to the specified location. Note: This routine DOES perform clipping of the text if it is off the screen. - Parameters: - *xyz - - This is the device coordinate for the text. The origin of the text is at the lower left corner. - - MCHAR *s - - The text to display. - - - - - Draws a marker at the specified location. - Parameters: - *xyz - - This is the device coordinate for the marker (with the origin at the lower left). - - MarkerType type - - See MarkerType. - - - - - This method draws a multi-segment polyline. - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. These are device coordinates with the origin at the lower left. - - *rgb - - If the shade mode is set to smooth and these colors for the vertices are specified the polyline will be drawn Gourand shaded. This is how 3ds Max draws lit wireframes for instance. If you simply want ordinary lines (drawn using the line color) pass NULL. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - This method is available in release 2.0 and later only. - - This method draws a multi-segment polyline. - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. These are device coordinates with the origin at the lower left. - - *rgb - - If the shade mode is set to smooth and these colors for the vertices are specified the polyline will be drawn Gourand shaded. This is how 3ds Max draws lit wireframes for instance. If you simply want ordinary lines (drawn using the line color) pass NULL. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - This is not currently used. Pass NULL. - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - This method draws a multi-point polygon. - Parameters: - int ct - - The number of points in the polygon. - - *xyz - - of points. These are device coordinates with the origin at the lower left. - - *rgb - - The color values at the vertices. The rendering mode must include GW_ILLUM for these values to be used. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW coordinates. The rendering mode must include GW_TEXTURE for these values to be used. - - - - - This method is used for drawing a series of triangles specified as 'strips'. It takes a count of 3 or more, and builds triangles in a strip. This sends a lot less data and the underlying graphics library has to set up a lot less data since it can use the previous information to start the rasterization. This results in a significant speed increase. - - Note that this routine does no clipping so all the points passed must be within view. - Parameters: - int ct - - The total number of points. After the first two points, each new point is used to create a new triangle. - - *xyz - - The point data with the origin at the lower left. For instance, to draw a quad, the first three points specify the first triangle and the next one is combined with the previous two to complete the square. - - The order for these points follows the 'standard' conventions for stripping used in most graphics libraries (for example Direct3D, OpenGL and Heidi). - - *rgb - - The colors for the vertices. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW texture coordinates for the vertices. - - - - - Draws 2D fixed font annotation text to the specified location. Note: This routine DOES perform clipping of the text if it is off the screen. - Parameters: - *xyz - - This is the device coordinate for the text. The origin of the text is at the upper left corner. - - MCHAR *s - - The text to display. - - - - - Gets the unscaled size of text displayed with wText/hText. Note : Only implemented for OGS viewport. Returns 11 on other graphics windows. - The unscaled point size in points. - - - - - Gets the width factor of the viewport text. Between 0.1 and 10. Note : Only implemented for OGS viewport. Returns 1 on other graphics windows. - The width factor (percentage). - - - - - Gets the weight viewport text. Note : Only implemented for OGS viewport. Returns 400 on other graphics windows. DONTCARE = 0, THIN = 100, EXTRALIGHT = 200, ULTRALIGHT = 200, LIGHT = 300, NORMAL = 400, REGULAR = 400, MEDIUM = 500, SEMIBOLD = 600, DEMIBOLD = 600, BOLD = 700, EXTRABOLD = 800, ULTRABOLD = 800, HEAVY = 900, BLACK = 900 - The weight. - - - - - Draws a marker at the specified location. - Parameters: - *xyz - - This is the device coordinate for the marker. - - MarkerType type - - See MarkerType. - - - - - This method draws a multi-segment polyline. - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. These are device coordinates with the origin at the upper left. - - *rgb - - If the shade mode is set to smooth and these colors for the vertices are specified the polyline will be drawn Gourand shaded. This is how 3ds Max draws lit wireframes for instance. If you simply want ordinary lines (drawn using the line color) pass NULL. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - This method is available in release 2.0 and later only. - - This method draws a multi-segment polyline. - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. These are device coordinates with the origin at the upper left. - - *rgb - - If the shade mode is set to smooth and these colors for the vertices are specified the polyline will be drawn Gourand shaded. This is how 3ds Max draws lit wireframes for instance. If you simply want ordinary lines (drawn using the line color) pass NULL. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - This is not currently used. Pass NULL. - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - This method draws a multi-point polygon. - Parameters: - int ct - - The number of points in the polygon. - - *xyz - - of points. These are device coordinates with the origin at the upper left. - - *rgb - - The color values at the vertices. The rendering mode must include GW_ILLUM for these values to be used. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW coordinates. The rendering mode must include GW_TEXTURE for these values to be used. - - - - - This method is used for drawing a series of triangles specified as 'strips'. It takes a count of 3 or more, and builds triangles in a strip. This sends a lot less data and the underlying graphics library has to set up a lot less data since it can use the previous information to start the rasterization. This results in a significant speed increase. - - Note that this routine does no clipping so all the points passed must be within view. - Parameters: - int ct - - The total number of points. After the first two points, each new point is used to create a new triangle. - - *xyz - - The point data with the origin at the upper left. For instance, to draw a quad, the first three points specify the first triangle and the next one is combined with the previous two to complete the square. - - The order for these points follows the 'standard' conventions for stripping used in most graphics libraries (for example Direct3D, OpenGL and Heidi). - - *rgb - - The colors for the vertices. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW texture coordinates for the vertices. - - - - - Draws 2D fixed font annotation text to the specified location. This method does perform clipping. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - This is the coordinate for the text. - - MCHAR *s - - The text to display. Note: This routine DOES perform clipping of the text if it is off the screen. - - - - - Draws a marker at the specified location in world space. This method does perform clipping. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - This is the coordinate for the marker. - - MarkerType type - - See MarkerType. - - - - - Draws a multi-segment polyline with the coordinates specified in world space. This method does perform clipping. - - Note: The arrays of points and vertex related data all must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max may crash. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. This array must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max will crash. - - *rgb - - If the shade mode is set to smooth and these colors for the vertices are specified the polyline will be drawn Gourand shaded. This is how 3ds Max draws lit wireframes for instance. If you simply want ordinary lines (drawn using the line color) pass NULL. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - This is not currently used. Pass NULL. - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - Draws a multi-segment polyline with the coordinates specified in world space. This method takes a polyline with a normal for each vertex. This is used for hardware accelerated lit wireframes (when GW_SPT_GEOM_ACCEL is TRUE). - - Note: The arrays of points and vertex related data all must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max may crash. - - This method does perform clipping. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - int ct - - The number of points in the polyline. The maximum number of points that may be used in drawing a polyline is 32. - - *xyz - - of points. This array must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max will crash. - - *nor - - The normal values at the vertices, one for each vertex. - - int closed - - If nonzero the first point is connected to the last point, i.e. the polyline is closed. - - int *es - - state array. This is an array that Indicates if the 'i-th' edge is one of three state: - - GW_EDGE_SKIP - - Non-existent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - This method is used to begin efficiently sending a lot of 3D line segments. First call this method, then call segment() many times (with two points), then call endSegments(). - - - - - This method draws a single 3D line segment between the specified points. Call startSegments() once before calling this method. - Parameters: - *xyz - - Points to the two line endpoints in world space. - - int vis - - Nonzero for the segment to be visible; zero for invisible. - - - - - Call this method after sending 3D line segments with segment(). - - - - - Draws a multi-point polygon. Note: All arrays (xyz, rgb, uvw) must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max may crash. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - int ct - - The number of points in the polygon. - - *xyz - - of points. - - *rgb - - The color values at the vertices. The rendering mode must include GW_ILLUM for these values to be used. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW coordinates. The rendering mode must include GW_TEXTURE for these values to be used. - - - - - Draws a multi-point polygon. Note: All arrays (xyz, nor, uvw) must be at least one element larger than the ct parameter that is passed in. The 3D clipper will use the "extra" space to clip as efficiently as possible. If room for the extra element is not provided, 3ds Max will crash. - - This method sends in normal vectors instead of color for 3D accelerated rendering (when GW_SPT_GEOM_ACCEL is TRUE) - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - int ct - - The number of points in the polygon. - - *xyz - - of points. - - *nor - - The normal values at the vertices, one for each vertex. - - *uvw - - The UVW coordinates. The rendering mode must include GW_TEXTURE for these values to be used. - - - - - This method is used for drawing a series of triangles specified as 'strips'. It takes a count of 3 or more, and builds triangles in a strip. This sends a lot less data and the underlying graphics library has to set up a lot less data since it can use the previous information to start the rasterization. This results in a significant speed increase. - Parameters: - int ct - - The total number of points. After the first two points, each new point is used to create a new triangle. - - *xyz - - The point data. For instance, to draw a quad, the first three points specify the first triangle and the next one is combined with the previous two to complete the square. - - The order for these points follows the 'standard' conventions for stripping used in most graphics libraries (for example Direct3D, OpenGL and Heidi). - - *rgb - - The colors for the vertices. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - *uvw - - The UVW texture coordinates for the vertices. - - - - - This method is used for drawing a series of triangles specified as 'strips'. It takes a count of 3 or more, and builds triangles in a strip. This sends a lot less data and the underlying graphics library has to set up a lot less data since it can use the previous information to start the rasterization. This results in a significant speed increase. This method sends in normal vectors instead of color for 3D accelerated rendering (when GW_SPT_GEOM_ACCEL is TRUE) - Parameters: - int ct - - The total number of points. After the first two points, each new point is used to create a new triangle. - - *xyz - - The point data. For instance, to draw a quad, the first three points specify the first triangle and the next one is combined with the previous two to complete the square. - - The order for these points follows the 'standard' conventions for stripping used in most graphics libraries (for example Direct3D, OpenGL and Heidi). - - *nor - - The normal for each vertex. - - *uvw - - The UVW texture coordinates for the vertices. - - - - - This method is called to begin sending a series of non-stripped triangles to render. Call this method, then any of the triangle*() methods many times, then endTriangles() to finish. - - - - - This method sends a single non-stripped triangle to render. Call startTriangles() first. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - The three points for the triangle. - - *rgb - - The color for each vertex. - - Note: The use of these colors is not supported under the OpenGL driver. The rgb values are ignored. Only the current material is taken into consideration. (This is how OpenGL works.) - - - - - This method draws a single triangle by specifying the vertex points in world space, a normal, and texture coordinates for each vertex. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - The three points for the triangle. - - *nor - - The three normals for the triangle. - - *uvw - - The texture coordinate for each vertex. - - - - - This method draws a single triangle by specifying the vertex points in world space, a normal, and a color for each vertex. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - The three points for the triangle. - - *nor - - The normal for each vertex. - - *rgb - - The color for each vertex. - - - - - This method draws a single triangle by specifying the vertex points in world space, a normal, a color, and a texture coordinate for each vertex. - - Note: This method maps points from the 's current transform to screen space. If the 's transform is set to the identity matrix then the mapping is done from points specified in world space. Otherwise the points given are transformed by the transform, and are then considered to be in world space. Thus, to get a world-space to screen-space conversion, you need to set the transform to the identity with gw->setTransform(Matrix3(1)). - Parameters: - *xyz - - The three points for the triangle. - - *nor - - The normal for each vertex. - - *rgb - - The color for each vertex. - - *uvw - - The texture coordinate for each vertex. - - - - - Call this method to finish rendering triangles. See startTriangles() above. - - - - - Sets the hit region used for hit testing. See Class . - Parameters: - *rgn - - The hit region to use. - - - - - This methods clears the hit code. Call this method before performing a hit test. - - - - - Returns TRUE if the hit code is set indicating a hit was made; otherwise FALSE. - - - - - This method allows drawing code to manually set the state of the hit code, which is returned by the checkHitCode() method. For more information see the topic on ~{ Hit Testing }~. - - The new methods setHitDistance() and setHitCode() make it possible to work with hit-testing in otherwise impossible situations. Why are they necessary? An example from is shown below. The patch object contains bezier spline-based edges which can consist of up to 102 vertices. Since the GraphicsWindow::polyline function can only plot lines with up to 32 vertices, it is impossible to plot these in a single call to the polyline function. Multiple calls to the polyline call do not return a proper hitcode when using a "window"-type hit region. By using the new setHitCode() method, code can properly handle this situation. The code below shows the function in use from the PatchMesh::renderEdge method: Note that the gw->polyline call is preceded by a call to clearHitCode(), and followed by code which checks the hit code, maintaining "hitAny" and "hitAll" flags. When all the segments are drawn, the setHitCode()gw-> call is made, setting the hit code depending on the hit region type. When the code which called this function checks the 's hit code, it will contain the proper value. This code also keeps track of the closest hit distance and places that into the when all line segments are drawn. - Parameters: - BOOL h - - to TRUE if the hit code is set, otherwise FALSE. - - - - - If checkHitCode() returns TRUE you may call this method to return the hit distance. In wireframe mode this is the distance to the line. In shaded mode, this is the z distance. This allows you to perform 'smart' hit testing by choosing the item with the smallest hit distance. This method only returns meaningful values when the hit region is a point. - - - - - This method is used internally. - - - - - These functions are avaliable for pick-only graphic window. - Note this function is expected to be reentrant with the pick-only graphic window provided by the system. - - - - - This method calculates the depth value of the screen pixel located at positon x,y. This method returns TRUE if the depth value is calculated, FALSE otherwise. It is currently supported in Direct3D and OpenGL driver. Thus returning FALSE for unsupported driver. This method is used to locate center pivot in SteeringWheel. - TRUE if calculated correctly, FALSE if the method failed or not supported. - - The x coordinate in screen space. - The y coordinate in screen space. - A pointer to the buffer that receives the calculated depth value. - - - - This method will clear the depth buffer bits of this . It is currently supported in Direct3D and OpenGL driver. This method is used clear the depth before actually drawing the ViewCube, which cannot be messed up with the scene geometry. - - - - - This take a and creates a hardware specific mesh buffers - the hardware specific IHWDrawMesh. - - the mesh used to create the Hardware specific buffers. - - - - This draws the hwMesh to the display. If the hardware mesh holds a valid IHWDrawMesh it will use that to draw the mesh in retained mode. Otherwise the buffers in the hwmesh will be used to draw the mesh in immediate mode which is much slower. - - the mesh to be drawn. - - - - A grip changed callback A callback object passed to IGripManager::RegisterGripChangedCallback() The method GripChanged is called every time a different grip or no grip becomes active. */. - - - - - Called whenever a new grip becomes active. - - - - - The new active grip. If NULL, no grip is active. - - - - Description: - This class is used by Bitmaps to implement an enhanced G-Buffer (providing more functionality than the 2.x G-Buffer). The new G-Buffer stores multiple layers at each pixel. The Virtual Frame Buffer includes a new spinner to the right of the "channels" drop down which lets you look at the different layers. (It only appears when there are G-Buffer channels present). - - The multiple layers of the G-Buffer allow rendering effects to do better antialiasing and handling of transparency. The frontmost layer is still stored in the G-Buffer as full, screen-sized arrays, one for each channel. The subsequent layers are stored in a variable number of "layer records" all of which are the same size (which depends on which channels have been requested via the GBuffer::CreateChannels() function). Even scenes with no transparency can have more than one layer at a given pixel. This can occur along the edges of an object, where the object partially covers some pixels, and another object (or objects) is visible in the remaining part of the pixel. Each visible face in the pixel will be represented by a fragment. A given object will not always appear on the same layer. If it is the only object in a pixel it will be in the frontmost layer, but where it is partially occluded it will lie in a layer behind the occluding object. - - Another way multiple layers can occur (aside from transparency) is when objects are given the "Render Occluded Objects" property in the object properties dialog. When an object has this property, it acts as if it were transparent, and objects behind it, though invisible, are rendered and stored in the G-Buffer. - - Another G-Buffer layer is added to contain the background color in its color channel for any pixel which is not empty and on which the background gets evaluated. This means the background layer will be present behind transparent objects or objects with "render occluded" turned on. It will also be present along the edges of objects where the background is partially visible in the pixel. Note: This does not depend at all on having the GB_BG flag set. It is necessary to have the GB_COLOR channel, however. - - All methods of this class are implemented by the System. - - Note on RPF files: The following information relates to the layer storage scheme used in the 3ds Max RPF files. - - The layer information for each scan line is stored as a series of run-encoded channels, each containing the same number of data elements, one per layer record. The first channel is a "psuedo-channel" that contains the x value for each layer record. If there are multiple layers for a given x, this will be reflected as several identical x values in a row. - - For instance, if the x channel contained - - 5,6,7,7,8,8,8,9,10 - - And the Z channel contained - - 100, 100, 100,200, 100,200,300, 100, 100 - - This would mean at pixel 7 there are 2 layers, and pixel 8 there are 3 layers. - - Pixel depths - - 5 100 - - 6 100 - - 7 100, 200 - - 8 100, 200, 300 - - 9 100 - - 10 100 - - As an extra note regarding RPF files, a new data member was added to class , which is saved with the RPF (and RLA) files. In order to avoid getting out of sync with previous file format implementations a "version" word preceding the record has been added into the format. The version is set to a value that will distinguish it from the first word of the data, enabling it to determine the version. If we make further additions to in the future, the version will allow us to keep it straight. To load both older and newer RPF and RLA files correctly, the code that loads the been modified, and therefore any plugins and 3rd party code that read these files need to be changed. Here's the code: - - - - - - - This method is used internally to set the size of the G-Buffer. - Parameters: - int ww - - The width to set in pixels. - - int hh - - The height to set in pixels. - - - - - Returns the width of the . - - - - - Returns the height of the . - - - - - Initializes the . Call this method before writing to the buffer. If present, the GB_Z channels is set to -BIGFLOAT and the GB_NODE_RENDER_ID channel is set to 0xffff. The Render ID Table is cleared. - Nonzero on success; otherwise zero. - Sample Code: - - - - - This method creates the specified channels in this G-Buffer. - Parameters: - ULONG channelMask - - Specifies the channels to create. See Image (G-Buffer) Channels. - The channels that are currently present. - - - - - This method delete specified channels. - Parameters: - ULONG channelMask - - Specifies the channels to create. See Image (G-Buffer) Channels. - - - - - Returns the channels that are currently present. See Image (G-Buffer) Channels. - - - - - Returns a pointer to the specified channel of the G-Buffer, and determines its type in terms of bits per pixel. NULL is returned if the channel can't be found. - Parameters: - ULONG channelID - - The channel to get. See Image (G-Buffer) ChannelsULONG& chanType - - The channel type. See G-Buffer Channel Types. - - - - - Creates and returns a pointer to a object. - - - - - Deletes the specified object. - Parameters: - *pRdr - - Points to the reader to delete. - - - - - Creates and returns a pointer to a object. - - - - - Deletes the specified object. - Parameters: - *pRdr - - Points to the writer to delete. - - - - - Returns TRUE if this is a default G-Buffer; otherwise FALSE. A 'default' G-Buffer is one that 3ds Max itself creates. Since is a virtual class a plug-in developer could create their own G-Buffers (for some very special purpose). In that case it would not be a 'default' G-Buffer and this method would return FALSE. - - - - - Copies the data from the specified G-Buffer to this one. This method maintains the multi-layer data correctly. The channels present in each G-Buffer must match. - Parameters: - *gbfrom - - Points to the source of the copy. - - - - - Copies the data from the specified G-Buffer and optionally scales its size while maintaining the multi-layer data correctly. This is used in Video Post whenever there is an input bitmap that is a different size than the current Video Post image dimensions. - Parameters: - *gbfrom - - Points to the source of the copy. - - int cw=-1 - - The width for the copy. If -1 is specified the copy is the same size as the original. - - int ch=-1 - - The height for the copy. If -1 is specified the copy is the same size as the original. - - - - - This method is used internally and is something that normally a developer shouldn't call directly. It is used inside the routines for manipulating bitmaps. It takes a sub rectangle of the G-Buffer which has an upper left corner at (srcx,srcy), and dimensions of (trgw,trgh), and moves it to be positioned at (trgx,trgy). Portions of the G-Buffer outside of this rectangle are discarded. - Parameters: - int srcy - - The source y location. - - int trgy - - The target y location. - - int srcx - - The source x location. - - int trgx - - The target x location. - - int trgw - - The target width. - - int trgh - - The target height. - - - - - Returns the total number of layer records for the specified scan line. On each scan line there is a single array of layer records. Each layer record contains an x value which tells at what pixel it is located, and then all of the G-Buffer data that is being stored in this particular G-Buffer. The layer records for a given pixel all have the same x value, and are ordered front-to-back in scene depth. - - This method is used by the RLA and RPF writer code. See /MAXSDK/SAMPLES/IO/RLA/RLA.CPP for an example. - Parameters: - int y - - The zero based index of the scan line. - - - - - This method goes through all the layer records and pulls out the values for a particular channel into an array, which is handy for run-encoding when saving to a file. - Parameters: - int y - - The zero based index of the scan line. - - int ichan - - The channel to check. See G-Buffer Channel Indices. When ichan=-1, it gives an array of the x values from each of the layer records. - - char *data - - Points to storage for the layer data. - TRUE on success; otherwise FALSE. - - - - - This method creates the specifed number of layer records for the scan line passed. - Parameters: - int y - - The zero based index of the scan line. - - int num - - The number of records to create. - TRUE on success; otherwise FALSE. - - - - - Sets the layer record data for the specified channel for the scan line passed. - Parameters: - int y - - The zero based index of the scan line. - - int ichan - - The channel to set. See G-Buffer Channel Indices. When ichan=-1, it sets an array of the x values from each of the layer records. - - char *data - - Points to storage for the layer data. - TRUE on success; otherwise FALSE. - - - - - This method searches the G-Buffer Z, UV and VELOC channels and stores the minimum and maximum values. This enables the GetChannelMin() and GetChannelMax() methods to work. This is called internally whey 3ds Max generates a G-Buffer. When developers get one from the renderer this method will already have been called. - - - - - Retrieves the minimum value in the specified channel. - Parameters: - int chan - - The channel to check. One of the following (the other channels are not supported): - - GB_Z - - Z-Buffer depth - float - - GB_UV - - UV coordinates - - - GB_VELOC - - Velocity - - - void *data - - Points to storage for the value to get. - TRUE if chan was valid and the value could be stored in data; otherwise FALSE. - - - - - Retrieves the maximum value in the specified channel. - Parameters: - int chan - - The channel to check. One of the following (the other channels are not supported): - - GB_Z - - Z-Buffer depth - float - - GB_UV - - UV coordinates - - - GB_VELOC - - Velocity - - - void *data - - Points to storage for the value to get. - TRUE if chan was valid and the value could be stored in data; otherwise FALSE. - - - - - This method returns a reference to the table of node names indexed by their NodeRenderId. See Class . - - - - - This method returns a reference to a table of floats. These are image blur multipliers indexed by NodeRenderID. - - - - - Description: - This is the object returned by GBuffer::CreateReader(). Methods of this class allow the G-Buffer data to be read. - - Here is an example of reading multiple layer data from the G-Buffer using methods of this class. - - All methods of this class are implemented by the System. - - - - - Call this method to start a new scan line. Call this method before the first scan line. - Parameters: - int y - - The zero based index of the scan line to start. - Returns -1 if there was no data for line, or the x value of first non-empty pixel. - - - - - Call this method to start a new pixel. This method automatically starts the first layer. - Parameters: - int x - - The zero based index of the pixel to start. - Returns TRUE. - - - - - This method is called to start a new line and pixel. This method is equivalent to: - - StartLine(y); - - return StartPixel(x); - - - - - This method is called to begin reading data from a new layer. Do not call this method before reading the first layer. - TRUE if more data to read; otherwise FALSE. - - - - - Call this method to prepare for reading the next pixel. - Returns TRUE. - - - - - Reads a data element from the specified channel of the G-Buffer from the current scan line and pixel. - Parameters: - The channel to read. One of the items from: G-Buffer Channel Indicesvoid *data - - Points to storage for the data. - TRUE if data was available; otherwise FALSE. - - - - - Reads all the data from the G-Buffer into the structure passed from the current scan line and pixel. - Parameters: - *data - - Points to storage for the data. See Structure . - TRUE if data was available; otherwise FALSE. - - - - - This method allows values in the specified layer to be written. Note that it may seem strange, writing data from the reader, but developers asked for the capability of writing to the already created gbuffer, and it is much simpler to add this capability to the than to , which is designed to construct gbuffers from scratch, not modify existing ones. - Parameters: - int chan - - Specifies the channel to write to. - - void *data - - Points to the data to write. - TRUE indicates success; FALSE indicates failure. - - - - - This method allows values in the current layer to be written. Note that it may seem strange, writing data from the reader, but developers asked for the capability of writing to the already created gbuffer, and it is much simpler to add this capability to the than to , which is designed to construct gbuffers from scratch, not modify existing ones. - Parameters: - *data - - Points to the data to write. - TRUE indicates success; FALSE indicates failure. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - Parameters: - int cmd - - The command to execute. - - ULONG arg1=0 - - Optional argument 1 (defined uniquely for each cmd). - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - - - - Description: - This is the writer object returned from GBuffer::CreateWriter(). This class assumes pixels are created in increasing order of x. - - Here is an example of writing multiple layer data to the G-Buffer using methods of this class. - - All methods of this class are implemented by the System. - - - - - This method should be called before writing every line. - Parameters: - int y - - The zero based index of the scan line to start. - - - - - This method must be called before writing each pixel and must be called with increasing x values on a line. - Parameters: - int x - - The zero based index of the pixel to start. - - - - - This method must be called before writing the first layer. - - - - - Call this method to write a data element to the specified channel of the G-Buffer to the current scan line and pixel. - Parameters: - int chan - - See G-Buffer Channel Indicesvoid *data - - Points to the G-Buffer data to write. - TRUE on success; FALSE on failure. - - - - - This method writes all the channel data from the structure passed to the current scan line and pixel. - Parameters: - *data - - Points to the G-Buffer data to write. See Structure . - TRUE on success; FALSE on failure. - - - - - This method should be called after writing each line. - TRUE on success; FALSE on failure. - - - - - This class implements a 4x4 matrix object. - - - - - Return a reference to the 'i-th' of the matrix - - - - - Assignment operator from a - - - - - Test for equality within the specified tolerance - - - - - Determine whether or not the matrix is an Identity matrix. - - - within the specified tolerance - True if the matrix is the Identity matrix - - Tolerance defaulted to epsilon = 1E-5f - - - - the Standard Identity Matrix. - - - - - Return Determinant of matrix. - - - - - Return Inverse of matrix. - - - - - Return a translation transformation. - - - - - Return a essential rotation transformation. - - - - - Return a scaling transformation. - - - - - Return 'parity' sign of the matrix, -1 if negative, 1 otherwise. - - - - - Access to the matrix column. - - - A containing the column - - The number of the column to retrieve - - - - the the matrix column. - - - - - Access to the matrix row. - - - - - to the matrix row to the desired data. - - - - - Extract a from the . - - - This is for backward compatibility. This is only of use if you use 3ds Max as a coordinate system, other wise standard 3ds Max algebra might not be correct for your format. - A 3ds Max form of the - - - - - Deprecated utility class for managing user interface colors - Description: - A useful utility class for managing user interface colors. This class has several purposes: - - Maintain the default 3ds Max palette for doing 256 color graphics. - - Provides a mechanism for allocating "animated color slots" in the default palette for use in the user interface. - - Provide various functions for doing dithered graphics using the default 3ds Max palette. - - All methods of this class are implemented by the system. - - The following global function is used to get a pointer that may be used to call the methods of this class: - - - - - Display an array of 24 bit colors in the HDC. If the current display is 8 bit it will display it (with dither) using in the palette, otherwise it will just blit to the screen. This method does NOT do gamma correction. - Parameters: - HDC hdc - - The handle of the device context. - - Rect& drect - - The destination rectangle in the hdc. - - int xsrc - - The X position within this source raster of the upper left corner of the rectangle to be copied. - - int ysrc - - The Y position within this source raster of the upper left corner of the rectangle to be copied. - - UBYTE *map - - Points to an array of BGR triples. - - int bytesPerRow - - The number of bytes per row on each scanline of map. - - - - - This version of DisplayMap() stretches the image if the source rectangle is not the same size as the destination rectangle. src should be the size of the image. - Parameters: - HDC hdc - - The handle of the device context. - - Rect& dest - - The destination rectangle in the hdc. - - Rect& src - - The source rectangle in map. - - UBYTE *map - - Points to an array of RGB triples. - - int bytesPerRow - - The number of bytes per row on each scanline of map. - - - - - Description: - This is the base class for the creation of Global Utility Plug-Ins. - - These plug-ins work as follows: At 3ds Max startup time, before 3ds Max begins its message loop and after all its subsystems are initialized, the Manager will scan the plug-in directory and load all plug-ins with the "<b>*.gup</b>" extension. One by one, the Manager will call the plug-in's Start() method. At that point the plug-in would do its initialization and decide if it wants to remain loaded or if it can be discarded. As an option, it is also possible for a plug-in for make 3ds Max fail and abort all together. If a plug-in wishes to remain loaded (after returning a GUPRESULT_KEEP result code from the Start() method described below), it should start a new thread for its code as there is no other call from 3ds Max. - - Unlike other 3ds Max plug-ins, 's do not provide a user interface. If developers of plug-ins desire to present an interface, they can develop a standard 3ds Max utility plug-in to do so. See Class . There is some sample code using this technique availalble in /MAXSDK/SAMPLES/GUP/COMSRV/MSCOM.CPP. This Utility plug-in (COMSRV.DLU) accesses the COM/DCOM plug-in and allows the user to "register" or "unregister" the COM interface. See the Advanced Topics section ~{ COM/DCOM }~. - Plug-In Information: - Class Defined In GUP.H - - Super Class ID GUP_CLASS_ID - - Standard File Extension - - Extra Include File Needed None - - - - - Implemented by the System. - - Returns the application instance handle of 3ds Max itself. - - - - - Implemented by the System. - - Returns the window handle of 3ds Max's main window. - - - - - Implemented by the System. - - Returns a pointer to an instance of a class which provides access to the DLL Directory. This is a list of every DLL loaded in 3ds Max - - - - - Implemented by the System. - - Returns an interface pointer for calling methods provided by 3ds Max. - - - - - Implemented by the System. - - Returns a pointer to the bitmap manager which may be used to manage the use of bitmaps within 3ds Max. - - - - - Implemented by the System. - - This may be called to enumerate every in the scene. - Parameters: - *proc - - This callback object is called once for each in the scene. - Nonzero if the process was aborted by the callback (TREE_ABORT); otherwise 0. - - - - - Implemented by the System. - - This method will execute the specified MAXScript command. If a developer needs to ask 3ds Max to do something and this "something" is not implemented within the COM interface, it is possible to send MAXScript commands through this method (and ExecuteFileScript() below). This method will execute whatever string is specified, for instance ExecuteStringScript("open \"MyScene.max""). - Parameters: - MCHAR *string - - Points to the MAXScript command to execute. scriptSource - - The source of the string containing the MAXScript command to execute. - TRUE indicates if the command was successfully sent to MAXScript; FALSE if it was not sent. Note that this does not reflect the success of the embedded command. - - - - - Executes the given script file. - - - - true if the script was successfully executed, false if not. Note that this does not reflect the result of the script. - - if captured_error_message is not null, no error dialog is displayed if an error occurs. - - if the script file name is persisted in the scene file, the script file should be handled as an Asset and executed using ExecuteScriptAsset(const & file, MSTR* capturedErrorMessage = nullptr) - Implemented by the System. - - - The fully qualified path to the existing file. This can be maxscript files (*.ms, .mxs), maxscript zip files (*.mzp), encrypted maxscript files (*.mse), or python files (*.py, *.pyc, *.pyw). - - for capturing error message, can be nullptr. - - - - Executes the given script file specified as an AssetUser. This function should be used for executing script files whose name is stored in the scene file. - - - - true if the script was successfully executed, false if not. Note that this does not reflect the result of the script. - - if captured_error_message is not null, no error dialog is displayed if an error occurs. - Implemented by the System. - - - The asset that points to the existing file. This can be maxscript files (*.ms, .mxs), maxscript zip files (*.mzp), encrypted maxscript files (*.mse), or python files (*.py, *.pyc, *.pyw). - - for capturing error message, can be nullptr. - - - - This method is called at boot time. At that point the plug-in should do its initialization and decide if it wants to remain loaded or if it can be discarded. As an option, it is also possible for a plug-in for make 3ds Max fail and abort all together. Obviously this should be used with caution and plenty of documentation from the part of the developer of the plug-in. If a plug-in wishes to remain loaded (after returning a GUPRESULT_KEEP result code), it should start a new thread for its code as there is no other call from 3ds Max. - One of the following values: - - GUPRESULT_KEEP - - Return this to value to have the plug-in remain loaded. - - GUPRESULT_NOKEEP - - Return this value to discard. - - GUPRESULT_ABORT - - Return this value to cause 3ds Max to shut down. - - - - - The Stop() method is called when 3ds Max is going down. The Manager will call this methods for all plug-ins that were maintained in memory right before it discards them. This method is called only for plug-ins that returned GUPRESULT_KEEP for the Start() method above. - - - - - This method is an entry point for external access to plug-in. For instance, Utility plug-ins can invoke their plugin counterpart and have direct access to them. - Parameters: - DWORD parameter - - The meaning of this parameter is defined by the plug-in. - The return value meaning is also defined by the plug-in. - Default Implementation: - { return 0;} - - - - - This method is called to save any data the plug-in may have into the 3ds Max file. - Parameters: - *isave - - An interface used for saving data. - - - - - This method is called to load any data the plug-in may have from the 3ds Max file. - Parameters: - *iload - - An interface used for loading data. - - - - - Description: - This class is used to collect and maintain type plug-ins and is for internal use only. - - - - - Compares this class instance to another one - - - - - Description: - This is an interface class used by GUPs (Global Utility Plug-Ins). - - All methods of this class are Implemented by the System. - - - - - Returns the application instance handle of 3ds Max itself. - - - - - Returns the window handle of 3ds Max's main window. - - - - - Returns a pointer to an instance of a class which provides access to the DLL Directory. This is a list of every DLL loaded in 3ds Max - - - - - Returns an interface pointer for calling methods provided by 3ds Max. - - - - - This may be called to enumerate every in the scene. - Parameters: - *proc - - This callback object is called once for each in the scene. - Nonzero if the process was aborted by the callback (TREE_ABORT); otherwise 0. - - - - - Description: - This class can be used to create instance of plug-ins on the fly, if needed. It is accessed through the object. It keeps a list of available plug-ins. An example of this can be found in /MAXSDK/SAMPLES/UTILITIES/COMSRV. This is a standard Utility plug-in which is used to give the plug-in COMSRV a user interface. - - - - - Returns the zero based index of the specified plug-in in the list maintain by this class. If not found -1 is returned. - Parameters: - id - - Identifies the plug-in to find using its unique . - - - - - This method is used to create a new instance of the plug-in whose is specified. If it succeeds, it returns a newly created instance of a object. A developer may then use the GUP::Control() method to communicate with the object. - Parameters: - id - - Identifies the plug-in to create. - - - - - Description: - The library exports a pointer variable which is used to access the Manager object (a global instance of this class): - - GUPManager* gupManager; - - The only methods of this class of interest are the instance of and the Interface() method. All other methods are for internal use only. - Data Members: - All data members are public. - - gupList - - The list of available plug-ins. - - - - - This method is for internal use only. - - - - - This method is for internal use only. - - - - - This method gives plug-ins access to 3ds Max main Inteface class. Plug-ins don't need to access directly as all the functionality is exposed in the class itself. - - - - - A triangular face, which is represented as indexes into a vertex array. - - - - - This is used as a base class to create helper object plug-ins. It simply provides implementations for a few of the methods of and . - - - - - Description: - This class represents an entry in a . All methods of the class are implemented by the system. - Data Members: - int data; - - This is the polygon number. For example a donut shape will have polygon 0 and polygon 1. This is an index into the list of polygons for the shape. - - int children; - - of children of this entry. - - *parent; - - Points to the parent entry. - - *sibling; - - Points to the first sibling. - - *child; - - Points to the first child. - - MSTR sortKey; - - The sort key. This is used internally by the hierarchy so that it can determine whether two hierarchies are compatible. Developers shouldn't alter this value. - - - - - Returns the level in the hierarchy this entry represents. This is the number of parents this item has. The root level is not counted. - The level in the hierarchy of this entry. - - - - - Adds a new child entry to this entry using the data specified. - Parameters: - int d - - The data value of the child. This is the polygon number. - - - - - Returns the specified child of this entry. - Parameters: - int index - - The child to retrieve. - The specified child of this entry. If the specified index is greater than or equal to the number of children INVALID_HIERARCHY is returned. - - - - - Returns the number of children of this entry. - - - - - Sorts the hierarchy using the sortKeys. - - - - - Description: - This is the callback object used with Interface::DoHitByNameDialog(). - - - - - Returns the title string displayed in the dialog. - Default Implementation: - { return _M(""); } - - - - - Returns the text displayed in the 'Select' or 'Pick' button. - Default Implementation: - { return _M(""); } - - - - - Returns TRUE if the user may only make a single selection in the list at one time; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - This gives the callback the opportunity to filter out items from the list. This is called before the dialog is presented. It returns TRUE if the filter() method (below) should be called; otherwise FALSE. - Default Implementation: - { return TRUE; } - - - - - This method will be called if useFilter() above returned TRUE. This gives the callback the chance to filter out items from the list before they are presented to the user in the dialog. This is called once for each node that would otherwise be presented. Return nonzero to accept the item and zero to skip it. - Parameters: - *node - - The node to check for inclusion in the list. - Nonzero to accept the item and zero to skip it. - Default Implementation: - { return TRUE; } - - - - - Normally, when the user selects OK from the dialog, the system selects all the chosen nodes in the scene. At times a developer may want to do something other than select the chosen nodes. If this method returns TRUE then the nodes in the list will not be selected, but the proc() method is called instead (see below). If this method returns FALSE, then the nodes are selected in the scene and proc() is not called. - Default Implementation: - { return TRUE; } - - - - - This allows the plug-in to process the nodes chosen from the dialog in any manner. For example if the developer wanted to delete the nodes chosen using this dialog, they would implement useProc() to return TRUE and this method to delete all the nodes in the table passed. - Parameters: - &nodeTab - - A table of those nodes selected by the user. See Class . - Default Implementation: - {} - - - - - Normally, when the dialog is entered, the nodes in the scene that are selected are highlighted in the list. If this method returns TRUE, the developer may control which items are highlighted by implementing doHilite() (see below). If this method returns FALSE the selected nodes will have their names highlighted in the list. - Default Implementation: - { return FALSE; } - - - - - This method is called for each item in the list if doCustomHilite() returns TRUE. This method returns TRUE or FALSE to control if each item is highlighted. - Parameters: - *node - - The node to check. - TRUE to highlight the node in the list; FALSE to not highlight it. - Default Implementation: - { return FALSE; } - - - - - This defaults to returning FALSE, which means that hidden and frozen objects will not be included in the select by name dialog list. If this method is overridden to return TRUE, then hidden and frozen nodes will be sent through the user-supplied filter as in version 1.x. (Note that, apart from Unhide by and Unfreeze by , the new default behavior is likely to be correct for all uses of this class.) - Default Implementation: - { return FALSE; } - - - - - This class is used during sub-object hit testing to identify sub-object components. If the 4 bytes available in the info data member of are insufficient to identify the sub-object component an instance of this class can be created to contain the necessary data. Note, a plugin should derive from this class. Then an instance of the derived class is passed to the system, which then will be responsible for owning and freeing the memory. Therefore do not free the memory for this instance after passing it to the system. - - - - - - - Sets the first hit entry in the list as the current hit - FALSE if no hit entries are in the list, otherwise TRUE - - - - - Sets the current hit to the next entry in the list - FALSE if the operation fails because no entries remain the list, otherwise TRUE - - - - - The distance of the current hit. If the user is in wireframe mode, this is the distance in pixels to the item that was hit. If the user is in shaded mode, this is the Z depth distance. Smaller numbers indicate a closer hit. - The distance of the current hit. - - - - - The index of the sub-object component of the current hit. For example, if faces were being hit tested, this would be the index of the face which was hit. - The index of the sub-object component of the current hit. - - - - - Initializes the wrapper to the specified object type, allocating the type-specific hit list used by the wrapper. This must be called before the wrapper can store any hit test results. - - - - one of the type enum values - - - - Releases the type-specific hit list used by the wrapper. This is normally called by the destructor. - - - - - This class provides a data structure for keeping a log of hits during sub-object hit-testing. It provides a list of HitRecords that may be added to and cleared. A developer may also request the 'closest' hit record in the list. - - - - - Clears the log of hits by deleting the list of HitRecords. - - - - - Implemented by the System. Returns the first . - - - - - Implemented by the System. Returns the that was 'closest' to the mouse position when hit testing was performed. This is the with the minimum distance. - - - - - Implemented by the System. This method is called to log a hit. It creates a new object using the data passed and adds it to the hit log. - - The node that was hit. - The of the modifier. - The 'distance' of the hit. An implementation defined value that is lower for hits that are closer. - Identifies the sub-object component that was hit. - If the info field is insufficient to indicate the sub-object component that was hit, pass an instance of the class that contains the needed information. Please Note, the system will own and therefore free the memory for this pointer. Do not attempt to free it. - - - - Description: - This is a class to hold a list of object space points for highlighting the geometry associated with a hit. One oddity of this class is that you need to allocate one point more than the number of points you actually need. This additional storage is used for clipping against the viewport at display time. For example the "endpoint" snap would alocate a three-point hitmesh to highlight the edge which was hit (See the example below) . - - The class has data members for the number of points and a pointer to the actual list. - - In practice, developers need only use the first two methods shown below. - - - - - - Access operator. Return the 'i-th' point. - Parameters: - int i - - Specifies the point to return. - - - - - Returns the number of points in this . - - - - - Sets the 'i-th' vertex to the specified value. - Parameters: - int i - - The vertex to set. - - &xyz - - The value to set. - - In practice, developers need only use the two previous methods. The following code segment from the mesh snap exemplifies their use. - - - - - - - Returns the 'i-th' vertex. - - - - - Returns a pointer to the array of points. - Operators: - - - - - This class provides a data structure used during sub-object hit-testing. - - - - - Points to the node that was hit. - - - - - Points to the of the modifier. - - - - - The 'distance' of the hit. An implementation defined value that is lower for hits that are closer. - - - - - A general unsigned long value. Most modifiers will just need this to identity the sub-object element. The edit mesh modifier uses the value to store the index of the vertex or face that was hit for example. - - - - - In case 4 bytes in hitInfo is not enough space to identity the sub-object element, this pointer is available. To use this, a developer would define a class derived from that would contain the necessary data. The class has one member function, a virtual destructor, so the derived class can be properly deleted when the instance is deleted by the system. - - - - - Each maintains a pointer to another . This method returns the next hit record. - - - - - Describes the properties of a region used for built-in hit testing of items in the interactive renderer. - - - - - The region type. One of the following values - - - - - Region direction. RGN_DIR_UNDEF by default. - - - - - If nonzero, elements that are contained within or that cross the region boundary are hit. If zero, only those elements entirely within the boundary are hit. This is not used for point hit testing. - - - - - Specifies the distance in pixels outside the pick point within which elements may be and still be hit. This is not used for rect or circle testing, is sometimes used with fence hit testing, where it doubles the size of the region, especially when selecting subobject edges or vertices and is always used for point hit testing. - - - - - Description: - The undo / redo system of 3ds Max uses a global instance of this class called theHold. Developers call methods of theHold object to participate in the undo / redo system. - - - - - The developer calls this method to register a new restore object with the system. - - - - true if successfully added, false if not. It will return false if it's not holding. - - The restore object to register. - - - - Starts an undoable operation. When a plugin is about to start a user-triggered operation that should be undoable (normally as a result of pressing a button or activating a UI control in some way), this method must be called to initiate the undoable operation. This method turns the undo system on - placing it in the "holding" state, such that any subsequent scene modifications will get registered as undoable operations. For example, any change in ParamBlock2 parameter values will automatically be registered with the undo system if and only if Begin() has been called. Failure to call Begin() before performing scene changes will render those changes permanent and impossible to undo. - - - Following the completion of the user-triggered operation, Accept() must be called to signal completion of the undo operation. - Internally, a counter is used to support overlapping undoable operations. The undoable operation is registered by the system only once the counter returns to 0 - i.e. once there have been an equal number of Accept() and Begin(). - For every call to Begin(), there should be a matching call to either Cancel() or Accept(). - - - - - Temporarily suspends holding. - - - - - Reports whether the hold system is suspended or not. - - - - - It resumes holding if it was suspended. - - - - - Indicates if theHold.Begin() has been called. Any operation that modifies the database checks to see if theHold is currently in a holding state. If the undo system is 'holding' it is ready to accept restore objects. For more details see the Advanced Topics section on ~{ The Undo and Redo System }~. - Nonzero if theHold is holding; otherwise 0. - - - - - Returns nonzero if the system is restoring and zero if not. - - This parameter is updated to indicate if the restore is coming from an undo. It's assigned nonzero if it is; zero if not. - - - - Returns nonzero if the system is redoing and zero if not. - - - - - Returns nonzero if the system is restoring or redoing and zero if not. - - - - - This is used internally. Plug-In developers should not call this method. Prevents Undo when Accept() is called. - - - - - This is used internally. Plug-In developers should not call this method. Allows Undo when Accept() is called. - - - - - This is used internally. Plug-In developers should not call this method. Returns state set by DisableUndo/EnableUndo. - - - - - Returns current nesting level of Begin() calls. - - - - - This method will call Restore() on all the restore objects registered since the last Begin(). This restores the database to the state it was in when Begin() was called. The restore objects are NOT deleted. - - - - - This tosses out the restore objects since the last Begin() but still continues holding. Group several Begin-End lists into a single Super-group. - - - - - This method is used internally to 3ds Max and should not be called by a plug-in developer. It leaves the database in its modified state but throws out the restore object. - - - - - For internal use only. - - - - - Signals the completion of an undoable operation. - - - Once a user-triggered, undoable operation has been completed, this method must be called to signal that completion to the system. The undoable operation is registered and published using the provided as its title. - For every call to Begin(), there should be a matching call to either Cancel() or Accept(). - - The string which is to be displayed to the user, as the name of the undo operation (e.g. to appear in the Edit menu). The system will prepend "Undo " to the string. - - - - Signals the completion of an undoable operation. - - - Once a user-triggered, undoable operation has been completed, this method must be called to signal that completion to the system. The undoable operation is registered and published using the information in its operation descriptor. - For every call to Begin(), there should be a matching call to either Cancel() or Accept(). - This method overload shall be used when the operation is also reported to ADP "MAX.MODEL" way point. - - The command description with all Adp reportable information together with string to be displayed to the user, as the name of the undo operation (e.g. to appear in the Edit menu). - - - - Aborts an undoable operation previously initiated with Begin(). - - - If an undo operation is to be aborted before it was completed (through Accept()), then this method should be called. All scene changes that have been registered since Begin() was called are undone by this method. - - - - - Implemented by the System. - - Normally this is NOT needed but in special cases this can be useful. This allows a developer to group a set of Begin()/Accept() sequences to be undone in one operation. - - Consider the case of the user using the Shift-Move command to create a new node in the scene. There are two parts to this process. First the node must be cloned and second the position must be tracked as the user moves the mouse to place the new node in the scene. Naturally if the user wanted to Undo this operation, they would expect a single selection of the Undo command would accomplish it. However the process was not a single operation. There was the initial cloning of the node, and then the iterative process of moving the node in the scene, restoring its position, moving it again, restoring it again, etc. Cases like this are handled using methods of theHold named SuperBegin(), and SuperCancel(). These allow the developer to group several restore objects together so that they may be undone via a single selection of Undo. Note that in this example it is only necessary to use SuperBegin() and SuperAccept() because the move was restoring interactively. Normally a developer does NOT need to use these methods even if they have several operations that modify the database. The undo system will automatically register all the restore objects needed as part of the undo object when theHold.Accept() is called and these may be undone using a single UNDO command. - Sample Code: - See the sample program /MAXSDK/SAMPLES/OBJECTS/BONES.CPP. - - - - - Implemented by the System. - - When a developer has used SuperBegin(), this method is used to Accept. This leaves the database in its modified state and registers the restore object with the undo system. This will allow the user to undo the operation. - Sample Code: - See the sample program /MAXSDK/SAMPLES/OBJECTS/BONES.CPP. - - The resource ID of the string to appear in the Edit menu next to Undo or Redo. - - - - Implemented by the System. - - When a developer has used SuperBegin(), this method is used to Accept. This leaves the database in its modified state and registers the restore object with the undo system. This will allow the user to undo the operation. - - The string to appear in the Edit menu next to Undo or Redo. - - - - Implemented by the System. - - When a developer has used SuperBegin(), this method is used to Cancel. This restores the database to its previous state and throws out the restore object. This cancels the operation. - Sample Code: - See the sample program /MAXSDK/SAMPLES/OBJECTS/BONES.CPP. - - - - - Implemented by the System. - - Returns current nesting level of SuperBegin() calls. - - - - - Returns the number of times Put() has been called in the current session of 3ds Max. - - - - - Returns the (approximate) memory usage of this hold. - - - The memory returned is the sum of all 's Size() methods, so the accuracy of this method depends on the accuracy of the restore objects. - Size, in bytes, of the restore objects held by this hold. ! - - - - - Description: - This class provides methods that are called when using the modeless color picker. All methods of this class are virtual. - - - - - This method is called when the user has pressed the mouse button. - Default Implementation: - {} - - - - - This method is called when the user has released the mouse button. - Parameters: - BOOL accept - - TRUE if the mouse button was released normally; FALSE if the user canceled. - Default Implementation: - {} - - - - - This callback proc gets called after the user changes the color. Implement this method to handle interactive updates. - Parameters: - DWORD col - - The new color. - - BOOL buttonUp - - Indicates if the mouse button has been released (is up). TRUE if the button is up; FALSE if it is down. - - - - - This callback proc gets called after the user changes the color. Implement this method to handle interactive updates. - Parameters: - col - - The new color. - - BOOL buttonUp - - Indicates if the mouse button has been released (is up). TRUE if the button is up; FALSE if it is down. - - - - - This callback proc gets called when the color picker is closed: - Parameters: - pos - - The last screen position of the color picker before it was closed. - - - - - This callback proc gets called when user click OK to confirm the color modification. Default Implementation: Do Nothing - - - - - This callback proc gets called when user click Cancel to cancel the color modification. Default Implementation: Do Nothing - - - - - Add an XRef object to the scene. - - - Add an XRef object to the scene from the specified source by object name - Pointer to the newly created XRef , NULL if not successful. - - The source 3ds file - The name of the object - - - - This class is another version of where the matrix is initialized to the identity by the default constructor. - - - - - Provides the components of the Illuminate function to Shaders, Materials and Render Elements. The interface to lights to return the illumination as a set of components. This interface separates the illumination into various components as well as the final result. - - - - - Vector - - - - - N dot L, N and L are normalized - - - - - The contrast applied to N.L... this is equivalent to the diffCoef returned by standard illuminate - - - - - attenuation fraction due to cone(s) or rect falloff - - - - - Attenuation due to distance falloff - - - - - The composite attenuation due to all shadowing objects transparent objects may supply some shadowAtten as well as filterAtten. 0 for all shadow, 1 for all light. light control over basic shading components - - - - - light control over ambitient shading components. 0 = no ambient, 1 = all ambient - - - - - light control over diffuse shading components. 0 = no diffuse, 1 = all diffuse - - - - - light control over specular shading components. 0 = no specular, 1 = all specular - - - - - Raw light color or mixed with light map value, unattenuated by shape, distance, or shadow. - - - - - color modulated by map value, then filtered by a transparent object, raw color * filterAtten, otherwise unattenuated. - - - - - Shadow color, attenuated by shape, distance and shadow fraction - - - - - Ambient color due to light, attenuated, without shadow color - - - - - Diffuse color due to light, attenuated, without shadow color - - - - - Specular color due to light, attenuated, without shadow color - - - - - Equivalent to 4.0 final illumination color, with and without shadows - - - - - Equivalent to finalColor, but with no shadow attenuation applied and no shadow - - - - - The number of user illumination channels, returned by nUserIllumChannels() - - - - - Pointer to shared name array, never destroyed - - - - - The user illumination color array, created and deleted with the class - - - - - of user illumination channels for material - - - - - Returns the name of the index in channels name array - The name of the user channel, NULL if no name specified - - The element in the userIllumNames array - - - - Returns the index associated with a name - The index of the user channel, -1 if name no found - - The channel name in the userIllumNames array - - - - the output illumination color to indexed channel - - The channel index in the userIllumOut array - The illumination color to set - - - - Get the output illumination color of indexed channel - The illumination color to get - - The channel index in the userIllumOut array - - - - It sets to black all the output colors - - - - - Description: - This class allows the Standard material to get the parameters from a plug-in. It also allows the to supply its computed color data back to the Standard material. The Standard material will handle the texturing but it needs to know the color before the texturing is done. - - The shader object holds some raw parameters. But these parameters may be textured. So for each pixel that will be shaded, the 3ds Max shade routine asks the shader to fill in the raw values. Then it applies the texture over the top of any of the values which are textured. - Data Members: - Shader* pShader; - - This parameter is available in release 4.0 and later only. - - A pointer to the shader. - - Mtl* pMtl; - - This parameter is available in release 4.0 and later only. - - A pointer to the material being shaded or NULL if it's a background. - - channels[32]; - - A color channel for each of the possible parameters that may be textured. Note that these channels don't have specific meanings. They are defined by each . The tells the Standard material what data is in these channels using its ChannelType() and StdIDToChannel() methods. - - float falloffOpac; - - Shaders using standard opacity can ignore this data member. This is available for certain Shaders which don't use the standard 3ds Max transparency equation. This allows these Shaders to simulate the 3ds Max version. This is the pre-computed textured opacity with standard falloff applied. The value here is pre-computed to consider all the standard opacity settings of falloff direction, etc. The standard transparency computation then uses this after shading. So a shader could modify this value if it wanted to to affect the transparency. - - Note: The regular opacity can be obtained from the channel data. - - float kR; - - This value is used when there is a reflection and an atmosphere present. Normally if there is no atmosphere (for instance no Fog in the scene) then the transparency of the reflection is 100% (it is unaffected). However, if there is an atmosphere present it will impart some level of opacity. This opacity (alpha value) is not available via the reflection color. Thus this data member is here to provide this opacity information to the . - - This value is the alpha which is returned by the reflection query that has the transparency of the atmosphere contained within it, which is then multiplied by the Amount spinner. This can then be used either by the or by the standard handling for reflection maps. - - ULONG hasComponents; - - These are the bits for the active components of bump, reflection, refraction and opacity mapping. If the bit is set that component is active. This provides a quick way for a to check if they're used (as opposed to looking through the channels array searching for these channel types). - - HAS_BUMPS - If bump mapping is present this is set. - - HAS_REFLECT - If there is any kind of reflection (raytraced, etc) then this is set. - - HAS_REFRACT - If there is any kind of refraction then this is set.. - - HAS_OPACITY - If opacity mapping is used this is set. - - HAS_REFLECT_MAP - If there is a reflection map only this is set. This is used by the Strauss shader for example. If it sees a reflection map present it dims the diffuse channel. - - HAS_REFRACT_MAP - If there is a refraction map only then this is set. - - ULONG stdParams; - - The standard parameter bits. See Standard Parameter flags. This is filled in by the Standard material. - - ambIllumOut; - - This is the ambient output from the Illum() method. - - diffIllumOut; - - This is the diffuse output from the Illum() method. - - transIllumOut; - - This is the transparency output from the Illum() method. - - selfIllumOut; - - This is the self illumination output from the Illum() method. - - specIllumOut; - - This is the specular illumination output from the Illum() method. - - reflIllumOut; - - This is the reflection output from the Illum() method. Certain shaders may wish to store the reflection output here (as opposed to providing it in the channels array). This is the '"raw " color from the direction of reflection (unattenuated). Some combiner implementations (Shader::CombineComponents())can get the reflection data here, others may get it from the channels. - - float diffIllumIntens; - - Used only by reflection dimming, intensity of diffIllum prior to color multiply. - - float finalAttenuation; - - The final attenuation for combining components. - - float finalOpac; - - This is the final opacity value used for combining components together in Shader::CombineComponents(). - - finalC; - - This is the final output color that the Shader::CombineComponents() composites together. - - finalT; - - This is the final transparency color output. - - - - - This method is called by the Standard material prior to calling the Illum() method of the . It sets to black all the output colors: - - ambIllumOut=diffIllumOut=transIllumOut=selfIllumOut= - - (0.0f, 0.0f, 0.0f); - - - - - Description: - This class represents the image file (*.bmp, *.tga, etc.) and is available through the built-in type instance imageFileDropType. - - - - - Description: - Image processing filter plug-ins are derived from . This class has virtual methods the developer implements to provide information about the plug-in version, and description. The developer also implements the Capability() method to indicate the properties of the plug-in such as if it is a one pass filter or compositor, and whether it has a control dialog to be displayed. - - The Render() method is the one that actually alters the source image to perform the work of the application. - - Filter plug-ins have access to several bitmaps associated with the video post data stream. All filter plug-ins will have at least a pointer to data member srcmap. This is Video Post's main image pipeline. Composition and transition (layer) filters will also receive a second bitmap (frgmap) which should be composited above the main bitmap (srcmap). If mskmap is not NULL, it will contain a pointer to a grayscale image to be used as a mask for the process. Note that developers should not delete these bitmaps as they are maintained by 3ds Max. - - If a plug-in is both a filter and a compositor, the plug-in can tell if it is running as a filter when the frgmap pointer is NULL. - - Note: If changes are made to an plug-in, the system will not automatically put up the 'The scene has been modified. Do you want to save your changes?' dialog if the user attempts to exit without saving. So that your plug-in does not go unsaved, you should call the following global function if you make changes. This will indicate to the system that the save requester needs to be brought up: - - void SetSaveRequired(int b=TRUE); - - Sets the 'save dirty bit'. This will indicate to the system that the save requester needs to be presented to the user. - Data Members: - protected: - - BOOL interactive; - - This data member is available in release 2.0 and later only. - - TRUE if the setup dialog is interactive; otherwise FALSE. - - HWND vpSetuphWnd; - - The window handle of the video post setup dialog. - - HWND vphWnd; - - The window handle of the Video Post dialog. - - HWND dlghWnd; - - The window handle of the filter's setup dialogue when in "Interactive" mode. - - *srcmap - - The Source (background). Note: The Video Post output resolution may be retrieved using this pointer. The width is srcmap->Width() and the height is srcmap->Height(). - - *mskmap - - The Image Mask (for grayscale masking). This bitmap is at the Video Post output resolution size when the developer needs to access it in the Render() method. - - *frgmap - - The Foreground (for layering/transitions). This bitmap is at the Video Post output resolution size when the developer needs to access it in the Render() method. - - *ifi - - A pointer to an instance of the class that provides information about this filter and the video post queue. - - timeChange; - - This data member is available in release 2.0 and later only. - - This class maintains this time change object so it may send FLT_TIMECHANGED messages. - - UndoNotify* undonotify; - - This data member is available in release 2.0 and later only. - - Points to an instance of the class that can be used so an plug-in can get notified on a change to its Track Node. - - - - - Returns an ASCII description of the filter plug-in (i.e. "ConvolutionFilter"). - - - - - Returns the name of the plug-in's author. - - - - - Implemented by the Plug-In - - Returns the plug-in ASCII Copyright message. - - - - - Returns the plug-in version number * 100 (i.e. v3.01 = 301). - - - - - This method returns a set of flags that describe the capabilities of this filter plug-in. These capabilities indicate if the plug-in is a filter, compositor, or has a control panel. To create a flag, "OR" the capabilities together, ie. (IMGFLT_CONTROL | IMGFLT_COMPOSITOR). Note: It is valid for a plug-in to both a Filter and a Compositor. If both flags are set, the user will be able to select it from both the Filter list and from the Compositor list. The plug-in will know it is running as a filter when the foreground map pointer, frgmap, is NULL. - See ImageFilter Capability Flags. - - - - - This method is called by the system to display the About Box of the plug-in. This dialog is mandatory so the developer must implement this method. - Parameters: - HWND hWnd - - The parent window handle of the dialog. - - - - - This method is called by the system to display the control panel for the plug-in. This control panel is optional and its existence should be flagged by the capability flag returned from Capability() (IMGFLT_CONTROL). If a plug-in does not have a control panel, don't implement this method and let it default to FALSE. - Parameters: - HWND hWnd - - The parent window handle of the dialog. - TRUE if the user selects OK to exit the dialog, and FALSE if the user selects Cancel. - Default Implementation: - { return FALSE; } - - - - - This is the method the plug-in implements to alter the image. This method performs the work of the filter or compositor. - Parameters: - HWND hWnd - - The window handle to which the plug-in will be sending progress and abort check messages. - TRUE if the render was completed; otherwise FALSE (error or canceled by user). - Sample Code: - Below is an example of a render loop through each horizontal band of the image demonstrating the posting of messages. At the start of the loop the progress and check abort messages are sent. The progress message updates the Execute Video Post dialog with how much of the image has been processed. The check abort message allows the plug-in to detect if the user has canceled the operation. - - Messages are sent via the Window API SendMessage() function. See ImageFilter-Related Messages. - - - - - Implemented by the System. - - This method returns an interface pointer for calling methods implemented in 3ds Max. See Class . - - - - - This method is used internally. - - - - - This method is used internally. - - - - - The system will call this method to determine the buffer size required by the plug-in. The plug-in can save its parameter block in this buffer by implementing the SaveConfigure() method. - The number of bytes required by the plug-in's parameter block. - Default Implementation: - { return 0; } - - - - - This method will be called so the plug-in can load its parameter block. Memory management is performed by 3ds Max using standard LocalAlloc() and LocalFree(). - Parameters: - void *ptr - - A pre-allocated buffer. - TRUE if the data was loaded OK; otherwise FALSE. - Default Implementation: - { return (FALSE) }; - - - - - This method will be called so the plug-in can transfer its parameter block to the host. - Parameters: - void *ptr - - A pre-allocated buffer the plug-in may write to. - TRUE if the data was saved OK; otherwise FALSE. - Default Implementation: - { return (FALSE); } - - - - - Implemented by the System. - - This method provides a preview facility for use by plug-ins. This can be used by plug-ins that want to have a preview bitmap while displaying a control dialog. - - Note: When you add a new Video Post event, an event object is created and it is added to the event queue when you hit the OK button. However, because the event is added to the queue only when you exit the dialogue, you cannot create a preview at that stage. Later, when you "Edit" the event, it is part of the queue and you can create a preview. Internally, there is no way for 3ds Max to tell if the "Setup" button was called from an "Add" event or from an "Edit" event. Plug-In developers can tell if they are in the "Add" event mode by looking at the return value from this method. It will be FALSE if in "Add" mode since the call will fail. - Parameters: - HWND hWnd - - This window handle will receive progress notification messages. The messages are defined in both BITMAP.H and FILTERS.H: - - FLT_PROGRESS - - wParam: Current - - lParam: Total - - FLT_CHECKABORT - - wParam: 0 - - lParam: BOOL* - - FLT_TEXTMSG - - wParam: 0 - - lParam: LPCMSTR - - BMM_PROGRESS - - wParam: Current - - lParam: Total - - BMM_CHECKABORT - - wParam: 0 - - lParam: *BOOL - - BMM_TEXTMSG - - wParam: 0 - - lParam: LPCMSTR - - **back - - A pointer to the Pointer (the Background). If the pointer is NULL, a new bitmap is created using the given dimensions. This pointer must be NULL the first time this function is called as the bitmap must be created by Video Post. Once this function is called and a bitmap is returned, it is OK to call it again using this map. In this case, Video Post will simply use it instead of creating a new one. Note: You must NOT delete the bitmap when done - Video Post will take care of it. - - int frame - - The desired frame in TICKS. Note that this is the position of the Video Post frame slider (in TICKS) and not the main 3ds Max frame slider. See the Advanced Topics section on ~{ Time Functions }~ for details on ticks. - - int width - - The desired width of the preview. - - int height - - The desired height of the preview. - - aspect - - The desired aspect ratio of the preview. - - **fore = NULL - - A pointer to the Pointer (the Foreground). For layer plug-ins, this points to the foreground image. This is only valid if flag is set to PREVIEW_BEFORE. In this case back will hold Video Post main queue and fore will have the foreground image to be composited. This is useful if you, a layer plug-in, want to collect the images and run a realtime preview. If flag is not PREVIEW_BEFORE, fore will be a NULL pointer indicating there is no bitmap. - - DWORD flag = PREVIEW_UP - - The flag controls how much of the queue to run. The options are: - - PREVIEW_BEFORE - - The queue is run up to the event before the filter calling it. - - PREVIEW_UP - - The queue is run up to the event (filter) calling this function. - - PREVIEW_WHOLE - - The whole queue is run including events after this filter. - TRUE if the creation was successful; otherwise FALSE. - - - - - If a filter wants to work with the G-buffer (geometry/graphics buffer) it implements this method. It is used to indicate what image channels this plug-in requires. Prior to rendering 3ds Max will scan the plug-ins in the chain of events and find out all the channels being requested. At the time the plug-in's Render() method is called, it will have access to these channels. The methods of class may be used to access the channels. - - Note: The generation of these channels should not normally be a default setting for the plug-in. These channels are memory intensive and if the plug-in won't use the channel it should not ask for it. Normally the plug-in would ask the user which channels to use and only then set the proper flags. - See Image (G-Buffer) Channels. - Default Implementation: - { return BMM_CHAN_NONE; } - - - - - Implemented by the System. - - This method may be used to allow a filter's dialog to operate interactively. This means that a user can have the filter's control dialog up and still operate 3ds Max and Track at the same time. This method should be called from the filter's method as part of the WM_INITDIALOG code. - - Note that even though this method can be called safely for any reason, developers should only call it when using animated parameters. It doesn't make sense to use it for filters with non-animated or no parameters. For sample code using this method see /MAXSDK/SAMPLES/POSTFILTERS/NEGATIVE/NEGATIVE.CPP. - Parameters: - HWND hWnd - - The parent window handle. - Sample Code: - - - - - Implemented by the System. - - Returns TRUE if the control dialog is interactive; otherwise FALSE. This means a user can have the filter's control dialog up and still operate 3ds Max and Track at the same time. - - - - - Whenever a filter instance is created or updated (i.e. the user went through the Filter Edit dialog) this method is called. The filter may use it to create or update its node controls. For an example see /MAXSDK/SAMPLES/POSTFILTERS/NEGATIVE/NEGATIVE.CPP. - Default Implementation: - {} - - - - - Implemented by the System. - - This method may be called to create a new Track Node. - - - - - Implemented by the System. - - This method is used to return the Track node for this filter. - - - - - This is called on file load to allow the plugin to version the plugin data. - - The holding the plugin data - The ILoad* if called when loading the from a scene file, NULL otherwise. - - - - Description: - This class provides information to an image filter plug-in. This is information such as state of any masks used, and the various frame ranges for the video post queue. It is analogous to the class in the Manager. - Data Members: - BOOL maskenabled; - - TRUE if the filter has a mask; otherwise FALSE. - - BOOL evCopy; - - This is used internally as a flag indicating this object is a temporary copy, and not the real thing. It is only an issue when filters have Track Nodes. This is only used internally. - - BOOL invertedmask; - - TRUE if the mask is inverted; otherwise FALSE. - - mask; - - The image used as the mask. - - WORD maskflag; - - This is used internally. It indicates what part of the mask image is used to create the grayscale mask. It may be one of the following values: MASK_R, MASK_G, MASK_B, MASK_A, MASK_L, MASK_Z, MASK_MTL_ID, MASK_NODE_ID. - - imgQueue; - - This is a that holds information about the current Video Post main queue image buffer. This can be used to get Video Post's (or the target image's) resolution, etc. - - QueueRange; - - This defines the entire Video Post Queue range. This is the range defined between VP Start Time and VP End Time in the video post user interface. - - ExecutionRange; - - When the queue is executed, this is the range of frames being rendered. - - FilterRange; - - The FilterRange is where this filter starts and ends. - - - - - Returns the name of the filter. - Operators: - - - - - Returns the resource name. - - - - - Assignment operator. - Parameters: - &from - - The source . - - - - - This method is used to return the Track node for this filter. Because Video Post Filter plug-ins have a short life, in other words, they are only loaded when they are actually needed and deleted right after, the Track node information is kept in the class kept by Video Post for each filter event. - - - - - Returns the of the Track node (if any). - - - - - Returns the optional label entered by the user while adding or editing a filter. This label replaces the filter's name in Video Post's tracks in Track for easier identification. This is the name that is entered in the 'Edit Filter Event' dialog Filter Plug-In Label field. The label defaults to Unnamed in which case the Filter's name appears (for example 'Negative'). - - - - - This method is used so dual mode filters can detect what mode they are running in (as a filter or as a compositor). In the 3ds Max 1.x SDK, filters that ran both as filters and layers had no way to determine what mode they were running while in "Setup" mode (in ShowControl()). At run time they would check for a foreground bitmap. If it was NULL, they were to assume they were running as simple filters. Now this method may be used to determine what mode they are running in. - One of the following values: - - FLT_FILTER - - FLT_LAYER - - - - - Description: - This class represents the import file (*.3ds, *.dxf, etc.) and is available through the built-in type instance importFileDropType. - - - - - Description: - Import class. Methods of this class allow the plug-in to create nodes in the scene, create camera and light objects, and create objects by specifying a super class ID and Class ID. Methods are also available to bind target nodes to their Look At nodes. All methods of this class are implemented by the system. - - - - - Creates a new node. Methods of may be used to assign properties to the node. See AddNodeToScene() to add a node to the scene given its pointer. - An pointer that may be used to set properties of the node. - - - - - Redraws the 3ds Max viewports. - - - - - Creates a camera object and returns a pointer to it. The pointer may be used to set the properties of the camera object. - Parameters: - int type - - One of the following values: - - FREE_CAMERA - - TARGETED_CAMERA - - - - - Creates a target object and returns a pointer to it. - - - - - Creates a light object and returns a pointer to it. The pointer may be used to set the properties of the light object. - Parameters: - int type - - One of the following values: - - OMNI_LIGHT - Omnidirectional - - TSPOT_LIGHT - Targeted - - DIR_LIGHT - Directional - - FSPOT_LIGHT - Free - - - - - Creates an object given its Super Class ID and its Class ID. - Parameters: - SClass_ID sclass - - The super class ID of the node to create. - - classid - - The unique class ID of the node to create. - A pointer to the item. - - - - - This method binds a node to a target using a Look At controller. This is typically used with target spotlights and cameras to bind them to their target node. - Parameters: - *laNode - - The node that will have the Look At controller assigned. - - *targNode - - The target node. - Nonzero if successful; otherwise 0. - - - - - Adds a node to the scene given its pointer. - Parameters: - *node - - The node to add to the scene. - - - - - Retrieves the animation range for the node (as an ). - - - - - Sets the current environment map to the specified map. - Parameters: - *txm - - The map to set. - - - - - Sets the ambient light color at the specified time. - Parameters: - TimeValue t - - The time to set the color. - - col - - The light color to set. - - - - - Sets the background color at the specified time. - Parameters: - TimeValue t - - The time to set the color. - - col - - The light color to set. - - - - - Sets the state of the environment 'Use Map' toggle. - Parameters: - BOOL onoff - - TRUE to turn on; FALSE to turn off. - - - - - Adds the specified atmospheric effect to the environment. - Parameters: - *atmos - - The atmospheric effect. See Class . - - - - - This method deletes all existing geometry in the scene. - - - - - Get import drag & drop import information. - Parameters: - POINT& screenLocationOut - - If the import was initiated by a drag & drop operation, the coordinates in the viewport window where the drop occurred. - - - TRUE if the import is a drag & drop operation; FALSE otherwise. - - - - - use of interactive placement after import. - Parameters: - BOOL wantPlacementMode - - Tells 3ds Max whether the importer wants to use the default placement mode, which is entered to finalize the import. Supplying TRUE will cause 3ds Max to enter the interactive placement mode after successful import to place the imported object(s) into the scene (the default behavior). Supplying FALSE lets the import plug-in control the imported object(s) location on a drag & drop. - - - - - Description: - Import Node class. Methods of this class may be used to set various properties of the node. All methods of this class are implemented by the system. - Sample Code: - The following sample code fragment (from /MAXSDK/SAMPLES/IMPEXP/DXFIMP.CPP) demonstrates the use of many of the methods of this class. - - - - - - - Sets the object that this node references. - Parameters: - ObjectHandle obj - - The object to reference. - One of the following values: - - REF_FAIL - - The operation failed. - - REF_SUCCEED - - The operation succeeded. - - - - - Sets the transformation matrix of the node. - Parameters: - TimeValue t - - The time to set the matrix. - - tm - - The new transformation matrix of the node. - - - - - Sets the name of the node. - Parameters: - const MCHAR *newname - - The new name for the node. bool registerForDuplicateNameCheck - - If true the new name for the node will be registered for duplicate node name checking. - - - - - Sets the pivot point of the node. - Parameters: - p - - The pivot point of the node. - - - - - Returns the pointer for the node. - - - - - Description: - This class is passed to Control::InitIKJoints() which is called when importing R4 3DS files that have IK joint data. - Data Members: - BOOL active[3]; - - The joint active settings. Index 0=X, 1=Y, 2=Z. - - BOOL limit[3]; - - The joint limit settings. Index 0=X, 1=Y, 2=Z. - - BOOL ease[3]; - - The joint ease settings. Index 0=X, 1=Y, 2=Z. - - min, max, damping; - - The joint min, max and damping settings. - - - - - Description: - This class is passed to Control::InitIKJoints2() which is called when importing R4 3DS files that have IK joint data. This class contains the added preferredAngle parameter. - Data Members: - preferredAngle; - - The preferred angle. - - DWORD flags; - - Not used (must be 0), reserved for future expansion. - - - - - - - class : public - - - Description: - An extension to Class to support various Spring parameters that are missing in and . It is designed for arguments of type . - - - Data Members: - - - bool springOn[3]; - - The Spring On settings. Index 0=X, 1=Y, 2=Z. - - spring; - - The Spring value - - springTension; - - The Spring Tension value - - - A pointer of can be tested and downcast to via the following two inlines: IsInitJointData3(InitJointData2*) and DowncastToJointData3(InitJointData2*). - - IsInitJointData3(InitJointData2* jd)inline bool - - { - - return (jd->flags & bJointData3); - - } - - DowncastToJointData3(InitJointData2* jd)inline InitJointData3* - - { - - return IsInitJointData3(jd) ? (InitJointData3*)jd : NULL; - - } - - - - - Description: - This class provides an interface for calling functions that are exported from the 3ds Max executable. All the methods in this class are implemented by 3ds Max itself. - - Methods are provided for putting up many standard 3ds Max dialogs, working with command modes, working with viewports, controlling the prompt, toolbar and status areas, and working with selection sets. There are also methods for creating objects and nodes in the scene, setting and getting the current time and animation ranges, working with the standard directories of MAX, and many more. See the Method Groups listed below for a breakdown of the various kinds of methods available. Note: When editing in the command panel, a developer gets passed an interface pointer during BeginEditParams(). This pointer is only valid before EndEditParams() is finished. A developer should not hang on to this pointer and call methods on it after EndEditParams() has returned. - - - - - Returns the handle of the font used by MAX. The default font is the same one returned from GetAppHFont(). So if a developer makes a dialog in the rollup page the correct font will be used automatically. - - - - - This method returns the cursor handle for the standard MAX cursors. Use SetCursor() from the Windows API to set the cursor. - Parameters: - int id - - One of the following values: - - SYSCUR_MOVE, SYSCUR_ROTATE, SYSCUR_USCALE, SYSCUR_NUSCALE, - - SYSCUR_SQUASH, SYSCUR_SELECT, SYSCUR_DEFARROW. - The handle of the cursor. - - - - - This method is reserved for future use. - - - - - This method may be called to cause the viewports to be redrawn. - Parameters: - TimeValue t - - The time at which to redraw the viewports. - - DWORD vpFlags=REDRAW_NORMAL - - You may specify one of the following: - - REDRAW_BEGIN - - Call this before you redraw. - - REDRAW_INTERACTIVE - - This allows the view quality to degrade to maintain interactively. - - REDRAW_END - - If during interactive redraw the state degraded, this will redraw the views in the undegraded state. - - REDRAW_NORMAL - - This redraws the views in the undegraded state. - - *change=NULL - - This parameter is not used - always let it default to NULL. - Example: - GetTime(),REDRAW_BEGIN); - - // More code ... - - GetTime(),REDRAW_INTERACTIVE); - - // More code ... - - GetTime(),REDRAW_END); - - - - - This allows you to specify the active viewport. - Parameters: - HWND hwnd - - The handle of the window to activate. - TRUE if the viewport was not previously active; otherwise FALSE. - - - - - Returns the reference of the active MAX viewport. NOTE: if none of the viewports are active, the first viewport of the current view tab is returned - - - - - Calling this method will cause all the viewports to be completely redrawn. Note: This method literally forces everything (every object, every screen rectangle, every view) to be marked invalid and then the whole scene is regenerated. (The individual object pipeline caches are not flushed, however.) So this routine is guaranteed to be slow. - Parameters: - BOOL doDisabled=TRUE - - If TRUE disabled viewports are redrawn; otherwise they are not. - - - - - Turns off scene redraws. - - - In order to increase the speed of certain operations, scene redraw should be turned off temporarily, then once the operation completed, should be turned back on. Scene redraw should be disabled in implementations of the Renderer::Open() method and re-enabled in implementations of Renderer::Close() method. - Calls to DisableSceneRedraw() and EnableSceneRedraw() should be paired up since the system counts the requests for disabling the scene redraw. If several scene disable requests are issued, it takes an equal number of scene enable requests to re-enable the redrawing of the scene. - - - - - Turns on scene redraws. - - - In order to increase the speed of certain operations, scene redraw should be turned off temporarily, then once the operation completed, should be turned back on. Scene redraw should be disabled in implementations of the Renderer::Open() method and re-enabled in implementations of Renderer::Close() method. - Calls to DisableSceneRedraw() and EnableSceneRedraw() should be paired up since the system counts the requests for disabling the scene redraw. If several scene disable requests are issued, it takes an equal number of scene enable requests to re-enable the redrawing of the scene. - - - - - Tells whether the scene redraw is disabled. - - - Call this method to find out whether the scene redraw is disabled. - The count of scene redraw disable requests. This will be positive, if the scene redraw is turned off, and zero or negative if it is turned on. - - - - - This method is used with Extended Viewports (see Class ). It is called when the extended viewport needs to become active. It should be called whenever the user clicks in the non-3D window (so as to deactivate the current 3D window, and redirect commands like the Min/Max toggle to the non-3D viewport window). - Parameters: - HWND hWnd - - The handle of the window which to made active. - - - - - This method is used with Extended Viewports (see Class ). It is called to put up the view type popup menu (for example the right-click menu). It should be called when the user right-clicks in a dead region of the non-3D window. This brings up the view selection menu so that the user can choose to replace the current window with a 3D or other non-3D window without having to go to the Views | Viewport Config dialog directly. - Parameters: - HWND hWnd - - The handle of the window the menu is to appear in. - - POINT pt - - The point at which the menu is put up. - Sample Code: - - - - - This method returns nonzero if the construction plane is 'head on' in the current viewport. For example if the construction plane was XY and you were looking from the Front view, this method would return nonzero. This is used for example during object creation because this process doesn't work very well when the view is 'head on'. - Nonzero if the construction plane is 'head on' in the current viewport; otherwise 0. - - For use with extended views: - make the extended viewport active (set on mouse click, for example) -put up the view type popup menu (put up on right-click, for example) - - - - - This method may be called to retrieve a value that describes the configuration of the MAX viewports. - The viewport layout configuration. The list below uses the following syntax: # is the total number of viewports. - One of the following values. Note: The bottom nibble (4-bits) is the total number of views. You may use the constant VP_NUM_VIEWS_MASK to mask off the 4 bits that contains the total number of viewports. - - - - - Returns TRUE if the current viewport is full screen; otherwise FALSE. - - - - - This method will maximize (set to a single full screen view) or minimize the current viewport. - Parameters: - BOOL max - - If TRUE the viewport is maximized; otherwise it is minimized. - - - - - This method performs a zoom extents on the viewport(s). This fills the viewport(s) with the objects of the scene. - Parameters: - BOOL doAll - - If TRUE all the viewports are zoomed to their extents; otherwise just the current viewport is. - - BOOL skipPersp=FALSE - - If TRUE perspective viewports are not altered; otherwise these views are zoomed to their extents as well. - - - - - This method allows you to zoom the current or selected viewport to a bounding region. - Parameters: - BOOL doAll - - This flag determines whether only the selected or all viewports get zoomed. TRUE for all, FALSE for selected only. - - box - - The bounding region to zoom to. - - - - - This method allows you to register a window that can appear in a viewport. - Parameters: - *vw - - The pointer to the view window to register. - TRUE if successful, otherwise FALSE. - - - - - This method allows you to unregister a window that can appear in a viewport. - Parameters: - *vw - - The pointer to the view window to unregister. - TRUE if successful, otherwise FALSE. - - - - - Returns this interface pointer cast as a pointer. - - - - - Returns this interface pointer cast as a pointer. - - - - - Returns the window handle of 3ds Max. - - - - - This method will draw the active view (if it is a camera view with a multi-pass effect enabled) with that effect active. - TRUE if the active view is a camera view with a multi-pass effect enabled, FALSE otherwise. - - - - - This method is called to open the current renderer. It must be opened before frames can be rendered. Either camNode or view must be non-NULL, but not both. Remember to close the renderer when you are done (using CloseCurRenderer()). - Parameters: - *camNode - - A pointer to the camera node to render, or NULL if a viewport should be rendered. - - *view - - A pointer to the view to render, or NULL if the camera should be rendered. - - RENDTYPE_NORMALRendType t = - - This provides an optional way to specify the view when opening the renderer. This specifies the type of render. - - int w=0 - - This specifies the width of the rendering. - - int h=0 - - This specifies the height of the rendering. - Nonzero indicates success; failure is zero. - - - - - This method is called to open the current renderer. It provides an optional way to specify the view when opening. - Parameters: - *vpar - - This class describes the properties of a view that is being rendered. See Class . - - RENDTYPE_NORMALRendType t = - - This provides an optional way to specify the view when opening the renderer. This specifies the type of render. - - int w=0 - - This specifies the width of the rendering. - - int h=0 - - This specifies the height of the rendering. - Nonzero indicates success; failure is 0. - - - - - This method is called to close the renderer. The renderer must be closed when you are finished with it. - - - - - This method is called to render a frame to the given bitmap. The renderer uses the width, height, and aspect ratio of the specified bitmap to control the size of the rendered image. - Parameters: - TimeValue t - - The time to render the image. - - *bm - - The bitmap to render to. This bitmap defines the size and aspect ratio of the render. See Class . - - *prog=NULL - - The is an optional callback. See Class . - - float frameDur = 1.0f - - This parameter should always be set to 1.0. - - *vp=NULL - - This parameter allows you to specify a different view transformation on each render call. For instance, you can render a given scene at a given time from many different viewpoints, without calling Render::Open() for each one. - - RECT *regionRect = NULL - - This value, if passed, defines the region to be rendered. This only works for RENDTYPE_REGION and RENDTYPE_REGIONCROP. - The result of the render - Nonzero if success; otherwise 0. - - - - - This method creates a default scanline renderer. This renderer must be deleted by calling IScanRenderer::DeleteThis(). - A pointer to a new object. - - - - - Registers a call back object that gets called every time the viewports are redrawn. The proc() method is called after the views are finished redrawing. - Parameters: - *cb - - Points to the callback object whose proc() method is called when the viewports are redrawn. See Class . - - - - - Un-registers the viewport redraw callback. - Parameters: - *cb - - Points to the callback object to un-register. See Class . - - - - - - Registers a call back object that gets called to filter the selection of nodes. - Parameters: - *cb - - Points to the callback object to register. See Class . - - - - - Un-registers the select filter callback. - Parameters: - *cb - - Points to the callback object to un-register. See Class . - - - - - Registers a call back object that gets called to filter the display of nodes. - - - Parameters: - *cb - - Points to the callback object to register. See Class . - - - - - - Un-registers the display filter callback. - Parameters: - *cb - - Points to the callback object to un-register. See Class . - - - - - Registers a callback object that will get called any time the user changes the reference coordinate system by: - - Changing the transform coordinate system drop-down menu. - - Changing the state of the transform center fly-off. - - Changing X, Y, Z, XY, YZ, ZX constraint buttons/fly-off. - - Using an accelerator or anything else that changes the above. - Parameters: - *cb - - Points to the callback to register. See . - - - - - Un-registers the axis change callback. - Parameters: - *cb - - Points to the callback to un-register. See . - - - - - Registers a callback object that will get called every time the current animation time is changed. - Parameters: - *tc - - Points to the callback object to register. See Class . - - - - - This method un-registers the time change callback. - Parameters: - *tc - - Points to the callback object to un-register. See Class . - - - - - Register a callback object that will get called when the user changes the command mode. - Parameters: - *cb - - Points to the callback object to register. See Class . - - - - - Un-registers the command mode change callback object. - Parameters: - *cb - - Points to the callback object to un-register. See Class . - - - - - Registers a whose Display() method will be called to allow a plug-in to draw in the MAX viewports. - Parameters: - BOOL preScene - - If TRUE the callback will be called before objects are rendered (typically, but not always); if FALSE the callback is called after the objects are rendered. - - In some cases redrawing the viewports may take two passes; once to re-render the background plane and once to re-render the foreground plane. In this case the order of events would be: - - Call pre callbacks - - Render scene - - Call post callbacks - - Call pre callbacks - - Render scene - - Call post callbacks - - The two calls to callbacks in the middle are neither pre nor post callbacks. However you could also look at this as two separate redraws. - - *cb - - Points to the callback object. See Class . - - - - - Call this method to un-register the viewport display callback object. - Parameters: - BOOL preScene - - If TRUE the callback will be called before object are rendered (typically, but not always); if FALSE the callback is called after the objects are rendered. - - *cb - - Points to the callback object. See Class . - - - - - This method is called to inform MAX that the viewport callback has changed. This is similar to when an object that is part of the reference hierarchy changes and it needs to call NotifyDependents() with the message REFMSG_CHANGE to inform the items that depend on it. In a sense a is like an object in the scene in that it has a Display() method that is called. However, the callback is not actually an object that is part of the reference hierarchy so it cannot send a REFMSG_CHANGE message when it changes. So this method provides the equivalent functionality. If the callback changes this method needs to be called. - - To understand why this is needed consider that if a plug-in called RedrawViews() five times in a row, the viewports may be redrawn the first time (if something has changed), but the next four calls won't do anything. This is because MAX maintains some flags that indicate if things have changed or not and these flags are reset on the first redraw to indicate that everything is up to date. Therefore, when a changes, it needs to call this method to let MAX know that changes have been made and the viewports indeed need to be redrawn the next time RedrawViews() is called. - Parameters: - BOOL preScene - - If TRUE the callback will be called before objects are rendered (typically, but not always); if FALSE the callback is called after the objects are rendered. - - *cb - - Points to the callback object. See Class . - - - - - Registers a whose Exit() method will be called when MAX is about to exit. The return value from the callback allows the plug-in to decide if MAX exits or not. - Parameters: - *cb - - Points to the callback object. See Class . - - - - - Un-registers the exit callback so it's no longer called. - Parameters: - *cb - - Points to the callback object. See Class . - - - - - This method brings up the track view pick dialog. - - - Parameters: - HWND hParent - - The handle of the parent window. - - *res - - The item chosen by the user. See Class - - *filter=NULL - - The call back object to filter selection in the track view. See Class . - - DWORD pickTrackFlags=0 - - See Track View Picking Flags IDs for a list of possible flags. - TRUE if the user selected OK to exit the dialog; otherwise FALSE. - Sample Code: - This code brings up the Track Pick Dialog and filters the input to MAX's controllers. After the controller is selected GetValue() is called on it. - - - - - - - This methods brings up a dialog that allows one to select multiple tracks. This method works much like the TrackViewPickDlg method above except it is passed a pointer to a table of a items instead. - - - Parameters: - HWND hParent - - The handle of the parent window. - - > *res - - This is a table (See Class ) of items chosen by the user. See Class . - - *filter=NULL - - The call back object to filter selection in the track view. See Class . - - DWORD pickTrackFlags=0 - - See Track View Picking Flags IDs for a list of possible flags. - - - - - This method is called to put up the standard MAX Hit By dialog. - - If the callback is NULL this method does a standard select by name. The nodes chosen by the user are selected if the user selects 'Select' from the dialog to exit. Use Interface::GetSelNodeCount() and GetSelNode(i) to retrieve the results. - - - Parameters: - *hbncb=NULL - - Points to the callback object. See Class . Developers should delete this callback when done. - TRUE if the user selects 'Select' from the dialog; otherwise FALSE. - - - - - This methods puts up the Choose Directory dialog box to allow the user to select a directory. The chosen directory including the drive and path is stored in dir. - - - Parameters: - HWND hWnd - - The parent window handle. - - MCHAR *title - - The title in the dialog box. - - MCHAR *dir - - The chosen directory is stored here. This points to an empty string on cancel. - - MCHAR *desc=NULL - - The string to go into the Label field of the dialog. This string may be changed by the user and is returned here. - - - - - This brings up the standard Exclude / Include dialog box used for light exclusion / inclusion lists. - - - Parameters: - *nl - - If the user selects OK, this is the list of names chosen by the user. See Class . - - BOOL doShadows=TRUE - - The shadows switch. - Nonzero if the user selected OK to exit the dialog; otherwise 0. - - - - - This method will convert a to an (the new format for Exclusion lists). - Parameters: - *nt - - A pointer to the name table. - - *excList - - A pointer to the resulting exclusion list. - - - - - This method brings up the / Map Browser dialog box. - - Parameters: - HWND hParent - - The parent window handle. - - DWORD vflags - - See Material Browser FlagsBOOL &newMat - - TRUE if the user has selected a new item; otherwise FALSE. If TRUE it is safe to modify this item. If FALSE the item may be an instance and a developer should not modify this as other materials may be using this same item. - - BOOL &cancel - - TRUE if the user canceled the dialog; otherwise FALSE. - If cancel is FALSE, the item chosen by the user is returned. See Class . - - - - - Puts the specified material into the material editor. The material is put to the specified slot, or if -1 is passed, a dialog is presented which allows the user to choose a sample slot for the material. - - - Parameters: - *mb - - The material to put to the material editor. - - int slot=-1 - - The Materials Editor slot number (a value in the range 0 to 23). If a slot number is specified, then this method will replace that material in the Materials Editor without user interaction. If -1 is passed (the default) then the function brings up the put dialog. - - - - - This method brings up the standard MAX object color picker dialog. - - - Parameters: - HWND hWnd - - The parent window handle. - - DWORD &col - - If the user picks a color then this will be set to the chosen color. This is stored in a 32 bit format, with the high order 8 bits as 0's, the next 8 bits as the Blue amount, the next 8 bits as the Green amount, and the low order 8 bits as the Red amount (0x00BBGGRR). See . - TRUE if the user picks a color and FALSE if the user cancels the dialog. - - - - - This method puts up the dialog to let the user configure the bitmap loading paths. - - - Nonzero on user selecting OK, zero on Cancel. - - - - - Puts up the space array dialog. If the callback is NULL it just does the standard space array tool. - - - Parameters: - *sacb=NULL - - The callback. See Class . - Returns TRUE if the user OKs the dialog, otherwise FALSE. - - - - - This method pushes the specified command mode on the stack. Typically this is used by developers handling their own creation using ClassDesc::BeginCreate(). See Class for more details. - - Note: This method works as documented but a developer may not want to use it. The problem is that other modes can be pushed on the stack (such as viewport transformation modes) and it becomes complicated to track when it is OK to pop your mode. See the methods below for alternatives (such as SetCommandMode). - Parameters: - *m - - A pointer to the command mode to push. - - - - - Pops the command mode off the top of the stack. - - - - - Returns the current mode on the top of the stack. - - - - - This is the typical method called by the developer to handle mouse interaction. It allows the developer to set the command mode to one of the standard command modes. For example: CID_OBJMOVE, CID_OBJROTATE, CID_OBJSCALE, CID_OBJUSCALE, CID_OBJSQUASH, CID_OBJSELECT, etc. - Parameters: - int cid - - The index of the command mode to set. See Standard Command Modes to review the full list. - - - - - Allows the developer to push one of the standard command modes on the command stack. For example: CID_OBJMOVE, CID_OBJROTATE, CID_OBJSCALE, CID_OBJUSCALE, CID_OBJSQUASH, CID_OBJSELECT, etc. - Parameters: - int cid - - The index of the command mode to set. See Standard Command Modes to review the full list. - - - - - Removes the specified command mode from the stack. This method pops items off the command mode stack up to and including the specified mode. The top item in the stack is then set as the active command mode. As usual, ExitMode() is called on the specified mode before it is popped and EnterMode() is called on the newly active mode. - Parameters: - *m - - Points to the command mode to remove. - - - - - If the developer sets or pushes a command mode, this method should be called when the developer is done with the mode to ensure that it is no longer anywhere in the stack. If the mode is already deleted this method does nothing. - - Note: It is normal for a developer to set the 'Select and Move' command mode to be the active one if their mode was at the top of the stack and is being deleted. For instance: - - ip->SetStdCommandMode(CID_OBJMOVE); - - ip->DeleteMode(&myCMode); - Parameters: - *m - - The command mode to delete. - - - - - Returns the number of command modes in the command mode stack. - - - - - Returns a pointer to the command mode at the specified position in the command mode stack. A developer may use this to determine if their command mode is in the stack. - Parameters: - int entry - - The index into the command mode stack of the entry to get. Pass 0 to get the current command mode. - - - - - Pushes a prompt to display on the prompt stack. - Parameters: - MCHAR *s - - The string to display. - - - - - Pops a displayed string off the prompt stack. The previous prompt will be restored. - - - - - Replaces the string on the top of the prompt stack. - Parameters: - MCHAR *s - - The string to display. - - - - - Displays the string passed for the duration passed. After the time elapses, the string is popped from the stack. This may be used to put up a temporary error message for example. - Parameters: - MCHAR *s - - The string to display temporarily. - - int msec=1000 - - The duration in milliseconds to display the string. - - - - - Removes the temporary prompt immediately. - - - - - Disables mouse tracking and display of coordinates to the X, Y, Z status boxes. Typically a plug-in would disable mouse tracking on mouse down and enable it on mouse up. - - - - - Enables mouse tracking and display of coordinates to the X, Y, Z status boxes. Typically a plug-in would disable mouse tracking on mouse down and enable it on mouse up. - - - - - Displays the point passed using the format passed in the X, Y, Z status boxes. - Parameters: - xyz - - The point to be displayed. - - int type - - The format of the point: - - STATUS_UNIVERSE - - Current system units. - - STATUS_SCALE - - 0=0%, 1=100%. - - STATUS_ANGLE - - Degrees. - - STATUS_OTHER - - Straight floating point value. - - - - - This method will convert the specified angle axis for status display. - Parameters: - aa - - The angle axis to convert and display. - - - - - Displays a progress bar in the status panel with a cancel button next to the progress bar. To represent progress of a task that can't be cancelled, use other version of ProgressStart(). When progress bar is up, user can't interact with any UI except cancel button. This method must be called from the main thread. - Note: It is not possible to use the progress bar APIs in the create or modify branches of the command panel. In the create or modify branch of the command panel, EndEditParams() gets called from this method. This is because most of MAX is "shut down" during a progress operation. For example, it is not appropriate for users to be moving objects during an IK calculation, or changing the camera lens while a preview is being created (all these operations use ProgressStart() API). It is for this same reason that Transform Type-in, Medit, Track and Video Post windows are hidden during a progress operation. Since EndEditParams() is called, the pointer a plug-in maintains is no longer valid after the operation is started. This method is useful for Utility plug-ins, and Import/Export plug-ins however. - true when progress mode was entered successfully, false otherwise - Sample Code: - This code demonstrates the use of ProgressStart(), ProgressEnd(), GetCancel() and SetCancel() APIs. There are two ways to use the APIs: - - : Identifies the task currently in progress. This is visible for the duration of the task. - : Unused parameter. - : Pointer to a function with this signature: . Pointer can be null. This function is always executed in the main thread. If not null, this function is called with argument passed at the end of . - : Argument passed to function . Can be null - - - - Similar to other ProgressStart() API. This uses the same logic as passing nullptr to fn and arg in other version Use this version with allowCancel = false to show progress of tasks that can't be cancelled. - true when progress mode was entered successfully, false otherwise. - - : Identifies the task currently in progress. This is visible for the duration of the task. - : If , cancel button appears next to progress bar. Hit cancel button or press ESC key to set cancel status to true If , no cancel button appears and ESC key presses are ignored. - - - - This method updates the progress bar. After ProgressStart() is called, this method should be called periodically to report progress. - - : Percentage completed (0 to 100). This causes the progress bar to move. - : If , percentage appears next to progress bar. - : of the current step of the operation. This is displayed next to progress bar. For example, this might change from "Extruding" to "Capping" to "Welding". - - - - This method removes the progress bar and frees the memory that was allocated internally to handle the processing. - - - - - This method returns the progress bar cancel button status. Also see SetCancel() below. - TRUE if the user pressed the cancel button; otherwise FALSE. - - - - - This method is used to render a preview image (or animation) from the currently active viewport using the real-time (viewport) renderer. - - - Parameters: - *pvp - - This class defines the way the preview is generated (via its data members). If NULL, the parameters from the preview rendering dialog box are used. See Class - - MSTR *filename - - The filename for the preview. If NULL, the filename setting from the preview rendering dialog is used. MSTR *snippet - - The MXS code snippet to execute on each frame. The returned string from snippet is displayed in the rendering output. If this value is NULL, the setting in the preview rendering dialog is used. - - MAXScript::ScriptSource scriptSource - - If snippet is specified, the source of the snippet string. - - - - - This method returns the grid spacing value that the user specifies in the Views / Grid and Snap Settings dialog in the Home Grid tab under Grid Spacing. - - - - - This method returns the value that the user specifies in the Views / Grid and Snap Settings dialog in the Home Grid tab under Major Lines every Nth. - - - - - If grid Auto Activation is on, sets the given node as the active grid object. This is used with grid helper objects to allow them to take effect. This method may also be used to activate the home grid. - - - Parameters: - *node - - The node to set as the active grid object. To activate the home grid pass NULL. - - - - - Returns the active grid node or NULL if the home grid is in use. - - - - - Returns the extended display mode flags. This method provides a mechanism to retrieve some additional information about an object that is more dependent on MAX than on the particular object. For example, when a spotlight is selected, it can use this method to detect that it is the only item selected, and display its cone. It checks this using and extended display mode EXT_DISP_ONLY_SELECTED. See Extended Display Modes. - - - - - Returns the number of milliseconds the user must hold down on a flyoff button before the flyoff is activated. - - - - - Returns the state of the 'crossing' preference for hit testing. - TRUE if crossing selection is on; FALSE if off. - - - - - Sets the state of one of the transform tool buttons. - Parameters: - int button - - The transform tool buttons: - - MOVE_BUTTON - - ROTATE_BUTTON - - NUSCALE_BUTTON - - USCALE_BUTTON - - SQUASH_BUTTON - - SELECT_BUTTON - - PLACE_BUTTON - - BOOL state - - TRUE indicates pressed, FALSE is not pressed. - - - - - Retrieves the state of the axis constraints flyoff. - One of the following axis constraints: - - AXIS_XY - - AXIS_ZX - - AXIS_YZ - - AXIS_X - - AXIS_Y - - AXIS_Z - - - - - Enables or disables the specified axis constraint. - Parameters: - int c - - The axis constraint. You may pass one of the following: - - AXIS_XY - - AXIS_ZX - - AXIS_YZ - - AXIS_X - - AXIS_Y - - AXIS_Z - - BOOL enabled - - TRUE to enable; FALSE to disable. - - - - - Pushes the specified axis constraint. This push/pop mechanism is used so that the appropriate axis mode can be restored after the Transform Gizmo has been used. The Gizmo itself calls this Push method is response to the HitTest with certain flags. - Parameters: - int c - - The axis constraint. You may pass one of the following: - - AXIS_XY - - AXIS_ZX - - AXIS_YZ - - AXIS_X - - AXIS_Y - - AXIS_Z - - - - - Pops the active constraint. After the Transform Gizmo pushes a constraint a selection processor pops it back again after the manipulators are deactivated. - - - - - Retrieves the state of the coordinate system center. - One of the following values: - - ORIGIN_LOCAL - - 's pivot. - - ORIGIN_SELECTION - - Center of selection set (or center of individual object for local or parent space). - - ORIGIN_SYSTEM - - Center of the reference coordinate system. - - - - - Enables or disables the coordinates system center. - Parameters: - BOOL enabled - - TRUE to enable; FALSE to disable. - - - - - Retrieves the reference coordinate system setting. - One of the following reference coordinate systems: - - COORDS_HYBRID - - COORDS_SCREEN - - COORDS_WORLD - - COORDS_PARENT - - COORDS_LOCAL - - COORDS_OBJECT - - COORDS_GIMBAL - - - COORDS_WORKINGPIVOTCOORDS_LOCAL_ALIGNED - - - - - Enables or disables the reference coordinates system. - Parameters: - BOOL enabled - - TRUE to enable; FALSE to disable. - - - - - Normally, with angle snap off, interactive rotation of a node uses a rate of 1/2 degree per pixel. With angle snap on, the angles are snapped to the nearest MAX angle snap value. - - This method may be used when interactive rotation is taking place with the mouse to snap the angle passed to the nearest MAX angle snap value. In this method, the input value/output value snap correspondence is accelerated as the angle grows. This prevents the user from having to move the mouse too much with larger angle values. This is why this method does not return a linear relationship between the input angle and the snapped output angle. - - Note that when angle snap is off, this method just returns the input value unaltered. - - Note for R3: This method formerly was set up with a single parameter, the angle to be snapped. If the angle snap toggle was on, snapping occurred. If not, it did nothing. There were two problems with this: - - 1) A multiplier was applied to the angle input, giving faster interactive results in object rotations, etc. This had a negative effect if you just wanted your input angle snapped to the nearest snap angle. - - 2) It only snapped if the angle snap toggle was on. Sometimes, you might want to snap something to the angle snap value even if the primary toggle was off. - - To remedy these shortcomings, the method has had two parameters added (fastSnap and forceSnap). - Parameters: - float angleIn - - Angle to snap in radians. - - BOOL fastSnap=TRUE - - If TRUE the snapping multiplier is used; if FALSE it is not. - - BOOL forceSnap=FALSE - - If TRUE snapping is used even if the primary angle snap toggle is off. - Angle snapped to the nearest angle snap setting (considering acceleration if specified), in radians, to be used for interactive rotation. - - - - - Given a value in the range 0.0 (0%) to 1.0 (100%) this method snaps the value using the current percentage snap. - Parameters: - float percentIn - - The value to snap. - The snapped value where 0.0 = 0% and 1.0 = 100%. - - - - - Retrieves the snap toggle state. - TRUE if snap is on; FALSE if snap is off. - - - - - Retrieves the current snap type. - One of the following values: - - SNAPMODE_RELATIVE - - SNAPMODE_ABSOLUTE - - - - - the current snap mode. Note that setting the mode to SNAPMODE_ABSOLUTE will fail if the reference coordinate system is not in set to Screen. - Parameters: - int mode - - One of the following values: - - SNAPMODE_RELATIVE - - SNAPMODE_ABSOLUTE - Returns TRUE if succeeded; otherwise FALSE. - - - - - Initialized the structure passed with the current snap settings. - Parameters: - *info - - Points to the structure to initialize. See Structure . - Returns nonzero if snap is on; zero if off. - - - - - This will set the command mode to a standard pick mode. The callback implements hit testing and a method that is called when the user actually picks an item. Note that this method, if called a second time, will cancel the pick mode and put the user into 'Select and Move' mode. This can be used to handle the case where a user clicks on a user interface control a second time to cancel to picking. - - Sample code using this API is available in /MAXSDK/SAMPLES/OBJECTS/MORPHOBJ.CPP. A utility plug-in that uses this API is /MAXSDK/SAMPLES/UTILITIES/ASCIIOUT.CPP. - Parameters: - *pCB - - A pointer to an instance of the class . - - - - - This method is called to make sure there are no pick modes in the command stack. - - - - - This method hit tests the screen position for nodes and returns an pointer if one is hit, NULL otherwise. - Parameters: - HWND hWnd - - Handle of the window to check. - - pt - - Point to check in screen coordinates. - - *filt=NULL - - This callback may be used to filter nodes from being picked. See Class . - pointer of node that was hit; NULL if no node was found. - - - - - This method performs a node level hit test on the specified rectangular region. Use either the ViewExp::GetClosestHit() or ViewExp::GetHit() method to access the result. - Parameters: - *vpt - - The viewport to perform the hit testing. - - *pt - - These points specify the box region to hit test. The first point in the array is the lower left. The second point is the upper right. - - BOOL crossing - - If TRUE Crossing selection is used; otherwise Window selection is used. - - *filt=NULL - - This callback may be used to filter nodes from being picked. See Class . - - - - - This method performs a node level hit test on the specified circular region. Use either the ViewExp::GetClosestHit() or ViewExp::GetHit(int i) method to access the result. - Parameters: - *vpt - - The viewport to perform the hit testing. - - *pt - - These points specify the circular region to hit test. The first point in the array is the center. The second point is a point on the radius. - - BOOL crossing - - If TRUE Crossing selection is used; otherwise Window selection is used. - - *filt=NULL - - This callback may be used to filter nodes from being picked. See Class . - - - - - This method performs a node level hit test on the specified arbitrary polygonal region. Use either the ViewExp::GetClosestHit() or ViewExp::GetHit() method to access the result. - Parameters: - *vpt - - The viewport to perform the hit testing. - - *pt - - These points specify the fence region to hit test. It is assumed the last point is connected to the first point to close the region. The fence knows when it's out of points when it hits a point that has negative x and y values. So, the initializer (-1, -1) added to the bottom of this list signals the end. - - BOOL crossing - - If TRUE Crossing selection is used; otherwise Window selection is used. - - *filt=NULL - - This callback may be used to filter nodes from being picked. See Class . - - - - - This method is used to 'flash' a group of nodes. This is usually used as a confirmation of some operation (for example as an indication of the completion of a pick node operation.) The nodes are briefly erased and then redrawn in the viewport to flash them. - Parameters: - *nodes - - Pointer to the table of nodes to 'flash'. - Sample Code: - - - - - This method registers the sub-object types for a given plug-in object type. See the Advanced Topics section on ~{ sub-object selection }~ for more details. - Parameters: - const MCHAR **types - - of strings listing the sub object levels. The order the strings appear in the array sets the indices used for the sub-object levels. Level 0 is always object level, the first string corresponds to level 1, and the second string corresponds to level 2, etc. In the sample code below, "Center" is level 1 and "Gizmo" is level 2. - - int count - - The number of strings in the array. - - int startIndex=0 - - Specifies which string to display initially in the sub-object type combo box. This is needed because the NURBS object computes its sub-object list dynamically, and sometimes it add a new sub-object level while already in a sub-object level. The default value of zero replicates the original behavior. - Sample Code: - const MCHAR *ptype[] = { _M("Center"), _M("Gizmo") }; - - ip->RegisterSubObjectTypes(ptype, 2); - - - - - Returns the state of the sub object drop-down. - 0 is object level and >= 1 refers to the levels registered by the object using RegisterSubObjectTypes(). The value refers to the order the item appeared in the list. 1 is the first item, 2 is the second, etc. - - - - - Sets the sub-object drop down. This will cause the object being edited to receive a notification that the current sub-object level has changed (via BaseObject::ActivateSubobjSel()). - Parameters: - int level - - The level registered by the object using RegisterSubObjectTypes(). 0 indicates object level. Values greater than 1 refer to the order the items appeared in the list. - - BOOL force = FALSE - - If this parameter is TRUE, this method will set the level even if the current level is the same as the level requested. This is to support objects that change sub-object levels on the fly, for instance NURBS. - - - - - This method returns the number of sub object levels that the currently edited object (or modifier) has. Like the other sub-object related methods in this class, this method will only return a valid answer if the modifier panel is displayed. - - - - - Plug-ins call this method to notify the system that the selection level in the pipeline has changed. The selection level flows up the pipeline so if you change the selection level you affect things later in the pipeline. For example an edit modifier that changes the sub-object level from vertex to object level must call this method after making the change to notify the system. Note that it is only called for modifiers whose sub-object levels propagate up the pipeline. For example, when entering a sub-object level within the Bend modifier, PipeSelLevelChanged() is not called. - - This method should be called from within ActivateSubobjSel() to notify the system that a selection level has changed in the pipeline. Note that calling this method from within ModifyObject() is no good since it involves re-evaluating the pipeline, which will call ModifyObject(), which will the call PipeSelLevelChanged() again, etc. - - - - - Gets the sub-object selection level at the point in the pipeline just before the current place in the history. - Parameters: - &levels - - The sub-object level. This value depends on the object. The only level defined is level 0, which means 'object' level selection. - - - - - This method may be called to perform a sub-object hit test. You may access the number of hits using: vpt->NumSubObjHits(); See Class for a list of the other methods that may be used to examine the results. - Parameters: - TimeValue t - - The time of the hit testing. - - int type - - The hit test type. See Scene and Node Hit Test Types.int crossing - - Nonzero for crossing selection; 0 for normal (window). - - int vflags - - The flags for hit testing. See Scene and Node Hit Testing Flags *p - - Point to check in screen coordinates. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. - Nonzero if the item was hit; otherwise 0. - - - - - A modifier may call this method to add sub-object named selection sets to the named selection set drop down list in the MAX toolbar. This should be done whenever the selection level changes (in the Modifiers BaseObject::ActivateSubobjSel() method). See Class for additional methods associated with sub-object named selection sets. - Parameters: - const MCHAR *set - - The named selection set to add to the list. - - - - - This method clears the named sub-object selection sets from the drop down. - - - - - This method clears the current edit field of the named selection set drop down. - - - - - Sets the edit field of the named selection set drop down to the set whose name is passed. - Parameters: - MCHAR *setName - - The name of the selection set to make current. - - - - - Calling this method tells the system that the named sub-object selection sets have changed and that the drop down needs to be rebuilt. This will cause BaseObject::SetupNamedSelDropDown() to be called on the current item being edited. This is often called inside restore objects that undo changes to the selection set. This causes the system to check if the current item being edited is in sub-object selection mode, and if so, will cause SetupNamedSelDropDown() to be called. Note that restore objects can be invoked at any time and the user may not be in sub-object selection mode (for instance they might be in the Display panel). Restore objects however can simply call this method and the system will figure out if the drop down needs to be updated. - - - - - A modifier may be applied to several objects in the scene. This method retrieves a list of all the ModContexts for the modifier at the current place in the modifier stack. It also gets a list of the nodes the modifier is applied to. For example a modifier may store data into the local data portion of the for each object affected by the modifier. In order to get at this data it needs to get each . - - Note: this method returns only the of the currently selected objects, even if the modifier is applied to several objects. - Parameters: - & list - - A reference to the list of ModContexts. See Class . - - & nodes - - A reference to the table of each of the nodes. See Class . - Example - - - - - Returns a pointer to the object (or modifier) that is currently being edited in the modifier panel. See Class . - - - - - In MAX the space bar freezes the selection set. This keeps the selection set from being inadvertently changed. This method access the status of the selection set frozen state. - TRUE if the selection set is frozen; otherwise FALSE. - - - - - Toggles the selection set to the frozen state. - - - - - Toggles the selection set to the thawed state. - - - - - Selection sets are handled as a virtual array and accessed using an index starting at 0. This method returns a pointer to the 'i-th' node in the current selection set. - Parameters: - int i - - Index of the node in the selection set. - Pointer to the 'i-th' node in the selection set. - - - - - Returns the number of nodes in the selection set. - - - - - This selects the specified node, either adding it to the current selection set, or creating a new selection set with the node. - - Note: A developer should call theHold.Begin() before this method and theHold.Accept() after this call. Otherwise, MAX may crash if the user selects undo after this call has been issued. See the sample code below. Also see ~{ The Undo and Redo System }~ for more details on this system. - Parameters: - *node - - The node to select. - - int clearSel = 1 - - If zero, the node is added to the current selection set. If nonzero, the node replaces the selection set. - Sample Code: - - - - - This method un-selects the specified node. - Parameters: - *node - - The node to deselect. - - - - - This method may be used to select or deselect a group of nodes all at once and optionally redraw the viewports when done. - Parameters: - &nodes - - The Table of nodes to select or deselect. - - BOOL sel - - If TRUE the nodes are selected; otherwise they are deselected. - - BOOL redraw=TRUE - - If TRUE the viewports are redrawn when done; otherwise they are not. - - - - - This method may be used to clear the current selection set and optionally redraw the viewports. - Parameters: - BOOL redraw=TRUE - - If TRUE the viewports are redrawn when done; otherwise they are not. - - - - - This method retrieves the world space bounding box of the current selection set. - Parameters: - TimeValue t - - The time to retrieve the bounding box. - - &box - - The bounding box is returned here. - - - - - This method allows you to clone nodes and node hierarchies. - Parameters: - & nodes - - The node table containing the nodes you wish to clone. - - & offset - - The position offset you wish to apply to the cloned nodes. - - bool expandHierarchies = true - - This determines if children will be cloned in hierarchies. - - CloneType cloneType = NODE_COPY - - The type of cloning you wish to do, which is one of the following; NODE_COPY, NODE_INSTANCE or NODE_REFERENCE. - - INodeTab* resultSource = NULL - - This node table will be filled in with the original nodes to be cloned. The reason for this is that there can be dependencies between nodes that cause other nodes to be added to the list. For example light/camera targets, nodes part of systems, belonging to groups or expanded hierarchies etc. - - INodeTab* resultTarget = NULL - - This node table will be filled in with the new cloned nodes. There is a one to one relationship between the nodes in the resultSource and the resultTraget. - TRUE if the nodes were cloned successfully, otherwise FALSE. Note that with R4.0 the return value will always be TRUE since no actual error checking is undertaken. - - - - - @ - - - - - Sets internal flag, returns old value. - - - the previous quiet mode state - - - to TRUE to indicate that no dialogs should be displayed to user. - - - - The return value from this method should be called before displaying any dialogs. - - - Returns internal flag set by SetQuietMode. - the current quiet mode. - - if TRUE, returns internal flag OR-ed with whether 3ds runs in server , i.e. UI-less mode. If client code needs save the current quiet mode's value in order to restore it later via a call to , it should retrieve it using Interface::GetQuietMode(FALSE). - - - - Query system AutoGrid feature enable state. - - - Returns internal flag set by SetAutoGridEnable. - the current AutoGrid enable state. - - - - - Query system AutoGrid feature state. - - - Returns internal flag set by SetAutoGrid. - the current AutoGrid state. - - - - - This method is called if a modifier wants to temporarily disable any modifiers following it. For example the edit mesh modifier does not let you edit a mesh while other modifiers later in the pipeline are affecting the result so it calls this method to disable the others temporarily. - Parameters: - BOOL enabled - - TRUE is enabled; FALSE is disabled. - - - - - Returns TRUE if the Show End Result button is on (pressed); otherwise FALSE. - - - - - Returns TRUE if the Preserve Selection button is on (pressed); otherwise FALSE. - - - - - Returns a value to indicate which branch of the command panel is currently active. - One of the following values: - - TASK_MODE_CREATE - - TASK_MODE_MODIFY - - TASK_MODE_HIERARCHY - - TASK_MODE_MOTION - - TASK_MODE_DISPLAY - - TASK_MODE_UTILITY - - - - - This method is used to add a rollup page to the command panel. It returns the window handle of the rollup page. - Parameters: - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the messages sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar of the rollup page. - - LPARAM param=0 - - Any specific data to pass along may be stored here. This may be later retrieved using the GetWindowLong() call from the Windows API if it was set in the window using SetWindowLong(). - - For example, at the beginning of the dialog proc do something like: - - BOOL CALLBACK MyDlgProc( - - HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - - MyUtil *u = (MyUtil *)GetWindowLong(hWnd, GWL_USERDATA); - - if (!u && message != WM_INITDIALOG ) return FALSE; - - . . . - - Then inside the code block handling the WM_INITDIALOG message do something like: - - - Then later in the dialog you can access the object passed in - in the case above an instance of MyUtil (using u->). - - DWORD rollUpFlags=0 - - The following flag value may be used: - - APPENDROLL_CLOSED - - Starts the page in the rolled up (closed) state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the rollUpFlags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - Sample Code: - The window handle of the rollup page. - - - - - Removes a rollup page and destroys it. - Parameters: - HWND hRollup - - The window handle of the rollup window. This is the handle returned from AddRollupPage(). - - - - - This replaces an existing rollup with another one and (deletes the original). - Parameters: - HWND hOldRollup - - The window handle of the old rollup. - - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the messages sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar of the rollup page. - - LPARAM param=0 - - Any specific data to pass along may be stored here. - - DWORD flags=0 - - The following flag value may be used: - - APPENDROLL_CLOSED - - Starts the page in the rolled up (closed) state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The window handle of the rollup. - original). This method is currently not being used. - Parameters: - HWND hOldRollup - - The window handle of the old rollup. - - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - DLGTEMPLATE *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the messages sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar of the rollup page. - - LPARAM param=0 - - Any specific data to pass along may be stored here. - - DWORD rollUpFlags=0 - - The following flag value may be used: - - APPENDROLL_CLOSED - - Starts the page in the rolled up (closed) state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the rollUpFlags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The window handle of the rollup. - - - - - This method returns a rollup window interface to the command panel rollup. This interface provides methods for showing and hiding rollups, adding and removing rollup pages, etc. Note: This interface does not need to be released with ReleaseIRollup() as MAX takes care of this when it shuts down. - - See Class . - - - - - This method allows hand cursor scrolling in the command panel when the user clicks and drags the mouse in an unused area of the dialog. When the user mouse-es down in dead area of the command panel, the plug-in should pass mouse messages to this function which will pass them on to the rollup. - - Note: This method is obsolete in MAX 2.0 and later. These messages no longer need to be passed along as this is handled internally. - Parameters: - HWND hDlg - - The window handle of the dialog. - - UINT message - - The message sent to the dialog proc. - - WPARAM wParam - - Passed in to the dialog proc. Pass along to this method. - - LPARAM lParam - - Passed in to the dialog proc. Pass along to this method. - Sample Code: - - - - - Sets the state of the Animate button to enabled or disabled. When disabled the user cannot turn on Animate mode. - - Note: Developers have additional functions available for controlling the state of the animate button. These functions are defined in /MAXSDK/INCLUDE/CONTROL.H. These functions can be used to determine if animating is on or off, or toggle it on and off without affecting the appearance of the Animate button in the user interface. In this way, a user will not be aware anything is happening. See Additional Controller Related Functions for documentation. - Parameters: - BOOL enable - - Pass TRUE to enable the button; FALSE to disable it. - - - - - Returns TRUE if the Animate button is enabled; otherwise FALSE. See the note in the method above as well. - - - - - Turns the animate button (and animate mode) on or off. - Parameters: - BOOL onOff - - TRUE to turn on; FALSE to turn off. - - - - - Returns TRUE is 3ds Max is in progressive mode. See BeginProgressiveMode(). - - - - - Turns on progressive mode for SetNodeTM(). - - In certain situations, a time sequence of matrices is computed and sent to the node via INode::SetNodeTM(TimeValue t, const & tm). If the node employs the standard PRS controller and the rotation is the standard Euler XYZ controller, 3ds Max can achieve better animation results if it computes euler angles at the current frame based on those from the previous frame. Progressive mode tells the Euler controller to derive angles based on the previous frame. It is assumed that in this mode, SetNodeTM() is called in a strictly forward time order. - Usage: - GetCOREInterface(); - - for (t = start_time, t < end_time; t += time_per_frame) { - - node.SetNodeTM(t, tm_at_t); - - } - - GetCOREInterface(); - - To test whether 3ds Max is currently in progressive mode, use: - - GetCOREInterface() )... - - - - - Turns off progressive mode. See BeginProgressiveMode(). - - - - - Returns the current time, i.e. the frame slider position. See the Advanced Topics section on ~{ Time Functions }~ for an overview of time in MAX. - - - - - the current time, updates the frame slider, and optionally redraws the viewports. - Parameters: - TimeValue t - - The time to set as current. - - BOOL redraw=TRUE - - If set to FALSE, the current time will be set to the specified time but the viewports will not be redrawn. - - - - - Returns the current setting of the animation interval. This can be used to get the total number of frames in the animation. Note: The values stored in the interval returned represent ticks not frames. - - - - - Returns the state of the real-time animation playback toggle. - - - - - This method returns the flag controlling which viewports are updated when the animation is played. - TRUE if all the viewports are updated during play; FALSE if only the active viewport is updated. - - - - - Begins animation playback. The animation may be played for all objects, or just the selected ones. - Parameters: - int selOnly=FALSE - - If TRUE only the selected objects are updated as the animation is played; otherwise all objects are. - - - - - Terminates the animation playback. - - - - - Returns TRUE if the animation is currently playing; otherwise FALSE. - - - - - This method returns the state of the "loop" checkbox in the time configuration panel. Note that the loop control is only active when "real time" is selected. - TRUE if loop is on; FALSE if off. - - - - - This method returns your current selected select filter in the toolbar. - - - - - This method returns the number of select filters in the drop down list. - - - - - This method returns the name that appears in the interface for the specified filter. - Parameters: - int index - - The index of the filter. - - - - - This method returns the state of a display filter. - Parameters: - int index - - The index of the display filter that you want to check. - - - - - This method allows you to set the state of a display filter. - Parameters: - int index - - The index of the display filter you wish to set. - - BOOL on - - TRUE for on; FALSE for off. - - - - - This method returns the number of display filters in the display panel. - - - - - This method checks the display filter at index, and sees if the node, class id, and super class id pass the filter check or not. - Parameters: - int index - - The index of the filter - - int sid - - The super class id - - cid - - The class ID - - *node - - The node to check. - TRUE if hidden, otherwise FALSE. - - - - - This method returns the name of the specified filter. - Parameters: - int index - - The index of the filter. - - - - - An item that is doing sub-object hit testing gets to specify what their sub-object axes systems are. For example a mesh may have separate coordinate systems for every face or group of selected faces, while, for instance, a bend modifier has its own axes system for the gizmo. This method gets the axes system for a particular node. Each node may have several axes systems identified by an index. - - See EDITMESH.CPP for an example of use. - Parameters: - *node - - The node to get the axis coordinates system of. - - int subIndex - - The index of the axis system of the node. - - BOOL* local = NULL - - If 'local' is not NULL, it will be set to TRUE if the center of the axis is the pivot point of the node, FALSE otherwise. - The axis system of the node. - take place. - Parameters: - *node - - The object the axis system should be based on. - - int subIndex - - The sub object which the axis system should be based on (the thing the user clicked on). - - BOOL* local = NULL - - If 'local' is not NULL, it will be set to TRUE if the center of the axis is the pivot point of the node, FALSE otherwise. - A matrix representing the axis system that transforms take place in. - - - - - This returns the number of axis tripods in the scene. When transforming multiple sub-objects, in some cases each sub-object is transformed in a different space. - One of the following values: - - NUMAXIS_ZERO - - Nothing to transform. - - NUMAXIS_ALL - - Use only one axis. - - NUMAXIS_INDIVIDUAL - - Do all, one at a time. - - - - - This method locks axis tripods so that they will not be updated. - Parameters: - BOOL onOff - - TRUE to lock; FALSE to unlock. - - - - - This method returns TRUE if axis tripods are locked. - - - - - Registers a dialog window so IsDialogMessage() gets called for it. This is not required if you add rollup pages to the command panel as this is done automatically, however if you create a floating, modeless dialog you must call this method. - - Important Note: ALL modeless dialogs in MAX must be registered to the application window with this method so that it, and any sub dialogs, will behave as they should. - Parameters: - HWND hDlg - - The window handle of the dialog. - - - - - Un-registers a dialog window so IsDialogMessage() is no longer called for it. - Parameters: - HWND hDlg - - The window handle of the dialog. - Nonzero if successful; otherwise 0. - - - - - Returns a pointer to the Action Manager interface class. The action manager is used to manage ActionTables which plug-ins can use to export operations that can be tied to UI elements like keyboard shortcuts, menus and toolbars. See Class . - - - - - Returns a pointer to the main manager for customizable menus. See Class . - - - - - Returns a pointer to the main manager for customizable quad menus. See Class . - - - - - Registers a callback invoked when the user presses the Delete Key. This allows the developer to override the default processing of the Delete Key. - Parameters: - *user - - Pointer to an instance of the class. - Sample Code: - See /MAXSDK/SAMPLES/MODIFIERS/EDITSPL.CPP. - - - - - Un-registers a Delete Key callback. - Parameters: - *user - - Pointer to an instance of the class. - - - - - Generates node names that are unique within the current scene. Given a name, this method will modify it to ensure it's unique. It does this by appending a unique numeric suffix to the end of the name. Notes: - Parameters: - MSTR &name - - The name to make unique. Any existent numeric suffix is stripped before the name is made unique. - - - - - Returns a class used for efficiently creating unique names. To use it, do the following: - - - An instance of class initialized at a given time with root node names is best used right after initialization to create several nodes. If the same instance is to be used several times, it's best to re-initialize it with the current root node names before it's used again. - Interface::MakeNameUnique is the recommended way for creating unique node names, while class is best used to create unique names based on a set of root names used to initialize a instance. - - if FALSE then the name maker is not seeded with the names of the objects in the current scene; otherwise it is - - - - Creates a new node in the scene with the given object. Normally a developer will use the standard creation methods for procedural objects and this method is not used. However if the developer wants to handle the creation process on their own they may need to use this method. - Parameters: - *obj - - Pointer to the to create. - Pointer to the node created. See also Interface::CreateObjectNode(Object*, const MCHAR*) - - - - - Creates a new camera object of the given type. - - - Creates a new camera object of the given type. - Pointer to the camera object created. - - type (FREE_CAMERA, TARGETED_CAMERA or PARALLEL_CAMERA as defined in ). - - - - Creates an instance of a registered class. This will call Create() on the class descriptor. - Parameters: - SClass_ID superID - - The super class ID of the item to create an instance of. - - classID - - The class ID of the item to create an instance of. See Class . - Pointer to the created instance. - Note: - There is a global method that duplicates the functionality of this class method to let you create an instance of any registered class wherever you are (without the interface pointer): - - CreateInstance(SClass_ID superID, Class_ID classID); - - - - - This method binds a node to a target using a lookat controller. - Parameters: - *laNode - - Pointer to the node to assign the lookat controller to. - - *targNode - - Pointer to the target node. - Returns TRUE if the node was bound; otherwise FALSE. - Sample Code: - This method is used in /MAXSDK/SAMPLES/OBJECTS/CAMERA.CPP. - - - - - Calling this method will result in ending the currently active object creation mode. The plugin's ClassDesc::EndCreate() method will also be called as a result of calling StopCreating(). Most often this method is called either from custom creation command modes in response to a change in the current object selection, or from functions that need to change the current object selection and could be invoked virtually any time, such as via a hot-key or MAXScript. Note that this method should not be called from within an object's creation callback in order to stop creating the current object. Rather, CREATE_STOP should be returned from the creation callback procedure. For more information, see ~{ Creation Methods }~. - - - - - This creates a new object/node without going through the usual create mouse proc sequence. The matrix is relative to the construction plane. This must be called during the creation phase of an object. For example, the procedural sphere uses it when the user clicks on the 'Create' button after they type in the parameters for the sphere. See ~{ Creation Methods }~. - Parameters: - tm - - The transformation matrix relative to the construction plane. - - - - - This method is presently only used in the Line object. It's used for repositioning the pivot point of the object at the end of the creation process. You simply pass it the new matrix, and the creation manager sets the TM for the node being created to the given TM * the construction plane TM. - Parameters: - tm - - The transformation matrix relative to the construction plane for the node. - - - - - Deletes the specified node from the scene. - - - Call this method to delete a specific node from the scene. Note that the object reference of the node is deleted as well if the only item referencing that object is the node. This is because when the node is deleted, it first deletes all its references. Whenever a reference is deleted, if the item is the last reference, then the system deletes the item as well. If the node deletion occurs while the undo system was engaged, RestoreObjs will hold references to the items removed from the node, preventing their immediate deletion. - The number of nodes that were deleted. - - The node to be deleted - If FALSE the viewports will not be redrawn after the node is deleted. This allows several nodes to be deleted at once without the viewports having to be redrawn after each one. - If TRUE, this method will delete nodes whose TM controllers implement to return TRUE. controls whether the node can be deleted from the scene. This parameter allows a driver controller to easily delete driven nodes if it needs to. - - - - Returns a pointer to the root node. From the root node one can retrieve the children (using INode::NumberOfChildren(), and INode::GetChildNode(i)). This allows a developer enumerated the scene by enumerating the node tree. - - - - - Sets the nodes transform relative to the current construction plane. This may be used during creating so you can set the position of the node in terms of the construction plane and not in world units. - Parameters: - *node - - The node whose transform will be set. - - & mat - - The transformation matrix. - - - - - This method may be called to retrieve the pointer for the node with the given name. - Parameters: - const MCHAR *name - - The name of the node to find. - - - - - Returns a pointer to the node whose handle is specified. In 3ds Max version 4.0 and later each node is assigned a unique handle. - Parameters: - ULONG handle - - The handle of the node to find. - - - - - Adds a light to the scene and registers the light with the viewports. - Parameters: - *node - - The light to add. - - - - - Returns the light cone constraint angle (in radians). This is the hotspot / falloff separation angle. - - - - - This method should be called in an light's BeginEditParams() method, after adding rollups to the modify panel: it puts up a rollup containing a list of all Atmospherics and Effects that use the current selected node as a "gizmo". - Parameters: - ULONG vflags=0 - - These are reserved for future use. - - - - - This is called in a light's EndEditParams() when removing rollups. - - - - - An or Rendering calls this when it adds or removes a "gizmo" reference. This is called to refresh the Special Effects rollup. The Atmospherics and Rendering Effects may also use the REFMSG_SFX_CHANGE message, though calling this method would have the same effect. - - - - - Returns the pathname of a directory used by 3ds Max. - Parameters: - int which - - One of the following directories. See . - The pathname of the directory. - - - - - This is the number of entries in PLUGIN.INI. PLUGIN.INI contains a list of descriptions and directories used by plug-in DLLs. - The number of entries in PLUGIN.INI. - - - - - Returns the 'i-th' description string from PLUGIN.INI. - - Parameters: - int i - - Specifies which description to return. - The 'i-th' description string from PLUGIN.INI. - - - - - Returns the pathname string for the 'i-th' plug-in directory from PLUGIN.INI. - Parameters: - int i - - Specifies which directory to return. - The 'i-th' pathname string from PLUGIN.INI. - - - - - Returns a pointer to the material in the specified slot in the Materials Editor. - Parameters: - int slot - - The number of the slot in the Materials Editor (a value in the range 0 to 23). - - - - - Returns a list of all the materials used in the scene. - See Class . - - - - - Before assigning material to scene, call this to avoid duplicate names. Note that this method may replace any existing scene materials with the same name as the supplied material with that supplied material. If you are calling this method from the UI layer, make sure to call theHold.Begin() before calling this method, and if this method returns FALSE, call theHold.Cancel(); - Parameters: - *m - - The material to get the name from, and the material used to replace any existing scene materials with same name. - - - TRUE if it is okay to assign the material; FALSE if not. - - - - - This method provides access to the currently loaded material library. - See Class . - - - - - The method deactivates the texture map in the viewports. - - Note: In the MAX 2.0 SDK a bug prevents this function from being used - it results in a link error. This is fixed in the 2.5 SDK. - Parameters: - *tx - - Points to the texmap to deactivate. - - *mtl - - The top level material containing the texture map. - - int subNum=-1 - - If mtl above it a Multi-material, this specifies which sub-branch of the material contains tx. - - - - - The method activates the texture map in the viewports. - - Note: In the MAX 2.0 SDK a bug prevents this function from being used - it results in a link error. This is fixed in the 2.5 SDK. - Parameters: - *tx - - Points to the texmap to activate. - - *mtl - - The top level material containing the texture map. - - int subNum=-1 - - If mtl above is a Multi-material, this specifies which sub-branch of the material contains tx. - - - - - Modifies the name of the material to make it unique. The name is of the form "<b>Material #1</b>" where the number is incremented as required to make ensure it's unique. - Parameters: - *m - - The material whose name is modified. - - - - - Modifies the name of the texture to make it unique. . The name is of the form "<b>Map #1</b>" where the number is incremented as required to make ensure it's unique. - Parameters: - *m - - The texmap whose name is modified. - - - - - This method makes sure the Materials Editor slots correctly reflect which materials are used in the scene, which are used by selected objects, etc. This is used internally for the drag-and-drop of materials to nodes - there is no reason why a plug-in developer should need to call it. - - - - - This function converts a material (class ) to a viewport material (class ). - Parameters: - TimeValue t - - The time to convert the material. - - &gm - - The viewport material (output). See Class . - - *mtl - - The material to convert (input). See Class . - - BOOL doTex - - Determines whether or not to include textures. TRUE for yes; FALSE for no. - - int subNum - - If the input material mtl is a sub-material then pass its subnum; otherwise pass 0. - - float vis - - The visibility value in the range of 0.0 (completely transparent) to 1.0 (fully opaque) for the viewport representation. - - BOOL &needDecal - - Pass TRUE if the texture needs decal mapping; otherwise FALSE. - - *node - - Points to the node that the material is assigned to. See Class . - - *needTex - - A that returns which map channels are needed. The is enlarged if needed. See Class . - - *gw - - The to do the conversion for. See Class . - - - - - Returns the name of the current MAX file (but not the path). For example, if the currently loaded file is "<b>D:\3DSMAX\SCENES\Expgears.max</b>" this method returns "<b>Expgears.max</b>". - - - - - Returns the file and path of the current MAX file. For example, if the currently loaded file is "<b>D:\3DSMAX\SCENES\Expgears.max</b>" this method returns "<b>D:\3DSMAX\SCENES\Expgears.max</b> ". - - - - - Returns the current material library file name. - - - - - This brings up the standard MAX file open dialog and allows the user to load a new scene. - - - - - This saves the current file. If the file has not been saved yet (and is thus unnamed) this brings up the standard MAX file Save As dialog box and allows the user to choose a name. - TRUE if successful, otherwise FALSE. - - - - - This brings up the standard MAX file save as dialog box and allows the user to save the current scene to a new file. - TRUE if successful, otherwise FALSE. - - - - - This brings up the standard MAX file save selected dialog box and allows the user to save the selected items from the current scene. - - - - - This resets MAX to its startup condition after a confirmation prompt. This performs the same operation as choosing File / Reset from the MAX menus. The confirmation prompt is not shown if running in quiet mode. - Parameters: - BOOL noPrompt=FALSE - - If TRUE the confirmation prompt is not presented. - - - - - This allows the user to merge another MAX file with the current scene. This performs the same operation as choosing File / Merge from the MAX menus. - - - - - This saves the current state of the scene to a temporary hold buffer (same as Edit / ). This state may later be restored using FileFetch() or (Edit / Fetch from MAX). - - - - - This restores the current state of the scene from the temporary hold buffer created using FileHold() (or from the MAX menu command Edit / ). - - - - - This method brings up the File Open dialog box and allows the user to select a material library to load. - Parameters: - HWND hWnd - - The parent window handle. - - - - - If the current material library has been saved previously (has been named) this method saves the material library to the same file. Otherwise it brings up the standard Save File As dialog box to allow the user to save the current material library. - Parameters: - HWND hWnd - - The parent window handle. - - - - - Brings up the standard Save File As dialog box to allow the user to save the current material library. - Parameters: - HWND hWnd - - The parent window handle. - - - - - This method loads the default material library 3DSMAX.MAT (if this file exists). - - - - - Loads the specified MAX file. A developer should normally specify a complete path name. This method does not bring up a file dialog. - Parameters: - const MCHAR *name - - The MAX file to load. - - BOOL refresh=TRUE - - this to FALSE to prevent the viewports from automatically being refreshed. - Nonzero if the file was loaded; otherwise 0. - - - - - Saves the current scene to the specified MAX file. This method does not bring up a file dialog. - Parameters: - const MCHAR *name - - The MAX file to save. - - BOOL clearNeedSaveFlag = TRUE - - if clearNeedSaveFlag is false, the scene 'dirty' flag is not cleared. - - BOOL useNewFile = TRUE - - if it's true, the saved file will become the current scene and the file is added to the MRU list, - Nonzero if the library was saved; otherwise 0. - - - - - Saves the selected nodes to the specified file. - Parameters: - MCHAR *fname - - The MAX file to save. - - - - - Saves the specified nodes to the specified file. - Parameters: - INodeTab* nodes - - Points to the table of nodes to save. See Class . - - MCHAR *fname - - The MAX file to save. - - - - - Loads the specified material library. This method does not bring up a file dialog. - Parameters: - const MCHAR *name - - The material library to load. - - *lib=NULL - - Points to the material library to load into. If NULL the library is loaded into the current material library. See Class . - - Note: You need to call MtlBaseLib::DeleteAll() on the library during a MAX reset operation. This will remove all its references to the materials and set its count to zero. - Nonzero if the library was loaded; otherwise 0. - - - - - Saves the specified material library to the specified file. This method does not bring up a file dialog. - Parameters: - const MCHAR *name - - The material library to save. - - Points to the material library to save from. If NULL the library is saved from the current material library. See Class . - Nonzero if the library was saved; otherwise 0. - - - - - Merges the specified MAX file into the current scene. In MAX 2.0 and later additional parameters allow automatic viewport updates to be optionally be turned off, cases of duplicate objects being merged may be handled, a table of names of the merged objects may be generated, and only specific named objects from the file may be merged. - Parameters: - const MCHAR *name - - The MAX file to merge. - - BOOL mergeAll=FALSE - - If TRUE all the items in the file are merged; otherwise the selector dialog appears allowing the user to choose. - - selMerged=FALSE - - If TRUE the nodes are selected when they are merged. - - BOOL refresh=TRUE - - this to FALSE to prevent the viewports from automatically being refreshed. - - int dupAction = MERGE_DUPS_PROMPT - - Determines what to do when duplicate named objects are encountered during the merge. See Duplicate Node Name Actions - NameTab* mrgList=NULL - - When you specify a pointer to a for this parameter, and don't set dupAction to MERGE_LIST_NAMES, then this method will merge the nodes whose names are listed in the mrgList. - - If dupAction==MERGE_LIST_NAMES, (and mergeAll==TRUE, and mrgList != NULL) then this method puts a list of the nodes in the file into mrgList, and simply returns (no merging is done). - - See Class . - - BOOL dupMtlAction=MERGE_DUP_MTL_PROMPT - - Determines what to do when duplicate material names are encountered during the merge. Must be one of the Duplicate Material Name Actions - BOOL reparentAction=MERGE_REPARENT_PROMPT - - Determines how to re-parent nodes during a merge operation. Must be one of the Node Reparent Actionsbool includeFullGroup=FALSE - - If TRUE, expand list of nodes to merge to include all group nodes associated with those nodes - Nonzero if the file was merged; otherwise 0. - - - - - This method can be used to write out a .MAX file if needed. First it ends animation if it's in progress. Next it determines whether a save operation is required (change marked in scene, or undo operations present). - If the save is not required, it returns TRUE; otherwise, it puts up a dialog box asking if the user wants to save. If the user picks No, it returns TRUE. If the user picks Cancel it returns FALSE. If the user picks Yes then the method proceeds as for FileSave() above. - - - - - This method allows a custom file open dialog to be registered. - Parameters: - MAXFileOpenDialog* dlg - - Points to the file open dialog object to use. See Class . - - - - - This method allows a custom file save dialog to be registered. - Parameters: - MAXFileSaveDialog* dlg - - Points to the file save dialog object to use. See Class . - - - - - Returns true if the specified file is a valid MAX file; otherwise false. - Parameters: - const MCHAR* filename - - The name of the file to check. - - - - - Returns true if the specified file is an internet cached file; otherwise false. - Parameters: - const MCHAR* filename - - The name of the file to check. - - - - - This method simply brings up the 'Select File to Import' dialog just as if the user picked this option from the File / Import... pulldown menu. - TRUE if the file was imported successfully; otherwise FALSE. - - - - - This method simply brings up the 'Select File to Export' dialog just as if the user picked this option from the File / Export... pulldown menu. - TRUE if the export file was written successfully; otherwise FALSE. - - - - - This method allows the import of the specified file by any of the supported import formats. This is done by specifying a full filename thus bypassing the file browser. If suppressPrompts is set to TRUE, the import mechanism will not display any prompts requiring user action. - - Note: Developers of Import plug-ins need to support the suppressPrompts mechanism for this to work properly. Developers of such plug-ins should see the Class for details. - Parameters: - const MCHAR *name - - The full file name (including extension - which identifies the importer used) of the input file. - - BOOL suppressPrompts=FALSE - - If TRUE the default choices in the import plug-in are used and no options dialogs are presented. If FALSE any options dialogs provided by the importer are presented to the user. - - *importerID=NULL - - The parameter specifies the of the import module to use. This is for those cases where more than one import module uses the same file extension. Omitting this class ID operates in the pre-R3 mode, i.e. the first importer found is used. - TRUE if the export file was written successfully; otherwise FALSE. - - - - - This method allows the export of the current MAX file to any of the supported export formats. This is done by specifying a full filename thus bypassing the file browser. If suppressPrompts is set to TRUE, the export mechanism will not display any prompts requiring user action. - - Note: Developers of Export plug-ins need to support the suppressPrompts mechanism for this to work properly. Developers of such plug-ins should see the Class for details. - Parameters: - const MCHAR *name - - The full file name (including extension - which identifies the exporter used) of the output file. - - BOOL suppressPrompts=FALSE - - If TRUE the default choices in the export plug-in are used and no options dialogs are presented. If FALSE any options dialogs provided by the exporter are presented to the user. - - DWORD options - - There is currently one option; SCENE_EXPORT_SELECTED which allows you to export only selected nodes. - - *exporterID=NULL - - The parameter specifies the of the export module to use. This is for those cases where more than one export module uses the same file extension. Omitting this class ID operates in the pre-R3 mode, i.e. the first exporter found is used. - TRUE if the export file was written successfully; otherwise FALSE. - - - - - This returns the state of the system zoom extents flag. Note that individual plug-ins can override this in their ZoomExtents() method. See Class . - TRUE indicates that zoom extents will occur after imports, FALSE indicates that no zoom extents. - - - - - This method will check is the specified file can be imported. - Parameters: - const MCHAR* filename - - The file name to check. - TRUE if the specified file can be imported by one of the import plug-ins; otherwise FALSE. - - - - - Combines the specified nodes into a MAX group. - Parameters: - *nodes=NULL - - The table of nodes to combine into a MAX group. If NULL is passed, the current selection set is used. - - MSTR *name=NULL - - The name of the group to create. If the name is NULL, a dialog box will prompt the user to select a name. - - BOOL selGroup=TRUE - - If TRUE, the group of nodes will be selected after the operation is completed. - A pointer to the group of nodes created. - - - - - Un-groups the specified nodes. - Parameters: - *nodes=NULL - - The table of nodes to un-group. If NULL is passed, the current selection set is used. - - - - - Explodes the grouped nodes. This completely un-groups nested groups. - Parameters: - *nodes=NULL - - The table of nodes to explode. If NULL is passed, the current selection set is used. - - - - - Opens the grouped nodes. Items in an opened group may be edited individually. - Parameters: - *nodes=NULL - - The table of nodes comprising a group that will be opened. If NULL is passed, the current selection set is used. - - BOOL selGroup=TRUE - - If TRUE, the group of nodes will be selected after the operation is completed. - - - - - Closes the specified group of nodes. Items in a closed group cannot be edited individually. - Parameters: - *nodes=NULL - - The table of nodes to close. If NULL is passed, the current selection set is used. - - BOOL selGroup=TRUE - - If TRUE, the group of nodes will be selected after the operation is completed. - - - - - This will go into a PeekMessage() loop until there are no more messages left. This is a way a plug-in can relieve control to the system. - - There may be certain circumstances where a plug-in wants to give control back to MAX. For example a plug-in may put up a progress bar with a cancel button during a lengthy operation. However the cancel button would not receive any messages if the user was clicking on it because no messages are being dispatched. - - This method will relieve control and let any messages that are in the queue get processed. If there are no messages it will return right away. This provides a way for a plug-in to yield control. - - Note: A developer must be prepared to handle a lot of different conditions if this is done. For example the user could click on the delete key and delete the object that was being processed. EndEditParams() could be called on the plug-in. So in EndEditParams() there must be some logic to signal the other lengthy process that EndEditParams() was called. - If this method returns FALSE then the user is attempting to quit MAX and the caller should return. - - - - - This method is used to specify the background asset used for all viewports. - Parameters: - AssetUser& asset - - The background asset representing the background image. - TRUE if the asset was set; otherwise FALSE. - - - - - This method is used to retrieve the asset of the background image used. - - - - - Retrieves the background image aspect ratio. This will be the viewport, the bitmap, or the rendering output aspect ratio. - One of the following values: - - VIEWPORT_BKG_ASPECT_VIEW - - VIEWPORT_BKG_ASPECT_BITMAP - - VIEWPORT_BKG_ASPECT_OUTPUT - - - - - This method determines if the background image is set to update with the current frame in the viewports. - - - - - This method establishes the range of frames used for an animated background. - Parameters: - int start - - The start frame number. - - int end - - The end frame number. - - int step=1 - - The frame increment. - - - - - This method retrieves either the start or end frame number. - Parameters: - int which - - One of the following values: - - VIEWPORT_BKG_START - - VIEWPORT_BKG_END - - - - - Sets the background Out of Range Type. This may be the start or end ORT. - Parameters: - int which - - One of the following values: - - 0 : Sets the Start Processing ORT. - - 1 : Sets the End Processing ORT. - - int type - - One of the following values: - - VIEWPORT_BKG_BLANK - - VIEWPORT_BKG_HOLD - - VIEWPORT_BKG_LOOP - - - - - Retrieves the background Out of Range Type. This may be the start or end ORT. - Parameters: - int which - - One of the following values: - - 0 : Gets the Start Processing ORT. - - 1 : Gets the End Processing ORT. - One of the following values: - - VIEWPORT_BKG_BLANK - - VIEWPORT_BKG_HOLD - - VIEWPORT_BKG_LOOP - - - - - This returns the "Start at" parameter from the Views / Background Image... dialog. - - - - - Returns the background "Sync Start to Frame" setting. - - - - - This method will convert the TimeValue passed to a frame number based on the background image settings (ORTs, start/end times, sync frame, etc.). - Parameters: - TimeValue t - - The time to convert. - The frame number corresponding to the time passed. - - - - - Return the solid background color of the active viewport. In 3ds Max2013, viewport background color can be solid or gradient. This method returns the solid color. - - - - - This method is called to open the specified renderer. It must be opened before frames can be rendered. Either camNode or view must be non-NULL, but not both. Remember to close the renderer when you are done (using CloseRenderer()). - Parameters: - *pRenderer - - Points to the renderer to open. - - *camNode - - A pointer to the camera node to render, or NULL if a viewport should be rendered. - - *view - - A pointer to the view to render, or NULL if the camera should be rendered. - - RENDTYPE_NORMALRendType type = - - This provides an optional way to specify the view when opening the renderer. This specifies the type of render. - - int w=0 - - This specifies the width of the rendering. - - int h=0 - - This specifies the height of the rendering. - Nonzero indicates success; failure is zero. - - - - - This method is called to open the specified renderer. It provides an optional way to specify the view when opening. - Parameters: - *pRenderer - - Points to the renderer to do the rendering. - - *vpar - - This class describes the properties of a view that is being rendered. - - RENDTYPE_NORMALRendType type = - - This provides an optional way to specify the view when opening the renderer. This specifies the type of render. - - int w=0 - - This specifies the width of the rendering. - - int h=0 - - This specifies the height of the rendering. - Nonzero indicates success; failure is 0. - - - - - This method is called to render a frame with the specified renderer to the given bitmap. The renderer uses the width, height, and aspect ratio of the specified bitmap to control the size of the rendered image. - Parameters: - *pRenderer - - Points to the renderer which will do the rendering. - - TimeValue t - - The time to render the image. - - *bm - - The bitmap to render to. This bitmap defines the size and aspect ratio of the render. See Class . - - *prog=NULL - - The is an optional callback. See Class . - - float frameDur = 1.0f - - This parameter should always be set to 1.0. - - *vp=NULL - - This parameter allows you to specify a different view transformation on each render call. For instance, you can render a given scene at a given time from many different viewpoints, without calling Render::Open() for each one. - - RECT *regionRect = NULL - - This value, if passed, defines the region to be rendered. This only works for RENDTYPE_REGION and RENDTYPE_REGIONCROP. - The result of the render - Nonzero if success; otherwise 0. - - - - - Closes the specified renderer. - Parameters: - *pRenderer - - Points to the renderer to close. - - To get more control over the renderer, the renderer can be called directly. The following methods give access to the current renderer and the user's current rendering settings. Note: These methods drive the renderer and not video post. - - - - - Retrieves a pointer to the renderer currently set as the active renderer. This will be either the production renderer or the draft renderer depending upon which is active. A developer can determine which renderer this is by calling the ClassID() method of the renderer. - Parameters: - bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - A pointer to the renderer. - - - - - Retrieves a pointer to the renderer currently set as the production renderer. A developer can determine which renderer this is by calling the ClassID() method of the renderer. - Parameters: - bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - A pointer to the renderer. - - - - - Retrieves a pointer to the renderer currently set as the draft renderer. A developer can determine which renderer this is by calling the ClassID() method of the renderer. - Parameters: - bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - A pointer to the renderer. - - - - - Returns a pointer to the specified renderer. - Parameters: - RenderSettingID renderSettingID - - One of these values: See Render Setting IDs. bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - A pointer to the renderer. - - - - - Assigns the renderer passed for use as either the draft renderer or the production renderer depending upon which is active. - Parameters: - *rend - - The renderer to assign. - - - - - Assigns the renderer passed as the production renderer. - Parameters: - *rend - - The renderer to assign. - - - - - Assigns the renderer passed as the draft renderer. - Parameters: - *rend - - The renderer to assign. - - - - - Assigns the renderer passed as one of the standard MAX rendering options (Production, Draft, etc). - Parameters: - RenderSettingID renderSettingID - - One of these values: See Render Setting IDs *rend - - Points to the renderer to assign. - - - - - Determines which renderer is active - draft or production. - TRUE for the draft renderer and FALSE for the production renderer. - - - - - Sets the specified renderer as active. - Parameters: - RenderSettingID renderSettingID - - One of these values: See Render Setting IDs. - - - - - Returns a value which indicates which renderer is current. See Render Setting IDs. - - - - - This method returns a pointer to the current render elements manager interface. - - - - - This method returns a pointer to the production or draft render element manager - passing in renderSettingID = RS_IReshade will return NULL. - Parameters: - RenderSettingID renderSettingID - - One of these values: See Render Setting IDs. - - - - - This method is called to fill in a structure that can be passed to the renderer with the user's current rendering settings. This is whatever was last used, or the default settings. - - In MAX 1.x note the following (this needs not be done in MAX 2.0 or later): In order to open a renderer using this method to setup the class the following code should be used: - - rp; - - SetupRendParams(rp, ...); - - rp.atmos = NULL; - - rp.envMap = NULL; - - As shown above, this method does not automatically set the values for envMap and atmos. You must do this manually if you are using the object to initialize the renderer. Then you can call Renderer::Open(..., rp, ...). In MAX 2.0 and later, atmos and envMap are properly initialized without the above code. - Parameters: - &rp - - This is the class instance whose data is filled in. See Class . - - *vpt - - This pointer only needs to be passed in if the RendType is RENDTYPE_REGION or RENDTYPE_BLOWUP. In these cases it will set up the regxmin, regxmax, regymin, regymax from values stored in the viewport. - - RendType t = RendType::RENDTYPE_NORMAL - - - - - - - This method fills in the specified structure based on type of node passed (camera or light). It can be used when instantiating a renderer and calling Open(), Render(), and Close() directly on it. - Parameters: - INode* vnode - - Points to the node to initialize from. - - & vp - - The structure to initialize. - - TimeValue t - - The time at which to initialize the structure. - - - - - This method may be called during a rendering to check if user has cancelled the render. - - - TRUE if user has cancelled; otherwise FALSE. If not rendering the method returns FALSE. - - - - - Calling this method during a render will set the flag that indicates that the render is to be aborted. - - - - - Retrieves the type of time range to be rendered. - One of the following values: - - REND_TIMESINGLE - - A single frame. - - REND_TIMESEGMENT - - The active time segment. - - REND_TIMERANGE - - The user specified range. - - REND_TIMEPICKUP - - The user specified frame pickup string (for example "1,3,5-12"). - - - - - Retrieves the renderer's start time setting. - - - - - Retrieves the renderer's end time setting. - - - - - Returns the renderer's 'n-th' frame setting. - - - - - Retrieves the state of the renderer's show virtual frame buffer flag. Returns TRUE if on; FALSE if off. - - - - - Retrieves the state of the renderer's save file flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the state of the renderer's use device flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the state of the renderer's use net flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the rendering file . This class describes the output file. See Class . - - - - - Retrieves the rendering device . This class describes the output device. See Class . - - - - - Retrieves the rendering output width in pixels. - - - - - Retrieves the rendering output height in pixels. - - - - - Retrieves the renderer's pixel aspect ratio setting. Note : to get the 'Image Aspect Ratio' setting use: - - GetRendImageAspect() - - - - - Returns the image aspect ratio. - - - - - Returns the aperture width in millimeters (mm). - - - - - Retrieves the renderer's field render flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the renderer's color check flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the renderer's super black flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the renderer's render hidden objects flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the renderer's force two-sided flag. - Returns TRUE if on; FALSE if off. - - - - - Sets the renderer's force two-sided flag. TRUE for on; FALSE for off. - - - - - Retrieves the renderer's uses atmospheric effects flag. - Returns TRUE if on; FALSE if off. - - - - - Returns TRUE if Rendering Effects will be used; otherwise FALSE. - - - - - Returns TRUE if rendering displacements is enabled; otherwise FALSE. - - Note: Developers should use the flags parameter of the class which is passed into GetRenderMesh() to determine if Displacement Mapping is being used because the values may not the same (for instance when rendering in the Materials Editor). See Class . - - - - - Retrieves the string holding the frames the user wants to render. For example "1,3,5-12". - - - - - Retrieves the renderer's dither true color flag. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the renderer's dither 256 color flag. - Returns TRUE if on; FALSE if off. - - - - - Sets the renderer's dither 256 color flag. - Parameters: - BOOL onOff - - TRUE for on; FALSE for off. - - - - - Retrieves the renderer's multi-threaded flag. - Returns TRUE if on; FALSE if off. - - - - - This retrieves the output file sequencing nth serial numbering setting. - Returns TRUE if on; FALSE if off. - - - - - Retrieves the video color check method. - One of the following values: - - 0 is FLAG - - 1 is SCALE_LUMA - - 2 is SCALE_SAT - - - - - Retrieves the rendering field order. - One of the following values: - - 0 is Even - - 1 is Odd - - - - - Retrieves the video color check NTSC or PAL setting. - One of the following values: - - 0 is NTSC - - 1 is PAL - - - - - Returns the super black threshold setting. - - - - - Returns the File Base in the 'Common Parameters' rollup of the Render Scene dialog. - - - - - Returns TRUE if the skip existing rendered frames state is on; otherwise FALSE. - - - - - Returns the state of the hide by category flags. - One or more of the following values: - - HIDE_OBJECTS - - HIDE_SHAPES - - HIDE_LIGHTS - - HIDE_CAMERAS - - HIDE_HELPERS - - HIDE_WSMS - - HIDE_SYSTEMS - - HIDE_NONRENDERABLES - - HIDE_ALL - - HIDE_NONE - - - - - Sets the state of the hide by category flags. - Parameters: - DWORD f - - One or more of the following values: - - HIDE_OBJECTS - - HIDE_SHAPES - - HIDE_LIGHTS - - HIDE_CAMERAS - - HIDE_HELPERS - - HIDE_WSMS - - HIDE_SYSTEMS - - HIDE_NONRENDERABLES - - HIDE_ALL - - HIDE_NONE - - - - - This method returns the node pointer from the id in the BMM_CHAN_NODE_RENDER_ID G-Buffer channel. The renderer will set the RenderID of all rendered nodes, and will set all non-rendered nodes to 0xffff. See Image (G-Buffer) Channels. - Parameters: - UWORD id - - The id from the G Buffer channel. - - - - - This method may be used to execute a MAX command. These are the same commands that may be assigned using the MAX Customize/Preferences.../Keyboard key assignment system. - - For MAX version 1.1 or later, this method may also be used to set various aspects of the preview display. The id to pass for these options is shown below: - - ExecuteMAXCommand(MAXCOM_API_PVW_GRID_OFF) - - This turns off the preview grid display. - - ExecuteMAXCommand(MAXCOM_API_PVW_GRID_ON) - - This turns on the preview grid display. - - ExecuteMAXCommand(MAXCOM_API_PVW_SMOOTH_MODE) - - This sets the preview rendering mode to "smooth". - - ExecuteMAXCommand(MAXCOM_API_PVW_FACET_MODE) - - This sets the preview rendering mode to "facet". - - ExecuteMAXCommand(MAXCOM_API_PVW_WIRE_MODE) - - This sets the preview rendering mode to "wireframe". - - Note: In MAX 2.0 and later there is an alternate (better) way to do this. See the method: - - *pvp=NULL)=0; - Parameters: - int id - - The command to execute. See 3ds Max Commands. - - - - - Returns the current environment map. - - - - - Returns TRUE if the 'Use Map' checkbox is checked in the Environment / Background dialog; otherwise FALSE. - - - - - Retrieves the color of the ambient light at the time passed and updates the validity interval passed to reflect the validity of the ambient light. - - The color as a . - - - The time to retrieve the ambient light color. - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Sets the color of the ambient light in the scene to the color passed at the specified time. - Parameters: - TimeValue t - - The time to set the color. - - col - - The new color for the ambient light. - - - - - Retrieves a pointer to the controller use to animate the ambient light. - - - - - Returns the rendering environment global lighting tint color at the specified time and updates the validity interval passed to reflect the validity of the tint color controller. - - - The time at which to return the color. - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Sets the rendering environment global lighting tint color at the specified time to the color passed. - Parameters: - TimeValue t - - The time at which to set the color. - - col - - The color to set. - - - - - Returns a pointer to the controller use to animate the tint color. - - - - - Returns the rendering environment global lighting level at the specified time and updates the validity interval passed to reflect the validity of the lighting level controller. - - - The time at which to return the level. - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Sets the rendering environment global lighting level at the specified time. - Parameters: - TimeValue t - - The time at which to set the lighting level. - - float lev - - The level to set. - - - - - Returns a pointer to the controller use to animate the lighting level. - - - - - Returns the number of atmospheric effects currently assigned. - - - - - Returns a pointer to the 'i-th' atmospheric effect. - Parameters: - int i - - Specifies which atmospheric effect to retrieve. - - - - - Sets the 'i-th' atmospheric effect. - Parameters: - int i - - Specifies which effect to set. - - *a - - A pointer to the atmospheric effect. - - - - - Adds the specified atmospheric effect to the list of effects. - Parameters: - *a - - A pointer to the atmospheric effect to add. - - - - - Deletes the specified atmospheric effect. - Parameters: - int i - - The index of the atmospheric effect to delete. - - - - - This method selects the specified atmosphere's gizmo and displays the parameters for it (if any). - Parameters: - *a - - Points to the plug-in. See Class . - - *gizmo=NULL - - Points to the gizmo node associated with the plug-in. - - - - - Retrieves the background color at the specified time and updates the validity interval passed to reflect the validity of the background color. - - - The time to retrieve the color. - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Sets the background color to the specified color at the specified time. - Parameters: - TimeValue t - - The time to set the color. - - col - - The color to set. - - - - - Returns a pointer to the controller animating the background color. - - - - - Returns the number of Render Effects currently assigned. - - - - - Returns a pointer to the 'i-th' Render . See Class . - Parameters: - int i - - The zero based index of the effect to return. - - - - - Sets the specified Render to the one passed. - Parameters: - int i - - The zero based index of the effect to set. - - *e - - Points to the to set. - - - - - Adds the specified to the existing list of effects. - Parameters: - *eff - - Points to the render effect to add. See Class . - - - - - Deletes the specified . - Parameters: - int i - - The zero based index of the effect to delete. - - - - - This method selects the specified gizmo and displays the parameters for it (if any). - Parameters: - *e - - Points to the plug-in. See Class . - - *gizmo=NULL - - Points to the gizmo node associated with the effect. - - - - - Returns the current sound object. See the sample code in /MAXSDK/SAMPLES/UTILITIES/UTILTEST.CPP. - - - - - - - Returns a pointer which may be used for calling methods to write information to the system log. See Class for details. - - - - - Returns a reference to the central DLL directory. See Class . - - - - - Returns a pointer to the central DLL directory. See Class . - - - - - This is a general purpose function that allows the API to be extended in the future. The MAX development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - Note: In R4 the return value changed from int to INT_PTR - - New in R5.1 An additional Command was added to allow the setting of certain directories such as Plugins. It looks like this: - - Execute(I_EXEC_SET_DIR, (ULONG_PTR)(int) which, ULONG_PTR)(MCHAR )dir) - - where 'which' designates the particular Max directory to be changed (like the corresponding argument of Interface::GetDir()), and 'dir' is the path as a string. - Parameters: - int cmd - - The index of the command to execute. See Interface::Execute Command Options . - - ULONG arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - - ULONG arg4=0 - - Optional argument 4. - - ULONG arg5=0 - - Optional argument 5. - - ULONG arg6=0 - - Optional argument 6. - An INT_PTR return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Returns a pointer for direct access to the scene. This is primarily used for hanging AppData off the entire scene as opposed to a certain . - - - - - This method returns a pointer to the Track Root Node. See Class . - - - - - This method returns an instance of the class. This class may be used to manipulate the track bar. See Class . - - - - - This method will creates a plain treeview window (no title,borders,etc.) as a child window of the given window. To destroy the window, delete the pointer. - Parameters: - ReferenceTarget* root - - Points to the root node of the hierarchy to display in the Track . - - HWND hParent - - The window handle of the parent for the dialog. - - DWORD style=0 - - The style flags; - - TVSTYLE_MAXIMIZEBUT - - Provide a maximize button. - - TVSTYLE_INVIEWPORT - - Display in the viewport. - - TVSTYLE_NAMEABLE - - The treeview is namable. - - TVSTYLE_INMOTIONPAN - - Used in the motion panel. - - ULONG id=0 - - The ID of the treeview window. - - int open=OPENTV_SPECIAL - - One of the following values: - - OPENTV_NEW - - Open a new treeview. - - OPENTV_SPECIAL - - Open a special treeview. - - OPENTV_LAST - - Open the last treeview. - - - - - This method traverses the scene reference hierarchy, calling Animatable::FreeAllBitmaps() on every . This will free up all the memory used by bitmaps. - - - - - This method may be used to enumerate all the bitmap files in the scene. The flags allow control over which files are enumerated. - Parameters: - & assetEnum - - The callback, called once for each bitmap. See Class . - - DWORD vflags - - See Auxiliary File Enumeration Flags. Note: if the FILE_ENUM_CHECK_AWORK1 flag bit is not set when this call is made, and the FILE_ENUM_RENDER flag bit is set, the implementation of this method calls ClearAFlagInAllAnimatables(A_WORK1) and sets the FILE_ENUM_CHECK_AWORK1 flag bit. - - - - - This method renders a textmap (or an entire textmap tree) to the specified bitmap. - Parameters: - *tex - - The to render to a bitmap. - - *bm - - A pointer to a bitmap to render to. This bitmap must be created at the resolution you wish to render to. - - float scale3d=1.0f - - This is a scale factor applied to 3D Texmaps. This is the scale of the surface in 3d space that is mapped to UV. This controls how much of the texture appears in the bitmap representation. - - BOOL filter=FALSE - - If TRUE the bitmap is filtered. It is quite a bit slower to rescale bitmaps with filtering on. - - BOOL display=FALSE - - If TRUE the resulting bitmap is displayed using the virtual frame buffer; otherwise it is not. TimeValue t - - The time at which to render the texmap to the bitmap, defaults to the current frame. bool bake - - Used to bake the texture to bitmap without including the effects of scale/rotation etc. If true, the function will render the unit square of 2D texture maps, by effectively disabling the UV Generator during texture rendering, so no settings like scale, rotation, tiling etc. have any effect on the result. This baked 2D representation can then later be scaled, rotated and tiled, for use in a renderer that may not support the particular texture, sent to a game engine, or similar. - - - - - - - This method will check if the system can import the specified bitmap file. - Parameters: - const MCHAR* filename - - The file name to check. - TRUE if the specified file is a bitmap file of a format that is supported by one of the bitmap reader plug-ins; otherwise FALSE. - - - - - - - This method is used to lock and unlock subobject mode registrations and is primarily used by the FileLink wrapper classes acting as proxies to other classes in 3D Studio VIZ. When a class calls this method with OnOff set to TRUE, then other classes are prevented from registering new subobject modes. This continues until the original class "releases" by calling CaptureSubObjectModes(FALSE, myClassID). The second argument insures that only the class which does the capture can do the release. Note that this is used only by certain VIZ plugins. - Parameters: - bool OnOff - - TRUE to prevent other classes from registering new subobject modes. - - cid - - The class ID. - TRUE is successful, otherwise FALSE. - - - - - This method simplifies downloading files from any given URL and displays a floating progress dialog. - Parameters: - HWND hwnd - - The window handle for owner window (required for the progress floating dialog). - - const MCHAR* url - - The string for the resource/file to download. - - const MCHAR* filename - - The target location and filename for the downloaded file. - - DWORD downloadFlags = 0 - - Additional controls to the download behavior. Currently only one flag is supported, DOWNLOADDLG_NOPLACE, which hides an option in the progress dialog that allows the user to place (move) a dropped object immediately after being dropped. - TRUE if successful, otherwise FALSE. - - - - - On drag-and-drop, if the drop type is a file, the drop handler searches for an importer plugin that can handle the file (based on its extension). Some drop operations, such as bitmaps and material XML files, can or must be dropped on to an object in the scene. - The node that the operation is performed on, if one is "hit" at the drop location. It returns NULL if no nodes were found at the drop location. - - - - - This method is used to rescale the world units of the entire scene, or optionally the current selection set, or optionally a specified set of nodes. - Parameters: - float f - - The scale factor to apply to the scene. - - BOOL selected - - TRUE to scale selected objects only; otherwise the entire scene or the specified set of nodes is scaled. Tab<INode*>* nodes - - If selected is FALSE, the set of nodes to scale; otherwise the entire scene is scaled. - - - - - Returns TRUE if the Time Configuration / Key Steps / Selected Objects Only check box is on; otherwise FALSE. - - - - - Returns TRUE if the Time Configuration / Key Steps / Use Current Transform check box is on; otherwise FALSE. - - - - - Returns TRUE if the Time Configuration / Key Steps / Position check box is on; otherwise FALSE. This value is only meaningful if Use Current Transform is off. - - - - - Returns TRUE if the Time Configuration / Key Steps / Rotation check box is on; otherwise FALSE. This value is only meaningful if Use Current Transform is off. - - - - - Returns TRUE if the Time Configuration / Key Steps / Scale check box is on; otherwise FALSE. This value is only meaningful if Use Current Transform is off. - - - - - Returns the state of the Time Configuration dialog 'Key Steps / Use TrackBar' checkbox. TRUE if checked; FALSE if unchecked. - - - - - Returns the state of the Transform Tools / Gizmo toggle. - TRUE if on; FALSE if off. - - - - - Indicates if the TransformGizmo will restore the axis constraint when released. Returns TRUE if it will; FALSE if it won't. - - - - - Returns the state of the Transform Tools / Constant Axis toggle. - TRUE if on; FALSE if off. - - - - - This method is used to hit test gizmos for sub-objects. - Parameters: - *p - - Point to check in screen coordinates. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. - - int axisFlags - - One or more of the following values: - - HIT_TRANSFORMGIZMO - - This flag is passed in on a MOUSE_FREEMOVE message so that the axis is hit tested and it highlights if it is hit, but it doesn't actually switch the transform mode. - - HIT_SWITCH_GIZMO - - In case of a MOUSE_POINT, this flag is used, and if the axis is hit, the 'hit' transform mode will be pushed on the transform mode stack. - Nonzero if the item was hit; otherwise 0. - - - - - Used to deactivate the Transform Gizmo when it is released. - - - - - This method is used to dynamically add a plug-in class. This method will update the control panel in the Create or Modify branches dynamically. - Parameters: - *pCD - - Points to the Class Descriptor to add. See Class . - Returns -1 if the superclass was unknown, 0 if the class already exists, or 1 if the class was added successfully. - - - - - This method is used to dynamically delete a plug-in class. This method will update the control panel in the Create or Modify branches dynamically. - Parameters: - *pCD - - Points to the Class Descriptor to add. See Class . - Returns -1 if the superclass was unknown, 0 if the class does not exist, or 1 if the class was deleted successfully. - - - - - Returns the number of properties of the specified property set. See the note at the start of this group of methods above for info on property sets. - Parameters: - int PropertySet - - See PropertySet Options. - - - - - Returns TRUE if XRefs are included in the traversal of the scene hierarchy; otherwise FALSE. See the method above for details. - - - - - Returns TRUE if the automatic updating of XRefs is suspended; otherwise FALSE. When an XRef file is changed and that causes an XRef object to update, the old XRef object gets deleted from memory which can cause problems for some plug-ins. For example, the Dynamics system would have a problem if an update occurred while a solution was solving. This method is used to disable the automatic updating to prevent the problem. - - - - - Sets if the automatic updating of XRefs is suspended or not. See the note in IsXRefAutoUpdateSuspended() for details. - Parameters: - BOOL onOff - - TRUE to suspend; FALSE to restore automatic updating. - - - - - Returns TRUE if the specified node is part of a scene XRef or FALSE if the node is a regular modifiable node in the current scene. - Parameters: - *node - - The node to check. - - - - - Returns TRUE if the application is running under a trial license, as opposed to a full, authorized license; otherwise FALSE. - - - - - Returns true if the application is running under a network license. - - - - - Brings up the RAMPlayer dialog and optionally loads one, or both channels with the supplied files. - - - Parameters: - HWND hWndParent - - The parent window handle. - - MCHAR* szChanA=NULL - - The file to load for channel A (for example, _M("movie.avi")). If NULL is passed no file is loaded into the channel. - - MCHAR* szChanB=NULL - - The file to load for channel B. If NULL is passed no file is loaded into the channel. - - - - - This function will flush the undo buffer. See the Advanced Topics section ~{ The Undo and Redo System }~. - - - - - In the Preferences dialog / General / Plug-In Loading section there is a checkbox labelled 'Load Plug-Ins when Used'. This method returns the state of this toggle.. See the Advanced Topics section ~{ Deferred Loading of Plug-Ins }~. - TRUE if on; FALSE if off. - - - - - In the Preferences dialog / General / Plug-In Loading section there is a checkbox labelled 'Load Plug-Ins when Used'. This method sets the state of this toggle. See the Advanced Topics section ~{ Deferred Loading of Plug-Ins }~. - Parameters: - bool onOff - - TRUE for on; FALSE for off. - - - - - If a Pick Mode is on top of the command stack, then this function will return the . If the Pick Mode is not on top of the command stack the it returns NULL. - - - - - This method gets a viewport interface given a window handle. If the input HWND is NULL, the interface of the active viewport will be returned. If the given non-NULL HWND doesn't match any of the viewport, the interface of the default view tab's first viewport will be returned. - Parameters: - HWND hwnd - - The window handle of the viewport. - - - - - Returns the number of permanent user paths associated with a particular type of asset. - - - A non-negative integer denoting the number of paths - Remember that this function gives you the count of permanent user paths, not session user paths. Session user paths are temporary. - - An enumeration constant representing the asset's type - - - - Returns the "ith" permanent user path associated with a particular asset type. - - - A c-string with an absolute path to the ith asset directory - Remember that this function returns a permanent user path, not a session user path. A session user path is temporary. - - The index of the directory you want - An enumeration constant representing the asset's type - - - - Adds a permanent user path associated to a particular asset type. - - - TRUE if the path was added, FALSE if not - Remember that this function is for adding permanent user paths, not session user paths. Session user paths are temporary. - - An absolute path - An enumeration constant representing the asset's type - - - - Adds a session user path associated to a particular asset type. - - - TRUE if the path was added, FALSE if not - Remember that this function is for adding permanent user paths, not session user paths - - An absolute path - An enumeration constant representing the asset's type - system configuration files with the new data - - - - Returns the number of session user paths associated with a particular type of asset. - - - A non-negative integer denoting the number of paths - Remember that this function gives you the count of session user paths, not permanent user paths. Session user paths are temporary. - - An enumeration constant representing the asset's type - - - - Returns the "ith" session user path associated with a particular asset type. - - - a c-string with an absolute path to the ith asset directory - Remember that this function returns a session user path, not a permanent user path. - - The index of the directory you want - An enumeration constant representing the asset's type - - - - Deletes the "ith" session user path associated with a particular asset type. - - - a c-string with an absolute path to the ith asset directory - Remember that this function returns a session user path, not a permanent user path. - - The index of the directory you want to delete - An enumeration constant representing the asset's type - system configuration files with the new data - - - - Returns the number of session (temporary) and permanent user paths associated with a particular type of asset. - - - A non-negative integer denoting the number of paths - Remember that this function gives you the total count of both session(temporary) and permanent user paths. - - An enumeration constant representing the asset's type - - - - Returns the "ith" session\permanent user path associated with a particular asset type. Session user paths come first in the list. - - - a c-string with an absolute path to the ith asset directory - Remember that session user paths come before permanent user paths. - - The index of the directory you want - An enumeration constant representing the asset's type - - - - Attach nodes to a group.It behaves just like the attach menu command in 3ds Max's main menu. You can't attach nodes which are already a group member to other groups. - Parameters: - & nodes - - The table of nodes that you want to attach to a group. - - & pTargetNode - - The target node you want attach the table of nodes to. The node should be a group head node or a group member node. The node can't be a member of nodes. - - - true if successful; false otherwise. - - - - - Detach nodes from the group to the scene root node. The nodes may belong to different groups. It behaves just like the detach menu command in 3ds Max's main menu. - Parameters: - & nodes - - The table of nodes that you want to detach from the group they belong to. The nodes must belong to open groups. - - - true if successful; false otherwise. - - - - - Creates an instance of the default renderer for the given render setting. - - - If the class ID of the default renderer (see SetDefaultRendererClassID()) does not exist, then an instance of the MAX scanline renderer is created. The instance returned must be deleted with Renderer::DeleteThis(). - The new renderer - - The render type to create a default renderer of - - - - Gets the class ID of the default renderer for the given render setting. - - - An instance of the default renderer can be created by using CreateDefaultRenderer() - The Class ID of the current default for renderSettingID - - The render setting to get the default renderer of. - - - - Gets the class ID of the default renderer for the given render setting. - - - An instance of the default renderer can be created by using CreateDefaultRenderer() - - The render setting to get the default renderer of. - The Class ID of a to set as the new default for renderSettingID - - - - Gets the renderer assigned to the MEdit slot. - - . - - - This ignores the state of the MEdit renderer lock, and will not necessarily get the renderer that is actually used for MEdit. - Parameters: - bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - the used to create the display for the Editor slots - - - - - Sets the renderer assigned to the MEdit slot. - - . - - - This ignores the state of the MEdit renderer lock, and will not necessarily set the renderer that is actually used for the Editor. - - A renderer that will be used to generate the display for the Editor slots - - - - Returns the renderer to be used for MEdit. - - . - - - This takes the lock into account - Parameters: - bool createRendererIfItDoesntExist - - If true, creates an instance of the renderer if one does not currently exist. The core will hold a reference to this renderer instance. - this will return the Current renderer if the MEdit lock is ON. Otherwise, the renderer assigned with AssignMEditRenderer will be returned - - - - - Gets the status of the MEdit renderer lock. - - - true if the Current renderer should be used to render in MEdit, else false to use the assigned renderer - - - - - returns the state of the toggle in the render dialog, "Area Lights/Shadows as Points". - - - true if area lights should be rendered as point lights. - - - - - Returns an interface pointer to the object snap manager. See Class . Also see the Advanced Topics section on ~{ Snapping }~. - - - - - This is used internally by the Manager. Plug-Ins don't need to use this method. - - - - - This is used internally to invalidate the osnap drawing mechanism. Plug-Ins don't need to use this method. - - - - - Returns true if the application operates in network render server mode. In this mode the application renders a specified scene and exists without showing its main user interface. This means that when this mode is active some plug-ins can chose not to display their user interface or not load at all. When in this mode, the application is also in quiet mode, see Interface::GetQuietMode(). - - - - - Extends Client code should retrieve this interface using GetCOREInterface10. - - - - - Get whether or not if we are in the trajectory mode in the motion panel. - - - true if we are in trajectory mode, false otherwise. - - - - - Get whether or not the trajectory is in the key subobject mode so that keys may be edited. - - - true if the trajectory is in key subobject mode is on, else false. - - - - - Get whether or not the trajectory is in the add mode of the key subobject mode so that keys may be added by interactively pressing left-click on the trajectory. - - - true if the trajectory is in mode to add keys, else false. - - - - - Delete the selected trajectory keys. - - - This function will only do something if trajectories are enabled and we are in the key subobject mode with selected keys. - - - - - Retrieves the animation preference controlling whether or not a default key is set when animating with Auto Key enabled on a controller with no keys. If it returns TRUE then a default key will get set, otherwise it won't. Note that biped controllers aren't affected by this flag since biped controllers never set a default key. - TRUE if a default key will get set when auto keying - - - - - Returns the animation preference controlling at what time a default key will get set when auto key is on. Note that default key option has to be on in order for the default key to get set at the specified time. - The time that the default key will get set when auto keying. - - - - - Finds nodes in the current scene that are similar to a set of "template" nodes. - - - Two or more nodes are considered similar if they are of the same "type" and their node properties match (see Interface10::ENodeProperties for a list of supported node properties) Nodes are considered of the same "type" if they are instances of the same ADT Style, or Autocad Block, or if they have the same class and superclass ID. Targets of cameras and lights are considered of the same type if their camera or light has the same class and superclass ID. - Use Interface::SelectNodeTab to select all the similar nodes - - - nodes similar to these ones need to be found - - the nodes that were found to be similar to the "template" nodes. This list of nodes contains no duplicates. - - Flag encoding the node properties to be matched. Only nodes whose property specified by this flag matches will be considered similar. - - - - Returns the string on the top of the prompt stack. - - - - - Formats a time value into a string, as shown in the render progress dialog. - - - - - Extends Client code should retrieve this interface using GetCOREInterface11. - - - - - Returns TRUE if the rendering uses the active viewport, FALSE if locked on a viewport. - - - This corresponds to the lock button for the viewport dropdown in the render dialog. - - - - - Returns the number of render presets in the render dialog's most-recently-used render preset list. - - - - - Returns the display name of an entry in the render dialog's mostly-recently-used render preset list. - - - If an invalid index is passed, it will wrap around to a valid index, since the MRU list contains a fixed number of items. - - The index within the most-recently-used render preset list - - - - Returns the filename associated with an entry in the render dialog's mostly-recently-used render preset list. - - - If an invalid index is passed, it will wrap around to a valid index, since the MRU list contains a fixed number of items. - - The index within the most-recently-used render preset list - - - - Returns the world transform location of the current transform gizmo. - - - Returns the world transform of the current transform gizmo in the active viewport. - The world transform of the transform gizmo in the active viewport. - - - - - Popup the viewport configuration dialog with specified tab page. - - - If an invalid index is passed, the dialog will show the first tab page when it starts up. - - The index of the tab page that to be showed on the dialog starts up - - - - Extends Client code should retrieve this interface using GetCOREInterface12. - - - - - Get the coordinates for the area within the main window available for client UI components. - - - The Application Frame reserves a portion of the client area for its own UI. Use the coordinates given by this method to determine the available space for control placement in the main UI. Absolute positioning of controls based on (0,0) is inappropriate and will cause controls to paint under the frame's UI. Similarly, this method should be used instead of GetClientRect, which will return an area including the region under the frame. - Main window client area, relative to the main window's upper left corner. - - - - - Extends Client code should retrieve this interface using GetCOREInterface13. - - - - - Returns the length of the numeric prefix used in names. The default suffix length is 3 digits. - - - - - Popup a dialog allowing a user to pick a plug-in class. Only one class may be picked. - - - Displays the names of each class of the given superclass, in a single-pick listbox, The list may be filtered using a callback provided by the caller. - The class picked by the user - - The parent window for the dialog - The title text for the dialog - The superclass of the class names to display - The filtering callback, defined by the caller - - - - Popup a dialog allowing a user to pick multiple plug-in class. - - - Displays the names of each class of the given superclass, in a multi-pick listbox. The list may be filtered using a callback provided by the caller. - The number of classes picked by the user - - The parent window for the dialog - The title text for the dialog - The superclass of the class names to display - The filtering callback, defined by the caller - The list of classes picked by the user, populated by the callee - - - - Returns whether rendering uses Iterative mode, when appropriate. - - - In Iterative mode, no files are output, no email notifications are sent, and no network or multi frame rendering is performed. Iterative is used only for Quick Renders, and only when this flag is set. - - - - - Saves the current scene into a format compatible with the specified 3ds Max version. - - - This method does not bring up a file save dialog. - true if the file was saved successfully; otherwise false - - - the name of the file the scene is to be saved to - - if true, the scene 'dirty' flag is cleared thus a subsequent save will do nothing - - if true, the saved file will become the current scene and the file is added to the "Most Recently Used" list of files - - the version of 3ds in which the file is to be saved. Currently it supports saving to the current version of 3ds (MAX_RELEASE) and previous three versions. A value of 0 is considered same as MAX_RELEASE. - - - - Saves the specified nodes into a format compatible with the specified 3ds Max version. - - - This method does not bring up a file save dialog. - true if the file was saved successfully; otherwise false - - - the name of the file the scene is to be saved to - - list of nodes to save - - the version of 3ds in which the file is to be saved. Currently it supports saving to the current version of 3ds (MAX_RELEASE) and previous three versions. A value of 0 is considered same as MAX_RELEASE. - - - - Saves the selected nodes into a format compatible with the specified 3ds Max version. - - - This method does not bring up a file save dialog. - true if the file was saved successfully; otherwise false - - - the name of the file the scene is to be saved to - - the version of 3ds in which the file is to be saved. Currently it supports saving to the current version of 3ds (MAX_RELEASE) and previous three versions. A value of 0 is considered same as MAX_RELEASE. - - - - Archives the current scene into a format compatible with the specified 3ds Max version. - - - true if the file was archived successfully; otherwise false - - - the fully qualified file name the scene is to be archived to - - the version of 3ds in which the file is to be saved. Currently it supports saving to the current version of 3ds (MAX_RELEASE) and previous three versions. A value of 0 is considered same as MAX_RELEASE. - - - - Gets whether the scene file is written compressed. - - - - - Sets whether the scene file is written compressed. - - - - - whether to compress on save - - whether to persist setting across 3ds sessions - - - - Gets a pointer to the . - - - - - Returns the Editor Dialog Mode, either Basic or Advanced. - - - Opening the editor using Interface7::OpenMtlDlg() opens the corresponding dialog; both cannot be open simultaneously. - A mtlDlgMode value - - - - - Returns whether the given Editor is open, either Basic or Advanced. - - - - A mtlDlgMode value - - - - Opens the given Editor, either Basic or Advanced. No effect if already open. - - - Opening multiple different editors simultaneously is not supported, and may lead to instability. - - A mtlDlgMode value - - - - Closes the given Editor, either Basic or Advanced. No effect if already closed. - - - - A mtlDlgMode value - - - - Extends Client code should retrieve this interface using GetCOREInterface14. - - - - - This method gets a interface given a view ID. If the given view ID doesn't match any of the viewport, the interface of the current active viewport will be returned. - - the unique ID of a viewport. The view ID can be retrieved by calling . Each view is uniquely identified by an ID which is persisted with the 3ds file. Client code that previously (3ds 2012 and earlier) stored a ViewExp*, can now store the view ID. Note that since views (viewports) can be destroyed as of 3ds 2013, plug-ins should not store pointers, as they will become invalid when the underlying view (viewport) is destroyed. Instead, plug-ins should store the view's unique ID. - - - - Get the viewport ID used, when the rendering is locked on a viewport, for the current renderer. - the ID of the viewport to be rendered when the rendering is locked on a viewport. - - - - - This method is used to access the data used when creating a preview image from the currently active viewport using the real-time (viewport) renderer. - A copy of the preview parameters - - - - - Retrieve Play Preview When Done option accessible in the Preferences dialog and the Make Preview dialog. - - - - - if true, don't use language specified in scene file when doing string conversions during scene file load, instead use value from LanguageToUseForFileIO() In scene files created by 3ds Max 2012, the 3ds Max language ID and active code page are stored in the file. Normally, string conversions during scene file load would be based on the saved language ID. If this method returns true, the user has specified to do string conversions based on the return value of LanguageToUseForFileIO() instead. - If true, use the language id from LanguageToUseForFileIO()for string conversions while reading scene files - - - - - if true, use the CodePage specified in scene file when doing string conversions during scene file load instead of using the LANGID in the file or specified by LanguageToUseForFileIO() In scene files created by 3ds Max 2012, the 3ds Max language ID and active code page are stored in the file. Normally, string conversions during scene file load would be based on the saved language ID. If this method returns true, the user has specified to do string conversions based on the saved active code page instead. - If true, use the code page specified in the scene file for string conversions while reading - - - - - if true, when saving non-scene legacy files that are readable by 3ds Max, allow use of UTF8 encoding of strings when it is necessary to convert from wide (Unicode) strings to narrow (ascii/mbcs) strings. If this method returns false, do string conversions based on the return value of LanguageToUseForFileIO() and CodePageForLanguage() instead. - If true, use the UTF8 codepage when writing non-scene legacy files - - - - - sets return value from LegacyFilesCanBeStoredUsingUTF8() - - The value to return from - - - - Helper method for converting AppDataChunks containing mbcs string data to utf8 encoded string data This method is used primarily in AppDataLoadCallbacks registered using Animatable::RegisterAppDataLoadCallback to convert AppDataChunks containing mbcs string data to utf8 encoded string data. The utf8 encoded string data is prepended with the utf8 BOM ("\xef\xbb\xbf") to signify that it is utf8 encoded. When retrieving the string from the , check to see if the first 3 chars are the utf8 BOM and convert accordingly. - - The to acquire the from. - The of the owner of the chunk. - The SuperClassID of the owner of the chunk. - The list of sub-chunk ids - The code page of the mbcs string data - - - - returns the default code page for Loading aux file This method would be used outside of scene file io, primarily when doing aux file io. If doing scene file load, should be using the result from ILoad::CodePage(). - - - - - returns the default code page for Saving aux file This method would be used outside of scene file io, primarily when doing aux file io. If doing scene file save, should be using the result from ISave::CodePage(). - - option to save the file in UTF8 encoding - - - - This method renders a texmap (or an entire texmap tree) to the specified bitmap. - Parameters: - *tex - - The to render to a bitmap. - - *bm - - A pointer to a bitmap to render to. This bitmap must be created at the resolution you wish to render to. - - FBox2* range - - A pointer to UV range to crop the texmap. When specified, the scale3d parameter won't have any effect. If NULL, will retain the UV parameters as specified in the scene at time t. - - TimeValue t - - The time at which to render the texmap to the bitmap, defaults to the current frame. float scale3d=1.0f - - This is a scale factor applied to 3D Texmaps. This is the scale of the surface in 3d space that is mapped to UV. This controls how much of the texture appears in the bitmap representation. - - BOOL filter=FALSE - - If TRUE the bitmap is filtered. It is quite a bit slower to rescale bitmaps with filtering on. - - BOOL display=FALSE - - If TRUE the resulting bitmap is displayed using the virtual frame buffer; otherwise it is not. bool bake - - Used to bake the texture to bitmap without including the effects of scale/rotation etc. If true, the function will render the unit square of 2D texture maps, by effectively disabling the UV Generator during texture rendering, so no settings like scale, rotation, tiling etc. have any effect on the result. This baked 2D representation can then later be scaled, rotated and tiled, for use in a renderer that may not support the particular texture, sent to a game engine, or similar. - - const MCHAR *name=NULL - - Display . - - float z=0.0f - - The w component of UVW. - - BOOL mono=false - - Use mono channel. Mono channels are those that don't have a color, but rather a single value. - - disableBitmapProxies=false - - Used to disable bitmap proxies. bitmap proxies are used to reduce the amount of memory required by the bitmapped textures. - - - - - - - Extends Client code should retrieve this interface using GetCOREInterface15. - - - - - returns the main 3ds Max thread id - - - - - returns the asset path for the template used at scene creation - - - - - Extends Client code should retrieve this interface using GetCOREInterface16. - - - - - Get the viewport ID used, when the rendering is locked on a viewport, for the specified renderer. - the ID of the viewport to be rendered when the rendering is locked on a viewport. - - - - - Sets the viewport ID used, when the rendering is locked on a viewport, for the specified renderer. If an invalid ID is set, attempts to launch a render will fail and an error dialog will be displayed. - - The ID of the renderer. See . - ID of the viewport to be rendered when the rendering is locked on a viewport. - - - - Returns the view which is currently selected for rendering, in the render settings panel. - - - - - gets whether world axis is shown in viewports - - - - - Get the current override material of the render settings. /return the current override material - - - - - Extends Client code should retrieve this interface using GetCOREInterface17. - - - - - Returns whether the trajectory of unselected nodes will show ticks at every frame. - - - - - Returns whether the trajectory of unselected nodes will show key markers. - - - - - Returns whether the trajectories will be drawn for only a subset of the whole animation duration. - - - - - Returns whether, if trajectories are trimmed, they are drawn for a fixed range of frames (or a range around the current frame) - - - - - - - Sets whether, if trajectories are trimmed, they are drawn for a fixed range of frames - - - - - - - - Returns the number of frames before and after the current frame that trajectories will be drawn. - - - - - Returns the start frame of the section of the animation range in which trajectories are drawn. - - - - - Returns the end frame of the section of the animation range in which trajectories are drawn. - - - - - Returns whether the trajectory of selected nodes will draw tangents for all keys, selected or not. - - - - - Returns whether the trajectory of selected nodes will show ticks at every frame. - - - - - Returns whether the trajectory of selected nodes will draw ticks in the path color (or in white) - - - - - Returns whether the trajectory of selected nodes will draw the key times for each key. - - - - - Returns whether the trajectory of selected nodes will draw the key identifier. - - - - - and get the TMCache flag for retaining computed node transforms. When this flag is active, all node transforms (except those in Biped) are cached on whole frame numbers (as determined by the current FPS). These transforms are retained until cleared by BaseNode::InvalidateTM(), change in FPS or setting SetEnableTMCache(false). - This makes retrieval of node transforms faster once they have been computed for the first time. However, please note that this means that invalidation through notifications (notably REFMSG_CHANGE, REFMSG_OBJECT_CACHE_DUMPED) are more critical (particularly the interval sent in the notifications) in cases where the node transform has been invalidated, since the node TM cache is invalidated only for frames within the interval specified. (You can always send the interval FOREVER, but this will of course force all node transforms to be recomputed when first requested.) - If you are seeing inconsistent results from node transforms you can turn this flag off to compare results. Turning the flag off temporarily to avoid using notifications is not recommended. - By default, EnableTMCache is true. - - - - - Gets whether running in Non Interactive Mode. In Non Interactive mode 3ds Max starts up minimized, loads the command line scene file, runs command line and startup scripts, and shuts down. - True if in non interactive mode. - In non interactive mode the following behavior exists: - - Whether to check if in Non Interactive Test Mode. If so, this method returns true even when not in non interactive mode. - - - - set that we are running in Non Interactive Test Mode. This is used for testing purposes. This does not affect licensing or startup behavior, rather the disabling certain functionality when running in Non Interactive Mode. - - - - - security measures include but is not limited to - - - - - Gets whether Ribbon support is enabled - - - - - Break the tangents of the selected trajectory keys. - - - This function will only do something if trajectories are enabled and we are in the key subobject mode with selected keys. - - - - - Unify the tangents of the selected trajectory keys, when unified they will move together. - - - This function will only do something if trajectories are enabled and we are in the key subobject mode with selected keys. - - - - - the tangents type for the selected trajectory keys. - - - This function will only do something if trajectories are enabled and we are in the key subobject mode with selected keys. - - Bezier Tangent Types see /ref keyFlagBits_bezierTangentTypes - - - - Forces a rebuild of the Scene library. - - - The Scene library is not guaranteed to be accurate after some scene operations. For example, if you delete a node, the material for that node may still appear in the Scene library. In order to force an update of the Scene library, call this method. - - - - - Sets the Rendering Format to Custom. - - - - - Brings up the standard Save File As dialog box to allow the user to save the specified material library. - - - - The parent window handle. - The material library to save. If null, the user material library is saved. - The seed file name. - If not null and the save is successful, set to the filename saved to. - - - - Fills the with the entries for saving a Library. The entries will include those for saving to a previous version of 3ds Max. - - - Sample Code: - - The to populate. - - - - Saves the specified material library to the specified file. This method does not bring up a file dialog. - - - True if the library was saved; otherwise 0. - - The file name to save to. - The material library to save. If NULL the current material library is saved. - The 3ds version release number (for example, MAX_RELEASE_R24 for 3ds 2022) to save as, 0 means current version. - - - - Returns whether can save to the specified 3ds Max version. 3ds Max supports saving to previous 3 versions. - - - True if can save to the specified 3ds Max version. - - The 3ds version release number (for example, MAX_RELEASE_R24 for 3ds 2022) to save as, 0 means current version. - - - - When the viewport statistics are enabled (polygons/triangles/Vertices/FPS etc), you may want to stop refreshing them since you are adding multiple nodes to the scene, such as during an import operation, and there is no point in refreshing the viewport statistics after each node is added to the scene. Another case is when you are adding multiple viewport RenderItems from a IObjectDisplay2::UpdatePerNodeItems() call. Note : calling EnableViewportStatisticsRefresh(true) will also trigger a complete refresh of the viewport statistics, same as calling RefreshViewportStatistics() below. If you do not want a refresh when enabling the statistics, please consider using EnableViewportStatistics(bool enable);. - - - - : if true, the refresh is enabled, if false it is disabled. - - - - When the viewport statistics are enabled (polygons/triangles/Vertices/FPS etc), this method forces a refresh. - - - - - When the viewport statistics are enabled (polygons/triangles/Vertices/FPS etc), you may want to stop refreshing them since you are adding multiple nodes to the scene, such as during an import operation, and there is no point in refreshing the viewport statistics after each node is added to the scene. Another case is when you are adding multiple viewport RenderItems from a IObjectDisplay2::UpdatePerNodeItems() call. Note : this will enable/disable the statistics, but will never refresh the viewport statistics, if you want to do so, you need to call RefreshViewportStatistics(). - - - - : if true, the refresh is enabled, if false it is disabled. - - - - Globally rescales all key frames in one specified interval to another specified interval. This method corresponds to the Re-scale Time dialog accessed from the Time Configuration dialog. - - - - The interval to scale from - The interval to scale to - If true, current animation time line is set to newSegment - If true, rescaled key frame times are moved to the nearest frame (rounding up) - - - - Whether the specified node is a regular modifiable node in the current scene. - - - true if the specified node is a regular modifiable node in the current scene. - - The node to check. - - - - Returns true if the specified screen coordinate is over a viewport. - - - true if the specified screen coordinate is over a viewport. - - The screen coordinate. - The viewport panel index. - The viewport index. - The viewport id. - The coordinate within the viewport. - The viewport HWND. - If not null, the topmost node at the screen coordinate - - - - Invalidate all pages in Grid and Snap Settings dialog. - - - - - Enable/Disable Angle Snap. - - - - : if true, Angle Snap is enabled, if false it is disabled. - - - - Enable/Disable Percent Snap. - - - - : if true, Percent Snap is enabled, if false it is disabled. - - - - Returns the User stored in scene files. Defaults to "". - - - - - Sets the User stored in scene files. - - - - - the User - - whether to persist setting across 3ds sessions - - - - Returns the Computer stored in scene files. Defaults to "". - - - - - Sets the Computer stored in scene files. - - - - - the Computer - - whether to persist setting across 3ds sessions - - - - This class extends Max's previous version of core interface (class ) "7" is the major version number of Max that exposes this interface. Call GetCOREInterface7 to acquire a pointer to this interface. - - - - - Retrieves the currently selected nodes into the supplied parameter. It clears the node tab supplied as parameter before using it. - - - - - Returns the current pivot mode the system is in. - - - - - Returns true if the transforms applied to a node will affect its children, otherwise returns false - - - - - Given a reference coordinate system id, returns the name of it. - - - - - Allows for setting the specified node's axis, as the current reference coordinate system - - - - - Only relevant for network rendering. It is possible to set a job flag indicates that max should attempt to continue to render even when an "error" has been detected. This method allows plug-ins to determine whether this flag has been set. - - - - - Methods used to sync use with Editor sample rendering. - - - - - Returns the window handle of the status panel window (this holds the MAXScript mini-listener) - - - - - Starts the MAXScript help. - - - - - Retrieves maxscript preferences. - - - - - Sets the focus to the specified track view window. - - - - - The mask bits are defined in MAXSDK/INCLUDE/ITREEVW.H. Internally, the mask bits are stored in two DWORDs The 'which' param tells which to work with - valid values are 0 and 1. - - - - - Returns that has specified object as base object or modifier. - - - The first found matching requirements. - - The object to search using. - If true, will return even if under scene xref root node. - If true, will return even if not found under scene root node or (if applicable) under scene xref root node. - If true, if obj is the delegate of a scripted plugin, will continue search using the scripted plugin. - If true, if obj is wrapped by an XRef , will continue search using the XRef . - If true, if obj is a branch of an object (such as ), will continue search using the object. - If true, if find node that is not selected, continue searching and if find node that is selected return the selected node instead. - - - - Returns Tab<INode*> which have specified object as base object or modifier. - - - The INodes found matching requirements. - - The object to search using. - If true, will return even if under scene xref root node. - If true, will return even if not found under scene root node or (if applicable) under scene xref root node. - If true, if obj is the delegate of a scripted plugin, will continue search using the scripted plugin. - If true, if obj is wrapped by an XRef , will continue search using the XRef . - If true, if obj is a branch of an object (such as ), will continue search using the object. - - - - Suspends / Resumes command panels specified via bits set in whichPanels param. - - - - - This method expands Interface::AddClass. It allows for adding new dynamically to create panel - - - - - Rebuilds the list of groups and categories of the Create Panel. - - - - - Returns FALSE if the editing is stopped. While stopped, it shouldn't be resumed. - - - - - Allows for changing the modifier panel's. - - - - - Fast node creation for FileLink. - - - - - Adds a permanent user path associated to a particular asset type. - - - TRUE if the path was added, FALSE if not - Remember that this function is for adding permanent user paths, not session user paths. Session user paths are temporary. - - An absolute path - An enumeration constant representing the asset type - Update system configuration files with the new data - - - - Deletes the "ith" permanent user path associated with a particular asset type. - - - a c-string with an absolute path to the ith asset directory - Remember that this function returns a permanent user path, not a session user path. - - The index of the directory you want to delete - An enumeration constant representing the asset type - Update system configuration files with the new data - - - - Updates system configuration files' asset directory section of a particular asset type, with changes made to the session and/or permanent asset directories of that particular asset type. - - - a c-string with an absolute path to the ith asset directory - Remember that this function returns a permanent user path, not a session user path. - - An enumeration constant representing the asset type - - - - Appends a string to the current file name and file path. It also updates the string in the application's title bar. - - - - - Returns empty MSTR if locType == LOC_REGISTRY. - - - - - - Schematic ----------------------------------------------- - /// - - - - - See 'Scene Display Flags' in maxapi.h for the possible values of 'flag'. - - - - - Access to the scene interface. - - - - - Returns whether any Editor is open. - - - Pertains to either the Basic or Advanced editor according to the current mode; both cannot be open simultaneously. - - - - - Opens the Editor. No effect if already open. - - - Opens either the Basic or Advanced editor according to the current mode; both cannot be open simultaneously. - - - - - Closes the Editor. No effect is already closed. - - - Closes either the Basic or Advanced editor according to the current mode; both cannot be open simultaneously. - - - - - Returns the window handle for the viewport frame. - - - - - Viewport access by index. - - - - - Viewport name access. - - - - - Viewport blow-up and sub-region access. - - - - - - - The time to redraw the viewports at - - See for a list of possible values - - - - - - The time to redraw the viewports at - - See for a list of possible values - - - - Returns the current viewport rendering level. - - - See Viewport Rendering Levels for possible values - - - - - Access dual plane settings. - - - - - When the flag is On, only frozen objects are hit tested during a pick. - - - - - Scale modes: CID_OBJSCALE, CID_OBJUSCALE, CID_OBJSQUASH (see cmdmode.h) - - - - - Center modes - see 'Origin modes' in maxapi.h. - - - - - related. - - - - - - XRefs ----------------------------------------------------- - - /// - - - This function is for internal use only. - - - - - 'f' parameter can take values defined as 'Xref flag bits' in inode.h - - - - - the given attribute on the passed nodes. - - - - - An array of nodes to set the attribute on - - One of the list of - - If true the attribute is set on all the nodes, if it is false, the attribute is cleared - - - - the given attribute on the passed node. - - - - - A pointer to the node to set the attribute on - - One of the list of - - If true the attribute is set on all the nodes, if it is false, the attribute is cleared - - - - Old style playback with no immediate return. - - - - - Tests of modifier applicability. - - - - - Returns FALSE if the specified modifier cannot be applied to the object. - - - - - Adds the specified modifier to a node. & node - the node the modifier will be added to & mod - the modifier instance that will be applied to node int beforeIdx - the index in the modstack where the modifier should be inserted. 0 means at the top of the modstack (just below the node) If the object's stack doesn't have beforeIdx number of modifiers in it, the modifier is added at the lowest possible index (just on top of the base object) Returns one of these error codes: kRES_INTERNAL_ERROR - if an error such as invalid pointer is encountered kRES_MOD_NOT_APPLICABLE - if the modifier is not applicable kRES_SUCCESS - on success - - - - - Deletes the first occurrence of the specified modifier from the node's modifier stack. Returns one of the following values: kRES_INTERNAL_ERROR, kRES_MOD_NOT_FOUND or kRES_SUCCESS - - - - - Deletes the modifier at the specified index from the node's modifier stack Returns one of the following values: kRES_INTERNAL_ERROR, kRES_MOD_NOT_FOUND or kRES_SUCCESS - - - - - Finds the first occurrence of the specified modifier on a node. It returns a pointer to the derived object to which this modifier belongs, the index of the modifier within this derived object and the index within the modifier stack. If the modifier is not found, returns NULL. It searches the WS, then the OS part of the geom pipeline of the node. - - - - - Finds the modifier at the specified modstack index on a node. It returns a pointer to the derived object to which this modifier belongs, the index of the modifier within this derived object, and a pointer to the modifier itself. If the modifier is not found, returns NULL. It searches both WS and OS part of the geom pipeline of the object - - - - - Finds the index of a modifier instance in a modstack of a node, when the node, the modifier it's corresponding cod context are given. It returns a pointer to the derived object to which this modifier belongs, the index of the modifier within this derived object, and a pointer to the modifier itself. If the modifier is not found, returns NULL. It searches both WS and OS part of the geom pipeline of the object node, mod and mc are input parameters, while modStackIdx and dobjidx are output params - - - - - A node's reference to its object should be replaced using this method. Returns NULL when the operation cannot be completed, such as for Actively (File) Linked objects or their user created clone-instances / references. - - - - - The interface class for max version 8. - - - This interface should always be retrieved over or when programming against version 8 of the application. It features new functionality and deprecates obsolete functions. - - - - - Launches a Quick Render, as though pressing the Quick Render button. - - - The result of the render - Nonzero if success; otherwise 0. - - The time to render the image. Pass TIME_PosInfinity or TIME_NegInfinity to use the current slider time - The bitmap to render to, or NULL for default handling. If a bitmap is provided, the caller is responsible for displaying the VFB and saving the file. - The is an optional callback. Pass NULL for the default render progress dialog - - - - Enumerates the frames for rendering, as specified in the Render Dialog. - - - - The frame number list; this is resized and set by the callee - - - - Returns the custom progress callback, if any, used for rendering through the UI. - - - If NULL, the renderer will use its default progress dialog - - - - - Returns the custom camera node, if any, used for rendering through the UI. - - - If NULL, the renderer will render from a viewport by default - - - - - Returns the "Put Image File List(s) in Output Path(s)" setting in the render dialog. - - - - - Returns the file format used when the renderer creates image sequence files. - - - For .imsq files this is 0, otherwise for .ifl files this is 1 - - - - - Saves image sequence files (in .imsq or .ifl format) based on the current output settings. - - - Equivalent to pressing the "Create Now" button for image sequence files in the render dialog - - An optional callback object to be called for each sequence file created - - - - Returns the AssetUser of the Pre-Render as indicated in the render dialog. - - - - - Returns the Enable setting for the Pre-Render in the render dialog. - - - - - Returns the Execute Locally setting for the Pre-Render in the render dialog. - - - - - Returns the AssetUser of the Post-Render as indicated in the render dialog. - - - - - Returns the Enable setting for the Post-Render in the render dialog. - - - - - Retrieves the default value of the animation preference which determines whether the active range of parametric controllers will be respected or not. This preference does not affect keyable controllers. When range is respected, the controller evaluation at a time before the activation range start time will return the value at start time and evaluation after activation range end time, the value at end time. Users can see the activation range of controllers as a black line in the Track , in Dope Sheet mode, when Edit Ranges is on. - - TRUE if by default, the animation range of controllers is not respected, FALSE otherwise - - - - - Get the default tangent type for both the "In" and the "Out" tangent. This tangent type is the one that gets applied to any new animation key created in Max. - - - default type for the "In" tangent. - - default type for the "Out" tangent. - - - - the default tangent type for both the "In" and the "Out" tangent. This tangent type will get set on any animation key created in Max. - - - default type for the "In" tangent. - - default type for the "Out" tangent. - - TRUE if tangent type values have to be written in the config file, FALSE otherwise. - - - - Returns whether quick manipulation mode for spring controllers is on. - - - Retrieves the animation preference controlling whether spring systems used in spring controllers are in quick edit mode. The default is to be OFF. If turned on, then when something invalidates a spring controller, instead of recomputing the results from start as would be required to get the correct results, it resets the system a certain number of frames back (see GetSpringRollingStart() below). This can make a big difference in interactivity. - - TRUE if the spring controllers are in quick edit mode - - - - - Returns the rolling start value of the quick manipulation mode for spring controllers. - - - Returns the animation preference controlling how many frames back the spring controllers will use as a rolling starting point for simulation - - - - - This method returns the color corresponding to the id in input. - - - This function represents the color-id mapping that is done for : - - - - - Register a callback object to be called during max shutdown. - - - the object - - - - Unregister a callback object to be called during max shutdown. - - - the object - - - - Opens a max-style File Save As dialog for generic file types. - - - Launches a generic File Save As dialog which supports arbitrary file types. The dialog includes 3ds Max specific browsing features such as browse history. When this function returns it will save the new filter index in 's data member m_newFilterIndex. This will allow developers to save the new index by calling FilterList::GetNewFilterIndex() and thus setting the correct filter index (calling FilterList::SetFilterIndex()) when this function is called again. This makes sure the dialog is showing the correct file extension to be used. - filename contains the long filename user selection if this function returns "true"; initialDir contains the path of the file selected, if this function returns true, otherwise it contains the original contents passed-in - true if the user makes an acceptable choice, false if canceled - - The window handle which should be this dialog's parent window. - The string to be set as the title of this dialog. - As an in parameter, can contain the long or short name of the file that should be default selection of the dialog. As an out parameter, filename contains the long name of the file selected by the user, if this function returns - As an in parameter, contains the initial dialog directory. If the user clicks OK, then this parameter contains the user selected directory path. - A list of extensions supported by this dialog. See documentation for details. - - - - Opens a max-style Open dialog for generic file types. - - - Launches a generic Open dialog which supports arbitrary file types. The dialog includes 3ds Max specific browsing features such as browse history. When this function returns it will save the new filter index in 's data member m_newFilterIndex. This will allow developers to save the new index by calling FilterList::GetNewFilterIndex() and thus setting the correct filter index (calling FilterList::SetFilterIndex()) when this function is called again. This makes sure the dialog is showing the correct file extension to be used. - filename contains the long filename user selection if this function returns true; initialDir contains the path of the file selected, if this function returns "true", otherwise it contains the original contents passed-in - true if the user makes an acceptable choice, false if canceled - - The window handle which should be this dialog's parent window. - The string to be set as the title of this dialog. - As an in parameter, can contain the long or short name of the file that should be default selection of the dialog. As an out parameter, filename contains the long name of the file selected by the user, if this function returns - As an in parameter, contains the initial dialog directory. If the user clicks OK, then this parameter contains the user selected directory path. - A list of extensions supported by this dialog. See documentation for details. - - - - Makes a window modeless during a render. - - - When a render is in progress, window messages to all windows but the virtual frame buffer and the progress window are suppressed in order to make the render operation modal. This method may be used to make a window modeless during the render operation. All messages sent to the given window handle will no longer be suppressed by the render executer. - Note: A modeless render dialog should, ideally, only display certain statistics or messages. It is unsafe to do any complex operation or user interaction from a modeless dialog while rendering. That is why 3ds max blocks most window messages while rendering by default. - PS: Be sure to un-register your window with UnRegisterModelessRenderWindow() when it is destroyed. - - Handle to the window to be registered. - - - - Un-registers a window registered with RegisterModelessRenderWindow(). See the documentation of RegisterModelessRenderWindow() for more details. - - - - Handle to the window to be un-registered. - - - - Returns true if a window is currently registered with RegisterModelessRenderWindow(). See the documentation of RegisterModelessRenderWindow() or UnRegisterModelessRenderWindow() for more details. - - - - Handle to the window for which the information is desired. - - - - Returns whether a file save operation is currently in progress. - - - true if a file save operation is in progress. - - - - - Loads the specified scene file. - - - true if success, false if there was an error - - the file to load - combination of flags. - - - - Opens a Windows Explorer window pointing to the passed in path. - - - This is a utility function for opening a Windows Explorer window with a given path. The path can point to a folder, or it can be a full path to a file. If the file path doesn't exist, a warning dialog will open indicating that the path does not exist and the explorer will not open. The explorer is executed using a ShellExecute command, and is independent of the calling application. In other words, shutting down max will not result in the explorer app being shut down. - An absolute path value <= 256 characters. A zero length path will result in the explorer opening to the system-default drive (most likely C:). An invalid path will result in a warning dialog, as described above. - An explorer window opens to the location specified by the path. - true if shell function returns a success code - - An absolute path for the location used as the default browse location of the explorer. - - - - The interface class for max version 9. - - - This interface should always be retrieved over , , or when programming against version 9 of the application. It features new functionality and deprecates obsolete functions. - - - - - Opens a application-style Open dialog for generic file types. - - - Launches the standard Browse For Folder dialog in max. - true if the user accepts a selection, false if the user cancels - - The handle to the window to whom this browse dialog should be a child to. - An parameter for specifying user instructions which will appear above the main selection area. These instructions can span multiple lines. If this parameter is an empty string, then default instructions will be specified. - This parameter is used to specify both the initial browse directory, and the user selection. If the user cancels the selection, then this variable will not be modified. If this parameter is an empty string, or if a non-existing directory is passed in, the Windows control will default to the My Documents directory. - - - - Deletes the specified nodes from the scene. - - - Call this method to delete the specific nodes from the scene. The result of this operation is the same as deleting the nodes interactively or via maxscript's "delete <node>" command. If you need to delete individual nodes, use Interface::DeleteNode. - - - - - Description: - This class provides a callback mechanism which can be registered with an interface on Acquire() so that it can be notified when the interface goes away as the server controls the lifetime. - - - - - This method gets called to notify the server is deleting the interface. - Parameters: - BaseInterface* bi - - A pointer to the appropriate . - Default Implementation: - { } - - - - - Returns a pointer to the interface whose ID is specified, for future notification extensions. - Parameters: - id - - The ID of the interface to return. - { return NULL; } - - - - - Description: - Class is the base class for interface servers in 3ds Max and should be inherited by any class that wishes to implement the GetInterface() protocol. The also adds a data member for storing interfaces, typically extension interfaces added to maintain API binary compatibility. - - - - - - Returns a pointer to the interface whose ID is specified. - Parameters: - id - - The ID of the interface to return. - Default Implementation: - { return NULL; } - - - - - Description: - This class is the interface ID for the Publishing System of 3ds Max. This class is structurally very similar to a , containing two randomly-chosen longwords to provide a unique global ID. The various constructors assign a value to each of these. There are also methods to assign and retrieve the individual parts and operators to check for equality or inequality. - - All the methods of this class are implemented by the system. - - - - - Returns the first part of the ID. - - - - - Returns the second part of the ID. - - - - - Equality operator. Returns nonzero if the two parts of the ID are equal to the ID passed; otherwise zero. - Parameters: - & iid - - The ID to check. - - - - - Inequality operator. Returns nonzero if either of the parts of the ID are NOT equal to the ID passed; otherwise zero. - Parameters: - & iid - - The ID to check. - - - - - Assignment operator. - Parameters: - & iid - - The ID to assign from. - - - - - Description: - This is simply a container class to hold some data while the controllers parameters are being edited. All methods of this class are implemented by the system. - Data Members: - HWND hParams; - - The window handle of the rollup page. - - *ip; - - The interface pointer. - - *cont; - - The controller that is being edited. - - - - - This callback may be provided to an intersection-testing function in order to receive information on shape intersections. When an intersection is found, the function will call this method with the 2D location of the intersection ('p') along with the indices of the two shape segments which intersect. - TRUE to continue finding intersections; FALSE to stop intersect tests. - - - - - This callback may be provided to an intersection-testing function in order to receive information on shape intersections. When an intersection in 2D space (ignoring the Z component) is found, the function will call this method with the 3D location of the intersection ('p') along with the indices of the two shape segments which intersect. - TRUE to continue finding intersections; FALSE to stop intersect tests. - - - - - Description: - An is a class that represents a length of time. It has two private data members, start and end that are each TimeValues. A TimeValue is a single instant in time. For more explanation see the Advanced Topics section on ~{ Intervals }~. All the methods of this class are implemented by the system. - - Definitions: - - - - - Checks for equality between two Intervals. - Nonzero if the intervals are equal; otherwise 0. - - - - - Checks for inequality between two Intervals. - false if and only if the intervals are not equal. - - - - - Return Nonzero if the TimeValue passed is greater than or equal to the start value and less than or equal to the end value and not equal to TIME_NegInfinity. Returns 0 otherwise. - Parameters: - const TimeValue t - Nonzero if the TimeValue passed is greater than or equal to the start value and less than or equal to the end value and not equal to TIME_NegInfinity; otherwise 0. - - - - - Returns nonzero if the interval passed is contained within the interval; otherwise 0. - - return InInterval( interval.Start() ) && InInterval( interval.End() ); - Parameters: - interval - - The interval to check. - Returns nonzero if the interval passed is contained within the interval; otherwise 0. - - - - - Returns whether an interval is a subset of this interval. This method is different from InInterval() in the way that it deals with infinite and empty sets. Infinite sets are supersets of everything. sets are subsets or everything. - - - - - Returns whether an interval intersects with another interval. - - - - - Returns 1 if the interval is EMPTY, i.e. has a start and end time equal to TIME_NegInfinity. Returns 0 otherwise. - - - - - Returns true if and only if the interval covers all possible time values, i.e. equals the result of calling SetInfinite(). - - - - - Sets the start and end times for the interval. - Parameters: - TimeValue s - - Start time for the interval. - - TimeValue e - - End time for the interval. - - - - - Sets the interval to be EMPTY, i.e. having a start and end time equal to TIME_NegInfinity. - - - - - Sets the interval to be FOREVER, i.e. have a start time equal TIME_NegInfinity and end time equal to TIME_PosInfinity. - - - - - Sets both the start and end times to the time passed. - - - - - Returns the start time of the interval. - - - - - Returns the end time of the interval. - - - - - Implemented by the System. - - Returns the duration of the interval (end points included). - Operators: - - - - - Intersects and i. The interval will have a start time of the greater of the two interval start times, and an end value which is the lesser of the two end values. If the end time is less than the start time, both the start and end times are set to TIME_NegInfinity. - An that is the intersection of the intervals. - - - - - This updates the invoking interval so it will have a start time of the greater of the two interval start times, and an end value which is the lesser of the two end values. - - return (*this = (*this&i)); - - - - - Expands the to include the TimeValue. - - if (t<start) start=t; if (t>end) end=t; return *this; - - - - - Offsets the entire interval; shifts the beginning and end by the provided time value. Only effective if the interval is neither empty nor infinite. The offset may be positive or negative. Upon returning, the duration of the interval will be identical to what it was before the call, unless this is made impossible by clamping at either end of the valid numerical range. - - - - - Class used to specify action item overrides. - - - The class is an abstract base class to be used to create an action item override. An action item override is an action item that will only execute as long as the action item keyboard shortcut is held. Once released the override will revert back to the state it was in before the action item executed. In order for an override to occur instead of an action item, the client needs to create an instance of a class that implements the virtual functions defined in this base class, and then activate it by calling IActionItemOverrideManager::ActivateActionItemOverride. - - - - - - that returns whether or not we this override is active. - - - TRUE if the override is active, FALSE if otherwise. - - - - - that's called when we start the action item override. - - - that's called when we start the action item override. Usually the subclass that overrides this method will store the state(s) that the override will change and then perform the action, usually as if ActionItem::ExecuteAction was called. - TRUE if we started the override correctly, FALSE otherwise - - - - - that's called when we end the action item override. - - - that's called when we end the action item override. Usually the subclass that overrides this method will restore the state(s) that were stored when IActionItemOverride::StartOverride() was cas called. - the context may be incorrect when this method is called, and that the context should be validated before performing actions. - TRUE if we ended the override correctly, FALSE otherwise - - - - - The interface for managing action item overrides. - - - This manager allows action item overrides to be activated, deactivated and retrieved. This static function-published interface is registered as a core interface. You retrieve this interface by calling Note that once an IActionOverrideItem is managed by this interface by activating it, it then will get deleted by this interface. - - - - - Get whether or not action item overrides are globally active or not. - - - TRUE if action item overrides may be active, FALSE if otherwise. - - - - - How much time, in seconds, that we need to hold a key before a suitable ction item becomes an override. - - - Returns how many seconds that we need to hold a key before an action time becomes an override. - - - - - to register an action item as a possible override. - - - to register an action item as a possible override. The purpose of this is to inform the system of a possible override so that the action item may get highlighted in the customize UI dialog. - - - The action item that may have an override. - Text description of what the override does. - - - - to unregister an action item as a possible override. - - - to unregister an action item as a possible override. The client should call this when either an action item will no longer be overridable of if the action item will get removed from the action table. - - The action item that we want to unregister. Nothing happens if the action item was never registered. - - - - to see if an action item has been registered, and thus may eventually be activated. - - - Return TRUE if the is registered, otherwise return FALSE. - - The aciton item that may have an override. - The text description of the override. - - - - to activate a particular action item with a particular override, which then allows the action item to work like an override also. - - - to activate a particular action item with a particular override. This function must be called in order for a particular action item to work like an override. - - The action item that will be associated with an override. - The action item override that will override the action item when a key is held. Note that once a object is activated the deletion of this object is now the responsibility of the , and so the client shouldn't delete it also. Usually the action item override will be activated after IActionManger::ActivateActionTable is called. - - - - to deactivate an action item override. - - - to unactive an action item with a corresponding action item override. Note that the activated instance will get deleted when this occurs. For efficiency, a user should unactivate their action item and action item overrides whenever they would also deactivate an action table via IActionManager::DeactiveActionTable, usually within a Animatable::EndEditParams function call. - - The action item that will be unactivated. The corresponding IActionActionItemOverride will also get removed and deleted. - - - - Find a particular activated given a particular . - - - Returns the object that's been activated with IActionItemOverrideManager::ActivateActionItemOverride. If none exists, it will return NULL. - - - - - Returns the action item that is currently being overriden. - - - Returns a pointer to the that is currently being overriden. If no action item is being overriden, it return NULL. - - - - - Manages a set of ActionTables, ActionCallbacks and . The manager handles the keyboard accelerator tables for each as well. You can get a pointer to a class implementing this interface using Interface::GetActionManager(). - - - - - - Saves the current keyboard shortcut configuration into the given file name. Note that just the user customized shortcuts will be serialized. The newly stored shortcut file will become the current selected shortcut set, which is used on 3ds Max startup shortcut loading or when the Customize Shortcuts dialog is opened. - TRUE if the file could be successfully saved; FALSE if not. - - The path of the file in which the keyboard shortcuts should be stored. The file must have the .hsx extension. - - - - Loads a keyboard shortcut configuration from the specified file name. The loaded shortcut file will become the current selected shortcut set, which is used on 3ds Max startup shortcut loading or when the Customize Shortcuts dialog is opened. - TRUE if the file could be successfully loaded; FALSE if not. - - The path of the file from which the keyboard shortcuts should be loaded. The file must have the .hsx extension. - - - - Returns the full path to the current keyboard shortcuts file. This can be a shortcut factory preset or a user customized shortcut set. The returned file will have the .hsx file extension. - - - - - Register an action table with the manager. Note that plug-ins that expose their action tables via their ClassDesc::NumActionTables() method. do not need to register their action tables explicitly, as 3ds Max will do it for them. Also note that plug-ins do not need to unregister or destroy their action tables and action items, as 3ds Max will take care of this when it shuts down. Also note that an action table needs to be activated once registered. For more information see IActionManager::ActivateActionTable() See . - - Points to the Action Table to register. - - - - Returns the number of ActionTables. - - - - - Returns a pointer to the nth . - - The zero based index of the table. - - - - Activate the action table. Action tables need to be activated by their owners. Some plug-ins (for instance Modifiers or Geometric Objects) may only want to activate the table when they are being edited in the command panel (between BeginEditParams() and EndEditParams()). Others, for instance Global Utility Plug-ins, may wish to do so when they are initially loaded so the actions are always available. Note that if this method is called multiple times, only the callback from the last call will be used. - TRUE if the action table was activated. FALSE if the table is already active or doesn't exist. - - Points to the callback object which is responsible for executing the action. - This is the ID of the table to activate. - - - - Deactivates the action table. After the table is deactivated (for example in EndEditParams()) the callback object can be deleted. Tables are initially active, please do not call this method without a preceding call to ActivateActionTable(). - TRUE if the action table was deactivated. FALSE if the table was already deactivated or doesn't exist. - - Points to the callback object responsible for executing the action. Pass the same callback that was originally passed to and do not set this to NULL. - The ID of the table to deactivate. - - - - Returns a pointer to an action table. - - The ID of the table to find. - - - - Retrieves the string that describes the keyboard shortcut for the specified . - TRUE if found; FALSE if not found. - - The ID of the action table. - The ID of the command for the action. - to contain the retrieved text. - - - - Retrieves a string that describes the specified operation from the action table whose ID is passed. - TRUE if found; FALSE if not found. - - The ID of the action table. - The ID of the command. - to contain the retrieved text. - - - - Registers an action context. This is called when you create the action table that uses this context. - If the specified action context is already registered FALSE is returned; otherwise TRUE is returned. - - The context ID. - The name for the action context. - - - - Returns the number of ActionContexts. - - - - - Returns a pointer to the nth . - - The zero based index of the . - - - - Returns a pointer to the specified . - A pointer to the or NULL if it not found. - - The ID of the context to find - - - - Checks if an is active or not. - Returns TRUE if the specified context is active; otherwise FALSE. - - Specifies the context to check. - - - - A mixin-interface extension to which allows a client to dispatch a Message back to the application if it is not handled by the focused control. Can be accessed as follows: - This interface is not intended for extension by 3rd-party developers. - - - - - Retrieves the value of the tangent at the nearest key to the given time, based on the given hitFlags. - - - - - Sets the value of the tangent at the nearest key to the given time, based on the given hitFlags. - - - - - Retrieves the flags of the key at the given time, or -1 if no such key exists - - - - - for perfoming workbench analysis functions. - - - This class peforms workbench functions related to analysis of biped fcurves. After analysis, a user may want to perform fixing - - - - - The interface to the functionality for animation layers. - - - This class contains key functionality for creating and manipulation animation layer.s You get this interface by calling - - - - - Brings up or hides the main Anim Layers Manager Dialog. - - - This funciton will bring up or hide the main Anim Layers manager toolbar. - - If true, then show the toolbar, otherwise hide it. - - - - This refreshes the UI in the Anim Layers Manager Dialog, if it's open. - - - - - Brings up the Enable Animation Layers Dialog. - - - This function will bring up a dialog where a user can specify where they want to enable layer animation by creating layer controllers where specified in the dialog. - - The nodes that the results of the filters chosen in the enable animation layers dialog will apply too. - - - - Enable animation layers on specified nodes given particular filters. - - - This function enables animations layers on specified nodes by creating layer controllers as specified by the filter parameter. Note that this function will only create layer controllers, it doesn't delete layer controllers if it's not specified in the filter. - Returns how many layer controllers where made on the specified nodes. - - The nodes where the layer controllers will be created. - Where the layer controllers will be created. - - - - Returns whether or not the specified animatable will be able to be converted to a layer control or not. - Returns true if we can replace it with a layer controller,else returns false. - - The animatable that we want to convert to a layer controller. - The parent of the animatable we want to replace. - The 'anim' animatable subanim's number on the client. - - - - This function will enable a layer on the specified anim in the parameter. If other layers exist on the node that the layer exists on, then the layer control will sync up with those layers. - Returns whether or not we successfully enabled a layer here. Some reasons why we may not be successful is if a a child subanim is already a layer controller(no nested layers) or the controller is a subanim of a position,rotation or scale, controller. - - The animatable that we want to replace with a layer controller. - The parent of the animatable we want to replace. - The 'anim' animatable subanim's number on the client. - - - - Return the total number of layers. - The total number of layers. - - - - - This function returns which layers exist on the passed in nodes. Note that a layer may only exist on some, not all of the nodes. - - The nodes where we are checking for layers. - The indices of which layers exist on these nodes. - - - - Sets the layer active - - The index to set active. If the index is out of range then nothing is set active. - - - - Sets the active layer only on the nodes that are passed in. Also if that layer doesn't exist on a node then nothing occurs. - - The index to set active. - The nodes whose layer will be set to active. - - - - Adds a layer to the specified nodes. If a layer with that name doesn't exist, a layer with that name is created, otherwise the layer with that name will be used to add to those layers. If a node already has that layer, then nothing happens. - - The name of the layer to add to the nodes. - The nodes which will have the named layer added to them. - If true, then the controller type in the active layer will be used to create the new layer, otherwise we will use the default controller type. - - - - Adds a layer to the specified nodes, by bringing up a dialog that lets you specify the layers name and what controller class the new layer will be. - - The nodes which will have the named layer added to them. - - - - Gets which layers are active on the passed in set of nodes. - - The nodes which we are checking for active layers - The layers that are active on these nodes - - - - Gets which nodes in the scene have the active layer on it. - - The nodes which have the active layer on it. Note that if we have multiple active layers, then we will get all of the nodes in those active layers. - - - - Delete this layer. Note that this completely deletes the layer, including any weight control, from the system and any nodes where it exists. - - The layer to delete. Note that we can't delete the first (0th) layer. - - - - Delete this layer from the specified nodes. Note that this only deletes the layer from these nodes, not the system or other nodes. - - The layer to delete. Note that we can't delete the first (0th) layer. - The nodes where the layer will be deleted. Nothing happens if the layer doesn't exist on a node. - - - - Copy this layer to a buffer so that it may be copied. - - The layer to copy. - The nodes where the layer will be copy. Nothing happens if the layer doesn't exist on a node. - - - - Paste the active copied layer at this index on these nodes. If no layer is copied on a node, then nothing will be pasted. - - Where to paste the copied layer over the existing layer. If the index is -1 or greater than the max number of layers already present, it will paste at the end. - The nodes where the layer will be pasted. Nothing happens if the layer doesn't exist on that node. - - - - the layer name at the specified index. If the name already exists, the name won't get changed. - - Where to change the name of the layer. - The new name. - - - - Get the name of the specified layer. - Returns the name of the specified layer. If the index is out of bounds, then an empty string is returned. - - Where to get the name of the layer. - - - - Get the layer weight for the specified layer at the specified time. - Returns the layer weight. - - Where to get the layer weight. - At what time to get the layer weight. - - - - the layer weight for the specified layer at the specified time. - - Where to set the layer weight. - At what time to set the layer weight. - The weight to set. - - - - Get the layer weight control for the specified layer. - Returns the layer weight control. - - Where to get the layer weight. - - - - the layer weight control for the specified layer. - Returns whether or not we were able to set the weight control or not. - - Where to set the layer weight. - The weight control we want to set at that index. It needs to be a float controller. - - - - Get whether or not a particular layer is muted or not. - Whether or not the layer is muted or not. - - Which layer to see if it's muted. - - - - whether or not a particular layer is muted or not. - - Which layer to mute or not. - The mute value for the specified layer. - - - - Get whether or not a particular layer's output is muted or not. - Whether or not the layer is muted or not. - - Which layer to see if it's muted. - - - - whether or not a particular layer output is muted or not. - - Which layer output to mute or not. - The output mute value for the specified layer. - - - - Get whether or not a particular layer is locked. A locked layer cannot be animated nor collapsed, or pasted over and an object with a locked layer cannot get disabled. - Whether or not the layer is locked or not. - - Which layer to see if it's locked. - - - - whether or not a particular layer is locked. A locked layer cannot be animated nor collapsed, or pasted over and an object with a locked layer cannot get disabled. - - Which layer output to lock or unlock. - the locked value for the specified layer. If true the layer is locked if false it is unlocked. - - - - Collapse the layer at the specified index so that it gets deleted and it's keys and values are baked down to the previous layer. - - - Where to collapse. The index must be greater than zero since we can't collapse the first layer. - The nodes where the layer will be collapsed. Nothing happens if the layer doesn't exist on that node. - - - - Disables and removes any layers on the specified nodes, by replacing the layer controller that exists with the first, base layer. Note that it will disable layer controllers that only have one layer. - - The nodes where layers will be disabled. Nothing happens if no layers exists or the layer has more than one layer. - - - - Brings up the Animation Layer Properties Dialog, which lets you set different animation layer properties, such as whether or not we should automatically mute layers greater than the active one. - - - - - Get whether or not trackview will only show the current active layer or all of the layers for all of the layer controllers. - Returns whether or trackview will only show the current active layer or all of the layers. - - - - - Get whether or not we will automatically mute layers greater than the active layer. - Returns whether or not we will automatically mute layers greater than the active layer. - - - - - Get the controller type we will collapse non keyable controllers onto. - Returns the type of controller to collapse non keyable controller onto. Either Bezier, Linear or Default. - - - - - Gets whether or not we will collapse a controller per frame or we will try to just collapse the keys of the two controllers that are being merged. We can only collapse the keys if the two controllers are of the same class and are both keyable. - If true it will always collapse per frame, otherwise it will try to only collapse onto keys if it can. - - - - - Gets whether or not if collapsing per frame we use the active range, or a specified range. - If true, when we collapse per frame we use the active range in the scene, otherwise we use a specified range. - - - - - Gets the collapse range, if we aren't collapsing over the active range interval. - The range we want to collapse a frame per key over. - - - - - of a parameter track object, a member of a track set. - - - The interface provides access to a member of a track set and - represents one track in the track view, for instance, the X position of a - node. A track is defined by a node and then a path of subanims, from the - node down to a leaf controller. For instance the track for the X position - of a node would keep the subAnims of the PRS control, then of the indePos and of the X position. At the moment only tracks that are under a node can belong to a track set. - - - - - Returns the node to which the parameter track belongs - - the node to which the parameter belongs - - - - - Returns the number of subanims for this track, from the node to the leaf controller - - the number of subanims in this track - - - - - Returns the desired subanim. For instance GetSubAnim(0) on the track "Cone01\Transform\Position\X Position" would return the PRS controller under Cone01 - - - zero-based index of the subanim - - - - Returns the desired subanim index. For instance GetSubAnim(0) on the track "Cone01\Transform\Position\X Position" would return the subanim index of the PRS controller under Cone01 - - - zero-based index of the subanim - - - - Returns a string describing the track, e.g. "Cone01\Transform\Position\X Position" - - a string describing the track - - - - - Sets the animation track from a string. The string will be parsed as a node followed with a backslash-separated list of subanims - - - string describing the track - - - - Retrieves the leaf controller of a track - - Pointer to the controller or NULL - - - - - This interface class allows for setting and retrieving assembly membership information to or from nodes. All methods are implemented by the system (Max). Client code can query an for this interface: - - INode* n; - - IAssembly* a = GetAssemblyInterface(n); - - - - - - - Method for setting state of assembly member. To close an assembly member call SetAssemblyMemberOpen(FALSE), as documented below. - - - Parameters: - BOOL b - - Specifies a new state for an assembly member. - - If TRUE the node is set as an assembly member. - - If FALSE removes a closed or open assembly member from membership. An open member will be closed first and then have it's membership flag removed. - - - - - - - Method for opening or closing an assembly member. It should only be called on members. - - - Parameters: - BOOL b - - Specifies the state of the assembly member. - - If TRUE the assembly member is opened. - - If FALSE the assembly member is closed. - - - - - - - Method to designate an assembly member as the assembly head. - - - Parameters: - BOOL b - - Specifies the head state of the member. - - If TRUE the node is set as the assembly head. - - If FALSE an open or closed assembly head becomes a non-head. If the head is open, it is first closed and then the head flag is removed. To close an assembly head call SetAssemblyHeadOpen(FALSE), as documented below. - - - - - - - Method for opening or closing an assembly head. It should only be called on an assembly head. - - - Parameters: - BOOL b - - Specifies the state of the assembly head. - - If TRUE the assembly head is opened. - - If FALSE the assembly head is closed. - - - - - - - Method to determine membership in an assembly. It will work with either open or closed members. - - - If TRUE, node is a member the assembly. - - If FALSE, node is not a member of the assembly. - - - - - - - Method to determine if a node is an assembly head. It works with either open or closed heads. - - - If TRUE, node is an assembly head. - - If FALSE, node is not an assembly head. - - - - - - - Method to determine if an assembly member is open. - - - If TRUE, the assembly member is open. - - If FALSE, the assembly member is not open. - - - - - - - Method to determine if an assembly head is open. - - - If TRUE, the assembly head is open. - - If FALSE, the assembly head is not open. - - - - - - - Method to detect assemblies within assemblies. It checks whether this assembly node is a head node and is also a member of the assembly headed by the node passed in as a parameter. - - - If TRUE, node is both a head node and is a member of another assembly. - - If FALSE, node is neither a head node nor a member of another assembly. - - - - - - - Method to retrieve the value of the bounding box display flag. - - If TRUE, the bounding box display is enabled. If FALSE, the bounding box display is disabled. - - - - - Write method for implementing persistence of the underlying object. - - - Parameters: - ISave* isave - - Pointer for write methods. - - - IO_OK, the call succeeded. - - IO_ERROR, the call was unsuccessful. - - - - - - - Read method for implementing persistence of the underlying object. - - - Parameters: - ILoad* iload - - Pointer for read methods. - - - IO_OK, the call succeeded. - - IO_ERROR, the call was unsuccessful. - - - - - A callback interface for declaring and modifying an asset reference. - - - A callback class used in conjunction with to declare an asset used by this application component. Accessor methods provide high-level information about the assets, and one mutator method - SetPath, is used at the time of declaration to retarget an asset. Classes implementing this interface need not worry about maintaining a persistent link to this interface. It should only be instantiated within the scope of a call to the client's EnumAuxFiles function. When the asset is declared, at that point the enumerating code may choose to retarget the asset. Notice that the accessor does not need to survive beyond the scope which contains the call to - GetPath(). The asset type must be one of the types declared as AssetType. - A client wishing to declare a new category of assets can do so by returning kOtherAsset as a type and implementing the GetAssetDesc() and GetAssetTypeIcon() functions. - Finally, other methods exist that allow a client to return varying amounts of information about an asset. See methods below for details. - - - - - Gets the AssetUser pointing on the asset. - - - enum AssetType has been moved to iAsset.h. See iAsset.h for the various assets types supported by this accessor.Gets the full path of the asset, as declared by the asset. - the asset's AssetUser - - - - - Implementing classes should implement this method so that a call to this method causes the component to point to a newly declared asset. - Note: If an error occurs while repathing, the client might choose to indicate this by returning an error message via GetRetargetErrorMsg(). - This call will only ever be made within the scope of an EnumAuxFiles call on the application component. - The component should now be referring to the new asset path passed into this method. - - An AssetUser of a new asset to refer to. The path of the AssetUser need not be a fully-qualified path. - - - - Should return whether this is an input asset. - - - This method should return true if the asset in question is used as an input to a render. An example of an asset that is not an input would be a RenderElements output asset. - - true if the asset is an input assetDefault implementation: returns true - - - - - Returns the asset type for this asset declaration. - - - Should return an asset type defined in the AssetType enum above. If the asset does not fall under one of the predefined categories, declare the asset as kOtherAsset. - In this case, the GetAssetDesc() should return an appropriate string defining the category to which this asset belongs. - the asset type for this declared asset - - - - - Returns an asset description string, or NULL if this is a standard asset. - - - A component can normally return NULL for this method if the asset declaration falls under one of the pre-defined categories. If an component declares an as kOtherAsset, then it should return an appropriate asset type description (i.e. in the vein of , Photometric, etc.) This description will be used to visually group assets together. A third-party developer can therefore define a new asset group type by consistently returning the same description string for their declared assets, and this will be reflected appropriately in the application interface. - NULL, or a string describing the asset type if the asset type returned for GetAssetType() is kOtherAssetDefault implementation: returns NULL - - - - - Returns the full path of an icon file associated with a custom asset description. - - - If the asset type returned by this accessor is kOtherAsset, and the asset description returned by GetAssetDesc() is non-NULL, then this method should be overwritten to return the full path of an icon file (*.ico) that should be used as the icon for this new asset category. Otherwise, the result from this field is ignored. - GetAssetType() == kOtherAsset, and GetAssetDesc() is non-NULL - The icon file (*.ico) that will be used as the icon to represent this new asset category.Default implementation: returns NULL - - - - - A brief description string of the asset client. - - - A one or two word description of an asset client. This description will be used to briefly describe the source client of this asset. - brief description string of the asset clientDefault implementation: returns NULL - - - - - Whether it is possible to retarget this client's asset. - - - There are cases where an asset can be declared, but cannot be retargeted. If this is the case for an implementing client, then false should be returned here. - Whether it is possible to retarget this client's assetDefault implementation: returns true - - - - - Allows a client to return an error message related to a failed SetPath attempt. - - - An asset client can report a SetPath error via this method. If an error occurs during the SetPath call, then this method should report the error. A manager which calls SetPath on an should call GetRetargetErrorMsg() to determine whether the SetPath succeeded. GetRetargetErrorMsg should return NULL if no error occurs. - NULL if there is no error to report, an error string if an error occured while repathing the asset Default implementation: returns NULL - - - - - The is a static interface to the Assign Vertex utility. - - - It can be obtained as follows: - - - - - Performs a lighting calculation. - - - The result is stored in the given VertexPaint modifier (if provided) or creates a new modifier instanced across the given nodes. - 0 if the vertex paint interface could not be applied, else 1. - - A pointer to an array of nodes pointers to apply the iVertexPaint interface to. This list of nodes will be filtered to include only nodes with geometry objects on return. - An instance of a derived class which supports the interface. If this parameter is null, an instance of the standard Vertex Paint modifier will be created and assigned to the nodes. - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - This class extends to include more options. - - - - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - This is container, anchor point for a set of atmospherics. It's used by the system in RendParams::atmos, enabling the attachment of multiple atmospherics where a single Atmospheric* exists. A pointer to this class may be obtained through a dynamic cast from an Atmospheric*, most notably RendParams::atmos. - - - - - Returns the number of atmospherics present in the container. - - - - - Returns the i'th atmospheric from the container. - - The index of the atmospheric to be returned. - - - - is an interface for getting/setting properties on the Attach controller. - - - The interface is returned by calling GetInterface(I_ATTACHCTRL). - - - - - the Node to attach to. - - - True if the node could be set as the attached to node - - The Node to attach to - - - - Get the Node to attached to. - - - The node attached to - - - - - a attach controller key, creating the key if necessary. - - - - The time of the key - The face index on the node's mesh to attach to - The barycentric coordinates on the face - - - - Get Attach controller Align property. - - - The Align state - - - - - Get Attach controller Manual Update property. - - - The Manual Update state - - - - - Invalidate the Attach controller and update its ui if displayed. - - - - If true, forces an update of the controller even if manual update is off. - - - - class for exposing methods associated with Autodesk 360. This class can be used to get some information on the login state of the current user into Autodesk 360. This informations may be helpful for dealing with rendering in the A360 cloud as well as for using the OxygenID of the current user that may be used for Autodesk AppStore related validations. - - - - - Logs into Autodesk 360. This function will return immediately, the login procedure gets performed in an asynchronous way. - - - - - - - Logs out of Autodesk 360. - - - - - - - Checks if the user is logged in into Autodesk 360. This function just checks if the user is logged in on this machine, but the login information might be cached and the session might not be valid any more. To Check if the session is valid, you have to call IsLoginValid(). - - - - - - - Checks if the user is logged into Autodesk 360 and the login session is still valid. Checks if the user is logged in into and the login session has not yet expired. To Check if a user is logged in only, you may also call IsLoggedIn(). - - - True if the user is logged in and the login session has not expired, false in all the other cases. - - - - - Gets the username if the user is logged in. - - - The Autodesk360 username of the logged in user, or an empty string, if the user is not logged in. - - - - - Gets the OxygenID of the logged in Autodesk360 user. The OxygenID can be used for Autodesk AppStore related validations. - - - The OxygenID of the logged in A360 user or an empty string, if the user is currently not logged in. - - - - - Initializes web-services if not previously initialized. The internal web-services get implicit initialized, so this function normally has not to be called at all, but since loading the services may be a costly operation, this call may be used to preload the needed web-services. - - - - - class for Autobackup. for AutoBackup class. This class has only one instance and is responsible for automatically saving the max scene at periodic time intervals. - - - - - true when Autobackup feature is enabled - - - - - true when Autobackup is temporarily disabled - - - - - of Autobackup files - - - - - Autobackup interval in minutes - - - - - Final countdown interval in minutes - - - - - File name of Autobackup file, excluding path and extension. - - - - - true if scene name is prepended to autobackup file name - - - - - true when Autobackup bailout is enabled - - - - - true when Autobackup files will be compressed - - - - - Performs the actual Autobackup operation. - - - - - Tells whether an Autobackup operation is currently happening. - - - - - Resets timer to interval. Does nothing when timer is not started - - - - - Resets timer to minutes. - - - - - Returns true if Autobackup timer is started. - - - - - Returns the number of seconds until the next Autobackup attempt. Returns -1 if Autobackup is disabled or if Autobackup timer is not started - - - - - Returns true if all conditions are satisfied for next Autobackup attempt to proceed, based on current state. If this is still true when GetSecondsUntilNextAttempt() goes down to 0, Autobackup kicks in. \ see GetSecondsUntilNextAttempt - - - - - Description: - Auto class for Effects auto-UI, instanced by ClassDesc2::CreateParamDialog(). It maintains a table of secondary EffectParamDlg for main EffectParamDlg (e.g., the one returned from CreateParamDialog()) and will broadcast appropriate method calls to them as the main receives them. - - - - - Returns the number of secondary dialogs. - - - - - Adds the specified dialog as another secondary dialog. - Parameters: - SFXParamDlg* dlg - - Points to the parameter dialog to add. - - - - - Returns a pointer to the 'i-th' secondary dialog. - Parameters: - int i - - The zero-based index of the dialog to return. - - - - - Sets the 'i-th' dialog to the one passed. - Parameters: - int i - - The zero-based index of the dialog to set. - - SFXParamDlg* dlg - - Points to the parameter dialog to set. - - - - - This method is used for deleting secondary dialogs from a main . Use this along with AddDlg() if you are dynamically changing the set of rollups for the plugin, so that the P_AUTO_UI system can correctly manage all current secondary rollups. - Parameters: - SFXParamDlg* dlg - - Points to the to delete. - - - - - Returns a pointer to the parameter map2 of this main dialog. - - - - - Description: - This is the Auto class for Editor auto-UI, instanced by ClassDesc2::CreateParamDlg(). It maintains a table of secondary ParamDlgs for main ParamDlgs (eg, the one returned from CreateParamDlg()) and will broadcast appropriate method calls to them as the main receives them. - - - - - This method causes the user interface controls to be re-drawn. - - - - - This method may be called to causes the viewports to be redrawn. It should be called when any parameter that affects the look of the material in the viewport has been altered. If the material is not on a visible node in a shaded view, nothing will happen. This method should not be called as a spinner is being dragged, but only upon release of the mouse button. - - - - - Returns the number of secondary dialogs. - - - - - Adds the specified dialog as another secondary dialog. - Parameters: - ParamDlg* dlg - - Points to the parameter dialog to add. - - - - - Returns a pointer to the 'i-th' secondary dialog. - Parameters: - int i - - The zero-based index of the dialog to return. - - - - - Sets the 'i-th' dialog to the one passed. - Parameters: - int i - - The zero-based index of the dialog to set. - - ParamDlg* dlg - - Points to the parameter dialog to set. - - - - - This method is used for deleting secondary dialogs from a main . Use this along with AddDlg() if you are dynamically changing the set of rollups for the plugin, so that the P_AUTO_UI system can correctly manage all current secondary rollups. - Parameters: - ParamDlg* dlg - - Points to the to delete. - - - - - Returns a pointer to the parameter map2 of this main dialog. - - - - - Implementation of a that handles the automatic creation and lifetime management for a parameter map of a renderer plugin. - - - - - Invalidates the UI for every parameter map controlled by this dialog and its sub-dialogs. - - - - - Returns the number of sub dialogs being controlled. - - - - - Adds a sub-dialog to be controlled by this main dialog. - - - - - Returns the sub-dialog with the given index. - - - - - Replaces the dialog, at the given index, with another. - - - - - Removes the given dialog from the set of sub-dialogs. - - - - - Returns the parameter map to which this dialog is connected. - - - - - Manages controller auto-tangent related options. This interface class allows for querying controllers for their auto-tangent support and the auto-tangent algorithm they use. 3ds Max 2012 introduces an improved auto tangent algorithm which is consistent with the ones used in other Autodesk products. allows to determine whether or not the legacy or the new auto tangent algorithm is used by 3ds Max controllers that implement support for auto tangents, such as the Bezier float and Bezier point3 controllers. Client code can get access to using the following code: - - - - - Returns whether a particular controller supports auto-tangents. - Returns true if the controller supports auto-tangents, for example a Bezier controller. - - The controller to check - - - - Gets the auto-tangent algorithm used by a given controller. - Returns the auto-tangent algorithm being used. If the controller doesn't support auto tangents then eNotSupported is returned. - - The controller to query - - - - Sets the auto-tangent algorithm to be used by a given controllers. - - The list of controllers. - The auto-tangent algorithm to set. eNotSuported is not a valid input. Note that if the controller doesn't support the auto tangent algorithm, no algorithm is set on that controller, effectively setting its type as eNotSupported. - - - - Gets the default auto-tangent algorithm that will be used when new controllers that support auto tangents are created. - Returns the default auto-tangent algorithm. - - - - - Access to name. The name is not case sensitive. - - - - - Returns the number of styles. - - - - - Gets a of IADTStyles for iteration. - - - - - Returns the number of all nodes in the scene that represent instances of all the styles that belong to this category. - - - - - Fills out the provided array with all the nodes in the scene that represent instances of all the styles that belong to this category. - Returns the count - - - - - makes a name unique - - - Creates a name that is unique among the style names and it's based on the given name. The unique name is seeded by passing in a seed-name through the name parameter - - represents a seed for the the unique name. As output parameter, it holds the unique name that was generated - - - - Gets the number of components. - - - - - Returns a of IADTSTyles for enumeration. - - - - - Access to client of ATS Provider. - - - This interface provides runtime access to the client application. - - - - - Send status message to client. - - - true if success, false if failure - - string contaning status message - Currently not used. status of message. - - - - Window handle of client. - - - HWND handle of parent window - - - - - Get UI colors. - - - Allows an ATS Provider to access custom application color settings. - color value. - - same index used in Window's GetSysColor method. - - - - Get silent mode status. - - - true if in silent mode, false if not. - - - - - Get ATS Client options. - - - ATS option flags - - - - - to Asset Tracking Custom Dependencies. - - - This interface gives access to the list of files defined as Custom Dependencies. Custom Dependencies are reported as external file dependencies. Any file can be added to the Custom Dependency list. - - - - - Launch Custom Dependency dialog. - - - true if success, false if failure - - HWND of parent window - - - - of Custom Dependency files. - - - of files - - - - - Get file by index. - - - string containing the filename - - 0-based index into list of files. - - - - Get list of files. - - - number files added to . - - reference to a of MSTRs. This parameter will be filled with a copy of the Custom Dependency files. - - - - Add file to list. - - - index of szFile in the file list - - string that contains a file name. If the file is already contained in the list, it will not be added. - - - - file name in list. - - - true if success, false if failure - - 0-based index into list of files. - string that contains a file name. - - - - Remove file from list by index. - - - true if success, false if failure - - 0-based index into list of files. - - - - Remove file from list by name. - - - true if success, false if failure - - string that contains a file name. - - - - Remove all files from list. - - - true if success, false if failure - - - - - Internal EnumAuxFiles method. - - - Used internally to allow Custom Dependencies to be reported as external scene file dependencies. - - - - - to Asset Tracking System. - - - This interface gives access to the Asset Tracking System. This includes control over the Asset Tracking dialog, support dialogs, and version control system integration. It also provides access to the Asset Repathing UI functionality and file dependency information. The version control system related methods (such as checkin, checkout, etc.) incorporate the common dialogs used for all providers. For lower level access to providers use the interface. - - - - - true if visible, false if not - - - - - of files selected in dialog. - - - number of files selected in dialog - - - - - Get selected files. - - - number of files selected in dialog - - reference to a of MSTRs. This parameter will be filled with a copy of the selected files names - - - - Get a tab of files based on their file system status. - - - number of files found - - is a mask of kATSFSStatusXXX flags used to match against file entries. - reference to a of MSTRs. This parameter will be filled with a copy of the files matching the dwFSStatus flags. - - - - Return the file system status of the specified file. - - - file system status flag - - string containing the filename to retrieve status from. - - - - Get the resolved file paths for a given list of files. - - - the number of resolved paths - - reference to a of MSTRs. - reference to a of MSTRs that contains the same number of entries in fileList. If the file was found or is still missing the entry in resolvedFileList will be the same as fileList. If the file was resolved the entry in resolvedFileList will contains the resolved file path. Resolved files are files not found in the location specified within the scene file but are found using the standard and user defined search paths. - - - - Get the list of unique filenames that are used by the given . - - - - The animatable for which the file dependencies are to be listed. - The table through which the file list is returned. - to true to list dependencies of the entire reference hierarchy of 'animatable'; set to false to limit the list to 'animatable'. - to false for method to handle asset filenames in a case insensitive manner when comparing filenames for determining uniqueness. - to false for method to collect the assets' specified filenames. If true, if the filename can be resolved then the resolved filename is collected otherwise the specified filename is collected. - - - - of files in dialog. - - - number of files in dialog - - - - - Get files. - - - number of files in dialog - - reference to a of MSTRs. This parameter will be filled with a copy of the files names in the dialog - - - - Populate an object. - - - number of files added to atsFileList - - reference to an object. - specifies if all of the files added to the object will be marked as active (kATSStatusActive) - specifies if files excluded from the current provider should be marked as excluded (kATSStatusExcluded) - - - - Get list of dependent files. - - - number of files added to fileList - - string containing the filename to list dependent files from - specifies if method should include all dependent files - reference to a of MSTRs. This parameter will be filled with a copy of the dependent files names - specifies if output files should be included in dependency list - - - - Determine if a file is an input file and a true dependent file. - - - true if the file is an input file, or false if it is an output or not found - - string that contains the file name - - - - Select files. - - - - reference to a of MSTRs. This parameter specifies the list of files to select in the dialog. - to false if fileList contains unresolved filenames and only files in the dialog that match that unresolved filename will be selected. If true, all files in the dialog that resolve to the filenames in the fileList will be selected. If a file in the dialog cannot be resolved the unresolved filename will be used for comparison. - - - - Clears all selections in dialog. - - - - - Refreshes the dialog. - - - This method both updates the dependent file list and if connected to an ATS Provider it will query the server for updated version control status - - - - - true if disabled, false if not - - - - - Get silent state of dialog. - - - If connected to an ATS Provider, the provider might not respect the silent flag and display dialogs. - true if silent, false if not - - - - - Get autologin state of dialog. - - - This will attempt to login to all registered ATS Providers when a project (scene file) is open. - true if autologin is enabled, false if not - - - - - Get state of tree view. - - - true if tree view is display, false if not - - - - - Get state of table view. - - - true if table view is display, false if not - - - - - Get state of Check Network Path property. - - - true if the ATS system checks for the existence of files on network drives - - - - - Get display state of excluded files. - - - true if excluded files are display, false if they are not - - - - - Get the exclusion state of output files. - - - true if output files are excluded, false if they are not - - - - - Display Working Comment dialog. - - - - - Display Status Log dialog. - - - - - number of registered ATS providers - - - - - Get pointer. - - - pointer to interface - - 0-based index of Provider - - - - Get ATS Provider name. - - - string that contains name of provider - - 0-based index of Provider - - - - Get active ATS Provider index. - - - index of active ATS Provider - - - - - Login to specified ATS Provider. - - - true if the login was successful - - 0-based index of Provider - - - - Logout of specified ATS Provider. - - - true if the logout was successful - - 0-based index of Provider - - - - Determine if a file is excluded by an ATS Provider. - - - true if the file is excluded by the provider, false if it is not - - 0-based index of Provider - string that contains the file name - - - - Determine if a file is share locked by an ATS Provider. - - - A file is considered share locked if the file is checked out by another user at a shared location. Share locked files should be treated as read-only by users who are accessing the file and are not the owner of the lock. - true if the file is share locked by the provider, false if it is not - - 0-based index of Provider. If iProviderIndex is -1, the method will check all providers for a share locked status. - string that contains the file name - - - - Checkin list of files to an ATS Provider. - - - true if status from version control provider was successful, false if otherwise - - 0-based index of Provider - reference to a of MSTRs. - reference to MSTR - - - - Checkout list of files to an ATS Provider. - - - true if status from version control provider was successful, false if otherwise - - 0-based index of Provider - reference to a of MSTRs. - reference to MSTR - - - - Undo Checkout for list of files fr an ATS Provider. - - - true if status from version control provider was successful, false if otherwise - - 0-based index of Provider - reference to a of MSTRs. - - - - Add list of files to an ATS Provider. - - - true if status from version control provider was successful, false if otherwise - - 0-based index of Provider - reference to a of MSTRs. - reference to MSTR - optional pointer to that corresponds to the fileList. A true entry indicates that the file will be added with a hidden status (if supported by the provider). - - - - Get latest version of list of files for an ATS Provider. - - - true if status from version control provider was successful, false if otherwise - - 0-based index of Provider - reference to a of MSTRs. - - - - This will verify that the dependent files, as reported by the ATS Provider, are up to date on the user's machine. - - 0-based index of Provider - string that contains the file name to check dependent files for - - - - Policy check for checked out files. - - - This will warn the user of any files that are currently checked out. This is typically called when a scene is about to be closed and the user should check in any checked out files. - - 0-based index of Provider - - - - Policy check for uncontrolled files. - - - This will warn the user of any files that are not under version control. This is typically called when a scene is about to be closed and the user should add any uncontrolled files to the ATS provider. - - 0-based index of Provider - - - - Policy check for out dated files. - - - This will warn the user of any files that are not up to date. This is typically called when a scene is loaded and the user should update outdated files. - - 0-based index of Provider - - - - Policy check scene file. - - - This will warn the user if the scene file is under control and it is not checked out. This is typically called when a scene is loaded. - - 0-based index of Provider - - - - Get the current Working Comment. - - - string that contains the comment - - - - - Append status message to Status Log. - - - - string that contains the status message - - - - Clear the contents of the Status Log. - - - - - Get the conents of the Status Log. - - - string that contains the contains the status log - - - - - Sets the path component of all listed assets to the value passed in to this function. - Note: If the Resolve files and folders to UNC paths option is turned on then this function will automatically convert mapped-drive paths to their UNC equivalent. - true if the action succeeds and the asset(s) are repathed - - The path value that will be applied to all listed assets. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Sets the path on the asset selection set. - - - Sets the path component of selected assets to the value passed in to this function. - Note: If the Resolve files and folders to UNC paths option is turned on then this function will automatically convert mapped-drive paths to their UNC equivalent. - 1+ assets should be selected in the ATS (see SelectFiles above) - true if the action succeeds and the asset(s) are repathed - - The path value that will be applied to all selected assets. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Retargets the common-root portion of all assets listed in the ATS. - - - Will retarget the common-root of all assets to the value passed in. - For example, if all assets belong to C:\ but are found in different sub-directories of C:\, then only the C:\ will be repathed. - Note: If the Resolve files and folders to UNC paths option is turned on then this function will automatically convert mapped-drive paths to their UNC equivalent. - That all editable assets have some common-root portion - true if the action succeeds and the asset(s) are repathed - - The path portion that will be prepended in the place of the common-root. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Retargets the common-root portion of assets selected in the ATS. - - - Will retarget the common-root of selected assets to the value passed in. - For example, if the selected assets belong to C:/resources/projectA/ but are found in different sub-directories of that folder, then only the C:/resources/projectA/ portion will be repathed. - Note: If the Resolve files and folders to UNC paths option is turned on then this function will automatically convert mapped-drive paths to their UNC equivalent. - That all selected assets have some common-root portion - true if the action succeeds and the asset(s) are repathed - - The path portion that will be prepended in the place of the common-root. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Retargets single-asset selection to the value passed in. - - - Retargets a single asset to the value passed-into this function. - That 1 asset only be selected in the ATS. - The single asset is retargeted to the value passed into this function. - true if the action succeeds and the asset(s) are repathed - - The value (including filename) that the single asset should be retargetd to. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Resolve the current selection set to its UNC equivalent,. - - - Resolves the current selection set to UNC, regardless of the current application setting. - That one or more assets be selected in the ATS - one of the assets must be an absolute path - One or more assets is resolved to UNC. - true if the action succeeds and the asset(s) are resolved - - - - - Converts the current selection set to relative paths. - - - Converts the current selection set to relative paths. - If the asset is Found (meaning that it is found in the search path) in a location other than that pointed to by the absolute path, then the relative path will be calculated based on this Found location. If not, then the absolute path is converted to an relative path relative to the current Project Folder setting, if possible. - That one or more assets be selected in the ATS - one of the assets must be an absolute path. - One or more assets is resolved to a path relative to the current Project Folder setting, as long as the absolute path exists on the same drive (or UNC) as the current Project Folder. - true if the action succeeds and the asset(s) are resolved - - - - - Converts the current selection set to absolute paths. - - - Converts the current selection set paths to absolute paths. If the asset is Found (meaning that it is found in the search path), then the absolute path will point to the found location. If not, then the relative path is converted to an absolute path relative to the current Project Folder setting. - That one or more assets be selected in the ATS - one of the assets must be a relative path - One or more assets is resolved to an absolute path. - true if the action succeeds and the asset(s) are resolved - - - - - Generically remaps assets declared by whose path value is equal to aOldPath (case-insensitive comparison), to the value aNewPath passed-in. This method calls the EnumAuxFiles implementation of to get a listing of assets. - true if the action succeeds and the asset(s) are repathed, false is returned if no asset is repathed - - The object from which assets are declared - Used to determine which asset to retarget. Any asset declared with this path will be retargeted to aNewPath. - The retarget value. - If repathing an output directory, and the path being repathed to does not exist, create path folder(s). - - - - Asset Tracking System Notification Callback . - - - This interface is implemented by any object that wants to receive notification messages. - - - - - Asset Tracking System Notification Callback method. - - - three values: kATSNotifyResultOk, kATSNotifyResultCancel, or kkATSNotifyResultStop. kATSNotifyResultOk will continue the notification through the system kATSNotifyResultStop will prevent the notification message from continuing kATSNotifyResultCancel is similar to kATSNotifyResultStop, but all previous objects that have ready received the notification will be sent a cancel notification. - - pointer to object that contains information about the notification message - pointer supplied by client when registered for notifications - - - - ATS Provider . - - - This is the main interface for interacting with an ATS Provider. It provides for basic version control functionality, retrieval of status, connections, dependency reporting, etc. - - - - - Get provider name. - - - string containing provider name - - - - - Get provider's support options. - - - This allows the provider to specify whether or not they support some of the more advanced version control method, such as dependency reporting and exploring. See kATSSupport* flags. - Support option flags (ATSOption) - - - - - Get initialization status. - - - true if the provider has been initialized, false if it has not. - - - - - Get project status. - - - true if the provider has a project open, false if it has not. - - - - - Initialize. - - - This is called when the user has decided to connect or logon to the provider. At this point, the provider should be prepared to open a project, launch provider, explorer provider, or show options. The provider might also ask the user to login if neccessary, although that can be delayed until a project is opened. - ATSResult value - - reference to object. Any data of interested should be copied locally to the provider. - default value kATSOptNone. kATSOptSilent is valid. - - - - Uninitialize. - - - This is called when the user has decided to disconnect or logout of the provider. - ATSResult value - - default value kATSOptNone. kATSOptSilent is valid. - - - - Open project. - - - This is called when the client has opened a project. At this point a project path has been determined from document or document related project files. For certain providers, the specified path might be used to determine if the project can be resolved to a workspace by the provider. - ATSResult value - - string containing the path to the project. This typically is the path in which the document was opened. - string containing any initial or default comment for the project. - default value kATSOptNone. kATSOptSilent is valid. - - - - Close project. - - - This is called when the client has closed a project. This occurs when the user has opened a new document or is closing down the client application. - ATSResult value - - default value kATSOptNone. kATSOptSilent is valid. - - - - Get working folder. - - - string containing current working folder used to resolve project files - - - - - working folder. - - - The working folder for most providers is used to map the root folder in the version provider's file system to the local file system. - ATSResult value - - string containing the new working folder. - - - - Checkin files. - - - Active files in the object should be checked in to the provider. - ATSResult value - - reference to object. The active file list should be used. - string containing the comment to include with this version. - default value kATSOptNone. kATSOptSilent and kATSOptKeepCheckedOut are valid. - - - - Checkout files. - - - Active files in the object should be checked out from the provider. - ATSResult value - - reference to object. The active file list should be used. - string containing the comment to include with this version. - default value kATSOptNone. kATSOptSilent and kATSOptReplaceLocalCopy are valid. - - - - Undo checkout. - - - Active files in the object should no longer be checked out by the provider. - ATSResult value - - reference to object. The active file list should be used. - default value kATSOptNone. kATSOptSilent and kATSOptReplaceLocalCopy are valid. - - - - Get latest. - - - Active files in the object should have their latest version downloaded. - ATSResult value - - reference to object. The active file list should be used. - default value kATSOptNone. kATSOptSilent is valid. - - - - Get version range. - - - Get the range of version numbers. If multiple active file entries are in atsFileList, the verMin is the minimum of all the files, and verMax is the maximum of all the files. - ATSResult value - - reference to object. The active file list should be used. - minimum version number - maximum version number - default value kATSOptNone. - - - - Get version. - - - Downloads the specified version for the active files in the object. - ATSResult value - - reference to object. The active file list should be used. - version number - default value kATSOptNone. kATSOptSilent is valid. - - - - Add files. - - - Active files in the object should be added to the provider. - ATSResult value - - reference to object. The active file list should be used. - string containing the comment to include with this version. - default value kATSOptNone. kATSOptSilent and kATSOptKeepCheckedOut are valid. - - - - Show version history. - - - The version history of the active files in the object should be shown. If multiple histories can not be displayed, the first active file should be displayed. - ATSResult value. If the history dialog resulted in a version change of one of the file, kATSResSuccessReload should be returned. - - reference to object. The active file list should be used. - default value kATSOptNone. kATSOptSilent is valid. - - - - Show file properties. - - - The properties of the active files in the object should be shown. If multiple file properties can not be displayed, the first active file should be displayed. - ATSResult value - - reference to object. The active file list should be used. - default value kATSOptNone. kATSOptSilent is valid. - - - - Get file status. - - - The status of the active files in the object should be updated. The status should be placed in the Out flags of the . - ATSResult value - - reference to object. The active file list should be used. - default value kATSOptNone. kATSOptSilent is valid. - - - - Get name of users that have files locked. - - - For each active file in the object, a corresponding atsUserList entry will be created. The provider will fill in an object with information about the user that has the active file locked or checked out. If a file in the active list is not locked, the provider will create a blank object in place. - ATSResult value - - reference to object. The active file list should be used. - reference to object. This will be populated by the provider. - default value kATSOptNone. - - - - Explore provider. - - - If supported, the provider should display a dialog to allow the user to explorer the contents of the provider. The file or files selected by the user will be returned and optionally downloaded. - ATSResult value - - reference to object. Active entries should be created for the selected files. - reference to object that defines the parameters for the explorer provider dialog. - default value kATSOptNone. - - - - Show provider options. - - - The provider should optional display a dialog containing any options. - ATSResult value. If any change in options might affect the status of the files, kATSResSuccessReload should be returned. - - default value kATSOptNone. - - - - Launch provider. - - - The provider should optional launch an associated client application. - ATSResult value. If any change in options might affect the status of the files, kATSResSuccessReload should be returned. - - default value kATSOptNone. - - - - Get associated files. - - - This method provides for specifying file associations. If supported, the provider should add the specified associated files for each file in the list as child for that . It should clear any children already in the list before adding its own. - ATSResult value. - - reference to object. If supported, the provider should add the specified associated files for each file in the list as child for that . It should clear any children already in the list before adding its own. - default value kATSOptNone. kATSOptSilent, kATSOptAssocChildren, kATSOptAssocParents, kATSOptAssocRecurse and are valid. - - - - Is provider using MSSCC interface. - - - This specifies whether an ATS Provider is directly supporting the interface or if the ATS core is supplying support through an MSSCC interface. - true if MSSCC dll, false if not. - - - - - A pure virtual interface for implementing grips. - - - A Grip or Caddy is a collection of modeless, transparent, in canvas UI elements that lets a user perform actions or modify values. A user can create their own grip by inheriting from , implementing 's pure virtual functions, and then enable it on via the interface. Based upon the number of grip items the grip contains and the type each item is, the system will create a set of in canvas UI representations for each item, which then interact with the item via various functions. Usually the implementation of the acts as a bridge between some existing data and the in canvas UI. For example if a grip was created to modify different soft selection values in a modifier, the grip would get the values from that modifier and then set the values back onto it. The grip itself will get displayed via the IGripManager::EnableGrip function which basically calls various functions to set up the in canvas UI and then ferry messages to and from the UI to the grip. - - - - - Whether or not, the Okay, Apply and Cancel grip buttons will get shown or not. - If true the grip will have Okay, Apply and grip buttons that will then trigger the correct callback functions listed below. If false, then the grip won't show these buttons. - - - - - Accept any necessary changes and disable the grip to close the UI. Basically do whatever operations you would do similar if the Okay button was pressed in a modeless dialog. Note that it's the implementations responsibility to disable the grip. - - The time at which to perform the okay. - - - - Disregard and cancel any necessary changes and disable the grip to close the UI. Basically do whatever operations you would do similar if the Cancel button was pressed in a modeless dialog. Note that it's the implementations responsibility to disable the grip. - - - - - Accept any necessary changes and perform any pending action if needed. Unlike Okay, after an Apply the grip stays active and displayed. - - The time at which to perform the apply. - - - - the value of the specified. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The time at which to set the value. - The value for that grip. See to see the values that are supported. - - - - Get ready to set this value. Sometimes an item needs to do some setup before a value get's set, for example cache some values, or get ready for an undo. This is called before SetValue is called and SetValue may be called multiple times after StartSetValue is called. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The time at which to set the value. - - - - The value is done setting values. Sometimes an item needs to do some cleanup after a value get's set, for example delete some cached values or accept an undo. This will get called immediately after the last SetValue function get's called. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The time at which the value was set. - If true the setvalue operation has succeeded and any undo's may be accepted if needed. If false then the setvalue operation was canceled and it's the implementors responsibility to rever the value back to it's original value it had when StartSetValue was called, for example it could do this by canceling the hold. - - - - Whether or nor we will use auto scaling when incrementing or decrementing this item. - - Returns true if the grip should auto scale this value, false if not. - - The zero based index of the grip item. - - - - Get the scale value for this item when we increment or decrement it. Will normally only get used if GetAutoScale and GetSCaleInViewSpace returns false. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The value of the scale. - - - - Get the scale value for this grip in view space, if one exists. - Returns true if we should support scaling in view space, false if not. If false then we either using auto scaling or the normal incremental scale value specified by GetScale, based upon the result of GetAutoScale. Screen space scaling is used when dragging on a grip item spinner. - - The zero based index of the grip item. - The screen space depth that the scale should use. /see for a more in depth description on screen depth. -200 is usually a good default value. - - - - Get the name of the grip. - - The name of the grip. - - - - Get the number of grip items this grip contains. - The number of grip items this grip contains. - - - - - Get the type that the specified grip item will control. - The type of the specified grip item. IBaseGrip::Type to see the different types that a grip item may be. The type that the grip item is determines what IBaseGrip::Value values the grip item supports. If the index is out of range then return Type::eInvalid. - - The zero based index of the item. - - - - Get the name of the specified grip item. - true if the operation succeeded, false otherwise. - - The zero based index of the item. - The name of the specified grip item. - - - - Get the file path of the icon that represents the specified grip item. Every grip item no matter it's type should try to provide an icon that represents the string that's returned by GetText. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The name of the resolved path of the icon. It's this functions responsibility to resolve the path completely. - - - - Get any special customization flags that this grip item needs to follow. - Returns a bitwise union of IBaseGrip::Customization types, casted to a DWORD, that specify what if any customizations this grip item will have that differ from the default behavior of that grip item. Note that this customization is only checked when the grip is activated and its UI is constructed. Return zero if index is invalid or no customization occurs. - - The zero based index of the item. - - - - Get the option possibilities for this combo grip item - Returns true if the options were correctly set up, false if not, for example if this grip item isn't a eCombo type. - - The zero based index of the item. - A returned tab of labels that describes each possible option for the type grip button. These values will be presented in the as the possible options which can be selected. Note that it's the responsibility of the client of this function to delete each allocated pointer in the . - - - - Get an icon for the IBaseGrip::eCommand grip item. Since a IBaseGrip::eCommand can have two different states, - the grip item can show additional icons, in addition to the one returned by GetResolvedIconName, to represent these states. - Returns true if an icon was resolved up, false if not, for example if this grip item isn't a IBaseGrip::eCommmand type. - - The zero based index of the grip item. - The name of the resolved path of the icon. It's this functions responsibility to resolve the path completely. - - - - Get the value of the specified grip item. - true if the operation succeeded, false otherwise. - - The zero based index of the grip item. - The time at which to get the value. - The value for that grip. See to see the values that are supported. - - - - Whether or not key brackets, which will show in a spinner that a key is present, should be shown at the specified time. - Usually this function will check to see if a key exists at this time. - true if a key bracket should be shown at that time, false otherwise. - - The zero based index of the grip item, which we are checking key brackets for. Will only check for those grip items which have spinners. - The time at which we are checking to see if we should show a key bracket. - - - - Get the range of this grip values. - true if the operation succeeded, false otherwise. - - The grip item - The minimum range value for this grip. If the grip type is Type::eAction then no valid value is expected. - The maximum range value for this grip. If the grip type is Type::eAction then no valid value is expected. - - - - Get the reset value of the grip. - true if the operation succeeded, false otherwise. - - The grip item whose reset value we will get. - The resetValue for that value. If the grip type is eAction then no valid value is expected. - - - - Reset the specified grip. - true if the operation succeeded, false otherwise. - - The time at which to reset. - Which grip item to reset. - - - - A virtual interface to extend . - - - - - - - Based on different sub-object selection, the grip updates the controls in it to be visible or hidden. - - - - - Description: - This class represents the interface for individual wire controllers. You can obtain a pointer to the Base Wire control interface using; This macro will return The Class ID's of individual wire controllers are: FLOAT_WIRE_CONTROL_CLASS_ID - POSITION_WIRE_CONTROL_CLASS_ID - POINT3_WIRE_CONTROL_CLASS_ID - ROTATION_WIRE_CONTROL_CLASS_ID - SCALE_WIRE_CONTROL_CLASS_ID - - All methods of this class are Implemented by the System. - - - - - This method returns the number of wires out of this controller (i.e. the number of dependent params). - - - - - This method returns a pointer to the i-th dependent parameter parent. - - - The index you wish to retrieve. - - - - This method returns the i-th dependent parameter subanim num in the animatable. param i - The index of the subanim. - - - - - This method returns a pointer to the i-th CoController. - - - The index of the controller. - - - - This method returns the expression string of the i-th wire parameter. param i - The index of the parameter. - - - - - This method allows you to set the expression string of the i-th wire parameter. - - - The index of the parameter - - The expression you wish to set. - - - - This method returns a pointer to the driven animation controller. - - - - - This method will return TRUE if the wire is a driver predicate, otherwise it will return FALSE. - - - - - This method will return TRUE if the wire is a driven predicate, otherwise it will return FALSE. - - - - - This method will return TRUE if the wire is a two-way predicate, otherwise it will return FALSE. - - - - - This method validates consistency of the WireController's linkages. - - - - - This method fixes inconsistencies of the WireController's linkages. - - - - - This method will return the parent of the wire controller. - - - - - This class is the manager of the batch rendering feature. - - - You can use this class to setup or query the batch renderer. - - - - - Get the number of views currently configured. - - - The number of batch render views - - - - - Get an interface to a given batch render view. - - - A batch render view interface, of NULL in case of an error - - - The index of the batch render view to access - - - - Find a batch render view with the given name. - - - The index of the batch render view with the given name, or NULL if none were found. - - - The name of the batch render view to find - - - - Start the batch renderer. - - - - - Create a new batch render view using the given camera. - - - The batch render view will be added to the batch render list and have a unique name and default values for all it's parameters. - A pointer to the newly created batch render view, or NULL if an error occurred. - - - The camera to render with the batch render view, or NULL to render from the current viewport - - - - Delete the given batch render view. - - - true if the entry was deleted, false if an error occurred - - - The index of the batch render view to delete - - - - Returns whether or not network rendering is enabled for the batch renderer. - - - true if network rendering is enabled, false otherwise - - - - - Returns whether or not a separate VFB will be opened (and kept open) for each batch render view when rendered. - - - In 3ds Max 8 this has no effect, and is for internal use only - true if a separate VFB is used for each batch render view, false otherwise - - - - - This will prepare the scene for a given batch render view. - - - This will load the preset and restore the scene state from the batch render view. - true if the preparation was successful and false if an error occurred. - - - The batch render view to prepare. - - - - This brings up the batch renderer dialog. - - - - - This method may be used to enumerate all the render preset files used by Batch Render. - - - - - The callback, called once for each render preset. - - Indicate what to enumerate. - - - - This class represent one entry in the list of batch render views. - - - You can use the properties in this class to read or change the parameters for each batch render view. - - - - - Get the camera that the batch render view is rendering. - - - A pointer to the camera node if the view has a valid camera node, NULL otherwise. When NULL, the current viewport will be used for rending - - - - - the camera that the batch render view is rendering. - - - true if the operation was successful, false if an error occurred - - - The camera node to use, or NULL to render from the current viewport - - - - Get the width of the rendering output. - - - Applicable only when the preset override is enabled. - The width of the output - - - - - the width of the rendering output. - - - Applicable only when the preset override is enabled. - true if the operation was successful, false if an error occurred - - - The width of the rendered output in pixels - - - - Get the height of the rendering output. - - - Applicable only when the preset override is enabled. - The height of the output - - - - - the height of the rendering output. - - - Applicable only when the preset override is enabled. - true if the operation was successful, false if an error occurred - - - The height of the rendered output in pixels - - - - Get the start frame of the segment to render. - - - Applicable only when the preset override is enabled. - The time used for the start frame - - - - - Get the end frame of the segment to render. - - - Applicable only when the preset override is enabled. - the time used for the end frame - - - - - Get the name of the batch render view. - - - The name of the batch render view - - - - - the name of the batch render view. - - - Batch render views must be unique in the same scene. - true if the operation was successful, false otherwise. - - - The new name of the batch render view - - - - Return the render preset used by the batch render view. - - - The filename of the render preset - - - - - Get the fully qualified path to the render preset. - - - true if successful, otherwise false - - - The fully qualified path of the render preset - - - - Get the scene state used by the batch render view. - - - The scene state used by the batch render view, or an empty string in case no scene state is used. - - - - - Check if the batch render view is enabled. - - - true if the batch render view is enabled, false otherwise - - - - - Get the parameters of the output file for the batch render view. - - - An object representing the output parameters (filename, filetype, etc...) for the batch render view - - - - - Get the pixel ascpect ratio used for the rendering. - - - Applicable only when the preset override is enabled. - The pixel aspect ratio - - - - - Check if the render preset will be overridden for this batch render view. - - - If this flag is 'false', the value of the width, height, start, end and aspect parameters will be taken from the render preset, or the current render settings if no preset is used. Only if this flag is true will these settings be taken from the values in this batch render view - true if the settings in this batch render view will be used, false if the render preset or current render settings will be used. - - - - - Description: - This class stores a Bezier floating point key. - Data Members: - float intan; - - The in tangent value. - - float outtan; - - The out tangent value. - - float val; - - The value of the key. - - float inLength; - - The in length of the horizontal handle. - - float outLength; - - The out length of the horizontal handle. - - - - - Description: - This class stores a Bezier key. - Data Members: - intan; - - The int tangent vector. - - outtan; - - The out tangent vector. - - val; - - The value of the key. - - inLength; - - The in length of the horizontal handle. - - outLength; - - The out length of the horizontal handle. - - - - - Description: - This class stores a Bezier key. - - The value of the intan and outtan values of returned from GetKey is actually the tangent of the angle that is spanned between the horizontal axis and the tangent. In order to get the actual handle of the tangent it is important to know that the horizontal (time) distance from the handle to the key value is dependent on the previous (for intan) or next (for outtan) point. The horizontal distance is basically a third of the total distance between the current key and the previous (or next) key : - - *c = node->GetTMController()->GetPositionController(); - - dt = (c->GetKeyTime(PreviousIdx)-c->GetKeyTime(CurrentIdx)) / 3.0f; - - since the value in pos_key.intan.x is the tan(alpha), you can easily get the vertical location of the handle by calculating : - - tan(alpha) = pos_key.intan.x = dy/dt -> dy = pos_key.intan.x * dt - - dt is the horizontal coordinate of the tangent handle relative to the key value. - - dy is the vertical coordinate of the tangent handle relative to the key value. - Data Members: - intan; - - The incoming tangent vector. This can be thought of as the tangent handle of a 3D spline. The value is relative to val. - - outtan; - - The outgoing tangent vector. This can be thought of as the tangent handle of a 3D spline. The value is relative to val. - - val; - - The value of the key. - - inLength; - - The in length of the horizontal handle. - - outLength; - - The out length of the horizontal handle. - - - - - Description: - This class stores a Bezier key. - Data Members: - intan; - - The int tangent vector. - - outtan; - - The out tangent vector. - - val; - - The value of the key. - - inLength; - - The in length of the horizontal handle. - - outLength; - - The out length of the horizontal handle. - - - - - Description: - This class stores a Bezier quaternion key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class stores a Bezier scale key. - Data Members: - intan; - - The int tangent vector. - - outtan; - - The out tangent vector. - - val; - - The value of the key. - - inLength; - - The in length of the horizontal handle. - - outLength; - - The out length of the horizontal handle. - - - - - A copy within a copy collection. - - - The copy is either a posture, pose, or track. - You can find out what it is with the GetCopyType function. You can get an instance of this class from a copy collection. - - - - - Gets the name of the copy. - - - the name of the copy - - - - - Sets the name of the copy. - - - name must be <= 256 characters - true if the name was set, false if it wasn't set - - - name of the copy - - - - Gets the type of the copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK. - - - the type of the copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - - - - into the biped driver controller for Max 10. - - - This contains functions supporting new biped features in Max 10, in particular Xtras. - - - - - Creates an Xtra with the specified number of links and base name. - - - The base of the Xtra will be attached to the biped's center of mass. - must be in figure mode - the base node of the new Xtra if the creation was successful, NULL if the creation was unsuccessful - - - the number of links in the new Xtra, between 1 and 25 - - the base name of the Xtra. ! The name can be the empty string, and names do not have to be unique. - - - - Creates Xtras which are the opposite of the specified Xtra and its children, if desired. - - - The new Xtras will have the mirrored position, orientation, and hierarchy of the original Xtras. Xtras which already have opposites are ignored. - must be in figure mode - the base node of the opposite of the Xtra sent in if the creation was successful, NULL if the creation was unsuccessful - - - an Xtra node - - if true, opposites of all the Xtra's children are created in a matching hierarchy - - - - Gets the opposite Xtra. - - - the opposite Xtra if there is one, NULL if there is no opposite - - - an Xtra node - - - - Deletes an Xtra. - - - must be in figure mode - true if the deletion was successful, false if not - - - the base node of the Xtra to delete - - - - Attaches an Xtra to a parent. - - - must be in figure mode - true if the attach was successful, false if not - - - the base node of the Xtra to attach - - the node which will become the Xtra's parent. The parent must be part of the same biped as the Xtra. - - - - Sets the base name of an Xtra, and uses that to set the names of all the nodes in the Xtra. - - - The first node in the Xtra will be called "name", the second "name01", the next "name02", and so forth. - - - the base node of the Xtra - - the base name of the Xtra - - - - Gets the base name of an Xtra. - - - the base name of the Xtra - - - the base node of the Xtra - - - - Pastes a copy of an Xtra posture onto each Xtra in the tab. - - - true if the paste was successful, false if the paste was unsuccessful - - - a biped copy of type posture, which must be a copy of a single Xtra - - a tab of Xtras to paste to. The copied posture will be pasted onto the entire Xtra track, regardless of which links from the Xtra are in the tab. - - method to paste TCB/IK values, one of the following: PST_DEF (default), PST_COPY (copied), PST_INTERP (interpolated). KeyPasteType is only relevant if you are in auto key mode. - - - - Pastes a copy of an Xtra track onto each Xtra in the tab. - - - true if the paste was successful, false if the paste was unsuccessful - - - a biped copy of type track, which must be a copy of a single Xtra - - a tab of Xtras to paste to. The copied track will be pasted onto the entire Xtra track, regardless of which links from the Xtra are in the tab. - - - - Saves a single layer of a biped animation. - - - true if the save was successful, false if the save was unsuccessful - - - the file name to save to - must be a valid path and filename - - the layer to save. The first layer is index one. A zero index will save the base layer without max objects or list controllers. - - - - Loads a BIP file into a single layer of a biped animation. - - - If more than one layer is stored in the BIP file the load will be unsuccessful. - the layer must exist - true if the load was successful, false if the load was unsuccessful - - - the file to load - must be a valid path and filename - - the layer into which the animation will be loaded. The first layer is index one. A zero index will load into the base layer without max objects or list controllers. - - - - Saves the base layer of a biped animation. - - - This is just like a regular BIP file save except that layers, if they exist, are not saved. - true if the save was successful, false if the save was unsuccessful - - - the file name to save to - must be a valid path and filename - - When kSAVE_NONE, no max objects are saved. When kSAVE_AUTOMATIC, all IK, Head Target, and linked objects in the scene are saved, and the maxObjects array is ignored. When kSAVE_SPECIFIED, the max objects specified in the maxObjects array are saved. - - an array of nodes in the scene, to be saved only if saveMaxObjects equals SAVE_SPECIFIED. Biped nodes are always saved, regardless of whether they appear in this array or not. - - When kSAVE_NONE, no list controllers are saved. When kSAVE_AUTOMATIC, all animation controllers assigned to the biped are saved, and the controllers array is ignored. When kSAVE_SPECIFIED, the controllers specified in the controllers array are saved. - - an array of specifying animation controllers, to be saved only if SaveListCntrls equals SAVE_SPECIFIED. Controllers not associated with Biped nodes are ignored. - - - - Loads a BIP file into the base layer of a biped animation. - - - If multiple layers are stored in the BIP file the load will be unsuccessful. - true if the load was successful, false if the load was unsuccessful - - - the file to load - must be a valid path and filename - - when true, the structure of the current biped is changed to match the structure in the BIP file - - when true, sets the lowest starting foot height to Z=0 - - When true, opens a Merge dialog for each object in the BIP file that has a duplicate in the scene. In this dialog, you can Merge, Skip, or Delete Old. If Prompt for Duplicates is off, the objects in your scene will be automatically overwritten. - - method to retarget max objects to biped size, one of the following: RETARGET_NONE, RETARGET_HEIGHT, RETARGET_LIMB - - - - into the biped driver controller for Max 11. - - - This contains functions supporting new biped features in Max 11. - - - - - Queries the value of Triangle Neck. - - - true if Triangular Neck is on, false if not - - - - - Sets Triangle Neck. - - - - - sets Triangle Neck to the value of bEnabled - - - - Queries the value of ForeFeet. - - - true if ForeFeet is on, false if not - - - - - Sets ForeFeet. - - - must be in figure mode - - - sets ForeFeet to the value of bEnabled - - - - Mirrors the biped animation in place. - - - The position and orientation of the center of mass at the current frame is maintained. - cannot be in figure mode, motion flow mode, or mixer mode - cannot be editing a biped layer - true if the operation was successful, false if the operation was unsuccessful - - - - - into the biped driver controller. - - - This contains functions supporting new biped features. - - - - - Queries the value of Knuckles. - - - true if Knuckles is on, false if not - - - - - Queries the value of ShortThumb. - - - true if ShortThumb is on, false if not - - - - - Gets the layer retarget state for a limb. - - - true if the limb's retarget state is on, false if not - - - KEY_LARM or KEY_RARM or KEY_LLEG or KEY_RLEG - - - - Sets the layer retarget state for a limb. - - - - - KEY_LARM or KEY_RARM or KEY_LLEG or KEY_RLEG - - sets the limb retarget state to the value of bEnabled. - - - - Gets the retarget reference biped. - - - the retarget reference biped if there is one, NULL if not - - - - - Sets the retarget reference biped. - - - true if the reference biped was set correctly, false if not - - - sets the reference biped to the node, which must be any node from a different biped. - - - - Retargets the current biped layer to its base layer. - - - For every limb whose retarget state is active, calculates the hand/foot position at every key, maintaining IK constraints to the base layer. - A layer must be active - - - When IK_Only is on, the biped's constrained hands and feet are retargeted only during the frames on which they are IK controlled. When IK_Only is off, the hands and feet are retargeted during both IK and FK keys. - - - - Retargets the current biped layer to the reference biped. - - - For every limb whose retarget state is active, calculates the hand/foot position at every key, maintaining IK constraints to the retarget biped. - A retarget biped must be specified. - - - When IK_Only is on, the biped's constrained hands and feet are retargeted only during the frames on which they are IK controlled. When IK_Only is off, the hands and feet are retargeted during both IK and FK keys. - - - - into the biped driver controller for Max 8. - - - This contains functions supporting new biped features in Max 8. These include euler versus quaternion rotations, locked com, twist bones, twist poses, bend links functions, and copy collections. - - - - - Gets whether or not a biped track is euler. - - - true if if the track is euler, false if it is quaternion - - - a biped track, as defined in - - - - Gets the euler order of a biped track. - - - eulerOrder - an EULERTYPE, as defined in euler.h - - - a biped track, as defined in - - - - Sets a biped track to euler with the specified euler order. - - - true if successful, false if not - - - a biped track, as defined in . Props, fingers, toes, footprints, horizontal, and vertical tracks cannot be set to euler. - - any of the EULERTYPEs, as defined , except for EULERTYPE_XYX, EULERTYPE_YZY, and EULERTYPE_ZXZ - - - - Sets a biped track to quaternion. - - - true if successful, false if not - - - a biped track, as defined in - - - - Sets a biped track to the specified euler order. - The euler order is only relevant if the track is euler or when it becomes euler. - - - true if successful, false if not - - - a biped track, as defined in - - any of the EULERTYPEs, as defined in , except for EULERTYPE_XYX, EULERTYPE_YZY, and EULERTYPE_ZXZ - - - - Queries the locked state of the com. - - - true if the com is locked, false if not - - - - - Locks or unlocks the com. - - - - - true to lock the com, false to unlock the com - - - - Queries the state of Twists for this biped. - - - true if the twists are on, false if the twists are off - - - - - Gets the twist bias for the specified twist track of this biped. - - - the twist bias, a number between 0.0 and 1.0 - - - one of the following twist track identifiers: TWS_LFARM, TWS_RFARM, TWS_LCALF, TWS_RCALF, TWS_LHORSE, TWS_RHORSE - - - - Sets the twist bias for the specified twist track of this biped. - - - - - one of the following twist track identifiers: TWS_LFARM, TWS_RFARM, TWS_LCALF, TWS_RCALF, TWS_LHORSE, TWS_RHORSE - - the bias, between 0.0 and 1.0 - - - - Queries the number of twist poses for the specified limb. - - - the number of arm or leg twist poses - - - KEY_LARM or KEY_RARM for arm poses, KEY_LLEG or KEY_RLEG for leg poses - - - - Creates a new arm or leg twist pose, and appends it the the existing poses. - The pose will be the current rotation of the upper arm for the arm track, and the thigh for the leg track. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to create an arm pose, and KEY_LLEG or KEY_RLEG to create a leg pose - - - - Sets an existing arm or leg twist pose. - The pose will be the current rotation of the upper arm for the arm track, and the thigh for the leg track. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to set an arm pose, and KEY_LLEG or KEY_RLEG to set a leg pose - - the index of the pose in the pose list - - - - Deletes an arm or leg twist pose. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to set an arm pose, and KEY_LLEG or KEY_RLEG to set a leg pose - - the index of the pose in the pose list - - - - Sets the arm or leg twist poses to the default poses. - - - - - KEY_LARM or KEY_RARM to set the arm poses, and KEY_LLEG or KEY_RLEG to set the leg poses - - - - Sets the name of an arm or leg twist pose. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to set an arm pose, and KEY_LLEG or KEY_RLEG to set a leg pose - - the index of the pose in the pose list - - the name to call the pose - - - - Sets the twist value of an arm or leg twist pose. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to set an arm pose, and KEY_LLEG or KEY_RLEG to set a leg pose - - the index of the pose in the pose list - - the twist value in degrees, between -180 and 180 - - - - Sets the bias value of an arm or leg twist pose. - - - true if the function was successful, false if not - - - KEY_LARM or KEY_RARM to set an arm pose, and KEY_LLEG or KEY_RLEG to set a leg pose - - the index of the pose in the pose list - - the bias value, between 0.0 and 1.0 - - - - Returns the name of an arm or leg twist pose. - - - the name of the specified pose - - - KEY_LARM or KEY_RARM to get an arm pose, and KEY_LLEG or KEY_RLEG to get a leg pose - - the index of the pose in the pose list - - - - Returns the twist value of an arm or leg twist pose. - - - the twist value of the specified twist pose - - - KEY_LARM or KEY_RARM to get an arm pose, and KEY_LLEG or KEY_RLEG to get a leg pose - - the index of the pose in the pose list - - - - Returns the bias value of an arm or leg twist pose. - - - the bias value of the specified pose - - - KEY_LARM or KEY_RARM to get an arm pose, and KEY_LLEG or KEY_RLEG to get a leg pose - - the index of the pose in the pose list - - - - Updates the limb to match an arm or leg twist pose. - - - - - KEY_LARM or KEY_RARM to get an arm pose, and KEY_LLEG or KEY_RLEG to get a leg pose - - the index of the pose in the pose list - - the twisties of the opposite limb will also be updated if this is true - - - - Loads a figure file without loading the twist poses stored in the file. - - - true if the function was successful, false if not - - - name of figure file - - redraw viewports if true - - pop up error dialogs if an error occurs - - - - Loads only the twist poses from a figure file. - - - true if the function was successful, false if not - - - name of figure file - - redraw viewports if true - - pop up error dialogs if an error occurs - - - - Zeros out the twist for the specified track of this biped. - - - - - one of the following track identifiers: KEY_SPINE,KEY_NECK,KEY_TAIL,KEY_PONY1,KEY_PONY2 - - - - Zeros out all the angles for all the links of the specified track of this biped. - - - - - one of the following track identifiers: KEY_SPINE,KEY_NECK,KEY_TAIL,KEY_PONY1,KEY_PONY2 - - - - Smooths the twist between the first and last link of the specified track of this biped. - - - - - one of the following track identifiers: KEY_SPINE,KEY_NECK,KEY_TAIL,KEY_PONY1,KEY_PONY2 - - the bias, between 0.0 and 1.0 - - - - Queries the number of copy collections. - - - the number of copy collections. - - - - - Gets a copy collection. - - - the specified copy collection, NULL if the index was out of bounds - - - index of desired copy collection - - - - Gets a copy collection. - - - the specified copy collection, NULL if the index was out of bounds - - - name of desired copy collection - - index of desired copy collection - - - - Creates a copy collection. - - - the newly created copy collection - - - name of new copy collection - - - - Deletes a copy collection. - - - true if the collection was deleted, false if the index was out of bounds - - - index of copy collection to delete - - - - Deletes all copy collections. - - - - - Copies the posture of the specified parts of this biped. - - - the new copy, NULL if a copy was not created - - - copy collection in which to place the new copy - - parts of the biped whose posture will be copied. If this is NULL, the posture of the selected parts of the biped will be copied. - - type of snapshot to store, one of the following: SNAP_VIEW (active viewport), SNAP_AUTO (automatic), SNAP_NONE (none) - - - - Copies the biped's pose. - - - the new copy, NULL if a copy was not created - - - copy collection in which to place the new copy - - type of snapshot to store, one of the following: SNAP_VIEW (active viewport), SNAP_AUTO (automatic), SNAP_NONE (none) - - - - Copies the animation of the specified parts of this biped. - - - the new copy, NULL if a copy was not created - - - copy collection in which to place the new copy - - parts of the biped whose animation will be copied. If this is NULL, the animation of the selected parts of the biped will be copied. - - type of snapshot to store, one of the following: SNAP_VIEW (active viewport), SNAP_AUTO (automatic), SNAP_NONE (none) - - - - Pastes a posture onto this biped. - - - true if the paste was successful, false if the paste was unsuccessful - - - a biped copy of type posture - - true to paste opposite, false to paste normal - - method to paste TCB/IK values, one of the following: PST_DEF (default), PST_COPY (copied), PST_INTERP (interpolated). KeyPasteType is only relevant if you are in auto key mode - - true to paste the horizontal com, false to keep the existing horizontal com - - true to paste the vertical com, false to keep the existing vertical com - - true to paste the rotation com, false to keep the existing rotation com. Hor, Ver, Trn are only relevant if you are pasting a posture with a copied com - - true to paste the com by velocity, false to paste the com absolute, relevant for true values of Hor, Ver, Trn - - - - Pastes a pose onto this biped. - - - true if the paste was successful, false if the paste was unsuccessful - - - a biped copy of type pose - - true to paste opposite, false to paste normal - - method to paste TCB/IK values, one of the following: PST_DEF (default), PST_COPY (copied), PST_INTERP (interpolated). KeyPasteType is only relevant if you are in auto key mode. - - true to paste the horizontal com, false to keep the existing horizontal com - - true to paste the vertical com, false to keep the existing vertical com - - true to paste the rotation com, false to keep the existing rotation com - - true to paste the com by velocity, false to paste the com absolute, relevant for true values of Hor, Ver, Trn - - - - Pastes a track onto this biped. - - - true if the paste was successful, false if the paste was unsuccessful - - - a biped copy of type track - - true to paste opposite, false to paste normal - - true to paste the horizontal com, false to keep the existing horizontal com - - true to paste the vertical com, false to keep the existing vertical com - - true to paste the rotation com, false to keep the existing rotation com - - - - Updates the biped user interface. - This will update all biped menus in the creation or motion panel, whichever is visible. - - - - - Get the new mixer interface for max 8 that supports max objects. - - - The interface - - - - - into the biped driver controller for Max 9. - - - This contains functions supporting new biped features in Max 9, in particularly new functionality for setting large number of keys onto a biped at once, e.g. by loadin an XAF file. - - - - - for specifying that we will be setting a group of biped keys. - - - Calling this function means that biped will soon get a large number of keys set on different biped body parts, usually via a SetNodeTM function call. Internally, this will allow biped to correctly set the keys based upon biped peculiarities, for example we need to set the biped up all at once per each frame that has a key (per pose), and we need to handle shared keys caused by unseperated tracks. - - - - - for specifying that we will are done setting a group of biped keys. - - - Calling this function means that the biped is done setting keys on it, and we can now go ahead and key the biped based upon all of the values that were set after the previous StartSettingBipedKeys call. Note that if no StartSettingBipedKeys function was called, then nothing happens. - - - - - for setting world transforms on a biped. - - - This function will set the world transform on a biped, similarly to INode::GetNodeTM. This function however will cache values based upon biped body part, when called within StartSettingBipedSetKeys/StopSettingBipedKeys(). This allows us to correctly and optimally set up a bipeds animation pose per pose. - - The time at which to set the pose. - The world transform. - The internal 'id' of the biped node. You get this by calling . - The internal 'link' of the biped node. You get this by calling . - - - - for setting local biped rotation values. - - - This function will set the a local rotation on the biped, in max's local coordinate space (not biped's own internal local coordinate space.) Also this function works within StartSettingBipedKeys and StopSettingBipedKeys for correctly setting the biped rotations locally, pose per pose. - - The time to set the rotation. - The local rotation. - The internal 'id' of the biped node. You get this by calling . - The internal 'link' of the biped node. You get this by calling . - - - - This class represents the interface for the IO BMP format. - - - The interfaceID is defined as BMPIO_INTERFACE. Through C++ you can access the interface the following way: - - - - - This method returns the format type, which is one of the following; BMM_PALETTED, BMM_TRUE_24 and BMM_NO_TYPE (which is equivalent to BMM_TRUE_24). - - - - - Description: - This class represents the interface for the IO JPG format. The interface ID is defined as BMPIO_INTERFACE. - - All methods of this class are Implemented by the System. - - - - - This method returns the quality level of the output image. - - - - - This method returns the smoothing level of the output image. - - - - - Description: - This class represents the interface for the IO PNG format. The interface ID is defined as BMPIO_INTERFACE. - - All methods of this class are Implemented by the System. - - - - - This method returns the bitmap type, which is one of the following; BMM_PALETTED, BMM_TRUE_24, BMM_TRUE_48, BMM_GRAY_8, or BMM_GRAY_16. - - - - - This method returns TRUE if the alpha flag is set, otherwise FALSE. - - - - - This method returns TRUE if the interlaced flag is set, otherwise FALSE. - - - - - Description: - This class represents the interface for the IO RGB format. The interface ID is defined as BMPIO_INTERFACE. - - All methods of this class are Implemented by the System. - - - - - This method returns the bytes per channel info of the output image. - - - - - This method tells whether the output image should have an alpha channel or not - - - - - This method tells whether the output image should be compressed or not - - - - - The class expands upon the previous IBitmapIO classes. - - - Description: - The class expands upon the previous IBitmapIO classes for .bmp, .jpeg, .png and .tga. Like these others, it is a static interface; the code to fetch the interface is given below. The interface does not directly change the configuration of an existing . Instead, these methods set the default values, which will be used the next time an RLA or RPF file is saved. The defaults will also appear in the bitmap configuration dialog if the user saves an RLA or RPF file. - Usage: - Both RLA and RPF have the same interface class, , but some of the methods of this class are RPF-specific, giving undefined behavior if used on an RLA instance of the class. - - - - - Description: - This class represents the interface for the IO TGA format. The interface ID is defined as BMPIO_INTERFACE. - - All methods of this class are Implemented by the System. - - - - - This method returns the color depth, which would be 16, 24, or 32. - - - - - This method returns TRUE if the compression flag is set, otherwise FALSE. - - - - - This method returns TRUE if the alpha split flag is set, otherwise FALSE. - - - - - This method returns TRUE if the premultiplied alpha flag is set, otherwise FALSE. - - - - - Description: - This class exposes parameters to the Pager. This pager reduces memory footprint by swapping bitmap data to and from disk, keeping the memory usage of bitmaps within a certain percentage of total available memory. Internally, all bitmaps are partitioned into separately allocated tiles, but tiles are only swapped to disk when the pager is enabled. For performance reasons the tile size varies dynamically for each bitmap, but is typically around 1-4 megabytes. Bitmaps smaller than one tile are not eligible for paging, and are held in memory at all times. - - - - - Returns whether bitmap paging is enabled. - - - Internally, all bitmaps are partitioned into separately allocated tiles. With paging is enabled, bitmap tiles are swapped to disk, keeping total bitmap usage below the memory limit. - - - - - Enables or disables bitmap paging. - - - Internally, all bitmaps are partitioned into separately allocated tiles. Passing TRUE immediately swaps bitmap tiles from memory to disk, reducing total bitmap usage below the memory limit. Passing FALSE does not immediately swap bitmap tiles from disk to memory, but no further tiles are swapped to disk while paging is disabled. - - - - - Returns the page file path. - - - - - Returns the memory limit percentage (as a fraction from 0.0 to 1.0) of available padded memory. - - - - - Returns the memory padding percent (as a fraction from 0.0 to 1.0) of available memory. - - - - - Returns whether Memory Limit Auto Mode is enabled for the pager. - - - - - Returns the current memory limit physical value, in bytes. - - - This is the value used internally in deciding whether to swap bitmap tiles to disk. The value is not live, but is calculated from the memory limit percentage at specific times, during file load, file reset, render begin and render end. - - - - - Returns the total memory usage of bitmap tiles (excluding tiles on disk), in bytes. - - - - - Returns the current memory padding physical value, in bytes. - - - - - Returns the amount of available memory for the entire application, after padding, in bytes. - - - - - Proxy Manager Function-Published . - - - - - Returns TRUE if the proxy system is enabled, FALSE otherwise. - - - - - The proxy render mode selected currently in use. - - - - - Returns the default factor by which proxies are scaled in size (half, quarter, etc.) - - - - - Returns the default minimum size, below which bitmap are not proxied. - - - - - Returns the proxy size factor for a specific bitmap. (proxySizeFactor_Half, proxySizeFactor_Quarter, etc.) - - - - - Sets the proxy size factor for a specific bitmap. (proxySizeFactor_Half, proxySizeFactor_Quarter, etc.) - - - - - Returns whether a specific bitmap uses global proxy settings instead of its own settings. - - - - - Sets whether a specific bitmap uses global proxy settings instead of its own settings. - - - - - Returns whether the desired proxy is ready for use, or is stale (in memory or on disk). - - - - - Reloads correct versions of proxies into memory, if proxy settings have changed. - - - - - Generates proxy bitmaps needed by the scene and caches them to disk. - - - - - Displays the UI to configure proxy settings for the given bitmaps, or to configure the global settings if the input is NULL. - - - - - Displays the UI to update the proxy cache for the given bitmaps, or to update all out-of-date cache files if the input is NULL. - - - - - Loads a proxy bitmap storage into the input bitmap, according to the input request info. - - - - - - - The class provides access to the UI controls of the Blob object; adding and removing nodes programatically, and initiating pick mode. These methods are exposed for MAXScript usage but also be called through the SDK. The interface can be obtained as follows: - - - - - Description: - This class is only available in release 5 or later. - - Certain problems plague the current ON/OFF controller that produces counter-intuitive results and makes it difficult to use it in an animation system. The objective of this feature is to overcome these problems, either by fixing the existing controller or by creating a new controller. In the beginning we'll focus on the first option. - - We have decided to keep the current ON/OFF controller as it is because of its utility to certain users and develop a new controller. - - This is a controller similar to On/Off. However, its animation behavior is quite different in that, unlike On/Off, it is NOT a flip flop control. Each key in On/Off merely creates a state change. Its output is -1 or 1. - - The controller is a True/False control. Its output is the value of the last key which can only be either 0 or 1, thus any number of similar keys may be in sequence; the controller is merely evaluated at the current time and its value is output. This is not possible with the On/Off controller where each key must necessarily be a change of state from either -1 to 1 OR 1 to -1. - - The Controller will be useful for any situation where something must be turned on and off and the user wishes to work in a non-linear fashion i.e. jumping backwards and forwards at will in the time line. For example, such binary functions as object smoothing, object visibility scale multipliers, light on/off state, etc. - - The most pressing need for the is in the IK enabled state. Currently, the enable state is controlled by the On/Off controller. The On/Off behavior is in direct conflict with the idea of non-linear IK/FK blend animation. For multiple reasons that are too difficult and involved to go into here the flip flop behavior of On/Off becomes cumbersome at best. Furthermore, in R4 the behavior of On/Off was modified to mitigate this problem: if the Animate button is active and the IK Enable button is pressed, the enable track is examined, if any enable keys exist in the track later in time they are "rippled" back to the current time in order to preserve the overall animated state of IK Enable. With the Animate button off On/Off behaves as it did in R3: the new key is introduced and all existing animation in the Enable track is inverted. It is only when an even number of keys is added to the track that existing animation is preserved. - - The code for this controller is in: maxsdk/samples/controllers/boolcntrl - - - - - Description: - This class is only available in release 5 or later. - - - Derived from standard with an additional data called val. - - - Parameters: - float val; - - of the last key which can only be either 0 or 1 - - - - - Description: - This class provides access to the boolean object's parameters. Given a pointer to an object whose ClassID is NEWBOOL_CLASS_ID, you can cast that pointer to this class and use the methods to access the parameters. The boolean object has four references. 2 references to the operand objects and 2 references to transform controllers providing a transformation matrix for the 2 operands. The following values may be used to access the boolean object's references: BOOLREF_OBJECT1BOOLREF_OBJECT2BOOLREF_CONT1BOOLREF_CONT2 All methods of this class are implemented by the system. - - - - - Returns TRUE if the specified operand is selected; otherwise FALSE. - Parameters: - int which - - Specifies which operand to check. - - 0 for operand A, 1 for operand B. - - - - - Sets the selected state of the specified operand. - Parameters: - int which - - Specifies which operand to select. - - 0 for operand A, 1 for operand B. - - BOOL sel - - TRUE to select it; FALSE to deselect it. - - - - - Returns the boolean operation setting. - One of the following values: - - BOOLOP_UNION - - BOOLOP_INTERSECTION - - BOOLOP_SUB_AB - - BOOLOP_SUB_BA - - BOOLOP_CUT - This option is available in release 3.0 and later only. - - - - - Returns the type if the 'Cut' operation is choosen. One of the following values: - - BOOLOP_CUT_REFINE - - BOOLOP_CUT_SEPARATE - - BOOLOP_CUT_REMOVE_IN - - BOOLOP_CUT_REMOVE_OUT - - - - - Returns the display result setting. If TRUE the result is display; otherwise the operands are displayed. - - - - - Returns the show hidden operands state. TRUE if on; FALSE if off. - - - - - Returns the state of the update mode. - One of the following values: - - BOOLUPDATE_ALWAYS - - BOOLUPDATE_SELECTED - - BOOLUPDATE_RENDER - - BOOLUPDATE_MANUAL - - - - - Returns the state of the optimize result setting. TRUE if on; FALSE if off. Note: This method does not work on 'new' boolean objects as there is no optimize setting for these. - - - - - Sets the node used for operand A. This method adds a restore object if theHold.Holding(), but the Begin() and Accept() should be done in the calling routine. - - Note the following: - - - Parameters: - TimeValue t - - The time at which to set the operand. - - *node - - Points to the operand A node. - - - - - Sets the node used for operand B. This method adds a restore object if theHold.Holding(), but the Begin() and Accept() should be done in the calling routine. - Parameters: - TimeValue t - - The time at which to set the operand. - - *node - - + Points to the operand B node. - - *boolNode - - Points to the node of the boolean object. - - int addOpMethod=0 - - One of the following values: - - BOOL_ADDOP_REFERENCE - - Operand is a reference to original node. - - BOOL_ADDOP_INSTANCE - - Operand is an instance of the original node. - - BOOL_ADDOP_COPY - - Operand is a copy of the original node. - - BOOL_ADDOP_MOVE - - Original node should be deleted. - - int matMergeMethod=0 - - One of the following values: - - BOOL_MAT_NO_MODIFY - - Combines materials without changing them or the ID's. - - BOOL_MAT_IDTOMAT - - Matches ID's to materials, then combines materials. - - BOOL_MAT_MATTOID - - Matches materials to ID's, then combines them. - - BOOL_MAT_DISCARD_ORIG - - Discards original material, uses new node's instead. - - BOOL_MAT_DISCARD_NEW - - Discards new node's material, uses original. - - - - - The interface to a brush preset object, holding parameters for the PainterInterface and other brush tools. - - - The interface to Brush Preset objects. A brush preset corresponds to a button on the brush preset toolbar, or a row listed in the brush preset manager dialog. A preset holds one set of parameters for each brush preset context registered with the manager. Applying or fetching a preset will apply or fetch parameters for each currently active context. The context and parameter objects are implemented by plug-ins, but the presets holding the parameter objects are implemented by the system. - - - - - Returns an ID which uniquely identifies this preset. - - - Presets have an ID number unique from other presets at any given time; however if a preset is deleted, its ID number may be reassigned to other presets created later. - - - - - Applies parameters from the preset into the UI, as per activating its toolbar button. - - - For each active brush preset context, the corresponding set of parameters held by the preset is applied via ApplyParams(). - - - - - Fetches parameters from the UI into the preset, as per deactivating its toolbar button. - - - For each active brush preset context, the corresponding set of parameters held by the preset is fetched via FetchParams(). - - - - - Returns the parameter set held by the brush preset for a given context. - - - - The ID of the context - - - - Returns the number of contexts for which this preset is holding parameters. - - - - - Translates the index number of a parameter set into the corresponding context ID. - - - The context ID for the parameter set, or if the index is out of range - - The index of the parameter set - - - - Translates the context ID for a parameter set into the corresponding index number. - - - The index of the parameter set, or -1 if the preset has no parameters for the given context - - The ID of the context - - - - to a brush preset context. - - - A context represents a specific brush-based feature, defining a set of parameters used by the features and a UI. Context objects are responsible for creating and deleting the parameter set objects held by a brush preset, and for providing general information about the parameters. Contexts are required to communicate with the manager in the following ways: 1) Contexts should register themselves with the manager as soon as they loaded into memory, using IBrushPresetMgr::RegisterContext(). If the context plug-in is loaded before the manager plug-in, then the context can use a notification handler to register with the manager after system startup. 2) When a context is active, meaning its UI is displayed and ready to begin painting, the context should call IBrushPresetMgr::BeginContext(), and EndContext() when the context is deactivated. 3) When the user changes any parameter in the context's UI, the context should call IBrushPresetMgr::OnContextUpdated(). - Implemented by the plug-in. - - - - - Returns the unique ID for the context. These ID numbers should be random, as per standard class IDs. - - - - - Returns a name for the context. This is for UI display and may be localized. - - - - - Creates and returns a parameter set object of appropriate type for this context. - - - - - Deletes a parameter set object created by this context. - - - This is called by the system when the user deletes a preset or at shutdown; the object passed is always a parameter set created previously by the context. - - - - - Returns the number of individual parameters in a parameter set of this context. - - - - - Translates the index number of a parameter value into the corresponding parameter ID. - - - The parameter ID for the value, or zero if the index is out of range - - The index of the parameter value - - - - Translates the ID of a parameter value into the corresponding parameter index number. - - - The index of the parameter value, or -1 if there is no parameter with the given ID - - The ID of the parameter value - - - - Returns the name of a parameter value. - - - - The ID of the parameter value - - - - Returns the type of a parameter value. - - - - The ID of the parameter value - - - - Returns the number of parameters that should be displayed in the brush preset manager dialog. - - - - - Translates the index number of a display parameter into the corresponding parameter ID. - - - The parameter ID for the value, or zero if the index is out of range - - The index of the display parameter - - - - Translates the ID of a parameter value into the corresponding display parameter index number. - - - The index of the parameter value, or -1 if there is no display parameter with the given ID - - The ID of the parameter value - - - - Returns the name of a display parameter. - - - - The ID of the display parameter - - - - Returns whether the given parameter should be displayed in the brush preset manager dialog. - - - TRUE if the parameter should be displayed, FALSE otherwise - - The ID of the parameter - - - - Returns whether the given parameter is transient. - - - Transient parameters are not stored to disk. This can be useful, for example, with display-only parameters, whose value is a user-friendly string built from other non-display parameters. - TRUE if the parameter is transient, FALSE otherwise - - The ID of the parameter - - - - Returns the class ID of a plug-in implemented in the same module as this context. - - - The class ID is used to support deferred plug-in loading. When the brush preset manager needs to ensure that a context implementation is loaded into memory, it will load the module using this ID. The manager calls this method when a context is first registered, and then stores the value in the brush preset file for later use. - - - - - Returns the superclass ID of a plug-in implemented in the same module as this context. - - - The superclass ID is used to support deferred plug-in loading. When the brush preset manager needs to ensure that a context implementation is loaded into memory, it will load the module using this ID. The manager calls this method when a context is first registered, and then stores the value in the brush preset file for later use. - - - - - to the brush preset manager. - - - The manager is a singleton object implemented by the system. It maintains the list of contexts and presets. It communicates with the contexts to track which is active, and when a context is updated. It tracks which preset is active in order to store parameters into the preset when contexts are updated. It has functionality to read and write brush preset files. Finally, the brush preset manager provides a maxscript interface to activate and deactivate presets. - - - - - Registers a context with the manager. - - - Contexts should call this method at system startup, or immediately when loaded into memory to support deferred loading. - - The context to register - - - - Unregisters a context with the manager. - - - Contexts may call this method if they are unloaded from memory, but it is not required during normal shutdown. - - The context to unregister - - - - Returns a context object from its ID. - - - This returns the context immediately if it is currently registered, otherwise it loads the context plug-in if it is not in memory but supports deferred loading. - - The ID of the context - - - - Returns the number of contexts. - - - This includes all currently registered contexts, plus contexts in deferred plug-ins which were registered previously but are not yet loaded. - - - - - Translates the index number of a context into the corresponding context ID. - - - The context ID, or if the index is out of range - - The index of the context - - - - Translates the ID of a context into the corresponding context index number. - - - The index of the context, or -1 if no context exists with the given ID - - The ID of the context - - - - Notifies the manager that a context is activated. - - - This should be called by a context when its UI is opened and ready for painting - - The ID of the context - - - - Notifies the manager that a context is deactived. - - - This should be called by a context when its UI is closed - - The ID of the context - - - - Returns TRUE if the given context is active, FALSE otherwise. - - - - The ID of the context - - - - Returns a brush preset object from its ID, or NULL if no preset exists with the given ID. - - - - The ID of the preset - - - - Creates a new preset, and adds a corresponding button to the brush preset toolbar. - - - - - Deletes a preset, removing the corresponding button from the brush preset toolbar. - - - - - Returns the current number of brush presets. - - - - - Translates the index number of a brush preset into the corresponding preset ID. - - - The preset ID, or zero if the index is out of range - - The index of the preset - - - - Translates the ID of a brush preset into the corresponding preset index number. - - - The index of the preset, or -1 if no preset exists with the given ID - - The ID of the preset - - - - Returns the ID of the active preset. - - - This corresponds to the currently checked button on the brush preset toolbar, or zero if no button is checked. - - - - - Notifies the manager that a parameter has changed within a brush preset context. - - - Contexts should call this method whenever they are active, and any parameter changes which needs to be stored into the active preset - - The ID of the updated context - - - - Reads a brush preset file, including the preset values and the layout of the toolbar. - - - Non-zero if successful, otherwise zero on error - - The path of the file, or NULL to use the standard startup file - - - - Writes a brush preset file, including the preset values and the layout of the toolbar. - - - Non-zero if successful, otherwise zero on error - - The path of the file, or NULL to use the standard startup file - - - - to a set of brush preset parameter values, associated with a particular Brush Preset context. - - - Implemented by the plug-in. - - - - - Returns the ID of the brush preset context associated with this parameter set. - - - - - Applies the values from the parameter set into the UI of the corresponding context. - - - The parameter object is assumed to be part of the same plug-in as its context object, and to have knowledge of its state. The parameter object should apply its values into the UI as appropriate. - - - - - Fetches the values from the UI of the corresponding context into the parameter set. - - - The parameter object is assumed to be part of the same plug-in as its context object, and to have knowledge of its state. The parameter object should fetch its values from the UI as appropriate. - - - - - Returns the number of individual parameters in the parameter set. - - - - - Translates the index number of a parameter value into the corresponding parameter ID. - - - The parameter ID for the value, or zero if the index is out of range - - The index of the parameter value - - - - Translates the ID of a parameter value into the corresponding parameter index number. - - - The index of the parameter value, or -1 if there is no parameter with the given ID - - The ID of the parameter value - - - - Returns a parameter value by ID. - - - The value of the parameter - - The ID of the parameter value - - - - Sets a parameter value by ID. - - - - The ID of the parameter value - The value to set - - - - Returns the value of a parameter as it should be displayed in the UI. - - - This is used to display values with a user-friendly format in the brush preset manager dialog. For example, a minimum and maximum value of 0 and 100 might be displayed together as one entry with the string value "0-100". In this case, the parameter set should return TYPE_VOID for the minimum and maximum display values, but provide a third, display-only parameter, with the string value. - The value of the parameter to display in the UI - - The ID of the parameter value - - - - Informs the parameter set of the brush preset holding it. - - - This is called by the system when parameter sets are created, to make them aware of the preset they are held by. No specific action is required by the parameter set. - - The brush preset parent which holds this parameter set. - - - - An interface for controllers that can be buffered. - - - Controllers that support this interface can take a copy of themselves in a buffer and restore it. The interface ID is I_BUFFERABLE defined in AnimatableInterfaceIDs.h. - - - - - Interchange the controller and its buffer. - - - true if the swap was made successfully - - - - - Make the buffer equal to this controller. ! - - - true if the Snapshot was made successfully - - - if true, only take a snapshot if no buffer currently exists - - - - Make this controller equal to its buffer. - - - true if the Revert was made successfully - - - - - Clear and deallocate the buffer. - - - - - This class makes it possible to get and set the category field (order number) for rollups in the RollupOrder.cfg file. Normally a developer would use this class in order to store the order of rollout panels as a result of a custom handled Drag and Drop operation (see IRollupWindow::HandleRollupCallback and IRollupCallback::HandleDrop). First it is necessary to loop through all rollup panels and update the category field in the like this: - After that the has to be saved with GetIRollupSettings()->GetCatReg()->; - In order to reset the rollup order, one has to call ICatRegistry::DeleteList() for a given SClassID and ClassID. The structure of the RollupOrder.cfg file (and thus CatRegistry) can be seen as a list of items that represent the rollup order for each particular group. A group is identified by a SClassID and a ClassID. - In 3dsMax we can have different possibilities to store the order of rollups. In the Create and Modify Panel we want to store the order of rollups for the currently edited object, which can be an object, or a modifier. Thus the ClassID and SClassID of the group is the one of the currently edited object. For the Display panel however, we want the rollups to be the same no matter which object is currently selected. To do this, we create a dummy ClassID which represents the display panel and store the rollup orders under this dummy ClassID. This ClassID is identified by the method IRollupCallback::GetEditObjClassID. - No has to exist for a dummy ClassID. The RollupOrder.cfg file will indicate "No ClassName" in case a dummy class id is used. - - - - - This method gets the category (order field) for the given SuperClass ID, ClassID and Rollup Title (and optional Context). - The category (order field) for the given SuperClass ID, ClassID and context, or the default value if there is no stored value for the given combination. - - The superclass ID. - The class ID. - The rollup title. - This is used for error checking; it becomes the default value returned by the function if the call fails. So if you pass -1000 and get a return value of -1000, that means the entry was not found. - Optional pointer to a boolean receiving the open/close state of the rollup. If the open/close value was not stored, it does not modify the boolean. - An optional context, can be used to specify a special rollup ordering based on e.g. specific sub-object selection. - - - - This method updates (sets) the category (order field) for the given SuperClass ID, ClassID and Rollup Title (and optional Context). - - The superclass ID. - The class ID. - The rollup title. - The category. - Optional pointer to the open/close state of the rollup. - Optional context, can be used to specify a special order based on e.g. specific sub-object selection. - - - - This method Saves the category settings in File "UI\RollupOrder.cfg" - - - - - This method Loads the category settings from File "UI\RollupOrder.cfg" - - - - - This method Erases all category settings (in memory only) - - - - - This method deletes a category list for a given superclass ID, class ID and context. - - The superclass ID. - The class ID. - Optional context. - If true, all contexts for the given superclass ID and class ID are deleted. Only used if context is a nullptr. - - - - Returns the unique ID for the particle container class. ID is used for constructing the container when loading since the particle container class is not inherited from class . - - - - - Returns number of channels in the container. - - - - - Returns i-th channel in the container. - - - - - Returns a channel with the given interface id. If privateOwner is NULL, then the channel is public. If privateOwner is specified, then the channel is private with the given private owner. - - - - - FnPub alternative for the method virtual IObject* GetChannel. - - - Essentially takes in the two (2) components that make up the full CHANNELCONTAINER_INTERFACE - - Corresponds to 0x74f93c00. Look at #define CHANNELCONTAINER_INTERFACE - Corresponds to 0x1eb34600. Look at #define CHANNELCONTAINER_INTERFACE - - - - FnPub alternative for method virtual IObject* GetChannel. - - - - - Returns true if the channel has been added. The channel may be rejected if there are duplicate interfaces in the added channel and in the container. The ParticleChannelReadWrite and ParticleChannelAmount interfaces don't count since every channel has them. - - - - - Returns a channel object if a channel with the given interface id is in the container. If such channel doesn't exist, that container makes an attempt to create and add a channel for the interface according to the specifications. The method is not for FnPub intentionally. - - - - interface id of channel to be present in the container - if interface is not present then create particle channel with the classID - if true then the created particle channel is wrapper - read ID for wrapping the particle channel - write ID for wrapping the particle channel - if true then the channel is transferable (contrary to temporary) - the parameter is used to record an action that created the channel this record can be used later on to identify if the action needs to initialize the channel values for new particles - the parameter is used to set a private owner of the channel. Only the action with the same object pointer may access this channel - if the channel was created by the same action node then it's responsibility of the action to initialize values - - - - Returns an interface if the interface with the given interface id is in the container. If such interface doesn't exist, that container makes an attempt to create and add a channel for the interface according to the specifications. The method is not for FnPub intentionally. - - - - interface id of channel to be present in the container - if interface is not present then create particle channel with the classID - if true then the created particle channel is wrapper - read ID for wrapping the particle channel - write ID for wrapping the particle channel - if true then the channel is transferable (contrary to temporary) - the parameter is used to record an action that created the channel this record can be used later on to identify if the action needs to initialize the channel values for new particles - the parameter is used to set a private owner of the channel. Only the action with the same object pointer may access this channel - if the channel was created by the same action node then it's responsibility of the action to initialize values - - - - Returns an interface of a channel with the given interface id and private owner. - - - - interface id of channel to be present in the container. - the parameter is used to identify a private owner of the channel. - - - - Returns an interface of a channel with the given interface id and private owner parameters: - iChanID: interface id of channel to be present in the container - privateOwner: the parameter is used to identify a private owner of the channel. - - - - - Makes a clone copy of the whole container (all channels), returns new container. - - - - - Makes a copy from the other container, returns true if successful. - - - - - Saves content of the channel to file. - - - - - Loads content of the channel from file. - - - - - Returns amount of memory used (in bytes) by the channel container to store the information. This is a total sum of the memory used by all channels and the data from the container itself. - - - - - Description: - This class provides interface methods used to support indirect material referencing and enhanced face / material associations. Generally, these methods will need to be implemented by the plug-in using them and cannot be called from a standard library, since the information required is intimately associated with the geometry of the object. - - All methods of this class are virtual. - - - - - Returns TRUE if the object can associate a particle number with a face number, and FALSE if not. - Default Implementation: - { return FALSE; } - - - - - Returns the particle to which the face identified by faceID belongs. - Parameters: - int faceID - - The ID of the face. - Default Implementation: - { return 0; } - - - - - Returns TRUE if the object can return a material pointer given a face being rendered, and FALSE if the object will be associated for that render pass with only the material applied to the node. - Default Implementation: - { return FALSE; } - - - - - Returns the number of different materials used on the object. This number is used in enumerating the different materials via the methods GetNthMtl() and GetNthMaxMtlID() below. - Default Implementation: - { return 0; } - - the following methods are meaningful. - - - - - If the method SupportsIndirMtlRefs() above returns TRUE then this method returns the different materials used on the object. - Parameters: - int n - - The zero based index of the material used on the object. - - Default Implementation: - { return NULL; } - - - - - If the method SupportsIndirMtlRefs() above returns TRUE then this method returns the maximum material ID number used with the specified material on the object - Parameters: - int n - - The zero based index of the material. - Default Implementation: - { return 0; } - - - - - If the method SupportsIndirMtlRefs() above returns TRUE then this method returns a pointer to the material associated with the face identified by faceID. - Parameters: - int faceID - - The ID of the face to check. - Default Implementation: - { return NULL; } - - - - - Description: - This class represents the virtual class to support collision objects. All collision detection classes should derive from this class. The purpose of this class is to improve the particle collision system for older particle systems and to let other systems such as Flex and MAXScript benefit from a more open architecture and to provide an interface to determine if a particle hit a surface. Additionally three basic collision detection classes are provided, a planar, a spherical, and a mesh deflection class. - - - - - This method returns the collision type supported by the engine. - One of the following; - - POINT_COLLISION for point collision, currently supported. - - SPHERE_COLLISION for spherical collision, currently not supported. - - BOX_COLLISION for box collision, currently not supported. - - EDGE_COLLISION for edge collision, currently not supported. - - - - - This method will be called once before the checkcollision is called for each frame which allows you to do any required initialization. - Parameters: - TimeValue t - - The time at which to initialize. - - TimeValue dt - - The delta of time the particle wil travel. - - - - - This method will be called at the end of each frame solve to allow you to destroy and deallocate any data you no longer need. - Parameters: - TimeValue t - - The time at which to initialize. - - TimeValue dt - - The delta of time the particle wil travel. - - - - - This method will be called to execute a point to surface collision and compute the time at which the particle hit the surface. - Parameters: - TimeValue t - - The end time of the particle. - - pos - - The position of the particle in world space. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute a sphere to surface collision and compute the time at which the particle hit the surface. - Parameters: - TimeValue t - - The end time of the particle. - - pos - - The position of the particle in world space. - - float radius - - The radius of the sphere. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute a box to surface collision and compute the time at which the particle hit the surface. - Parameters: - TimeValue t - - The end time of the particle. - - box - - The box itself. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - This method will be called to execute an edge to surface collision and compute the time at which the particle hit the surface. - Parameters: - TimeValue t - - The end time of the particle. - - edgeA - - The first edge. - - edgeB - - The second edge. - - vel - - The velocity of the particle in world space. - - float dt - - The delta of time that the particle travels (t-dt being the start of time of the particle) - - float &at - - The point in time that the collision occurs with respect to the dt. - - &hitPoint - - The point of collision. - - &norm - - The bounce vector component of the final velocity. - - &friction - - The friction vector component of the final velocity. - - inheritedVel - - The approximated amount of velocity inherited from the motion of the deflector. - TRUE if there's a collision, otherwise FALSE. - - - - - Description: - This class is an interface to the Manager. Within 3ds Max using the Customize pull down menu / Customize User choice / Colors tab a user is able to alter the colors used for various UI elements. They can change the saturation, value and transparency of elements, and load and save color schemes. - - Using the methods of this class developers can do the same (the 3ds Max color manager uses this class internally). Developers can add their own named custom colors. Developers wanting to do this need to pick a random 32-bit ColorId to identify it. (Note: typedef DWORD ColorId;). The generator may be used for this where only one of the two DWORDS is used. See Class for more details. The low integer ColorIds are reserved for 3ds Max internal use. These colors should be registered on startup, so a Global Utility Plug-In () is the best way to handle this. See Class for details. Methods that are marked as internal should not be used. - - - - - This method registers a new color with the system. For plug-in developers this should be done at startup using a Global Utility Plug-in which calls this method. See the Description section above for details. If developers want to add a color of their own, they need to pick a random 32-bit integer ColorId to identify it. - Returns false if the color is already registered; otherwise true. - - The ID of the color to register. This should be generated by the developer using a single DWORD from the output of the program. See Class for more details. - The name for the color. - The category for the color. If the name passed matches one of the existing 3ds categories the color will be place in there, otherwise a new one will be created. - The default value for the color. This is the value that the color will be reset to when a 3ds user presses "Reset" in the color customization dialog. See . - The default disabled value for the color. Used in various elements to signal the disabled state of a control. This parameter is optional and will be set to 0xff000000 as a default value, what is defined to be "no color". - The default hover value for the color. Used in various elements to paint a control, if the mouse is hovering it. This parameter is optional and will be set to 0xff000000 as a default value, what is defined to be "no color". - - - - This method will load the specified color file from the current UI directory. - Parameters: - MCHAR* pFileName - - The filename of the color file to load. - TRUE if the load was successful, otherwise FALSE. - - - - - This method will save the specified color file from the current UI directory. - Parameters: - MCHAR* pFileName - - The filename of the color file to save. - TRUE if the save process was successful, otherwise FALSE. - - - - - This method returns the file name of the current color file. - - - - - Sets the color value of the previously registered color whose ID is passed. - Returns true if the color was set and false if the id passed could not be found. - - Specifies which color to set. - The color value to set. See . - Specifies which color state for the color - - - - Returns the color value of the color whose ID is passed. - The color is returned or black (RGB(0,0,0)) if the ColorId passed was not found. - - Specifies which color to get. - Specifies which color state for the color - - - - This method returns the color associated with a specified color ID as a . - The color is returned or black (RGB(0,0,0)) if the ColorId passed was not found. - - Specifies which color to get. - Specifies which color state for the color - - - - Returns a handle to the brush for the color whose id is specified. NULL is returned if the id passed is not found. Note that the color manager does resource management for brushes, so the value returned should not be deleted. - The brush handle of the color - - The color whose brush handle is returned. - Specifies which color state for the color - - - - Returns the name of the color whose ID is passed. - Parameters: - ColorId id - - The ID of the color. - - - - - Returns the category string of the color whose ID is passed. - Parameters: - ColorId id - - The ID of the color. - - - - - This method takes the specified windows color definition (for example COLOR_BTNHILIGHT) and returns the 3ds Max customized version of that color. Anyone writing a plug-in with custom windows code should use this call (and CustSysColorBrush() below) instead of the Win32 GetSysColor() and GetSysColorBrush() if they want to participate in the 3ds Max custom color scheme. - - Note the following #define which may be used to simplify coding: - - GetCustSysColor(which)->CustSysColor(which)) - Parameters: - int which - - Specifies the windows color definition. See Standard Color IDs. For a full list of windows color definitions, please refer to the Win32 API, in particular the methods GetSysColor() and SetSysColor(). - - - - - This method returns a handle identifying a logical brush that corresponds to the specified color index. Note that the color manager does resource management for brushes, so the value returned should not be deleted. - Parameters: - int which - - Specifies the windows color definition. See Standard Color IDs. For a full list of windows color definitions, please refer to the Win32 API, in particular the methods GetSysColor() and SetSysColor(). - - Note the following #define which may be used to simplify coding a bit: - - GetCustSysColorBrush(which)->CustSysColorBrush(which)) - - - - - Returns the specified color value for drawing various items in the viewports. This is the same as the previous GetUIColor() function. - Parameters: - int which - - Specifies which color to retrieve. See ViewportDrawingColors. - The color as a . - - - - - Sets the specified color value for drawing various items in the viewports. This is the same as the previous SetUIColor() function. - Parameters: - int which - - Specifies which color to retrieve. See ViewportDrawingColors *clr - - Points to the color value to set. - - - - - Returns the default color used for drawing various items in the 3ds Max user interface. The values returned are not affected by the user's color selections or those set by SetUIColor(). This is the same as the previous GetDefaultUIColor() function. - Parameters: - int which - - Specifies which color to retrieve. See ViewportDrawingColors. - - - - - Returns a floating point value (in the range 0.0f to 1.0f) that is one of the scale factors applied to the specified icon type. These scale values used to do image processing on the icons at start-up time. - Parameters: - IconType type - - The icon type. One of the following values: - - kDisabledIcon - - The disabled icons. - - kEnabledIcon - - The enabled icons. - - IconColorScale which - - The icon color scale. One of the following values: - - kSaturationScale - - The saturation scale. - - kValueScale - - The value scale. - - kAlphaScale - - The alpha scale. kContrastScale - - The contrast scale. kGradientMapScale - - The gradient map scale. - - - - - Sets the specified scale factor for the icon type passed. The color manager maintains the values for the 3ds Max icon image processing system. Developers can set values to scale the saturation, value and transparency for enabled and disabled icon images using this method. - Parameters: - IconType type - - The icon type. One of the following values: - - kDisabledIcon - - The disabled icons. - - kEnabledIcon - - The enabled icons. - - IconColorScale which - - The icon color scale. One of the following values: - - kSaturationScale - - The saturation scale. - - kValueScale - - The value scale. - - kAlphaScale - - The alpha scale. - - float value - - The value to set (in the range 0.0f to 1.0f). - - - - - Returns true if the invert flag is set for the specified icon type and false if not set. - Parameters: - IconType type - - The icon type. One of the following values: - - kDisabledIcon - - The disabled icons. - - kEnabledIcon - - The enabled icons. - - - - - Sets the invert flag for the specified icon type to on or off. - Parameters: - IconType type - - The icon type. One of the following values: - - kDisabledIcon - - The disabled icons. - - kEnabledIcon - - The enabled icons. - - bool value - - Pass true for inverted; false for not inverted. - - - - - Returns the current color theme. - - - - - - - Returns the file name of the currently loaded color file. - - - - - Returns the default color for the specified ID. The default color is the value passed as defaultValue in RegisterColor(), regardless if a SetColor() has been done subsequently. This is used by the UI when the user presses "Reset" to reset a color to its default value. - The color is returned or black (RGB(0,0,0)) if the ColorId passed was not found. - - Specifies which default color to get. - Specifies which color state for the default color - - - - This method returns the color associated with a user interface color as a COLORREF. - Parameters: - int which - - The UI color index (see gfx.h). - in the viewports as a COLORREF. - Parameters: - int which - - Specifies which color to retrieve. See ViewportDrawingColors. - - - - - This method allows you to issue a repaint of the user interface. - Parameters: - RepaintType type - - The type of repaint you wish to issue; kRepaintAll, kRepaintTrackBar, kRepaintTimeBar. - - - - - This method takes the name of a folder that must be in 3ds Max "UI" folder. If the folder exists, then it sets 3ds Max icon folder to point to it, and redraws the UI with those new icons.Warning: All of the 3ds Max standard icon BMP files must exist in that folder. If any of the standard files are missing, icons will appear blank in the UI. All the icons files needed live in the UI/icons folder, which is the default icon folder. - Parameters: - MCHAR* pFolder - - The icon folder to set. - - - - - Description: - The color swatch control puts up the standard 3ds Max modeless color selector when the control is clicked on. The plug-in may be notified as the user interactively selects new colors. - - To initialize the pointer to the control call: - *GetIColorSwatch(HWND hCtrl, COLORREF col, MCHAR *name); - - For example: custCSw = GetIColorSwatch(GetDlgItem(hDlg, IDC_CSWATCH), RGB(255,255,255), _M("New Wireframe Color")); - - This returns the pointer to the control, sets the initial color selected, and displays the text string passed in the title bar of the selection dialog. - - To release the control call: ReleaseIColorSwatch(IColowSwatch ics); - - The value to use in the Class field of the Custom Properties dialog is: ColorSwatch This message is sent as the color is being adjusted in the . - - CC_COLOR_CHANGE - - lParam = pointer to ColorSwatchControl - - LOWORD(wParam) contains the ID of the control. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) contains 1 if button UP, or 0 if mouse drag. - - This message is sent if the color has been clicked on, before bringing up the color picker. - - CC_COLOR_SEL - - lParam contains a pointer to the ColorSwatch . - - LOWORD(wParam) contains the ID of the control. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) contains 0. - - This message is sent if another color swatch has been dragged and dropped on this swatch. - - CC_COLOR_DROP - - lParam contains a pointer to the ColorSwatch . - - LOWORD(wParam) contains the ID of the control. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) contains 0. - - This message is sent when the color picker is closed. - - CC_COLOR_CLOSE - - lParam contains a pointer to the ColorSwatch . - - LOWORD(wParam) contains the ID of the control. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) contains 0. - - - - - This method sets the current color value. - Parameters: - COLORREF c - - You can pass specific RGB values in using the RGB macro. For example, to pass in pure blue you would use RGB(0,0,255). - - int notify=FALSE - - If you pass TRUE for this parameter, the dialog proc for the dialog will receive the CC_COLOR_CHANGE message each time the color is changed. - This method returns the old color. - - - - - This method may be used to retrieve the color selected by the user. - The COLORREF structure returned may be broken down into individual RGB values by using the GetRValue(color), GetGValue(color), and GetBValue(color) macros. - - - - - This method sets if the color shown in the color swatch is dithered on not. - Parameters: - BOOL onOff - - TRUE to force the color to be dithered; otherwise FALSE. - - - - - Call this method to have the color selector comes up in a modal dialog. This forces the user to select OK before the user may operate the rest of the program. - - - - - This method is called to indicate that the color swatch is in a dialog that has been become active or inactive. A color swatch that is in an inactive dialog will be drawn as dithered due to the limited number of color registers available on an 8-bit display. - Parameters: - int onOff - - If TRUE the color swatch is in an active dialog. If FALSE the control is in an inactive dialog. - - - - - If there is already a color picker up for a color swatch, this method switches it over to edit the color swatch on which EditThis() was called. - Parameters: - BOOL startNew=TRUE - - If there was no color picker up, if this parameter is set to TRUE, then a color picker is created. If this parameter is set to FALSE, and there was no color picker up, then nothing happens. - - - - - This methods indicates how change notifications are sent, while the color picker is open. - FALSE indicates the dialog proc for the dialog receives multiple CC_COLOR_CHANGE messages as the user makes changes interactively in the color picker. TRUE indicates the dialog proc for the dialog receives only one CC_COLOR_CHANGE message, when the color picker is closed, and only if the user clicks OK instead of Cancel. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - - - class - - - Description: - This class is an interface for changing the name of a color swatch. Previously the only way to change the name of a swatch was to reinitialize it with a new GetIColorSwatch call, and this would not help with swatches that were already being displayed in a color selector dialog. Using this new interface, developers can change the name of a swatch and - - simultaneously change the name of a color selector dialog that's associated with the swatch. An example of its usage can be seen below :- - - It's used in Editable Poly as follows - when the user changes the radio button that affects whether our swatch is used as a "Select by Color" or a "Select byIllumination" swatch, the following code is used to update the swatch. - - These first three lines are adequate when the color selector is not being displayed: - - mpEPoly->getParamBlock()->GetValue (ep_vert_sel_color, t, selByColor, - - mpEPoly->FOREVER); getParamBlock()->GetValue (ep_vert_color_selby, t, - - mpEPoly->byIllum, FOREVER); - - iCol = GetIColorSwatch (GetDlgItem (hWnd, IDC_VERT_SELCOLOR), selByColor, - - GetString (byIllum ? IDS_SEL_BY_ILLUM : IDS_SEL_BY_COLOR)); - - That will update the swatch to the correct name and color. However, if the - - color selector is being displayed, we need to use the new interface to ensure - - that the name is promptly updated in the UI: - - pInterface = iCol->GetInterface (COLOR_SWATCH_RENAMER_INTERFACE_51); - - if (pInterface) { - - *) pInterface; - - pRenamer->SetName (GetString (byIllum ? IDS_SEL_BY_ILLUM : IDS_SEL_BY_COLOR)); - - } - - Finally, don't forget to release the swatch: ReleaseIColorSwatch (iCol); - - - - - - - Sets the name of the color swatch, and of any associated color picker dialog. - - - - - Description: - This class represents the interface to the Command Panel. You can obtain a pointer to the Command Panel interface using; GetICommandPanel()ICommandPanel* . This macro will return - - (ICommandPanel*)GetCOREInterface(COMMAND_PANEL_INTERFACE). - - All methods of this class are Implemented by the System. - - - - - This method returns the command panel's rollup threshold. - - The threshold (which defaults to 50 pixels) affects the way rollups are placed when the command panel is resized (from one to multiple columns). A number of rollups remain in the left column while others move over to the second and/or additional columns based on this. A lower threshold will increase the likelihood that a panel gets shifted over to the next column. - - - - - The interface for global container functionality. - - - Operations on a specific container can be accessed through the container itself. - - - - - Create a container. - - - the container node if successfully created - - - - If created, the container node will be selected - - - The container node will be created at the average of the content nodes, or at the origin if the is empty - - - - Nodes to be added as content of the container - - - - Inherit a container into the scene. - - - the container node if a container was successfully inherited - - - If the asset is invalid, the user will be presented with a file dialog. - - - The container asset representing the definition file to be used - - - - Test if a node is in a container or not. - - - the container interface if the node is in a container - - - The node that we are testing to see if it is in a container - - - - Test if a node is a container or not. - - - the container interface if the node is a container - - - The node that we are testing to see if it is a container - - - - IContainer provides access to the container object functionality. - - - Container - - A container is a helper object in the scene. Once created, the user can choose its content, that is, nodes that are meant to be grouped together. Containers should be self-contained blocks without references from the content to nodes outside of the container, otherwise the references will be lost during operation of the container. Containers hold the content, and moving or deleting a container will affect the content, but containers and content are not the same thing. - For example, content can be unloaded, while the container remains in the scene. The container is associated to a container definition file, which is a Max file that stores only the container and its contents. Container definitions are tracked as file assets. - There are two types of containers: - Content nodes of containers are all children of the container. It is possible to have objects linked to containers or contents of containers without being inside, but this is not recommended. It is not - possible to instance containers, but they can be copied, and then changes to one of the copies can be saved, and all containers can be reloaded, and all copies will inherit the changes. Many containers can point to the same definition. - In addition to the content, containers also govern what users of a container are allowed to do with the content if they inherit the container. This is called the container rules. At the moment, the only options are either no access (the user can only read in the content but make no modification) or edit in-place, which allows someone inheriting the container to modify the content and save the result, overwriting the original definition. - Containers can be closed, making the content uneditable. When a container is closed the content behaves like an xreffed scene, displayed and rendered but not selectable or editable. - - - - - Returns the content nodes for this container. - - - - - if true include nested content - - returned content nodes - - - - Checks for content membership. - - - - true if the node is part of the content. - - - node to check for membership - - include nested containers child nodes when checking - - - - Checks for inherited content membership. - - - - true if the node is part of the inherited content. - - - node to check for membership - - check content of nested containers - - - - Adds a node and its children to the container. - - - The container node becomes the parent of the content node. Some nodes are automatically added to the local content along with the input node. The children of the node are added. If the node is part of a system [like biped or bones], all nodes in the system are also added. - - If the node has a target [as in INode::GetTarget() - for instance a camera target], then its - - target is added and if it is a target, the targeting node is also added - - true if the node was added. - - - node to add to the container - - - - Adds several nodes to the container. - - - - true if all nodes were added. - - - array of nodes to add to the container - - - - Removes a node from the container. - - - Some nodes are automatically removed along with the input node. The children of the node are removed. If the node is part of a system, all nodes in the system are also removed. If the node has a target, its target is removed and if it is a target, the targeting node is also removed - - true if the node was removed from local content. - - - node to remove from the container - - whether or not the removed node should also be unlinked from its parent - - - - Definition files have the format of a max file, but use a different file extension: .MAXC. - - This is to allow users to distinguish container definitions from regular max scenes when browsing folders, and prevent mistaken edits of container definitions. It is possible to rename the container definition and open it as a MAX file. Local containers use a local definition file. Inherited containers reference a source definition file. - Gets the local definition file for the container. If the container is inherited, the name is empty - - - - - Sets the local definition file for the container - - - - - Gets the source definition file for the container. If the container is local, the name is empty - - - - - Sets the source definition file for the container - - - - - Saves the current content and rules as the new definition. If there is no definition file name, the user will be prompted for one. - - - - - if true, prompt the user for a definition file name - - - - Updates the content from its definition, preserving local modifications. - - - - - Saves the local definition and deletes the content from the scene. - - - - - Reloads content from its definition and local modifications. Only available when unloaded. - - - - - Reloads content from its definition and local modifications. Same as load but is always available. Discards unsaved local changes. - - - - - Turns an inherited container into an unsaved local container, merging its content into the scene. - - - - - Merges a container source, and recursively merges any nested container among its content. - - - - - Returns whether the container is inherited (or local) - - - - - Returns whether the container is open. - - - - - Opens or closes the container. Depending on the container state, this may not be allowed. - - - - the open state of the container after the operation. - - - - - Returns whether the open status of the container can be changed in its current state. - - - - - Returns whether the container is unloaded, that is, whether its content has been temporarily deleted. - - - - - Returns whether the container is unique, that is, whether it is local as well as any container it may contain. - - - - - Returns whether the container, when inherited, will allow editing in place. - - - - - Temporarily makes an inherited container that allows it to act like a local container. - - - - - Returns whether the container is currently editing in place. - - - - - For an imported container, returns whether it allows editing in place. - - - - - Returns whether the container will automatically update if it is closed and its definition is updated. - - - - - Returns whether the container displays its name in the viewport. - - - - - Sets whether the bounding box for the container object will be extended to encompass all of its content. - - - - - Returns whether the bounding box for the container object will be extended to encompass all of its content. - - - - - Returns whether the container overrides the object properties (wire color, hidden status etc) of its content. - - - - - Sets the size of the container helper object. - - - - - Returns the size of the container helper. - - - - - Returns the node containing this container object. - - - There can only be one node since we cannot create instances of container objects - - - - - extends container object functionality. In particular it provides support for new access rules that inherited containers may follow. - - - - - Previously, containers would only allow for no access when inherited or access to edit in place so that a user can save over the original definition. Now in addition a container can grant access to only add new objects over the inherited container or get full freedom to access anything that was unlocked on the original source definition. For the latter case the user can specify additional locks over certain items, such as all materials, all modifiers, all transforms or all objects, to restrict what's accessible further. - - - - - Returns the type of access that the container will provide when inherited. - Returns the enum AccessType flag specifying what type of access is allowed. - - - - - Returns the type of access that the container has based upon the access provided by its inherited source. - If it has no inherited source it will default to return the same value as IContainerObject13::GetAccessType. - Returns the enum AccessType flag specifying what type of access is allowed. - - - - - what will be automatically locked when the access type is set to AccessType::eAnythingUnlocked. - - - - - Type of content that will be automatically locked. - - - - Clear the locked content rules so that nothing is automatically locked. - - - - - Get if this content will be automatically locked when the access type is set to AccessType::eAnythingUnlocked. - - - Returns true if that content type specified by the LockedContents enum will be locked, false otherwise. - - - The content type that we are checking to see if it will be locked. - - - - Returns the proxy type used by the container. - - - Proxies offer the possibility to represent container content by something other than their definition. The following are the proxy types currently supported: PROXYTYPE_NONE: (default value) the container displays its definition PROXYTYPE_ALTERNATE: the container will display one of possibly several alternate definitions, one of which is current. - - - - - Returns the number of alternate definitions for the container. - - - - - Returns the alternate definition for the container from an index. - - - - - zero-based index of the alternate definition file to retrieve - - - - Sets an alternate definition for the container. - - - - true if the alternate definition was successfully set. - - - zero-based index of the alternate definition file to set. The index must be less than the current number of alternate definitions - - an alternate definition file: either an empty asset or an asset of type kContainerAsset - - - - Appends one alternate definition to the container alternate definitions. - - - - true if the alternate definition was successfully appended. - - - an alternate definition file: either an empty asset or an asset of type kContainerAsset - - - - Removes one alternate definition from the container alternate definitions. - - - - true if the alternate definition was successfully removed. - - - zero-based index of the alternate definition file to remove. - - - - Returns the zero-based index of the current alternate definition of the container. - - - - - Returns the current alternate definition of the container. - - - - - Saves the content and rules as the new definition into a format compatible with the specified 3ds Max version If there is no definition file name, the user will be prompted for one. - - - true if the operation was successful; false otherwise - - - if true, prompt the user for a definition file name - - the version of 3ds in which the file is to be saved. Currently it supports saving to the current version of 3ds (MAX_RELEASE) and to 3ds 2010 (MAX_RELEASE_R12). - - - - Returns a status string for the container. - - - - - Returns whether the container displays its status in the 3D viewports. - - - - - Returns the user name currently editing the definition for the container. - - - - - Returns whether the container is out of date with its definition. - - - - - Returns whether the container is both inherited and its content is not currently local. - - - - - extends container object functionality. In particular it provides support for control of how layer merges are handled. - - - - - - - - Returns whether to duplicate matching Layers without an identical parent hierarchy when merging layers. - - - - - This interface provides access to the container preferences. - - - - - Returns the global override of individual container viewport status display. - - - - - - - Returns whether automatic detection of out of date containers is set. - - - - - Returns whether an eventual out of date source definition will be updated on load. - - - - - Sets whether an eventual out of date source definition will be updated on load. - - - - - Returns whether an eventual out of date source definition will be updated on reload. - - - - - Sets whether an eventual out of date source definition will be updated on reload. - - - - - Returns the time interval between container status updates, in seconds. - - - - - This class provides an interface to retrieve what new node will replace an existing one during the local edit process. An instance of this class is passed in the function ILockedContainerUpdate::PreReplacement and ILockedContainerUpdate::PostReplacement. - - - - - - - This functions returns what node will replace the main node in the scene during the container update process. - - - The node that replaces the main node. If it's the same as the mainNode parameter then that node isn't replaced, and if returns NULL the node is deleted, otherwise it will return a different node than the mainNode parameter. - - The node that we are querying to see how it will get replaced. - - - - A collection of copies. - - - This contains a collection of IBipCopy objects - postures, poses, and tracks. Access to an IBipCopy object is based on its type and its index in the collection of copy objects. An instance of can be gotten from the GetCopyCollection and CreateCopyCollection functions. - - - - - Gets the name of the copy collection. - - - the name of the copy - - - - - Sets the name of the copy collection. - - - name must be <= 256 characters - true if the name was set, false if it wasn't set - - - name of the copy collection - - - - Gets the number of copies of the specified type (posture/pose/track). - - - the number of copies of the specified type - - - type of copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - - - Gets the copy of the specified type at the specified index. - - - the copy of the specified type at the specified index, and NULL if the copy was not found - - - type of copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - the index of the desired copy - - - - Gets a copy of the specified type with the specified name. - - - the copy of the specified type with the specified name, and NULL if the copy was not found - - - type of copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - the name of the desired copy - - the index of the desired copy - - - - Deletes a copy. - - - true if the copy was deleted, false if the copy was not found - - - type of copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - the index of the copy to delete - - - - Deletes all copies of a particular type (posture/pose/track) in a collection. - - - - - type of copy, one of the following: COPY_POSTURE, COPY_POSE, COPY_TRACK - - - - Description: - This class is an interface to a single curve used by a . A pointer to one of these is returned from the method ICurveCtl::GetControlCurve(). - - All methods of this class are implemented by the system. - - - - - Sets the pen properties of a curve - Parameters: - COLORREF color - - The color for the curve lines. - - int width = 0 - - The width of the lines in pixels. - - int style = PS_SOLID - - The pen style to use. One of the following types may be used. See the Win32 API Reference for more information on pen styles. - - PS_SOLID - - PS_DASH - - PS_DOT - - PS_DASHDOT - - PS_DASHDOTDOT - - PS_NULL - - PS_INSIDEFRAME - - - - - Retrieves the color, width and style of a curve. - Parameters: - COLORREF &color - - The color in use. - - int &width - - The width in use. - - int &style - - The style in use. One of the following types: - - PS_SOLID - - PS_DASH - - PS_DOT - - PS_DASHDOT - - PS_DASHDOTDOT - - PS_NULL - - PS_INSIDEFRAME - - - - - Sets the pen properties of a curve if it is disabled. - Parameters: - COLORREF color - - The color to set. - - int width = 0 - - The width to set. - - int style = PS_SOLID - - The style to set. One of the following types: - - PS_SOLID - - PS_DASH - - PS_DOT - - PS_DASHDOT - - PS_DASHDOTDOT - - PS_NULL - - PS_INSIDEFRAME - - - - - Retrieves the color of a curve if it is disabled. - Parameters: - COLORREF &color - - The color in use. - - int &width - - The width in use. - - int &style - - The style in use. One of the following types: - - PS_SOLID - - PS_DASH - - PS_DOT - - PS_DASHDOT - - PS_DASHDOTDOT - - PS_NULL - - PS_INSIDEFRAME - - - - - Returns the Y-value for a given X-Value of the curve. Note that values outside the X-range are extrapolated from the curve using a straight line based on the tangents of the first or last point. - - - The time to get the value. - - The input X value. - - The interval into which the validity of the evaluated parameters is intersected. - - If TRUE a lookup table is used to get the value (for speed). If FALSE the value is computed. This is used to speed up value access. The default value for the lookup table size is 1000. The lookup table will be calculated whenever this method is called with TRUE and the current lookup table is not initialized yet, or invalid (it will be invalidated, when a point or tangent is moved, or the time has changed in case it is animated). - - - - Returns the Y-value for a given X-Value of the curve. Note that values outside the X-range are extrapolated from the curve using a straight line based on the tangents of the first or last point. - Parameters: - TimeValue t - - The time to get the value. - - float fX - - The input X value. - - BOOL UseLookupTable = FALSE - - If TRUE a lookup table is used to get the value (for speed). If FALSE the value is computed. - - This is used to speed up value access. The default value for the lookup table size is 1000. The lookup table will be calculated whenever this method is called with TRUE and the current lookup table is not initialized yet, or invalid (it will be invalidated, when a point or tangent is moved, or the time has changed in case it is animated). - - - - - Returns TRUE if the curve can be animated; otherwise FALSE. - - - - - Returns nonzero if the specified point is animated; otherwise zero. - Parameters: - int index - - The zero based index of the curve to check. - - - - - Returns the number of points in the curve. - - - - - Returns a which contains the selected / de-selected state for each point. The is GetNumPts() in size where the 0-th bit corresponds to the 0-th point. - - - - - Sets the selected state of the points in the curve using the passed. Bits which are are affected as specified by the flags. - Parameters: - &sel - - Specifies which points are affected. The 0-th bit corresponds to the 0-th point. - - int flags - - One or more of the following values: - - SELPTS_SELECT - - Select the points. - - SELPTS_DESELECT - - De-select the points. - - SELPTS_CLEARPTS - - If this bit is set the method de-selects (clears) all the points before performing the operation as specified by the flags above. - - - - - Sets the specified point at the time passed. - Parameters: - TimeValue t - - The time at which to set the point. - - int index - - The zero based index of the point in the curve. - - *point - - Points to the curve point to set. - - BOOL CheckConstraints = TRUE - - When you're setting a point, it checks the in and outtan handles to prevent them from going beyond the previous or next point's location, since that would create an invalid curve. Thus the Curve will adjust the tangents due to the constraints. However, if you set the first point, there is no next point, to check the tangent location against, thus you have to have a possibility to turn CheckConstraints off, so the constraints won't be checked (developers have to make sure that they are inserting valid points/tangents. ) - - BOOL notify = TRUE - - This parameter is available in release 4.0 and later only. - - This allows developers to control whether the command sends windows messages or not. When set to FALSE windows messages are not sent to the message handler. This lets developers constrain points when the user attempts to move them without getting into a message loop. When TRUE messages are sent. - - - - - Retrieves data about the specified point and updates the validity interval to reflect the validity of the point's controller. - - - The time to get the data. - - The zero based index of the point. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Retrieves data about the specified point. - Parameters: - TimeValue t - - The time to get the data. - - int index - - The zero based index of the point. - - - - - - - This method returns the out of range type. - One of the following; CURVE_EXTRAPOLATE_LINEAR, CURVE_EXTRAPOLATE_CONSTANT - - - - - Inserts the specified point at the location passed. - Parameters: - int where - - This value becomes the new index of the point. - - &p - - The point to insert. - Nonzero if the point was inserted; otherwise zero. - - - - - This is identical to the Insert above but allows you to turn off/on the hold that occurs.this is useful when you are doing interactive inserts and moves from code, the original Insert hold would often get in the way - Parameters: - int where - - This value becomes the new index of the point. - - &p - - The point to insert. - - BOOL do_not_hold - - TRUE in order not to hold; otherwise FALSE. - Nonzero if the point was inserted; otherwise zero. - - - - - Deletes the point whose index is passed. - Parameters: - int index - - The zero based index of the point to delete. - - - - - Returns the current size of the lookup table. See SetLookupTableSize() above. - - - - - Description: - This class is an interface to the curve custom control. An example of this control in the 3ds Max user interface can be seen in the Map section of the Output rollup of a 2D Texture map. Sample code using these APIs is available in /MAXSDK/SAMPLES/UTILITIES/CCUTIL/CCUTIL.CPP. - - - - - This method indicates if the dialog box for the control is up or not. Returns TRUE if active; otherwise FALSE. - - - - - This method is used to bring up or close the dialog box. - Parameters: - BOOL sw - - TRUE to open; FALSE to close. - - - - - Returns the window handle of the control. - - - - - Sets the number of curves used in this control. Note, that this method actually create the curves, which means, that the NewCurveCreatedCallback method will be called. However, this happens only if a is registered already. Thus it is important,that the is registered BEFORE this method is called. - - - The number of curves to use. - - This will cause the function to register an Restore if set to TRUE. - - - - Deletes all curves associated with the curve control. - - - - - Returns the numbers of curves used by the control. - - - - - Sets the absolute position of the first and last CurvePoints. - Parameters: - float min - - The minimum value. - - float max - - The maximum value. - - BOOL rescaleKeys = TRUE - - This parameter is available in release 4.0 and later only. - - This parameter controls whether changing the X range will rescale the keys and key tangents or not. When this is TRUE, the default, the keys and tangents get resinced to the total X range. Setting this to FALSE allow developers to have move control over the exact placement of keys and tangents when the X range changes. This also allow developers to set ranges from within the points changed message handler without getting into a loop. - - - - - This determines the absolute upper and lower Y-constraint. This method only has an effect if the CC_CONSTRAIN_Y flag is set. - Parameters: - float min - - The minimum value. - - float max - - The maximum value. - - - - - Returns the X Range. - - - - - Returns the Y Range. - - - - - This methods registers a callback object used to handle certain aspects of the control. The callback object will be used for updating of the display button image list and tool tip text for the curve control. It also gets called when the user executes a Reset or creates a new control. - - This registers a reference target which implements the method Animatable::GetInterface() for the id I_RESMAKER_INTERFACE by returning an object derived from class . - Parameters: - *rmak - - Points to the reference target which returns the callback object. Note that the CurveControl holds this reference target in a SingleWeakRefMaker member, and that if no other references are held to this reference target when the CurveControl is deleted, the reference target will automatically be deleted as the reference is dropped. - - - - - Returns the current zoom values. - Parameters: - float *h - - Points to storage for the horizontal zoom value. - - float *v - - Points to storage for the vertical zoom value. - TRUE if valid values were returned; otherwise FALSE. - - - - - Sets the zoom values. To determine the values to use developers should use the CCUtil plug-in, create a pop-up window as big as is appropriate for the final control, adjust the zoom and scroll values interactively, and then simply read out the values from the CCUtil user interface (GetZoom and GetScroll). - Parameters: - float h - - The horizontal value to set. - - float v - - The vertical value to set. - - - - - Returns the horizontal and vertical scroll values. - Parameters: - int *h - - Points to storage for the horizontal scroll value. - - int *v - - Points to storage for the vertical scroll value. - TRUE if valid values were returned; otherwise FALSE. - - - - - Sets the scroll values. To determine the values to use developers should use the CCUtil plug-in, create a pop-up window as big as is appropriate for the final control, adjust the zoom and scroll values interactively, and then simply read out the values from the CCUtil user interface (GetZoom and GetScroll). - Parameters: - int h - - The horizontal scroll value to set. - - int v - - The vertical scroll value to set. - - - - - Performs a zoom extents operation to the curve view. - - - - - Sets the title of the dialog box to the specified string. This is only used if the CC_ASPOPUP is used to create a pop-up dialog. - Parameters: - MCHAR *str - - The title string to display. - - - - - Returns and interface to the specified curve. This interface allows you to set the color of the curve and retrieve the Y value of the curve given an X value. - Parameters: - int numCurve - - The zero based index of the curve. - - - - - Returns a which indicates which curves are toggled on or off. - - - - - Returns the curve control flags. See Custom Curve Control Flags. - - - - - Sets the parent window for the control if the controll is not a popup window. - Parameters: - HWND hParent - - The window handle of the parent. - - - - - Call this method and the following window messages will be sent to the window whose handle is passed. The contents of the lParam and wParam parameters passed to the window proc are shown. - - WM_CC_SEL_CURVEPT - - Sent when a point is selected or deselected. - - lParam = * , LOWORD(wParam) = The number of points which are selected. - - WM_CC_CHANGE_CURVEPT - - Sent when a point is changed. - - lParam = * , LOWORD(wParam) = The zero based index of the changed point. - - WM_CC_CHANGE_CURVETANGENT - - Sent when a point's in or out tangent is changed. - - * , LOWORD(wParam)= The zero based index of the changed point, - - HIWORD(wParam) contains a flag, that indicates if the changed tangent is the in, or out tangent. You can check these flags as HIWORD(wParam) & IN_CURVETANGENT_CHANGED and HIWORD(wParam) & OUT_CURVETANGENT_CHANGED, for the in and out tangent respectively. - - WM_CC_DEL_CURVEPT - - Sent when a point is deleted. - - lParam = * , LOWORD(wParam) = The zero based index of the deleted point. - - WM_CC_INSERT_CURVEPT - - This option is available in release 4.0 and later only. - - *, LOWORD(wParam) = The zero based index of the inserted point. - Parameters: - HWND hWnd - - The handle of the window which will receive the messages. - - - - - Returns a value which indicates the current command mode. One of the following values (which correspond directly to toolbar buttons in the UI. See the 2D texture map Output rollup for example): - - CID_CC_MOVE_XY - - CID_CC_MOVE_X - - CID_CC_MOVE_Y - - CID_CC_SCALE - - CID_CC_INSERT_CORNER - - CID_CC_INSERT_BEZIER - - - - - This method redraws the custom curve control. - - - - - Returns an which reflects the validity of every point of every curve used by the curve control. - Parameters: - TimeValue t - - The time about which the interval is computed. - - - - - Updates the validity interval passed with the overall validity of the curves in the control. This simply does: - - valid &= GetValidity(t); - - - The time about which the interval is computed. - - The interval into which the validity of the evaluated parameters is intersected. - - - - This sets the position of the vertical line drawn over the graph showing the current X value. See flag CC_SHOW_CURRENTXVAL in Custom Curve Control Flags. - Parameters: - float val - - The value to set. - - - - - This method allows you to turn on/off the display code. It is useful when you are doing lots of changes and don't want the window to continually redraw. - Parameters: - BOOL enable - - TRUE to enable; FALSE to disable. - - - - - Description: - This is the base class from which the 3ds Max custom controls are derived. All methods of this class are implemented by the system. - - - - - Returns the handle of the control. - - - - - This method is used to enable the control so it may be operated by the user. - - TRUE to enable; FALSE to disable. - - - - This method is used to disable the control so it may not be selected or used. When disabled, the control usually appears grayed out. - - - - - This returns TRUE if the control is enabled and FALSE if it is disabled. - - - - - This method is used internally and should not be called by plug-in developers. This second enable function is used to disable and enable custom controls when the associated parameter has a non-keyframable parameter. The effective enable state is the AND of these two enable bits. - - For example, when a parameter has a controller plugged into it, and the controller is not keyframable, any spinner control associated with it won't be effective. That's because the controller doesn't take input - it only outputs values. To prevent the user from being confused by the ineffectiveness of the spinner the control it's automatically disabled by the system using this method. - - TRUE to enable; FALSE to disable. - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - The command to execute. - Optional argument 1 (defined uniquely for each ). - Optional argument 2. - Optional argument 3. - - - - Sets a tooltip for the custom control. - - - This method allows for turning on or off the tooltip for a custom control. - - - if true, the tooltip is enabled, otherwise disabled. When disabled, the tooltip won't be displayed when the the mouse hovers on top of the control. Enabling the tooltip repeatedly will have the same effect as enabling it once. - - pointer to a string representing the text to be displayed in the tooltip window. This parameter is ignored when the tooltip is being disabled. - - - - Helper function to disable or enable this UI control based on whether the associated with it is keyframable or not (locked parameter or scripted parameters are not keyframable). When a UI control is associated with a parameter residing within a parameter block with the optional p_ui tag then the control will be automatically disabled when the parameter is non-keyframable and this method does not need to be used. When the control is not using that automatic association this helper method can be used. Caller needs to identify the parameter associated to the control as the subanim number of an . - - - - The parent of the this control is associated with (if NULL, this method will do nothing). - The subanim number of the associated with this control. For use to get subNum from ParamID (see sample code, for instance maxsdk\samples\materials\stdShaders.cpp). - - - - Class used to handle some custom controls options. - - - - - to print or not the icons paths and to persist or not that option. - - - - - Indicates whether icon paths are printed to the listener. - - - - - to print or not ui text-clipping errors and to persist or not that option. - - - - - Indicates whether ui text-clipping errors are printed to the listener. - - - - - Get the x sensitivity for reporting test-clipping errors. - - - Differences greater than or equal to this value will be reported - - - - - the x sensitivity for reporting test-clipping errors and to persist or not. - - - - - Get the y sensitivity for reporting test-clipping errors. - - - Differences greater than or equal to this value will be reported - - - - - the y sensitivity for reporting test-clipping errors and to persist or not. - - - - - Gets the additional user UI scaling factor. - - - The users UI scaling factor. - - - - - to print or not the tool clip information and to persist or not that option. - - - - - Indicates whether tool clip information is printed to the listener. - - - - - Description: - Render Presets compatibility interface: - - used by renderers to support renderer specific presets. If the renderer does not support this interface, the entire renderer will be saved. - - - - - This interface provides access for setting and querying the state of flag that defines whether a Custom Attribute should survive a stack collapse. - - - When the calling code needs to collapse the stack, it should bracket the call with an Enumeration using a class derived from . Now the maxsdk contains two types of enumeration callbacks. One which collapses the stack with out any regard to Custom Attributes, and another that will copy Custom Attributes to the base object. The calling code can find out which to use by using this interface, the user can set the state of flag explicitly defining the path to take. - The calling code should only really need to query the flag, and not set it. The user will most likely control the flag - - - - - Gets the current state of the survive stack collapse flag. - - - - - Gets the current state of the retain subAnim Custom Attributes flag. - - - - - Description: - This class represents the interface class to a custom attributes container. - - - - - This method returns the number of custom attributes. - - - - - This method allows you to retrieve the custom attribute by its specified index. - Parameters: - int i - - The index of the custom attribute you with to obtain. - - - - - This method allows you to append a custom attribute. - Parameters: - *attribute - - A pointer to the custom attribute you wish to add. - true if the was appended, false if not. Will fail if attribute is null or would cause a circular dependency. In this case it is the responsibility of the caller to delete the if need be. - - - - - This method allows you to set the custom attribute at the specified index. - Parameters: - int i - - The index for which to set the custom attribute. - - *attribute - - A pointer to the custom attribute you wish to set. - true if the was set, false if not. Will fail if attribute is null, would cause a circular dependency, or the index is out of range. In this case it is the responsibility of the caller to delete the if need be. - - - - - This method allows you to insert a custom attribute at the specified index. - Parameters: - int i - - The index at which to insert the custom attribute. - - *attribute - - A pointer to the custom attribute you wish to insert. - true if the was set, false if not. Will fail if attribute is null, would cause a circular dependency, or the index is out of range. In this case it is the responsibility of the caller to delete the if need be. - - - - - This method allows you to remove a custom attribute. - Parameters: - int i - - The index of the custom attribute to remove. - - - - - This method gets called when the material or texture is to be displayed in the material editor parameters area. The plug-in should allocate a new instance of a class derived from to manage the user interface. - Parameters: - HWND hwMtlEdit - - The window handle of the materials editor. - - *imp - - The interface pointer for calling methods in 3ds Max. - A pointer to the created instance of a class derived from . - - - - - This method will copy the parameters from a specified reference maker. - Parameters: - *from - - A pointer to the reference maker to copy the parameters from. - - &remap - - This class is used for remapping references during a Clone. See Class . - - - - - This method returns a pointer to the owner of the custom attributes. - - - - - Finds the first custom attribute in a custom attribute container, that has a specific interface id. - - - Returns a BaseInterface* to the found custom attribute, or NULL if there is no custom attributes with the given interface id exist in the custom attribute container. - - The interface id to be search for - - - - Description: - Custom buttons may be one of two different forms. A Check button (which stays pressed in until the user clicks on it again), or a Pick button (which pops back out as soon as it is released). Buttons may be implemented as a Fly offs. A fly off offers several alternative buttons which fly out from the button after it is press and held briefly. - - - - The buttons may contain text or graphic images. Fly off buttons only use graphic images. The plug-in developer has control over the appearance of the button in each of its four states (Enabled&Out, Enabled&In, Disabled&Out, Disabled&In). - - Note: When the user presses a button a WM_MENUSELECT message is sent so that the client can display a status prompt describing the function of the tool. The fuFlags parameter is set to this value: CMF_TOOLBUTTON. - - In 3dsmax version 4.0 you can remove borders from an ; - - *cb = (); - - cb->Execute(I_EXE_CB_NO_BORDER); - - To initialize the pointer to the control call: - *GetICustButton(HWND hCtrl); - To release the control call: - ReleaseICustButton(ICustButton *ics); - The value to use in the Class field of the Custom Properties dialog is: CustButton - - - - - This retrieves the text displayed by the button. - - Storage for the text to retrieve. - Specifies the maximum length of the string returned. - - - - This specifies the text displayed by the button. - - The text to be displayed by the button. - - - - This retrieves the text entered into the control. - - Storage for the text to retrieve. - - - - This retrieves the length of the text entered into the control. It returns the length of the text in characters (so without the terminating NULL). Note that this value may be higher than the actual length of the text when it contains multi-byte characters. - - - - - This method is used to establish the images used for the buttons. - - The image list. An image list is a collection of same-sized images, each of which can be referred to by an index. Image lists are used to efficiently manage large sets of icons or bitmaps in Windows. All images in an image list are contained in a single, wide bitmap in screen device format. An image list may also include a monochrome bitmap that contains masks used to draw images transparently (icon style). The Windows API provides image list functions, which enable you to draw images, create and destroy image lists, add and remove images, replace images, and merge images. The next four parameters () are indices into the image list. They indicate which images to use for each of the four possible button states. You may specify a unique image for each one of these states by passing a different index for each state. Or you may supply a single image to be used for all the states by specifying the same index four times. - Out&Enabled. - In&Enabled. - Out&Disabled. - In&Disabled. - The width of the button image. - The height of the button image. - - - - This sets the icon image used for a button. - - Points to the icon. - The width of the button image. - The height of the button image. - - - - This sets the icon image used when a button is pressed. - - Points to the icon. - The width of the button image. - The height of the button image. - - - - Sets a multi-resolution icon to the button. - - The name of the icon. - The default width of the button icon at 100% dpi scale. An iconWidth of 0 will use the default toolbar button image size as default. This value will internally get scaled according to the current dpi setting. - The default height of the button icon at 100% dpi scale. An iconHeight of 0 will use the default toolbar button image size as default. This value will internally get scaled according to the current dpi setting. - - - - Returns the name of the multi-resolution icon assigned to the button. - - - - - This method sets the button type. - - One of the following values: A Push button pops back out as soon as it is released.. A Check button stays pressed in until the user clicks on it again. - - - - This method sets the button to work as a fly off control. - - The number of buttons in the fly off. - An array of instances of the class . This class uses four indices into the image list to describe the button in each of the possible states: Out&Enabled, In&Enabled, Out&Disabled and In&Disabled. In the simple case, where all the buttons have the same image, you can do the following: Each button will use the same images regardless of its pressed in / disabled state. Note the button is automatically drawn pushed in (i.e. shaded lighter) when the user is dragging the cursor over the button, but the actual image on the button is not changed. If you require different images for these states, supply different indices into the image list for each. See the sample program for an example of how this is done. - This is the time in milliseconds the button must be held pressed before the fly off appears. You may specify 0 if you want the buttons to fly off immediately. To retrieve the value that 3ds uses internally for its flyoffs use a method of Class called . This returns a value in milliseconds. - This is the initial button displayed. - This parameter is optional. It is used to indicate which direction the buttons should fly off. The choices for direction are: The default. The system will determine the direction of the fly off. The buttons fly off above. The buttons fly off beneath. The buttons will fly off either left or right with the system determining the direction. The buttons fly off to the left. The buttons fly off to the right. - - - - - This method sets the button to work as a fly off control. - - A of icon names. The icon names are used to create multi-resolution icons for the buttons in the fly off control. A simple fly off can be defined by: - This is the time in milliseconds the button must be held pressed before the fly off appears. You may specify 0 if you want the buttons to fly off immediately. To retrieve the value that 3ds uses internally for its flyoffs use a method of Class called . This returns a value in milliseconds. - This is the initial button displayed. - This parameter is optional. It is used to indicate which direction the buttons should fly off. The choices for direction are: The default. The system will determine the direction of the fly off. The buttons fly off above. The buttons fly off beneath. The buttons will fly off either left or right with the system determining the direction. The buttons fly off to the left. The buttons fly off to the right. - - - - - Returns a list of the multi-resolution icon names used in the button fly off control. - - - - - This method establishes which button is displayed by passing its index. - - The index of the flyoff button to display. - This indicates if the call to this method should notify the dialog proc. If TRUE it is notified; otherwise it isn't. - - - - Returns the index of the button which is currently displayed. - - - - - Determines if the button is checked. This method returns TRUE if the check button is currently in the In state (i.e. checked) and FALSE otherwise. - - - - - Passing TRUE to this method sets the button to the In or checked state. - - If TRUE the button is set to the checked state; if FALSE the button is unchecked. - - - - This method controls if the check button is displayed in the highlight color when pressed in. - - TRUE if you want the button to use the highlight color; otherwise pass FALSE. - - - - Specifies if messages are sent when the user clicks or releases the button. If this method is called with TRUE, a message is sent immediately whenever the button is pressed down or released. The message BN_BUTTONDOWN is sent on button down and BN_BUTTONUP is sent when the button is released. The BN_BUTTONUP message is sent even if the button is released outside the button rectangle. - - TRUE if notification should be send by the button; FALSE if notifications should not be sent. - - - - Specifies if messages are sent when the user right clicks the button. - - If TRUE, the message is sent whenever the users right clicks on the button. If FALSE no message are sent on right clicks. - - - - This methods returns the highlight color for the check button. - - - - - Returns a pointer to the drag and drop manager for this button control. - - - - - Returns a pointer to any macro button data for this button. See Class . - - - - - If set to true, the button will be displayed with both an icon (if present) and text - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - This control is a simple text input control. The user may type any string into the field and the plug-in is notified when the user presses the ENTER key. There are also methods to parse and return integer and floating point values entered in the control. - To initialize the pointer to the control call: - - To release the control call: - The value to use in the Class field of the Custom Properties dialog is: CustEdit The following messages may be sent by the edit control: WM_CUSTEDIT_ENTER - This message is sent when the control loses focus or when the user presses the ENTER key while using the control. Note that if the control is associated with a spinner or slider, no notification occurs on losing focus if the edit field value equals the spinner/slider value. - wParam contains the custom edit control resource ID. lParam contains the HWND of custom edit control. - - - - - This retrieves the text entered into the control. - - Storage for the text to retrieve. - Specifies the maximum length of the string returned. - - - - This retrieves the text entered into the control. - - Storage for the text to retrieve. - - - - This retrieves the length of the text entered into the control. It returns the length of the text in characters (so without the terminating NULL). Note that this value may be higher than the actual length of the text when it contains multi-byte characters. - - - - - This method places the text into the control for editing. - - The text to place in the control. - - - - This method allows you to pass in an integer value to the control. The integer is converted to a string and displayed in the control. - - This value is converted to a string and displayed in the control. - - - - This method allows you to pass in a floating point value to the control. The float is converted to a string and displayed in the control. - - This value is converted to a string and displayed in the control. - The precision argument is simply the number of decimal places that get represented in the string that appears in the edit field. So if the arguments were (1.0f/3.0f, 3) then the string "0.333" would appear in the edit field. - - - - This method parses and returns an integer value from the control. - - This pointer, if passed, is set to TRUE if the input is 'valid'; otherwise FALSE. FALSE indicates that something caused the parsing of the input to terminate improperly. An example is a non-numeric character. So for example, if the user entered "123jkfksdf" into the field the valid pointer would be set to FALSE. - - - - This method parses and returns a floating point value from the control. - - This pointer, if passed, is set to TRUE if the input is 'valid'; otherwise FALSE. FALSE indicates that something caused the parsing of the input to terminate improperly. An example is a non-numeric character. So for example, if the user entered "123jkfksdf" into the field this pointer would be set to FALSE. - - - - A developer doesn't normally need to call this method. This offsets the text vertically in the edit control. - - This parameter specifies the number of pixels to offset. - - - - This method allows custom handling of the RETURN key. If you pass TRUE to this method an EN_CHANGE message will be sent to the control when the RETURN key is pressed. The EN_CHANGE message is sent when the user has taken any action that may have altered text in an edit control so developer need to also call GotReturn() (documented below) to see if it was indeed a RETURN key press. - Sample Code: - Below is the way this is handled by the Hit By dialog. In that dialog, when the user enters a wild card pattern into the name match field and presses RETURN, the dialog is exited with the items matching the pattern selected. The way this is accomplished is by pass TRUE to WantReturn() and then processing the EN_CHANGE message on the control. If GotReturn() is TRUE the Win32 function PostMessage() is used to send the IDOK message to exit the dialog. If this wasn't done, pressing RETURN in the edit control would only enter the text - the user would have to move the mouse over the OK button and press it. - - - - If TRUE, then when the user presses the RETURN key in that control, the edit field will send an message to the owner, and calling will return TRUE. - - - - This method should be called on receipt of an EN_CHANGE message. It return TRUE if pressing the RETURN key generated the message; otherwise FALSE. - - - - - Calling this method gives the control the focus to receive input. - - - - - Returns TRUE if the control has the focus to receive input; otherwise FALSE. - - - - - Determines whether the TAB key may be used to jump to the next control in the tab sequence. - - TRUE to enable the TAB key to move to the next control; FALSE to disable the TAB key from moving the focus. - - - - Normally when a user exits an edit filed the notification WM_CUSTEDIT_ENTER is sent. Many plug-ins key off this message to finalize the input of values. For instance, if the user is entering a value into an edit field and they hit the TAB key to leave the field the value should be entered. Normally this is the desired behavior. However, as a special case condition, if a developer does not want to update the value, this method may be called so the WM_CUSTEDIT_ENTER notification won't be sent when the edit control loses focus. - - TRUE to turn on; FALSE to turn off. - - - - Sets the text font in the edit control to display in a bold format or normal. - - TRUE to turn bolding on; FALSE to turn off. - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - The custom image control provides a recessed area in the dialog to display a bitmap image. - - To initialize the pointer to the control call: - *GetICustImage(HWND hCtrl); - To release the control call: - ReleaseICustImage(ICustImage *ici); - The value to use in the Class field of the Custom Properties dialog is: CustImage - - - - - This method sets the image to display. - Parameters: - HIMAGELIST hImage - - An image list. An image list is a collection of same-sized images, each of which can be referred to by its index. Image lists are used to efficiently manage large sets of icons or bitmaps in Windows. All images in an image list are contained in a single, wide bitmap in screen device format. An image list may also include a monochrome bitmap that contains masks used to draw images transparently (icon style). The Windows API provides image list functions, which enable you to draw images, create and destroy image lists, add and remove images, replace images, and merge images. - - int index - - This is the index of the image to display in the image list. - - int w - - The image width. - - int h - - The image height. - - - - - Sets a multi-resolution icon to the image. - - The name of the icon. - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - This provides a simple separator item. Methods are available to get and set the visibility. - - The value to use in the Class field of the Custom Properties dialog is: CustSeparator - - - - - Returns TRUE if the control is visible; otherwise FALSE. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - The custom status control provide a recessed area of the dialog which the developer may use as a status prompt display. - - To initialize the pointer to the control call: *GetICustStatus(HWND hCtrl); - To release the control call: - ReleaseICustStatus(ICustStatus *ics); - The value to use in the Class field of the Custom Properties dialog is: CustStatus - - - - - This method specifies the text message to display. - Parameters: - MCHAR *text - - Points to the text to display. - - - - - This methods controls the formatting of the text in the status control. - Parameters: - StatusTextFormat f - - One of the following options: - - STATUSTEXT_LEFT - - Left justified in the control. - - STATUSTEXT_CENTERED - - Centered in the control. - - STATUSTEXT_RIGHT - - Right justified in the control. - - - - - This retrieves the text entered into the control. - Parameters: - MSTR& text - - Storage for the text to retrieve. - - - - - This retrieves the length of the text entered into the control. It returns the length of the text in characters (so without the terminating NULL). Note that this value may be higher than the actual length of the text when it contains multi-byte characters. - - - - - Retrieves the text currently displayed in the custom status control. - Parameters: - MCHAR *text - - A pointer to storage for the text to return. - - int ct - - The maximum length of the string to return. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - This control mimics the edit control as well as a status control. It may be set to 'read-only' so the user can read but cannot edit the displayed string. - - The value to use in the Class field of the Custom Properties dialog is: CustStatusEdit - - - - - Retrieves the text entered into the control. - Parameters: - MCHAR *text - - Storage for the text to retrieve. - - int ct - - Specifies the maximum length of the string returned. - - - - - This retrieves the text entered into the control. - Parameters: - MSTR& text - - Storage for the text to retrieve. - - - - - This retrieves the length of the text entered into the control. It returns the length of the text in characters (so without the terminating NULL). Note that this value may be higher than the actual length of the text when it contains multi-byte characters. - - - - - This method places the text into the control for editing. - Parameters: - MCHAR *text - - The text to place in the control. - - - - - This method allows you to pass in an integer value to the control. The integer is converted to a string and displayed in the control. - Parameters: - int i - - This value is converted to a string and displayed in the control. - - - - - This method allows you to pass in a floating point value to the control. The float is converted to a string and displayed in the control. - Parameters: - float f - - This value is converted to a string and displayed in the control. - - int precision=3 - - The precision argument is simply the number of decimal places that get represented in the string that appears in the edit field. So if the arguments were (1.0f/3.0f, 3) then the string "0.333" would appear in the edit field. - - - - - This method parses and returns an integer value from the control. - Parameters: - BOOL *valid=NULL - - This pointer, if passed, is set to TRUE if the input is 'valid'; otherwise FALSE. FALSE indicates that something caused the parsing of the input to terminate improperly. An example is a non-numeric character. So for example, if the user entered "123jkfksdf" into the field the valid pointer would be set to FALSE. - - - - - This method parses and returns a floating point value from the control. - Parameters: - BOOL *valid=NULL - - This pointer, if passed, is set to TRUE if the input is 'valid'; otherwise FALSE. FALSE indicates that something caused the parsing of the input to terminate improperly. An example is a non-numeric character. So for example, if the user entered "123jkfksdf" into the field this pointer would be set to FALSE. - - - - - A developer doesn't normally need to call this method. This offsets the text vertically in the edit control. - Parameters: - int lead - - This parameter specifies the number of pixels to offset. - - - - - This method allows custom handling of the RETURN key. If you pass TRUE to this method an EN_CHANGE message will be sent to the control when the RETURN key is pressed. The EN_CHANGE message is sent when the user has taken any action that may have altered text in an edit control so developer need to also call GotReturn() (documented below) to see if it was indeed a RETURN key press. - Parameters: - BOOL yesNo - - If TRUE, then when the user presses the RETURN key in that control, the edit field will send an EN_CHANGE message to the owner, and calling GotReturn() will return TRUE. - - - - - This method should be called on receipt of an EN_CHANGE message. It return TRUE if pressing the RETURN key generated the message; otherwise FALSE. - - - - - Calling this method gives the control the focus to receive input. - - - - - Returns TRUE if the control has the focus to receive input; otherwise FALSE. - - - - - Determines whether the TAB key may be used to jump to the next control in the tab sequence. - Parameters: - BOOL yesNo - - TRUE to enable the TAB key to move to the next control; FALSE to disable the TAB key from moving the focus. - - - - - Normally when a user exits an edit filed the notification WM_CUSTEDIT_ENTER is sent. Many plug-ins key off this message to finalize the input of values. For instance, if the user is entering a value into an edit field and they hit the TAB key to leave the field the value should be entered. Normally this is the desired behavior. However, as a special case condition, if a developer does not want to update the value, this method may be called so the WM_CUSTEDIT_ENTER notification won't be sent when the edit control loses focus. - Parameters: - BOOL onOff - - TRUE to turn on; FALSE to turn off. - - - - - Sets the text font in the edit control to display in a bold format or normal. - Parameters: - BOOL onOff - - TRUE to turn bolding on; FALSE to turn off. - - - - - Sets if the control is 'read-only'. That is, the string is displayed but cannot be edited. - Parameters: - BOOL onOff - - TRUE for read-only; FALSE to allow editing. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - This control allows the creation of toolbars containing buttons (push, check, and fly-offs), status fields, separators (spacers), and other Windows or user defined controls. - - \ The standard size for 3ds Max toolbar button icons is 16x15 or 16x16 pixels. - - In 3ds Max 3.0 and later toolbars may have multiple rows, or appear vertically. They may also have macro buttons (added with the class) which may have icons or text. - - To initialize the pointer to the control call: - *GetICustToolbar(HWND hCtrl); - To release the control call: - ReleaseICustToolbar(ICustToolbar *ict); - The value to use in the Class field of the Custom Properties dialog is: CustToolbar - - Note: The TB_RIGHTCLICK message is sent when the user right clicks in open space on a toolbar: - Also Note: To add tooltips to the toolbar controls you can do so by capturing the WM_NOTIFY message in the dialog proc. For complete sample code see /MAXSDK/SAMPLES/HOWTO/CUSTCTRL/CUSTCTRL.CPP. The specific message is processed as shown below. - - - - - - This method establishes the image list used to display images in the toolbar. - Parameters: - HIMAGELIST hImage - - The image list. An image list is a collection of same-sized images, each of which can be referred to by an index. Image lists are used to efficiently manage large sets of icons or bitmaps in Windows. All images in an image list are contained in a single, wide bitmap in screen device format. An image list may also include a monochrome bitmap that contains masks used to draw images transparently (icon style). The Windows API provides image list functions, which enable you to draw images, create and destroy image lists, add and remove images, replace images, and merge images. - - - - - The developer calls this method once for each item in the toolbar. The items appear in the toolbar from left to right in the order that they were added using this method. (Note that this method adds tools to the custom toolbar and not the 3ds Max toolbar). - Parameters: - & entry - - Describes the item to add to the toolbar. - - int pos=-1 - - Controls where the added tool is inserted. The default of -1 indicates the control will be added at the right end of the toolbar. - - - - - Currently this method is identical to the AddTool() method. - Parameters: - & entry - - Describes the item to add to the toolbar. - - int pos=-1 - - Controls where the added tool is inserted. The default of -1 indicates the control will be added at the right end of the toolbar. - - - - - This method is used to delete tools from the toolbar. - Parameters: - int start - - Specifies which tool is the first to be deleted. - - int num=-1 - - Specifies the number of tools to delete. If this parameter is -1 (the default) it deletes 'start' through count-1 tools. - - - - - Passing TRUE to this method draws a border beneath the toolbar. You can see the appearance of the bottom border in the sample toolbar shown above. If this is set to FALSE, the border is not drawn. - Parameters: - BOOL on - - TRUE to draw the border; FALSE for no border. - - - - - Passing TRUE to this method draws a border above the toolbar. You can see the appearance of the top border in the sample toolbar shown above. If this is set to FALSE, the border is not drawn - Parameters: - BOOL on - - TRUE to draw the border; FALSE for no border. - - - - - Returns the width needed for specified number of rows. - Parameters: - int rows - - The number of rows. - - - - - Sets the number of rows that the toolbar may hold. - Parameters: - int rows - - The number of rows to set. - - - - - This method is used to return a pointer to one of the toolbar's buttons. Using this pointer you can call methods on the button. If you use this method, you must release the control after you are finished with it. - Parameters: - int id - - Specifies the id of the toolbar button. - A pointer to one of the toolbar's buttons. If the button is not found it returns NULL. See Class . - - - - - This method is used to return a pointer to one of the toolbars status controls. Using this pointer you can call methods on the status control. If you use this method, you must release the control after you are finished with it. - Parameters: - int id - - Specifies the id of the toolbar button. - A pointer to one of the toolbars status controls. See Class . - - - - - Returns the handle to the toolbar item whose ID is passed. - Parameters: - int id - - Specifies the id of the toolbar button. - - - - - Returns the number of items in the toolbar. - - - - - Each item in the toolbar has an ID. When items are programatically added to the toolbar via Class an ID is passed to the constructor. This method returns the ID for the specified item in the toolbar. - Parameters: - int index - - Specifies which toolbar item to return the id of. This is an index between 0 and GetNumItems()-1. - When the button is added using Class this is the id that is part of that structure. When the user operates a tool the dialog proc get a WM_COMMAND message and this is also the id in LOWORD(wParam). - - - - - Returns the index into the list of toolbar entries of the item whose id is passed. - Parameters: - int id - - The id of the control to find. - - - - - Deletes the toolbar item whose id is passed. - Parameters: - int id - - The id of the control to delete. - - - - - Computes the required size of a floating CUI Frame which is linked to a toolbar. The values returned will be zero if the frame is not linked to a toolbar. - Parameters: - SIZE *sz - - The computed size is returned here. sz.cx is the width, sz.cy is the height. - - int rows=1 - - The number of rows for the toolbar used in the computation. - - - - - This method is used to return a pointer to the custom status edit control whose id is passedIf you use this method, you must release the control after you are finished with it. See Class . - Parameters: - int id - - Specifies the id of the toolbar button. - - - - - This resets the icons in the toolbar. This tells all the buttons in this toolbar to delete their icon image cache. If a plug-in has created a toolbar with any MaxBmpFileIcons on it, it should register a callback for color changing, and call this method on the toolbar. See for registering the color change callback. - - - - - This method resizes all of the toolbar's buttons to follow the width and height specified. - - The new width of the toolbar's buttons. - The new height of the toolbar's buttons. - The new width of the button icons. - The new height of the button icons. - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Get a pointer to a '' table array of pointers to enabled Direct3D Lights from GFX. - - - - - Get Texture Tiling for specified texStage and texCoord from GFX. - - - - - Get the current viewport dimensions. - - - Get the current viewport dimensions. This is useful for doing multi pass rendering and the off screen buffer needs to be created the same size as the viewport currently being drawn. - - - The width of the current viewport. - - The height of the current viewport. - - - - Get MSAA status from GFX. - - - TRUE if viewport MSAA is enabled. Otherwise, return FALSE. - - - - - Description: - This class is only available in release 10 or later. - - This interface provides access to the D3D HWMeshCache Manager. This allows nodes or any other "thing" that needs to display to register a HW with the manager these hardware meshes are sorted and displayed by material to maximize performance and minimize state switch. - - - - - This method resets the list. It removes all the D3D meshes from the manager. - - - This method removes all the D3D meshes from the manager. This should be called whenever the manager needs to flushed, for instance file resets, load etc. - - - this will also remove any material list that are present. Typically you do not want to do this so on the next add the data struct will not need to be rebuilt. - - - - This method lets users add a D3D mesh to the manager to be drawn. - - - This method lets you add a D3D mesh to the manager to be drawn. It will be drawn batched based on the material supplied in the current display mode. - - TRUE if the node was successfully added, otherwise FALSE. - - - The inode that owns this d3d mesh, it can be null - - The handle of the DirectX mesh which is a pointer to a D3DXMesh - - The material for this mesh, can be null - - The HardwareMaterial for this mesh, required. - - The color of the wireframe mesh since it can be different than the shaded diffuse color - - The world space transform for the mesh, if null the gw transform will be used - - The attribute of this particular mesh typically it is the material ID - - The display limit for this particular mesh. See . - - - - This allows you to set a render limit for the HW cache manager. - - - This allows you to set a render limit for the HW cache so when you add a mesh to the manager you can filter it by the display limit. This is useful for when the display is swapping draw modes and you only want to batch a certain mode. - - this is this the limit filter so only objects matching this limit will be added If this is set 0 there will be no filtering - - - - This allows you to get a render limit for the HW cache manger. - - - This allows you to get a render limit for the HW cache so when you add a mesh to the manager you can filter it by the display limit. This is useful for when the display is swapping draw modes and you only want to batch a certain mode. - - - - - This method lets user add a HWMaterial. - - - This method lets add a user add a HWMaterial. This is useful if you are preprocessing materials so you can add them as you process them - - this is the HardwareMaterial for this mesh and must be supplied - this is color of the wireframe mesh since it can be different than the shaded diffuse color - - - - This method lets the user remove add a D3D mesh from the manager. - - - This method lets the user remove add a D3D mesh from the manager - - this is the handle of the directx mesh to be removed - - - - This method draws the D3D HW Meshes. - - - This method draws the D3D HW Meshes - - which is the graphics window to draw to - - - - Description: - A data channel is a homogeneous collection of objects of a user defined type (data objects). Data channels are uniquely identified by a . Data channels can be associated with any element type of a 3ds Max object: faces or vertexes of Meshes, etc. You can use the macro GetDataChannelInterface(obj) to obtain a pointer to this interface. - - - - - - This method returns the unique class ID of the channel. - - - - - This method returns the number of data objects in this channel. - Default Implementation: - { return 0; } - - - - - Whether or not it's controlled by the daylight system. - - - - - Pointer to the daylight system. - If true the light object is controlled by the daylight system and and should query the interface, in order to get any necessary illuminance, irradiance, temperature, etc. values. - - - - to set simulation parameters that may be used by the controlled light. - - - - of parameters that may be used by the controlled light to determine how it illuminates. Note that if any of the parameters have a value of IDCLS_ILLEGAL_VALUE then that parameter shouldn't be used in any calculations. - - - - Use this interface to access the sun and sky components of a daylight system created by . This interface can be obtained when the daylight system is created. See IDaylightSystemFactory::Create In the case of an already existent daylight system, this interface can be obtained from the base object of the daylight assembly: - - - - - - - Returns the sun component of the daylight system. It can be directional light, IES sun or MR sun depending on the market defaults. - - - pointer on the sun. - - - - - Returns the sky component of the daylight system. It can be standard sky, IES sky or MR sky depending on the market defaults. - - - pointer on the sky. - - - - - Returns the position of the compass of the daylight system. - - - position of the compass of the daylight system. - - - - - Returns the orbital scale of the system. - - - orbital scale value. Note that the orbital scale does not have an effect on the sun's precision or how it's rendered. - - - - - Returns the value of the north direction. - - - the value of the north direction. The angle is in degree. The value is expected to be >=0. - - - - - Returns the compass diameter of this daylight system. Note that the compass diameter does not have an effect on the sun's precision or how it's rendered. - - - compass diameter. - - - - - Returns the current time associated with this daylight system. - - - current time of the daylight system. The format is : (hour,minute,second). - - - - - Returns the current date associated to this daylight system. - - - the current date associated to this daylight system. The format is (month,day,year). - - - - - the latitude and longitude of this daylight system, note that the time zone, city, azimuth and altitude are automatically calculated. - - - - latitude of the location (used to determine city) - longitude of the location (used to determine city) - - - - Returns latitude value of this daylight system. - - - Latitude value of this daylight system. - - - - - Longitude value of this daylight system. - - - Longitude value of this daylight system. - - - - - Returns the daylight saving time parameter. - - - isDaylightSavingTime When on, calculates daylight savings by adjusting azimuth and altitude during the summer months. - - - - - Extends with new functionality This interface can be obtained when the daylight system is created. See IDaylightSystemFactory2::Create In the case of an already existent daylight system, this interface can be obtained from the base object of the daylight assembly: - - - - - - - Computes the approximate time zone from a longitude. - - - The approximate time zone corresponding to a given longitude The time zone will be in the [-12, 12] range. - - The longitude from which the time zone is computed. The longitude is expected to be in the [-180.0, 180.0] range. It it isn't, it's converted to this range. - - - - Sets the sun object of the daylight system. - - - A pointer to the new sun object or NULL if the operation failed - - Class ID of new sun. The supper class id of the sun is assumed to be LIGHT_CLASS_ID. - - - - Sets the sun object of the daylight system. - - - A pointer to the new sky object or NULL if the operation failed - - Class ID of new sky. The supper class id of the sky is assumed to be LIGHT_CLASS_ID. - - - - Returns how the location of the sun in the daylight system is being controlled. - - - Returns how the location of the sun in the daylight system is being controlled. If the return value is eDataAndTime, the daylight system is controlled by a specified date and time. If the return value is eManual, then the postion of the sun is controlled manually, if the value is eWeather File then the postion of the sun is driven by a weather file. - - - - - Returns the name of the location of the daylight system. Usually this is the city name. - - - Returns the name of the location, usually a city name. If no location is specified in the Daylight System an empty string will be returned. - - - - - Get the alititude and the azimuth angles of the sun at that particular time. - - - - The time at which to get the alitude and azimuth of the sun. - The angle of the sun above the horizon. In radians, ranges from 0 at the horizon to PI/2 at the zenith. - The angle of the sun about north. In radians, ranges from 0 at due north, PI/2 at due east, etc.. - - - - Get the name of the weather file that is in use in the daylight system. - - - Returns an AssetUser pointing on the weather file. Note that a valid name may be returned even if the weather file isn't being used to drive the sun position. - - - - - Opens the weather file dialog. Opens the Weather File Dialog. Note that if the daylight system isn't being controlled by the weather file,. - - - - - - - Get temperature values. Get temperature values usually from a weather file based upon the current time. - - - Will return false if the daylight system isn't being controlled by a weather file of the weather file can't be opened correctly or if the weather file doesn't contain these values accurately otherwise if it gets the values correctly it will return true. In the future these values may be stored elsehwhere besides weather files. - - The dry bulb temperature usually stored in the weather file at the current time. - The dew point temperatureusually stored in the weather file at the current time. - - - - Get extraterrestrial radiation values. Get extraterrestrial radiation values usually from a weather file based upon the current time. - - - Will return false if the daylight system isn't being controlled by a weather file of the weather file can't be opened correctly or if the weather file doesn't contain these values accurately otherwise if it gets the values correctly it will return true. In the future these values may be stored elsehwhere besides weather files. - - The extraterrestrial horizontal radiation usually stored in the weather file at the current time. - The extraterrestrial direct normal radiation usually stored in the weather file at the current time. - - - - Get the radiation values. Get radiation values usually from a weather file based upon the current time. - - - Will return false if the daylight system isn't being controlled by a weather file of the weather file can't be opened correctly or if the weather file doesn't contain these values accurately otherwise if it gets the values correctly it will return true. In the future these values may be stored elsehwhere besides weather files. - - The global horizontal radiation usually stored in the weather file at the current time. - The direct normal radiation usually stored in the weather file at the current time. - The diffuse horizontal radiation usually stored in the weather file at the current time. - - - - Get the illuminance values. Get illuminance values usually from a weather file based upon the current time. - - - Will return false if the daylight system isn't being controlled by a weather file of the weather file can't be opened correctly or if the weather file doesn't contain these values accurately otherwise if it gets the values correctly it will return true. In the future these values may be stored elsehwhere besides weather files. - - The global horizontal illuminance usually stored in the weather file at the current time. - The direct normal illuminance usually stored in the weather file at the current time. - The diffuse horizontal illuminance usually stored in the weather file at the current time. - The zenith illuminance usually stored in the weather file at the current time. - - - - Extends with new functionality This interface can only be obtained from an already existent daylight system, from the base object of the daylight assembly: - - - - - - - Get the alititude and the azimuth angles of the sun at that particular time. - - - - The time at which to get the alitude and azimuth of the sun. - The angle of the sun above the horizon. In radians, ranges from 0 at the horizon to PI/2 at the zenith. - The angle of the sun about north. In radians, ranges from 0 at due north, PI/2 at due east, etc.. - - - - Factory for daylight system objects. The type of Sun and Sky components are specified by the current Market Default. Use this interface to create instances of the daylight system. Client code can get to this interface as follows: - - - This interface is implemented by 3ds Max. - - - - - Creates a daylight system and adds it to the scene, at a default position of (0,0,0) - - - The type of the sun and the sky components that are created depends on the current Market Defaults settings. See the 3ds Max User Guide for more details. - A pointer to the Daylight assembly node of the daylight system. - - returns the component of the daylight system which can be used to access the sun and sky. See . - - - - Factory for daylight system objects. Allows for specifying the type of Sun and Sky components. Use this interface to create instances of the daylight system. Client code can get to this interface as follows: - - - This interface is implemented by 3ds Max. - - - - - Creates a daylight system with sun and sky components of specified type and adds it to the scene at a default position of (0,0,0) - - - A pointer to the Daylight assembly node of the daylight system. NULL if the daylight system could not be created, for example because either the Sun or the Sky type specified was invalid. - - returns the component of the daylight system which can be used to access the sun and sky. See . - Class ID of Sun plugin component to be used when creating the daylight system. The supper class id of the Sun is assumed to be LIGHT_CLASS_ID. If left NULL, the Sun type specified by the Market Defaults will be used. - Class ID of Sky plugin component to be used when creating the daylight system. The supper class id of the Sky is assumed to be LIGHT_CLASS_ID. If left NULL, the Sun type specified by the Market Defaults will be used. - - - - An interface class to the delegate. - - - The class provides functions to directly query specific delegate information. It is mainly intended to be used by a crowd behavior plugin. This class can be returned by calling the method GetInterface() from a Delegate node. For Example: - - - - - Queries whether the delegate is constrained in the Z plane. - - - true if the delegate is constrained to the z plane, false if not - - - - - Gets the average speed of the delegate. - - - the average speed of the delegate - - - the time to retrieve the value - - - - Gets the maximum acceleration of the delegate. - - - the maximum acceleration of the delegate - - - the time to retrieve the value - - - - Gets the maximum heading velocity of the delegate. - - - the maximum heading velocity of the delegate, in degrees. - This is shown as the Max Turn Velocity in the delegate's interface. - - - the time to retrieve the value - - - - Gets the maximum heading acceleration of the delegate. - - - the maximum heading acceleration of the delegate, in degrees. - This is shown as the Max Turn Accel in the delegate's interface. - - - the time to retrieve the value - - - - Gets the maximum pitch velocity of the delegate. - - - the maximum pitch velocity of the delegate, in degrees. This is shown as the Max Turn Velocity in the delegate's interface. - - - the time to retrieve the value - - - - Gets the maximum pitch acceleration of the delegate. - - - the maximum pitch acceleration of the delegate, in degrees. - This is shown as the Max Turn Accel in the delegate's interface. - - - the time to retrieve the value - - - - Gets the maximum incline angle of the delegate. - - - the maximum incline angle of the delegate, in degrees - - - the time to retrieve the value - - - - Gets the maximum decline angle of the delegate. - - - the maximum decline angle of the delegate, in degrees - - - the time to retrieve the value - - - - Queries if the the delegate should display the forces acting upon it during a simulation. - - - If this returns true, and the behavior has a force to display, then the behavior plugin is expected to display its force during the Perform function, by calling the 's LineDisplay function. - true if the delegate's Show Forces checkbox is checked, false if not. - - - - - Queries if the delegate should display its velocity during a simulation. - - - true if the delegate's Show Velocity checkbox is checked, false if not. - This is probably not needed by any behavior plugins, since velocity display is performed by the crowd system. - - - - - Queries if the delegate should display its cognitive controller state during a simulation. - - - true if the delegate's Show Cog States checkbox is checked, false if not. - This is probably not needed by any behavior plugins, since cog control states are displayed by the crowd system. - - - - - This function should be used instead of calling GetNodeTM during a simulation loop. - - - This function must be called to get the transform, because internally as an optimization, the Crowd system caches the delegate's positions and doesn't set the Node's MAX transform until after the simulation is done running. - If for some reason (based on the active flag, backtracking, etc) this function determines that the delegate's values are not cached, it will then call GetNodeTM. So it is always best to use this function to get the delegate's TM, particularly during the Perform, Constrain, or Orient function of a behavior, which are only called during a Crowd simulation. - the transformation matrix of the delegate in world space at the current frame in the simulation. - - - The delegate's node. - - the time to retrieve the value. - - - - Gets the position of the delegate. - - - the position of the delegate in world space at the current frame in the simulation - - - - - Gets the velocity of the delegate. - - - the velocity of the delegate at the current frame in the simulation. - It may or may not be normalized. If not, it's length is equal to it's current speed. - - - - - Gets the previous velocity of the delegate. - - - the velocity of the delegate at the previous frame in the simulation. - - - - - Gets the speed of the delegate. - - - the speed of the delegate at the current frame in the simulation - - - - - Gets the delegate's velocity at the start of a simulation. - - - If the node is a delegate and the start time is the simulation start time, this will return the initial velocity of the delegate, exactly as the Crowd system computes it. - - This function is particularly useful to call from within a behavior's InitBeforeSim function, in order to make sure the behavior is perfectly repeatable. - the velocity of the node at a given start time - - - the node that the velocity is to be calculated for - - the time to retrieve the value - - - - Draws a line segment while the simulation is running. - - - - - the start position of the line segment in world space - - the end position of the line segment in world space - - the color of the line - - whether or not the line should be scaled by the Vector Scale value specified in the Crowd Solve rollout. - - - - Draws a bounding box while the simulation is running. - - - - - the minimum point of the bounding box in world space - - the maximum point of the bounding box in world space - - the color of the bounding box - - - - Draws a sphere while the simulation is running. - - - - - the center point of the sphere in world space. - - the radius of the sphere. - - the color of the sphere. - - - - Draws text while the simulation is running. - - - - - the world position of where the text will start - - the color of the text - - the string of text that will be printed - - - - Queries whether the delegate is currently active in a running crowd simulation. - - - true if the delegate is currently active in a running crowd simulation, false if not - - - - - Queries whether a particular assignment is active at a particular time. - - - This is a way to ask the Crowd system whether or not a particular assignment is active at a particular frame. It is not really related to this particular delegate, but since internally the delegate has access to the crowd, it is used to get this information. Typically, this is called from within BaseBehavior::InitBeforeSim to see whether or not an assignment was active at a particular point in time during the simulation. ! - true if the assignment is active at this time, false if not. - - - an index into the list of behavior assignments in the Behavior Assignments dialog ! - - the time to retrieve the value ! - - - - Get the delegate's identifier. - - - an integer > 0, that is an unique identifier for a delegate while a crowd simulation is running. - - - - - Gets a random id to generate varying behavior for different delegates performing the same behavior. - - - an integer value > 0 that specifies a number that can be used as part of a seed when calculating random numbers from within a behavior. For instance, this number is used by the pathfollow, speedvary, surfacearrive, and wander behaviors. For behaviors which use the RandId, two or more delegates that have the same RandId will exhibit the same random behavior. Unless the RandId has been specifically changed by the user, it will be unique for all delegates. The Crowd system assures this. - - - - - Queries the whether the delegate is associated with a computing biped. - - - true if this delegate is associated with a biped whose crowd motion is currently being computed, false if not - - - - - This function is used internally. - - - - - This function is used internally. - - - - - This function is used internally. - - - - - This function is used internally. - - - - - Description: - This class provides an interface into derived objects. Methods of this class are provided so developers can access the modifier stack, add and delete modifiers, etc. All methods of this class are implemented by the system. - - To use this interface you must #include the following file: - - #include "modstack.h" - - To get an pointer from the pipeline of a node in the scene first retrieve the object reference using INode::GetOjbectRef(). Given this pointer check its SuperClassID to see if it is GEN_DERIVOB_CLASS_ID. If it is, you can cast it to an . - - Note: The following functions are not part of class but are available for use in conjunction with its methods. - - - - - Adds a modifier to this derived object. - Parameters: - *mod - - The modifier to add. - - *mc=NULL - - The mod context for the modifier. - - int before=0 - - If this value is set to 0 then the modifier will be placed at the end of the pipeline (top of stack). If this value is set to NumModifiers() then the modifier will be placed at the start of the pipeline (bottom of stack). - - - - - Deletes the specified modifier from the stack. - Parameters: - int index=0 - - The index of the modifier to delete. - - - - - Returns the number of modifiers this derived object has. - - - - - Gets the object that this derived object references. This is the next object down in the stack and may be the base object. - The object that this derived object references. - - - - - Sets the object that this derived object references. This is the next object down in the stack and may be the base object. - Parameters: - *pob - - The object that this derived object should reference. - One of the following values: - - REF_SUCCEED - - REF_FAIL - - - - - Returns the modifier specified by the index. - Parameters: - int index - - The index of the modifier to return. - - - - - This method replaces the modifier in the stack whose index is passed. - Parameters: - int index - - The index of the modifier in the stack. - - *mod - - The modifier that will replace it. - - - - - Returns the of the specified modifier. - Parameters: - int index - - The index of the modifier in the stack. - - - - - This method is available in release 4.0 and later only. - - This method allows you to evaluate the pipeline starting with a specific modifier index. Prior to version 4.0 you had to turn all the modApps off, evaluate and then turn them on again. Now this can be easily done by specifying the modifier index. - Parameters: - TimeValue t - - Specifies the time to evaluate the object. - - int modIndex = 0 - - The index of the modifier. - The result of evaluating the object as an . - - - - - to Dialog Monitor System. - - - This interface gives access to the Dialog Monitor System. - - - - - Get Dialog Monitor state. - - - This checks if the Dialog Monitor is enabled. - true if the Dialog Monitor is enabled, false if not. - - - - - Dialog Monitor state. - - - - true to enable, false to disable. - - - - Get the Interactive Mode state. - - - If true, then a dialog pops up asking if you want to close a dialog or not. This helps when debugging a script or attempting to do anything interactively. - true if Interactive Mode is enabled, false if not. - - - - - Interactive Mode state. - - - - true to enable, false to disable - - - - Register for Dialog Monitor Notification Messages. - - - true if success, false if failure - - pointer to interface - - - - Unregister for Dialog Monitor Notification Messages. - - - true if success, false if failure - - pointer to interface - - - - Dialog Monitor Notification Callback . - - - This interface is implemented by any object that wants to receive Dialog Monitor notification messages. - - - - - Dialog Monitor Notification Callback method. - - - Returned value 'true' will prevent the notification message from continuing - true if window processed (closed) by client, false otherwise - - the window handle sent by Dialog Monitor System - - - - Manager class for Drag and Drop The Drag and Drop system is managed through a Core FP interface (DND_MGR_INTERFACE), defined by this class. It provides control over the drag and drop system, manages handler registration and exposes some useful utility methods for downloading URL's, simulating drops, etc. - - . - - - The DragAndDropMgr supports multiple 's registered against a single HWND window. This allows new components and 3rd-party developers to incrementally add handlers for new dropTypes to common windows such as viewports, that the default handlers don't know how to handle. - - The IDragAndDropMgr::EnableDandD(HWND hwnd, BOOL flag, DragAndDropHandler* handler) method can be called multiple times on the same window with different handler instances. The drag and drop manager keeps track of all the DragAndDropHandlers on each window and will call their drag and drop event methods as needed, in order of registration, until one of them returns S_OK. For example, on a viewport, the DefaultDragAndDropHandler is registered by default. The event methods (such as DragEnter, DragOver, Drop, etc.) return E_FAIL if the dropping IDataObject or is not recognized by them. Then, if a new component registers its own handler to deal with some new droptype, the default handler will fail to recognize the new droptype and so the new handler will be called to process the new drop type. - - Note that this means event methods must correctly return S_OK or E_FAIL depending on whether they handle the IDataObject or currently dropping, so that the appropriate handler is found and called by the DnDMgr. - - - In Max 2011, the management of memory lifetime was changed. In previous versions, it was up to 3rd party developers to 'unregister' (Passing in FALSE to IDragAndDropMgr::EnableDandD) their drag and drop handlers (DragAndDropHandler*), before max was shutdown. If they didn't max would crash on shutdown. Now, unitialization has been moved up before 3rd party plugins are unloaded. Now, the manager automatically 'unregisters' all pointers during a broadcast of NOTIFY_SYSTEM_SHUTDOWN. This means that the manager calls DragAndDropHandler::Release on all pointers registered with it. After the manager cleans up during the NOTIFY_SYSTEM_SHUTDOWN broadcast, any subsequent calls to register a drag and drop handler will return FALSE. Also any subsequent calls to 'unregister' a handler will just silently do nothing. - - - - - Globally enables or disables the drag and drop interface. - - - - - TRUE to enable, FALSE to disable. - - - - returns TRUE if the global drag and drop interface is enabled, otherwise FALSE. - - - - - Enables drag and drop for a given window (and its children). - - - If no custom is supplied, a default one is used that will accept dropped scene files for opening and scripts for running. When the application is shutting down, it is prohibited to enable or disable a handler. Therefore after a NOTIFY_SYSTEM_SHUTDOWN broadcast this method will always return FALSE. - TRUE if the method was successful, otherwise FALSE. - - - A handle to the window you wish to enable or disable drag and drop for. - - TRUE to enable, FALSE to disable. - - A pointer to a custom drag and drop handler, or NULL to accept a default one. - - - - This method allows the simulation of a package of files into a window at a given point. A package of files, specified as a list of URL strings is the common form of data from iDrop sources and files dragged from the Windows desktop. The entire package is downloaded, as needed, but only the first file in the list is actually dropped into 3ds Max. The other files in the package are presumed to be support files, such as texmaps or xref sources, for the main drop file. - - After the drop, the URL strings in the are converted to fully-specified path names to local file copies, if any had to be downloaded from the web. - - - TRUE if the drop was successful, otherwise FALSE. - - - A handle to the window. If this is set to NULL, the default 3ds window is used. - - The point at which to drop. - - A reference to the local copies of the URL strings. - - - - Used to download a package of URLs to the specified directory. If the hwnd argument is supplied, any progress or other messages are centered over that window. - TRUE if the download was successful, otherwise FALSE. - - - A reference to the local copies of the URL strings. - - The directory path string to download to. - - A handle to the window. If this is set to NULL, the default window is used. - - The download progress dialog can be displayed by passing true. - - - - Returns the fully-specified path to the directory in which package drops are downloaded. - - - - - Gets the number of handlers associated with the given window. - - - - - A handle to the window. - - - - Returns a pointer to a specified drag and drop hander of a specified window. - - - - - A handle to the window. - - The I-th handler. - - - - Downloads the file referenced by the URL to disk. - - - TRUE if the download was successful, otherwise FALSE. - - - A handle to the window. - - The URL string of the file to download. - - The filename string of the URL to store on disk. - - Additional controls to the download behavior. Currently only one flag is supported, DOWNLOADDLG_NOPLACE, which hides an option in the progress dialog that allows the user to place (move) a dropped object immediately after being dropped. - - - - Returns a pointer to the import context node. - - - - - Description: - This class represents the iDrop XML package. - - - - - An interface class to manage access to various parameters used by DirectX effects. - - - Description: - The file has many internal presentations and as such the DxMaterial does not always store a one to one look up. Many parameters are stored in a ParamBlock and can be accessed that way. - The paramblock index for the is located at 0 (the material maintains 5 ParamBlocks) and hosts all the parameters with the param name being that of the parameter in the effect File. - - However not all entries in the paramblock match the parameter type of the effect file directly. One such example is the light data, which in the paramblock will use a TYPE_INTLISTBOX, where in the file it is a vector. - - To overcome this, the interface provides direct access to the lights and textures used by the effect. It is possible to both get and set the bitmaps, but only read access is available for the lights. - - - - - Reloads the current active effect. - - - - - Returns the number of bitmaps used by the currently loaded effect. - - - The number of bitmaps returned will be equal to the number of bitmap entries found in the effect file. This will include bitmap slots that haven't been assigned, so it is important to check the return value from the various related functions that take an index. - The number of bitmaps - - - - - Gets the bitmap used by the effect. - - - A pointer for the bitmap used - - The index of the bitmap to retrieve - - - - the bitmap used by the effect. - - - - The index of the bitmap to set - A pointer for the bitmap to set - - - - Get the Dx file AssetUser. - - - This can also be accessed via the paramblock, but it is simply provided for completeness - The effect file in use - - - - - Get the bitmap used for the software rendering overrride. - - - This can also be set by the Paramblock, it is just used for completeness return The used - - - - - Get the number of light based parameters. - - - This will return the number of parameters that are light based, even . Care needs to be taken with as it could also have a Swatch associated with it, so could already have been exported as part of the ParamBlock. - - The number of light based parameters - - - - - The actual node used by the parameter. - - - This represent the light node used by the parameter. Care needs to taken as this could be a NULL pointer. There are two reason for this. The first is that the LightColor Semantic is stored internally as a LightElement, but the writer of the file may not have specified a parentID for the light, this will result in a NULL. Secondly if the user has not actually assigned a light via the UI drop down list, then again this will again result in a NULL pointer. - The for the active light. - - The index of the light to return. - - - - The name of the parameter in the file. - - - - - The light semantic as defined in the effect file. - - - - - Description - This includes a new interface to help extract mapping and texture usage. With the new UI and general updates to the DirectX 9 , the developer can access the mapping data directly from the paramblock hosting the effect parameters - - - - - Get the Mapping channel defined for the texture. - - - The mapping channel as specified in the file. If no mapping is defined then this will be mapping channel 0 - The mapping channel for the texture - - The index of the bitmap to access - - - - Get the usage of the bitmap. - - - This is typically the usuage as seen from 3dsmax. The usage is based on the Semantic used in the effect file This would be used in conjunction with GetNumberOfEffectBitmaps - The usage of the bitmap - - The index of the bitmap to query - - - - the mapping channel for the bitmap. - - - This would be used in conjunction with GetNumberOfEffectBitmaps - - The index of the bitmap - The mapping channel value - - - - Access to the current active parser for the loaded effect file. - - - The current parser - - - - - Get the active light node based on the D3DXHANDLE. - - - The light node - - The handle based on the effect file - - - - Get the active Parameter Manager. - - - The current parameter manager owned by the material - - - - - Get total number of Techniques. - - - Returns the total number of validated techniques used by the DirectX material - The number of techniques - - - - - Get the technique name. - - - - - Get the active technique name. - - - - - Get the active light manager. - - - Provides access to the light manager maintained by the material. This provides access to various light data like position, color and attenuation - The current active light manager - - - - - A system to manage the current state of the Dx Scene and render passes. - - - This will provide support for RTT scene based effects, as well as handling matrix conversions. - - - - - Add a scene effect to the database - - A pointer to a DirectX Shader Material - Describes what type of effect is being stored - How many passes are required. This is only really useful for environment effects - - - - Add a scene effect to the database - - A table of effects. This would be used to copy a complete block over. This is useful when setting multi effects, or the ordering has changed. - - - - of Scene effects active - The number of scene effects - - The type of effect to query - - - - Get the scene effect - The material at the index - - The index of the material to access - The type of effect to query - - - - flush out the effects, and reset all Render Targets - - - - - Remove specified Effect. - - - - The index of the effect to remove - The type of effect - - - - Called at the beginning of the Scene Traversal - All effects PreRenders are called here. - - The current viewport being rendered - - - - Called at the end of traversal. The main effects Render method is called here. - - The current viewport being rendered - - - - Special Debugging mode - textures will be saved for each pass/combiner - USE WITH CAUTION !! - - - The various passes will be saved as DDS file to the specified location - they will be titled XXX_Pre_pass and XXX_post_pass - the final rendered pass is not saved, as this is available in the viewport. The XX is the name prefix supplied - - Turn debug on/off - A pointer to a string containing the path, ending with "\" - A pointer to a string containing a name prefix - - - - Turn on the traversal system. When activated the developer can control what is rendered to the viewport - - a boolean used to turn the traversal on/off - A callback used to validate and sort nodes - - - - access to the Transform manager - - - This provides scene level access to the various DX transforms. When rendering scene based effects these transforms should be used It is safe when drawing object level effect to still use this, but only for PROJECTION and VIEW. World should be obtained from the regular methods. - A pointer to - - - - - A one time per scene initialisation that must be called first before the scene is rendered - - The viewport being rendered - - - - The number of passes required to render the scene based on the effects loaded - the total number of passes - - - - - The value of the current pass - The current pass number - - - - - Provides access to the type of pass being rendered. This allows developers to pre process or switch techniques based on whether environmental effects are being calculated or actual scene drawing is taking place - The active pass - - - - - Specifies whether the current scene effects are valid or not. - - - The system will check the validity channel of the post effects to determine whether a full scene update is required. This is mainly for effects that require a TIME semantic, which denotes that it constantly runs and updates the scene. - True if the effects are valid and require no scene update - - - - - An interface to allow access to scene transforms. This is important as depending on the pass different transforms may be required. Using this system makes sure the correct transform is used. - - - - - the current Matrix. - - - the Projection and Matrix for the parameter supplied. This currently only supports lights - - A pointer to a string containing the name as defined in the effect file. - - - - Description: - This is a new type of custom control used to provide drag and drop to and from things other than Custom Buttons. An example of an item that uses this control is a sample sphere window in the Editor. - - To initialize the pointer to the control call: - - - - - Returns a pointer to the drag and drop manager for this control. - - - - - This method establishes a window proc that is called to handle all the normal processing after the drag and drop processing is done. - Parameters: - WindowProc *proc - - The window proc. Note the following typedef: - - typedef LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); - - #define SLIDERWINDOWCLASS _M("SliderControl") - - // LOWORD(wParam) = ctrlID, - - // HIWORD(wParam) = TRUE if user is dragging the slider interactively. - - // lParam = pointer to - - #define CC_SLIDER_CHANGE WM_USER + 611 - - // LOWORD(wParam) = ctrlID, - - // lParam = pointer to - - #define CC_SLIDER_BUTTONDOWN WM_USER + 612 - - // LOWORD(wParam) = ctrlID, - - // HIWORD(wParam) = FALSE if user cancelled - TRUE otherwise - - // lParam = pointer to - - #define CC_SLIDER_BUTTONUP WM_USER + 613 - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Versioning. - - - The system uses this to determine whether the effect is compatible to the current GFX loaded on MAX - 8.1 or 9.0 etc... - - - - - Viewport DXEffect interface. - - - A Direct X 8.1 shader should implement this class. It is used by the system to get information from the shader If a material implements this class, then all it needs to do is pass back a pointer in the GetInterface implementation. - - All the other methods can simply be a no op. class : public - - - Description: - This class is only available in release 5 or later. - - This is the interfaced used by the Viewport plugins. For the manager to load up a Viewport it must implement this class. - - As well as implementing the dialog loading it also provides a link to the GFX. This means the developer is free use IDX8VertexShader and IDX8PixelShader interfaces, for more advanced shaders. Examples of these shaders are - - /MAXSDK/SAMPLES/HardwareShaders/Cubemap/Cubemap.cpp and - - /MAXSDK/SAMPLES/HardwareShaders/Membrane/Membrane.cpp - - . This must return "DXViewportEffect" otherwise it will not be listed in the database. The reason for this is that the Manager supports deferred loading, and this is one way of checking the plugin without requiring a full DLL load. - - For an example of this class in use by ViewportShader plug-ins see /MAXSDK/SAMPLES/HardwareShaders/LightMap/Lightmap.cpp - - If the Viewport plugin hosts any animated parameters that will be viewed in the Trackview then it is important the plugin implements the following Reference Message - - This will make sure that the Parameters show up under the Viewport Manager in the correct format. - - All methods of this class are virtual. - - - - - - - The Viewport Manager will call this to display the dialog (if needed) - A new pointer which the Viewport Manager will uses as a child of its window added as a child of the Viewport Manager. - Parameters: - HWND hWnd - - The window handle to the parent window - - * imp - - This can be used in the call to CreateParamsDlg. - - - - The parent window handle - A pointer to IMtlParam - see the main max SDK for info on this class - - - - This is no longer used. - - - Currently this method is not used - - - - - - - Get the UI name of the effect - this is only used for Viewport MAnager effects - not materials - A string containing the name This may be extended for future use, but currently it is only used in the trackview. - - - - - For effects that will be using the fixed function pipeline. This provided access to the IHArdwareMaterial allowing access to DirectX FFP. - Parameters: - * pHWMtl - - Provides access to various drawing techniques - - * pMtl - - A pointer to the parent material. - - A pointer to the internal hardware material. - A pointer to the parent Class to perform custom drawing of an object. This could be special texture setups and control over the Render States and Texture Stages. If the developer needs finer control over the object, then the r4 interfaces IDX8VertShader can be used instead, and this function will not do anything. This method will be called whenever the object needs drawing. For a detailed example of this usage, please look at the Lightmap sample in the sdk - - - - An that provides access to the actual manager. The manager is responsible for displaying the Viewport Manager which is implemented as a Cust Attribute on the material - Description: - This class is only available in release 5 or later. - - The class provides access to the Viewport Manager feature in release 5. The viewport manager controls the loading of Viewport Shaders in 3ds Max and is displayed on each material. The class provides methods to query the manager to find out whether it is visible or active, and also to retrieve the active shader. - - The viewport manager ONLY works in DirectX mode. It can however be visible in Heidi and OpenGL, so as to provide the artist feedback when loading someone else's file. - - There is a global method you can call to get access to the DX manager. - - GetDXShaderManager()IDXShaderManagerInterface* - - - - - - - This method will check the passed into find out whether it contains the ViewportManager Custom Attribute. If it does it will return its pointer, otherwise it will be NULL. This pointer can safely be cast to . - - - Parameters: - MtlBase* mtl - - The material to search for the Viewport Manager. - - - - - - - This method will add the ViewportManager custom atrribute to the material supplied. If successful it will return the newly created custom attribute. This pointer can safely be cast to . - - - Parameters: - MtlBase* mtl - - The material to add the Viewport Manager to - - - - - - - This method allows the system to either show or hide the ViewportManager. This will physically remove it from the Editor, whoever the manager will still exist on the material - - - Parameters: - BOOL show - - The value to set the visible state of the manager. - - - - - - - This method will return the actual visible state of the manager - - - - - Description: - This class is an interface used by the scripter and the SDK to access the Edit Normals modifier. See the documentation for that modifier for background on the normals and the basic operations like Break and Unify. - - All but the last two of these methods are available via the scripter with commands like: - - - - - "Get" accessor for selection level - one of these values: - - EN_SL_OBJECT, EN_SL_NORMAL, EN_SL_VERTEX, EN_SL_EDGE, EN_SL_FACE - - - - - - - "Set" accessor for selection level - one of these values: - - EN_SL_OBJECT, EN_SL_NORMAL, EN_SL_VERTEX, EN_SL_EDGE, EN_SL_FACE - - - - - - - Moves the ends of currently selected normals by the offset indicated - then renormalizes them to unit length. - - Note that the time is currently ignored, as the Edit Normals modifier is not yet animatable - - - - - - - Rotates currently selected normals by the rotation indicated. - - Note that the time is currently ignored, as the Edit Normals modifier is not yet animatable - - - - - - - Breaks the indicated normals into separate normals for each face. - - In 3ds Max 6, the Edit normals modifier had an average function added to its tool set. This allows the user to average the normals across the surface of the object(s). The toAverage parameter was added to this method to provide access to this new functionality. - - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - bool toAverage=false - - Default is false. When true, this parameter causes the normals to be averaged across the surface of the object(s). - to its tool set. This allows the user to average the normals across the surface of the objects(s). This method and the next four methods were added to an existing interface to provide access to this new functionality. - Breaks the indicated normals into separate normals for each face. - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - Unifies the indicated normals so there's at most one normal per vertex. (Basically, causes normals to be shared across faces at a vertex.) - - In 3ds Max 6, the Edit normals modifier had an average function added to its tool set. This allows the user to average the normals across the surface of the objects(s). The toAverage parameter was added to this method to provide access to this new functionality. - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - bool toAverage=false - - Default is false. When true, this parameter causes the normals to be averaged across the surface of the object(s). - - - - - Makes the indicated normals completely non-explicit and unspecified. Generates a rebuild & computation to determine the topology and direction of the newly unspecified normals. - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. - - If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Specifies the normals indicated to be fixed to the faces they're currently used by. - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Make the indicated normals explicit, so they won't be based on underlying face normals. - Parameters: - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Copies the indicated normal into the Edit Normals modifier's copy/paste buffer. - Parameters: - int normalID - - The ID of the normal we want to copy. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Pastes the normal currently in the Edit Normals modifier's copy/paste buffer into the normals indicated, making them specified and explicit. - Parameters: - *normalSelection = NULL - - An optional selection set to use. If NULL, the current selection is used. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Added in 3ds Max 6 SDK. - Parameters: - bool useThresh=false - - float threshhold=0.0f - - *normalSelection=NULL - - An optional selection set to use. If NULL, the current selection is used. - - - - - Added in 3ds Max 6 SDK. - Parameters: - bool useThresh=false - - float threshhold=0.0f - - - - - Added in 3ds Max 6 SDK. - Parameters: - *pNode1 - - int normID1 - - *pNode2 - - int normID2 - - - - - - - Returns a pointer to the current selection. - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Sets the normal selection to the selection given. - Parameters: - &selection - - The desired selection - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - True if the selection was changed; false if the new selection was the same as the old selection. - - - - - - - Selects, deselects, or inverts the selection of the normals indicated. - Parameters: - &selection - - The normals whose selection we are trying to change. - - bool invert=false - - If true, indicates that the normals in <selection> should have their selection status inverted - - bool select=true - - If <invert> is true, this is ignored. Otherwise, if true, the normals indicated should be selected; if false, they should be deselected. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - True if the selection changed, false otherwise. - - - - - - - Converts a vertex selection into a selection of normals, by setting bits on normals based at selected faces. - Parameters: - & vertexSelection - - The vertex selection we're converting - - & normalSelection - - The output normal selection - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - Converts an edge selection into a selection of normals, by setting bits for normals used on either end and either side of selected edges. - Parameters: - & edgeSelection - - The edge selection we're converting - - & normalSelection - - The output normal selection - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Converts a face selection into a selection of normals, by setting bits on normals used by selected faces. - Parameters: - & faceSelection - - The face selection we're converting - - & normalSelection - - The output normal selection - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the current number of normals. - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns a pointer to the normal indicated. - Parameters: - int normalID - - The index of the normal - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - TimeValue t=0 - - This is currently unused - but might be important if we add animation capabilities to Edit Normals in the future. - - - - - - - Sets the indicated normal to a specific value. NOTE that this does not set the "explicitness" of this normal. If the normal is not made - - explicit, it will be restored to its default value the next time non-explicit normals are recomputed. - Parameters: - int normalID - - The index of the normal - - & direction - - The desired normal direction. If not already normalized to a length of 1, - - this method will normalize it. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - TimeValue t=0 - - This is currently unused - but might be important if we add animation capabilities to Edit Normals in the future. - - - - - - - Controls whether a given normal is built from smoothing groups or set to an explicit value (Also makes the normal specified for all faces using this normal.) - Parameters: - int normalID - - The index of the normal - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Makes the indicated normal explicit (or not). If setting the normal to explicit, it will also be set to "specified" on all faces using it. If - - setting it to non-explicit, the modifier recomputes all non-explicit normals to bring it up to date. - Parameters: - int normalID - - The index of the normal - - bool value - - True to make this normal explicit, false to make it non-explicit. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the number of faces in the normal specification.. - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the degree of the face indicated. (3 for triangle, 4 for quad, etc.) - Parameters: - int face - - The desired face. *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Gets the index of the normal in the indicated corner of the indicated face - Parameters: - int face - - The desired face. - - int corner - - The desired corner, in the range of 0 to EnfnGetFaceDegree(face)-1. *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Sets the index of the normal in the indicated corner of the indicated - - face - Parameters: - int face - - The desired face. - - int corner - - The desired corner, in the range of 0 to EnfnGetFaceDegree(face)-1. - - int normalID - - The index of the desired normal - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Indicates whether a particular corner of a particular face is specified - - to use a specific normal or not. - Parameters: - int face - - The desired face. - - int corner - - The desired corner, in the range of 0 to EnfnGetFaceDegree(face)-1. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - - - Controls whether a corner of a face uses a specific normal ID, or builds normals based on smoothing groups. If called to set a corner - - to unspecified, it generates a rebuild of nonspecified normals and a recomputation of nonexplicit normals at next update. - Parameters: - int face - - The desired face. - - int corner - - The desired corner, in the range of 0 to EnfnGetFaceDegree(face)-1. - - bool specified - - True to specify, false to set as unspecified. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the number of vertices in the current mesh cache.. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the vertex used in a corner of a face, in the current mesh cache. (Useful for determining the "base" of the normal used in that corner of - - that face.) - - - Parameters: - int face - - The desired face. - - int corner - - The desired corner, in the range of 0 to EnfnGetFaceDegree(face)-1. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the location of the vertex indicated (in the current mesh cache). - - - Parameters: - int vertexID - - The desired vertex. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - TimeValue t=0 - - This is currently unused - but might be important if we add animation capabilities to Edit Normals in the future. - - - - - - - Returns the number of edges in the current mesh cache. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns the index of the edge used on a particular side of a particular face, in the current mesh cache - - - Parameters: - int faceIndex - - The desired face. - - int side - - The desired side, in the range of 0 to EnfnGetFaceDegree(faceIndex)-1. - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Tells you which side of the face a given edge is on. (Can be useful for getting normal and vertex information around the edge.) - - - Parameters: - int faceIndex - - The desired face. - - int edgeIndex - - The desired edge - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - The side of the face, in the range of 0 to EnfnGetFaceDegree(faceIndex)-1, or -1 if the edge was not found on this face - - - - - - - Returns the vertex at the end of the edge. - - - Parameters: - int edgeIndex - - The desired edge. - - int end - - The desired end - either 0 or 1 - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Tells you what face is on a particular side of a particular edge. - - - Parameters: - int edgeIndex - - The index of the edge in the 's edge array. - - int side - - Indicates which side of the edge you want the face from. (Values: 0 or 1.) - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - The index of the desired face, or -1 if there's an error or if there is no face on that side. - - - - - - - Returns the normal associated with a particular end and side of this edge. - - - Parameters: - int edgeIndex - - The index of the edge in the 's edge array. - - int end - - Indicates which end of the edge should be used. (Values: 0 or 1.) - - int side - - Indicates which side of the edge should be used - the edge may have different normals used by the faces on either side. (Values: 0 or 1.) - - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - The index of the desired normal.. - - - - - - - Forces the modifier to rebuild all non-specified normals from the face smoothing groups. Note that this can change the number of normals in some cases, and often changes their order. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Forces the modifier to recompute all non-explicit normals. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - - - - - - Returns a pointer to the cached copy of the held by the EditNormalsModData. This is a "stripped-down" copy of the last mesh that was output by the modifier. It contains no maps, vertex or edge data, or normals. It's mainly used as a temporary "parent" to the localdata's in operations such as Display. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - TimeValue t=0 - - This is currently unused - but might be important if we add animation capabilities to Edit Normals in the future. - - - - - - - Returns a pointer to the used by the EditNormalsModData. This is not part of any particular , rather it's used as the local data of the EditNormalsMod to indicate what normals should be applied to the mesh coming up the pipe. Its "parent" pointer is generally set to NULL, and should be set to a mesh like the one you get from EnfnGetMesh before you do certain operations. (See class for details on which methods require an accurate "parent" pointer. - - - Parameters: - *pNode = NULL - - If the Edit Normals modifier is instanced across several nodes, this parameter can be used to indicate which node you mean to modify normals in. If you want to modify normals in all nodes, you must make a separate call for each node. If NULL, it assumes you want to modify normals in the "first" node. (This is fine if the modifier is only applied to one node, as is usually the case.) - - TimeValue t=0 - - This is currently unused - but might be important if we add animation capabilities to Edit Normals in the future. - - - - - Implemented by a plugin, typically a material, to provide access to the underlying shader code. - - - A developer can use this interface to access the actual shader code used to draw the material when in hardware mode. The interface can be accessed with the following code - - IEffectFile* l_pEffectFile = static_cast<IEffectFile*>(lpMaterial->GetInterface(EFFECT_FILE_INTERFACE)); - All methods are implemented by the host plugin - - - - - Save the current material as a D3D compliant file. - - - This will save the underlying shader code to the file provided. The shader code will be as a UTF8 encoded string without a UTF8 Byte Order Marker (BOM). - TRUE if successful - - The name of the file to save - - - - The Effect Manager is responsible for displaying effect parameters. In 3ds Max this is implemented by the DirectX 9 Material. - - - All parameters except textures are handled by the Effect Manager. This includes setting the data on the render pass. Textures are controlled by the Effect , as the the parser understands the usage, the manager simply provided the resource name from the UI It is the managers responsibility to make sure the data is set for each pass. This may or may not mean providing a UI, but the methods provide enough hints to be able to implement this. - - - - - Display a floating point value in the Dialog box - - The handle to the parameter in the effect file - The name of the actual parameter. This will be used in the paramblock - The name to be displayed in the Dialog box - The default value - The minimum value for the control - The maximum value for the control - The increment value for the control - The semantic of the parameter. - - - - Display an integer value in the Dialog box - - The handle to the parameter in the effect file - The name of the actual parameter. This will be used in the paramblock - The name to be displayed in the Dialog box - The default value - The minimum value for the control - The maximum value for the control - The increment value for the control - The semantic of the parameter. - - - - Display a boolean value in the Dialog box. This will be a standard 3ds Max check box - - The handle to the parameter in the effect file - The name of the actual parameter. This will be used in the paramblock - The name to be displayed in the Dialog box - The default color to display - The semantic of the parameter. - - - - Display a bitmap selection button - - The handle to the parameter in the effect file - The name of the actual parameter. This will be used in the paramblock - The name to be displayed in the Dialog box - The default filename to display - The semantic of the parameter. This is defined in the effect file and is used for render to texture. - Specifies whether the mapping channel should be shown for the texture - This provides the default mapping channel to use. - - - - Display a selection box, or provide access to lights based on the parameter - - The handle to the parameter in the effect file - The name of the actual parameter. This will be used in the paramblock - The name to be displayed in the Dialog box - Specifies if the light is a directional light. This is used to filter the light list. - The semantic of the parameter. - - - - Non UI Element used to set various transforms defined in the effect file - - The handle to the parameter in the effect file - The semantic of the transform to set. - - - - Non UI Element used to set various geometry based data defined in the effect file - - The handle to the parameter in the effect file - The semantic of the transform to set. - - - - Non UI Element used to set various environmental based data defined in the effect file - - The handle to the parameter in the effect file - The semantic of the transform to set. - - - - the techniques used in the effect file. The default is used as the primary technique especially for multi pass effects - - The handle to the technique - The name to display in the - The default technique to used - - - - Get the current DirectX version. - - - Currently this will ONLY return kDirectX9 - This will return kDirectX9. In the future this could also be kDirectX10 - - - - - Implemented by Effect . - - - Effect parsers will implement this interface in order to actually render the effect - - - - - Parse the actual effect file. All data that is needed to actually render the effect is extracted here. If a UI is needed, then the interface can be used for this purpose - true/false depending on whether the parsing was successful - - The main D3D device - The actual file asset that represents the effect file - A pointer to the Effect Manager - - - - The UI code will use this to make sure the effect has all the textures loaded and applied to the effect when they change from the UI - true/false depending on whether loading was successful - - The main D3D device - The handle of the texture parameter from the effect file - The name of the texture to load - If true don't pull the texture from a cache, you need to load from disk - If supplied the DirectX resource system will use data contained in to load the file based on the user's settings. This will be used when the DirectX texture loader fails to load the file directly, at which point the internal 3ds representation could be used as pointed to by the structure. - - - - Remove the parser - - - - - Render the actual object, based on the data supplied in the effect file - - The main D3D device - The render mesh that needs to be drawn - The actual technique that should be used for the final result. - - - - Alows the user to change the mapping channel used by the texture in the UI - - The handle of the parameter to set - The value of the mapping channel - - - - Used internally. - - - - - Load a shader based on the filename supplied. - - - The parser must keep a pointer to this effect, and manage any resources associated with it - True if successful - - The DirectX device - A pointer to the instance - A string containing the effect - this can either be a filename or a buffer contaning the effect - Defines whether the string contains a file name or a buffer - If true don't pull the effect from a cache, you need to reload from disk - - - - retrieves the last error message maintained by the parser - - - - - Allow the EffectManager access to lighting data, so it can expose it through the public interfaces. - - - The EffectManager used to maintain all the lights, now it simply host the UI. This means the parser needs to keep tabs on the lights, or at least what parameters of the lights are needed. This is simple for the parser, as it will need to keep a local list of the light data so it can request the actual 3ds Max data from the LightManager.The number of light based parameters the effect contains - - - - - The light parameter usage. - - - - - Get a handle to the light based on the index supplied. - - - - - Called when a Lost Device is detected - free any resources here. - - - - - Called when a ResetDevice is detected - free and rebuild any resources here. - - - - - Provides the ability to load a texture created out side the parser. - - - True/False depending on whether the texture was uploaded correctly - - A pointer to DirectX texture resource - The name of the parameter who should receive the texture - - - - Description: - This class is only available in release 5 or later. - - Function-published class: emission color, for self-illuminates meshes in viewport - - - - - K Prototype - - Returns the emission color as . - - - - - K Prototype - - Gets the alpha color value for the emission in the range of 0.f to 1.f. - - - - - An extension of that exposes an interface for providing more detailed information about an asset. - - - An extension of that allows an application component to declare more information about an asset, and to provide a callback method for retargeting that asset. A client wishing to expose more asset information should follow the following code example: - - - - - Allows a client to implement and return an asset accessor object. - - - An application component wishing to declare an asset should implement the interface and return an instance of that implementation via this method. It is important to note that a link to this interface is not kept by the object receiving the interface. The interface need only be valid for the length of the DeclareAsset method call. This allows a component to pass in a stack object that will be destroyed at the end of the scope containing this method call. - See class description for a code sample. - - An asset accessor object. - - - - Allows a client to declare a new asset sub-group. - - - Allows a client to declare a new asset subgroup. An example of a sub-group would be an xref file that has its own assets. This method declares that we are now enumerating a sub-group of assets, meaning that declared assets will be added to this group. It is possible to nest groups further by making repeated calls to this function. To end the declaration of a group, call EndGroup(). - The asset accessor should not return NULL for a newly declared group. It is the onus of the asset client to check that IAssetAccessor::GetPath returns a non-null value. If null is returned, neither DeclareGroup nor EndGroup should be called. - - An asset accessor describing the asset which holds a a sub-group of assets. - - - - Used to end the declaration of a sub-group of assets. - - - Called when a client is done declaring a sub-group of assets. See DeclareGroup(IAssetAccessor&) for details. - - - - - is an interface for euler controllers so we can get/set their xyz ordering. - - - The interface is returned by calling GetInterface(I_EULERCTRL). - - - - - Get/Set the XYZ Order of the euler controller. - - - Returns the order of the xyz eulers as defined in euler.h - - - - - Main property access. - - - base Class used by all exporters participating in the properties system - - - - - Retrieve the Property Container. - - - The PropertyContainer for this entity. - - - - - Is the Entity directly supported. - - - IGame provides direct support for certain 3ds Max objects and materials. For instance, IGame supports the standard material and bitmap texture directly, i.e provides direct API calls to get the properties. - - TRUE if IGame supports the parameters for a particular ClassID directly through its API - - - - - Retrieves the name of the entity class. - - - The name of the entity class - - - - - Description: - This class represents the face-data channel interface and as such is an abstraction of a collection of data objects that is associated with faces of 3ds Max objects. 3ds Max objects that have face-data channels call the methods of this interface when those faces change in some way. The data channels can then react to the changes to the faces. You can use the macro GetFaceDataChannelInterface(obj) to obtain a pointer to this interface. - - Currently in version 4.0 only Meshes support face-data channels. - - - - - This method is called when num new faces are created at the index at in the object's list of faces. - Parameters: - ULONG at - - The index in the object's array of faces where the new faces are inserted. - - ULONG num - - The number of new faces which are created. - TRUE if successful, otherwise FALSE. - - - - - This method is called when the owner object has cloned some of its faces and appended these to its list of faces. The bits in the set array correspond to the cloned faces. - Parameters: - & set - - The array of bits. Note that this array has as many bits as there are faces in the owner object. - TRUE if successful, otherwise FALSE. - - - - - This method is called when faces were deleted in the owner object. The bits in the set array correspond to the deleted faces. - Parameters: - & set - - The array of bits. Note that this array has as many bits as there are faces in the owner object. - TRUE if successful, otherwise FALSE. - - - - - This method is called when faces were deleted in the owner object. This method allows for a more efficient deletion of a range of data objects than the previous based one. - Parameters: - ULONG from - - The index in the object's array of faces. Faces starting at this index were deleted. - - ULONG num - - The number of faces that were deleted. - TRUE if successful, otherwise FALSE. - - - - - This method is called when all faces in the owner object are deleted - - - - - This method is called when a face has been copied from index from in the owner object's array of faces to the face at index to. - Parameters: - ULONG from - - The index of the source face. - - ULONG to - - The index of the destination face. - TRUE if successful, otherwise FALSE. - - - - - This method is called when a new face has been created in the owner object based on data interpolated from other faces. - Parameters: - ULONG numSrc - - The number of faces used in the interpolation. - - ULONG* srcFaces - - The array of numSrc face indices into the owner object's face array. These faces were used when creating the new face. - - float* coeff - - The array of numSrc coefficients used in the interpolation. - - ULONG targetFac - - The index in the owner object's array of faces of the newly created face. - TRUE if successful, otherwise FALSE. - - - - - This method will allocate an empty data-channel. - - - - - The data-channel needs to allocate a new instance of itself and fill it with copies of all data items it stores. Note: This method makes it more efficient to clone the whole data-channel. - - - - - The data-channel needs to append the data objects in the fromChan to itself. - Parameters: - const IFaceDataChannel* fromChan - - The channel containing the data objects to append. - TRUE if successful, otherwise FALSE. - - - - - Description: - This is an interface class that will allow a callback procedure to execute for all face data channels of an object. You should derive your own classes from this interface and overwrite the Proc() method to call the desired method. It is up to the derived class to interpret the context parameter passed to Proc(). - - Classes that hold face data channels can implement the method: - - EnumFaceDataChannels(IFaceDataEnumCallBack& cb, void* pContext) - - This method would be called with a reference to an instance of a class derived from IFaceDataEnumCallBack in which Proc() is overwritten. The implementation of EnumFaceDataChannels would call cb.Proc for each of the face-data channels of the object - - Note: Do not delete data channels from within the Proc(). This could lead to unexpected behaviour. - - - - - The callback method that should be overridden. - Parameters: - IFaceDataChannel* pChan - - A pointer to the face-data channel interface. - - void* pContext - - A pointer to the context data. - TRUE if successful, otherwise FALSE. - - - - - Description: - This class represents an interface for managing per-face-data. Geometric objects that wish to support multiple per-face-data channels should implement this interface. Both and support the interface. They have full control over the lifetime of the face-data manager they expose. Consequently, client code should not cache an interface aquired from or for later use. - - - - - This method returns the number of face-data channels. - - - - - This method returns a pointer to the face-data channel. - Parameters: - & ID - - The class ID of the channel you wish to retrieve. - - - - - This method adds a face-data channel to the object. - Parameters: - IFaceDataChannel* pChan - - A pointer to the face-data channel. - TRUE if successful, otherwise FALSE. - - - - - This method removes a face-data channel from the object. - Parameters: - & ID - - The class ID of the channel you wish to remove. - TRUE if successful, otherwise FALSE. - - - - - This method appends a face-data channel to the object. - Parameters: - const IFaceDataChannel* pChan - - The face-data channel to append. - TRUE if successful, otherwise FALSE. - - - - - This method adds or appends face-data channels from the from object, to this object If the channel already exists on this object, it's appended otherwise it gets added. - Parameters: - const IFaceDataMgr* pFrom - - The face-data channel to copy from. - TRUE if successful, otherwise FALSE. - - - - - This method removes all face-data channels from this object. - - - - - This method provides a mechanism for executing an operation for all face-data-channels on this object: For all face-data-channels calls IFaceDataEnumCallBack::proc() with a pointer to that face-data- channel and a context data - Parameters: - & cb - - A pointer to the face-data channel enumerator callback. - - void* pContext - - A pointer to the context data. - FALSE if the callback returns FALSE for any of the face-data channels. - - - - - Saves the face-data to the max file. - - - - - Loads the face-data from the max file. - - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - a MSTR with an absolute path or the where the asset is located if successful; otherwise returns an empty MSTR if it fails to find the asset file - - : is a possible location of the asset file. This location may be a relative or absolute file path. If filePath is a relative file path, it may rooted at the max project folder(by default the folder that contains the 3dsmax.exe file) or it may be rooted at the folder holds the scenefile, or it may be rooted at one of the User Paths for the specified assetType, in this order. filePath includes the asset's filename. - e.g. kXRefAsset, kBitmapAsset, kVideoPost, etc - : If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : is a possible location of the asset file. This location may be a relative or absolute file path. If filePath is a relative file path, it may rooted at the max project folder(by default the folder that contains the 3dsmax.exe file) or it may be rooted at the folder holds the scenefile , or it may be rooted at one of the User Paths for the specified assetType, in this order. filePath includes the asset's filename. filePath is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - e.g. kXRefAsset, kBitmapAsset, kVideoPost, etc - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : the AssetUser to retrieve the asset file information from - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : the AssetUser to retrieve the asset file information from - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : a unique ID that specifies a particular asset - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : a unique ID that specifies a particular asset - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - a MSTR with an absolute path or the where the asset is located if successful; otherwise returns an empty MSTR if it fails to find the asset file - - : the AssetUser to retrieve the asset file information from - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Resolves the physical location of an asset file. - - - Gets an absolute UNC path of an asset file - a MSTR with an absolute path or the where the asset is located if successful; otherwise returns an empty MSTR if it fails to find the asset file - - : the AsssetId to retrieve the asset file information for - If set to true, the file resolution manager bypasses the cache and attempts to find the asset file on disk or network. - - - - Returns the maximum age of cached data in milliseconds for it to be valid Cache data that is older that than this duration is not used of file asset resolution. - - - the maximum age of cached data in milliseconds for it to be valid - - - - - Returns true if the file resolution manager is using cached data to resolve files. - - - true if caching is used - - - - - This makes the file resolution manager use cached results when resolving files. - - - - - This makes the file resolution manager not use cached results when resolving files. - - - - - Pushes current state and sets whether caching of unresolved results is permitted Normally caching of unresolved results is off, and turned on only when loading a lot of asset files quickly, like at the beginning of a render. - - - - : whether caching of unresolved results is permitted. - - - - Pops state of whether caching of unresolved results is permitted. - - - - - Transforms an absolute file path to a UNC path. - - - Transforms an absolute file path to a UNC path - - : an absolute file path that is transformed into a UNC path. It is only converted to a UNC path if the user preference "Resolve Path to UNC" is turned on - - - - Transforms an absolute file path to a UNC path. - - - Transforms an absolute file path to a UNC path - - : an absolute file path that is transformed into a UNC path. It is only converted to a UNC path if the user preference "Resolve Path to UNC" is turned on. - - - - Return the number of asset types currently registered. - - - number of currently registered types - - - - - Returns the asset type ID for the asset type name If the asset type does not exist, it registers the new asset type identified by the string passed in parameter and returns the asset type ID. If the asset type is already registered, it returns the ID corresponding to the asset type name. - - - the asset type ID - - : the asset type name. - - - - Returns the asset type name for the asset type If the asset type does not exist, a null pointer is returned. - - - the asset type name - - : the asset type ID to return a name for - - - - for perfoming workbench filter functions This class peforms workbench functions related to the filtering of fcurves. - Filter can occur without any previous analysis. You get this interface by calling GetCOREInterface(FILTER_INTERFACE) - - - - - - - for perfoming workbench fixer functions. - - - This class peforms workbench functions related to the fixing of fcurves. - Fixing is done after analysis is done and works by fixing the analysis detection locations. - - - - - Description: - exposes the FrameTagManager - - - - - Get number of frame tags. - - - - - Get ID for the i'th frame tag in the list of frame tags. - - - the list is maintained in sorted order, so a given tag can move around in the list. Each tag has a unique ID, so all access to the tag is via this ID - The ID of the tag at index i - - - - - Get the tag's time value. - - - - - The id of the tag to query - - if TRUE, time is relative to the tag this tag is locked to, if any. If false, or this tag is not locked to another tag, the time is absolute - - - - the tag's time value. - - - - - The id of the tag to set - - The new time value to set on the Tag - - if TRUE, time is relative to the tag this tag is locked to, if any. If false, or this tag is not locked to another tag, the time is absolute - - - - get the tag this tag is locked to. - - - The ID of the tag id is locked to, or 0 if not locked - - - The ID of the tag to query on - - - - set the tag this tag is locked to. - - - If you attempt to set a lock that would cause a circular dependency, the current lock will not be changed and the method will return FALSE. See CheckForLoop for testing for loops - TRUE if the lock was set. - - - The ID of the tag to query on - - value of 0 means not tagged - - - - get the tag's name - - - - - set the tag's name - - - - - get whether to scale the tag's time when time is scaled - - - - - set whether to scale the tag's time when time is scaled - - - - - get the index of the tag in the sorted tag list. - - - The index of the tag with the given ID, or -1 if a tag with the given ID was not found - - - - - finds the first tag in the sorted list, if any, for the given absolute time value - - - - - creates a new tag. - - - The ID of the created flag - - - The name of the tag - - The tags absolute time - - The ID of the tag this new tag is locked too. if 0, the tag is not locked to another tag - - Whether or not to scale the tags time when time is scaled - - - - deletes the specified tag - - - - - deletes all the tags - - - - - returns true if tag testID is dependent on tag id - - - - - A generic animation key wrapper class. - - - A generic Bezier Key class for IGame - - - - - based In and out tangents. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - based tangent lengths. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - based In and out tangents. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - based tangent lengths. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - Quaternion based value. - - - This would be accessed when using the IGameControlType::IGAME_ROT specifier - - - - - Scale based value. - - - This would be accessed when using the IGameControlType::IGAME_SCALE specifier - - - - - based In and out tangents. - - - This would be accessed when using the IGameControlType::IGAME_POINT4 specifier - - - - - based tangent lengths. - - - This would be accessed when using IGameControlType::IGAME_POINT4 specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POINT4 specifier - - - - - Simple wrapper for camera objects. - - - An IGame Wrapper around 3ds Max's cameras. This is a generic interface for all the cameras - - - - - Get the Field of Data. - - - A pointer to - - - - - Get the Far Clip plane Data. - - - A pointer to - - - - - Get the Near Clip plane Data. - - - A pointer to - - - - - Get the Target Distance. - - - A pointer to - - - - - Get the Target. - - - If the camera is target camera then this provides access to the target - a pointer to for the target. Return NULL for non target cameras - - - - - Simple wrapper class for constraints. - - - A unified wrapper around the various constraints that are available in 3ds Max. There is access to the type of constraint in use, plus easier access to the constraints. If further access it needed, the interface can be used and additions made to property file used to access other data, as the source for these constraints is available in the SDK. - - - - - of constraining Node. - - - The number of nodes in use by the Constraint system - The number of nodes - - - - - Get the constraint Node. - - - The actual node of the index passed in that is working in the system - A pointer to - - The index of the node to retrieve - - - - Get the influence of the bone. - - - This is the weight, or influence the specified node has in the constraint system. The index used here is the same as the index used in IGameConstraint::GetConstraintNodes, otherwise the weights will not match. This has no effect for a Link Constraint - The weight value - - The node index to query - - - - Get the start frame for the Link constraint. - - - This specifies when the link for the n'th node will start. - The start frame for the node queried. - - The node index - - - - Get the type of Constraint. - - - This defines the actual constraint being used on the controller - The type of max constraint. It can be one ConstraintType enum - - - - - A simple access class for controllers. - - - provides a simplified access to the various key frame controllers used throughout 3ds Max. In 3ds Max a controller needs to be queried for the key interface and then its class ID checked before casting to the appropriate Key class. This class provide the developer with all the keys based on the key type being asked for. As the game engine may only support certain type of max controllers it is far more efficient for a developer to ask IGame for all the Bezier Postion keys then to check with 3ds Max for the controller type. This class also provides direct support for Euler Rotation controllers. The developer can use IGameControl::GetControlType to see if the rotation is Euler and can then can use IGameControlType::IGAME_EULER_X in the appropriate control access type to retrieve the keys. - In 3ds Max some controllers such as TCB, Linear, and Bezier support direct access to their keys. Other controllers are more private and usually base them selves on a float or controller. If there is no direct access then sampling is the easiest choice. IGame supports two types - Full and Quick. Full samples across the full animation range, whilst Quick only samples where keys are found. The limitation of Quick, is that it does not support IGameControlType::IGAME_TM or controllers that do not set keys. - - - - - Return the Bezier Keys. - - - will check the appropriate control and fill the IGameKeyTab with the Key data. The keys should be accessed in maintained by IGameKey::bezierKey. - TRUE is the controller was accessed successfully. - - The to receive the data - The controller type (based on Transform style) to query. This can be one of the following IGAME_POS IGAME_ROT IGAME_SCALE IGAME_FLOAT IGAME_POINT3 IGAME_EULER_X IGAME_EULER_Y IGAME_EULER_Z - - - - Return the Linear Keys. - - - will check the appropriate control and fill the IGameKeyTab with data - TRUE is the controller was accessed successfully. - - The tab to receive the data - The controller type to query. See for more info - - - - Return the TCB Keys. - - - will check the appropriate control and fill the IGameKeyTab with data - TRUE is the controller was accessed successfully. - - The tab to receive the data - The controller type to query. See for more info - - - - Return the Sampled Keys. - - - will sample the control based on the type supplied. It will sample the node TM , float or point3 controllers. The TM sample will be in the Coord System that defined when initialising IGame. This method will sample the controller across the complete animation range. The method of access can be provided (absolute and relative) It is important to read the 3ds Max sdk docs on Control::GetValue to understand the usage when used with non IGameControlType::IGAME_TM controllers. IGame will still however fill out the respective structures even when the 3ds Max sdk docs mention access It is set to Relative as default, as this was the default for IGameControlType::IGAME_TM usage before the method changed. If you are sampling anything else than IGameControlType::IGAME_TM this should be set to false to behave like the 3ds Max default and IGame before this change. - TRUE if the controller was accessed successfully. - - The tab to receive the data - This is the number frames that the controller will be sampled at. It will be converted to Ticks internally - The controller type to query. This can be any of the standard type but also include IGAME_TM - This defines whether the controller is sampled for relative or absolute values. It defaults to relative true. Please read the max sdk section on for details on the internal usage. - - - - Return the Sampled Keys. - - - will sample the control based on the type supplied. It will sample float or point3 controllers. The TM sample will be in the Coord System that you defined when initialising IGame. This method only samples the controller where a key is , so it will not support the IGameControlType::IGAME_TM type. If the controller does not support setting of keys, it will return false. This method will only sample the controller at times where keys exist. This is useful to limit the data where controller can not be accessed directly - TRUE if the controller was accessed successfully. - - The tab to receive the data - The controller type to query. This can be any of the standard type but also include IGAME_TM - - - - Return an individual . - - - Fills out the supplied with the bezier data for the key index supplied - TRUE if successful - - The controller type to query. See for more info - - The key to retrieve - - - - Return an individual . - - - Fills out the supplied with the TCB data for the key index supplied - TRUE if successful - - The controller type to query. See for more info - - The key to retrieve - - - - Return an individual . - - - Fills out the supplied with the Linear data for the key index supplied - TRUE if successful - - The controller type to query. See for more info - - The key to retrieve - - - - Get the total number of keys for this controller. - - - This return the total number of keys for the controller supplied, WARNING: support leaf controllers only - The total number of keys - - The controller type to query. See for more info - - - - Get the controller type. - - - Retrieves what type of IGame Controller it is (based on transformation style) - The type of controller, It can be one of the following - IGAME_UNKNOWN - IGAME_MAXSTD - IGAME_BIPED - IGAME_ROT_CONSTRAINT - IGAME_POS_CONSTRAINT - IGAME_LINK_CONSTRAINT - IGAME_LIST - - IGAME_INDEPENDENT_POS - IGAME_POINTCTRLCONTAINER - - - The controller to query. See for more info - - - - Get the name of the controller class. - - - Retrieves the controller class name based on the type - - The controller to query. See for more info - The class name string - - - - Access to actual animation. - - - Indicates whether the IGame Controller actually has animation (based on transformation style) - TRUE if controller actually has animation; otherwise FALSE - - - The controller to query. See for more info - - - - Check for sub-controllers. - - - Indicates whether the IGame Controller is a leaf (has no any sub-controllers or references) controller (based on transformation style) - TRUE if controller has no any sub-controllers or references; otherwise FALSE - - - The controller to query. See for more info - - - - Access to the Constraints. - - - If a controller has a constraint system, then this will provide access to it - A Pointer to , or NULL if not available - - The controller to check. This can be either of IGAME_POS IGAME_ROT IGAME_TM - - - - Get the order of Rotation. - - - This provides a way of determining the order of rotation for Euler controllers. This is important so that the rotation can be rebuilt correctly on import. - This data is also important when accessing the controller keys. You still access the Euler data bsed on X,Y and Z - but you would use the ordering to work out the meaning of each controller. So if EulerOrder was ZXZ, then controller access would mean x=z, y=x, z=z. - The order of Rotation. This can be a value from the EulerOrder - - - - - Get access to the actual max controller. - - - The 3ds Max controller - - This can be either of IGameControlType - - - - Access the list controller. - - - Access the n'th controller from the List controller. - An interface - - The index into the list controller - The type to access - - - - Get the number of controllers maintained by the list controller. - - - The number of controllers maintained by the list controller for the Controller type being queried - The number of controllers in the list controller - - The controller to type - - - - Get the number of subcontroller tracks maintained by the Point Controller Container. - - - The number of subcontroller tracks maintained by the Point Controller Container. This is NOT actual number of subcontrollers, but total number of vertices - The number of subcontroller tracks in the Point Controller Container, zero if no vertex animation - - - - - Access the n'th subcontroller from the Point Controller Container. - - - Access the n'th subcontroller from the Point Controller Container. - An interface, if vertex is not animated return NULL - - The index into the Point Controller Container, the actual vertex index - - - - A developer can use this class to define what Coord Systems IGame exports the data in. - - - IGame will convert data from the standard 3ds Max RH Z up system to any defined system. At the moment direct support for DirectX and OpenGL are provided. This means that all Matrix and vertex data will have been converted ready to use on your target system. - The coordinate system should set up straight after initialising IGame. The default is to provide everything in 3ds Max native formats. - - - - - Get the Coordinate System. - - - The default system is the 3ds MAX system. - The current Coordinate System used, one of the IGameConversionManager::CoordSystem - - - - - the User defined Coordinate system, if the CoordSystem has been defined as IGAME_USER. - - - Allow a user definable Coordinate System. See comments above. - - THe data to define the system - - - - Error callback. - - - Define a callback for error reporting. This will be called when ever an error has been reported by the system. The developer can then call GetIGameErrorText to retrieve a more detailed error description. The callback can be set by using SetErrorCallBack() - - - - - The error callback. - - - This needs to be implemented by the developer and is used by the system to report the error - - The error code of the last error - - - - A generic class. - - - Any modifier that is not known to IGame will be implemented as a "Generic" modifier, so that basic access can be provided - - - - - A for IGame. - - - This object represents any object that is unknown to IGame - this could be a new pipeline object for example. It return IGAME_UNKOWN for its IGameObject::ObjectTypes - - - - - Simple wrapper for IKChains. - - - An IGame wrapper around the IKChain object. - This object be used as a basis for character export. All nodes used in the chain are maintained by the interface. This allows animation to be exported based on whether it is in IK or FK mode. If the IK is enabled then the retrieved from the will be that of the End Effector for the chain. If it is in FK mode then the from the nodes in the chain would be used for the FK calculation. - - - - - Get the number of nodes that make up the chain. - - - The number of nodes in the chain - - - - - Access to the n'th node in the chain. - - - An representation of the node - - The index of the node to access - - - - Get the swivel data. - - - The swivel data used in the IK calculation - The for the swivel data - - - - - Get the controller for the IK enable. - - - Access to the Enabled controller - this defines whether IK or FK are used. When IK the end effector is used to control the transforms, in FK the individual nodes can be positioned independent of the effector - An pointer for the Enabled controller. This controller does not have direct access, so should be sampled using IGameControlType::IGAME_FLOAT - - - - - Main animation key container. - - - A simple container class for direct Key access of all the available Key types - - - - - The time the key was set. - - - - - Flags various selection states for the key. - - - - - The TCB Keys. - - - This key access would be used if you used one of the IGameControl::GetTCBKeys methods - - - - - The Bezier Keys. - - - This key access would be used if you used one of the IGameControl::GetBezierKeys methods - - - - - The Linear Keys. - - - This key access would be used if you used one of the IGameControl::GetLinearKeys methods - - - - - The Sampled Keys. - - - This key access would be used if you used one of the IGameControl::GetSampledKeys methods - - - - - Simple wrapper for spline knots. - - - An IGame wrapper for Knot information - - - - - Get the in vector. - - - The in vector - - - - - Get the out vector. - - - The out vector - - - - - Get actual knot position. - - - The knot position - - - - - Get the type of knot. - - - The knot as a IGameKnot::KnotType - - - - - Get the knot controller. - - - Get the actual IGameController for the knot - this provides access to any animated data - The controller for the specified knot - - The knot to access - - - - Simple wrapper for light objects. - - - An IGame Wrapper around 3ds Max's lights. This is a generic interface for all the lights - - - - - Get the Data. - - - A pointer to - - - - - Get the Multiplier Data. - - - A pointer to - - - - - Get the Attenuation End Data. - - - A pointer to - - - - - Get the Attenuation Start Data. - - - A pointer to - - - - - Get the Falloff Data. - - - A pointer to - - - - - Get the Hot spot Data. - - - A pointer to - - - - - Get the Aspect Ratio Data. - - - A pointer to - - - - - Get the Decay Start Data. - - - A pointer to - - - - - Get the type as defined in the UI. - - - The Type. Returned value corresponds to IGameLight::LightType Enum - - - - - Get the overshoot. - - - TRUE if the supports overshoot - - - - - Get the Decay Type of the . - - - The Decay Type as integer - 0 - None - 1 - Inverse - 2 - Inverse Square - - - - - - Get the shape of the . - - - The shape can be one of the following - RECT_LIGHT - CIRCLE_LIGHT - - - - - - Get the Target of the . - - - If the light is of type Spot light then this provides access to the target - A pointer to for the target. Return NULL for non target lights - - - - - Check if is On. - - - True if the is on - - - - - Check Exclude List. - - - Determines whether the exclude list actually maintains a list that is infact included by the light - TRUE if the light maintains an included list - - - - - Get the number of excluded nodes from the . - - - This list contains nodes that should not be included in lighting calculations. It can also contain a list of only those lights that SHOULD be included. This all depends on the state of IsExcludedListReversed. - The total number of excluded nodes - - - - - Get the excluded node based on the index pass in. - - - An pointer for the excluded node - - The index of the node to access - - - - A generic animation key wrapper class. - - - A generic Linear Key class for IGame - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - Quaternion based value. - - - This would be accessed when using the IGameControlType::IGAME_ROT specifier - - - - - Scale based value. - - - This would be accessed when using the IGameControlType::IGAME_SCALE specifier - - - - - Simple wrapper for 3ds Max materials. - - - is IGame Wrapper around a basic . It provides access to the basic material properties and Textures used by the material. Any material will be wrapped in this class, but only Standard is directly supported with API access to the properties. If the material is not directly supported then the data can be access via the interface. - - - - - Check if the material is a Multi type. - - - This could be for a Blend or Mix material - TRUE if is Multi material - - - - - Check if the material is a SubObject style Multi . - - - This could be for 3ds Max's Multi Subobject material - TRUE is a Subobject material - - - - - Get the material name as seen in the Editor. - - - The name of the material - - - - - Get the material class as seen in the Editor. - - - The name of the material class - - - - - Get the number of sub materials. - - - The value is used by IGameScene::GetSubMaterial - The number of Sub material - - - - - Access to any sub material. - - - The sub material is any material used by a multi material. For example, a Top/Bottom material the sub materials would be the top and bottom - A Pointer to a - - Index into the submaterial - - - - Get the MatID for subobject materials. - - - This value represents the MatID used on objects to define what faces receive this material - The MatID of the material - - The index of the submaterial to retrieve - - - - Get the Ambient Data. - - - A pointer to - - - - - Get the Diffuse Data. - - - A pointer to - - - - - Get the Emissive Data. - - - A pointer to - - - - - Get the Specular Data. - - - A pointer to - - - - - Get the Opacity Data. - - - A pointer to - - - - - Get the Glossiness Data. - - - A pointer to - - - - - Get the Specular Level Data. - - - A pointer to - - - - - Get the Emissive Amount Data. - - - A pointer to - - - - - Get the number of Textures used by the material. - - - The texture count. - - - - - Access to the actual Texture Map. - - - A pointer to a - - The index to the Texture Map to retrieve - - - - Access to the actual 3ds Max material definition. - - - This allows developer access to the complete 3ds Max material if further data access is needed - A pointer to a standard max class - - - - - Simple wrapper for tri mesh objects. - - - An IGame wrapper around the standard 3ds Max class. It provides unified support for Vertex colors and normals Mirroring is taken into account so the data you retrieve is swapped. - Many of the geometry lookups used by use the 3ds Max Class . You can use the returned to find out whether the call was successful as the count would be greater then zero. - In 3ds Max 6.0 and above version of IGame, Tangent space is calculated. For this to work, each face must be a member of a smoothing group. - - - - - Vertex Index - - The face ID to use - The face corner to use - - - - Get Map Vertex Index for specified face and corner. - - - Texture Vertex by default Should be used to get vertex index for Vertex , Alpha, Illum, etc - Map Vertex Index - - The face ID to use - The face corner to use - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get Normal Vertex Index for specified face and corner. - - - Normal Vertex Index - - The face ID to use - The face corner to use - - - - Get Tangent and Binormal Vertex Index for specified face and corner. - - - Tangent and Binormal Vertex Index if successful, -1 otherwise - - The face ID to use - The face corner to use - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get Smoothing Group for specified face. - - - Smoothing Group value - - The face ID to use - - - - Get ID for specified face. - - - ID value - - The face ID to use - - - - Get Visibility value for specified face and edge. - - - 1 if edge visible, 0 otherwise - - The face ID to use - The edge to use - - - - N-Polygon support - Get the number of polygons in the - The total number of polygons contained in the - The number of polygons, zero if mesh can not be converted to - - - - - Get the number of Normals in the - - - The total number of Normalscontained in the - The number of Normals, zero if mesh can not be converted to - - - - - Get Polygon polygon corners. - - - The degree (corners) for given polygon in the - The degree (corners) for polygon, zero if mesh can not be converted to - - The polygon index is being evaluated - - - - Get Polygon vertices. - - - The vertices ID's for given polygon in the - The vertices ID's as an array, empty if mesh can not be converted to - - The polygon index is being evaluated - - - - Get Polygon normals. - - - The normals ID's for given polygon in the - The normals ID's as an array, empty if mesh can not be converted to - - The polygon index is being evaluated - - - - Get Polygon normals array - - - The normals array - The normals as an array, empty if mesh can not be converted to - - The polygon index is being evaluated. Default is -1, returning all normals for If parameter defined (other than -1) returns normals for provided polygon only. - - - - Get Polygon map vertices. - - - The map vetrices ID's for given polygon in the - The map vertices ID's as an array, empty if mesh can not be converted to - - The polygon index is being evaluated - The map channel is being evaluated - - - - Get Polygon Edges Visibility. - - - The Edges Visibility values for given polygon in the - The Edges Visibility array (1 if edge visible, 0 otherwise), empty if mesh can not be converted to - - The polygon index is being evaluated - - - - Get Smoothing Group for specified Polygon. - - - Smoothing Group value - - The polygon index is being evaluated - - - - Get ID for specified Polygon. - - - ID value - - The polygon index is being evaluated - - - - Get Polygon Indices based on ID. - - - The Polygon ID's for given ID in the - The vertices ID's as an array, empty if mesh can not be converted to - - The face index is being evaluated - - - - Get Polygon . - - - The for given polygon in the - The Polygon , NULL if not exists - - The polygon index is being evaluated - - - - Initialize Binormal and Tangents data - - - Binormal and Tangents can be initialized and accessed separately from other mesh data see IGameObject::InitializeData() for more details To initialize entire mesh data (including Binormals and Tangents) IGameObject::InitializeData() should be called - true if successful, false otherwise - - - - - Get number of Vertices. - - - The total number of vertices found in the mesh - The number of Vertices - - - - - Get number of Texture Vertices. - - - The total number of Texture vertices found in the mesh - The number of TextureVertices - - - - - Get the actual Vertex. - - - Get the vertex at the specified index. This is in the World Space Coordinate System - A representing the position of the vertex - - The index of the vertex - Defines what space the vertex is in. This defaults to World space to be compatible with previous versions - - - - Get the actual Vertex. - - - Get the vertex at the specified index. This is in the World Space Coordinate System - TRUE if successful - - The index of the vertex - A to receive the data - Defines what space the vertex is in. This defaults to World space to be compatible with previous versions - - - - Get the actual Texture Vertex. - - - Get the Texture vertex at the specified index - A representing the Texture vertex - - The index of the Texture vertex - - - - Get the actual Texture Vertex. - - - Get the Texture vertex at the specified index - TRUE if successful - - The index of the Texture vertex - A to receive the data. - - - - [METHOD IS RETIRED] Specify whether normals are calculated based on face angles - - - To tell IGame to calculate normals based on a weight made from the angle of the edges at the vertex, the developer needs to call this beforeIGameObject::InitializeData() is called. The default is not to use weighted normals which is also the default in 3ds Max 4.0 - - - - - Get number of normals. - - - The total number of normals found in the mesh - The number of normals - - - - - Get the Vertex Index associated with the Normal - - - Get the Vertex Index associated with the Normal index. - Vertex Index associated with the Normal inex - - The index of the normal in the flat list - - - - Get the actual normal. - - - Get the normal at the specified index. - - A representing the normal - - The index of the normal in the flat list - defines what space the normal is in. This defaults to World space to be compatible with previous versions - - - - Get the actual normal. - - - Get the normal at the specified index in the flat list - TRUE if successful - - The index of the normal - A to receive the data. - Defines what space the normal is in. This defaults to World space to be compatible with previous versions - - - - Get the normal based on face and corner. - - - TRUE if successful - - The index into the face array - The vertex whose normal is requested - A point3 to receive the data - Defines what space the normal is in. This defaults to World space to be compatible with previous versions - - - - Get the normal based on face and corner. - - - A containing the normal - - The pointer of the face whose normals are to be accessed - The vertex whose normal is requested - Defines what space the normal is in. This defaults to World space to be compatible with previous versions - - - - Get the normal based on face and corner. - - - TRUE if successful - - The pointer of the face whose normals are to be accessed - The vertex whose normal is requested - A point3 to receive the data - Defines what space the normal is in. This defaults to World space to be compatible with previous versions - - - - Get the normal based on face and corner. - - - A containing the normal - - The index into the face array - The vertex whose normal is requested - - - - Get number of Illuminated Vertices. - - - The total number of Illuminated Vertices found in the mesh - The number of Illuminated Vertices - - - - - Get number of Alpha Vertices. - - - The total number of Alpha Vertices found in the mesh - The number of Alpha Vertices - - - - - Get number of Vertex Colors. - - - The total number of Vertex Colors found in the mesh - The number of Vertex Colors - - - - - Get the actual Vertex. - - - Get the color vertex at the specified index - A representing the color of the vertex. Return (-1,-1,-1) if the index is invalid - - The index of the color vertex - - - - Get the actual Vertex. - - - Get the color vertex at the specified index - TRUE if successful - - The index of the color vertex - A to receive the color data - - - - Get the actual Alpha Vertex. - - - Get the Alpha vertex at the specified index - A float representing the Alpha value of the vertex. Return -1 if the index is invalid - - The index of the Alpha vertex - - - - Get the actual Alpha Vertex. - - - Get the Alpha vertex at the specified index - TRUE if successful - - The index of the Alpha vertex - A float to receive the value - - - - Get the actual Illuminated Vertex. - - - Get the Illuminated vertex at the specified index - A float representing the Illuminated value of the vertex. Return -1 if the index is invalid - - The index of the Illuminated vertex - - - - Get the actual Illuminated Vertex. - - - Get the Illuminated vertex at the specified index - TRUE if successful - - The index of the Illuminated vertex - A float to receive the data - - - - Get the number of faces in the mesh. - - - The total number of faces contained in the mesh - The number of faces - - - - - Get the actual face. - - - The face represented by the index. The data in can be used to lookup into the various arrays - A pointer to , or NULL if an invalid index is passed in - - The index of the face to return - - - - The number of verts in a mapping channel. - - - Get the number of the vertices for a particular mapping channel - The number of verts - - The mapping channel to use - - - - Get the mapping vertex. - - - Get the actual mapping vertex for the channel - The actual mapping data. This will be 0 if the Mapping channel is not found - - The channel to query - The vertex index - - - - Get the mapping vertex. - - - Get the actual mapping vertex for the channel - TRUE if successful - - The channel to query - The vertex index - A to receive the data - - - - The number of Binormals - - - Get the number of the binormals - - The number of binormals for specified map channel - - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get the actual Binormal - - - Get the Binormal at the specified index - A representing the Binormal for specified map channel - - The index of the Binormal - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get the actual Binormal - - - Get the Binormal at the specified index - TRUE if successful - - The index of the Binormal - A point3 to receive the Binormal for specified map channel - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - The number of Tangents - - - Get the number of the Tangents - The number of Tangents for specified map channel - - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get the actual Tangent - - - Get the Tangent at the specified index - A representing the Tangent for specified map channel - - The index of the Tangent - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get the actual Tangent - - - Get the Tangent at the specified index - TRUE if successful - - The index of the Tangent - A point3 to receive the Tangent for specified map channel - The valid MESH MAP channel, range (-2...99), default - Texture Coordinates - - - - Get the active mapping channels. - - - Extracts the active mapping channels in use by the object. Starting with 3DXI V2.0 this returns all active channels including the standard ones such as Texture Coordinates, Vertex Colors, Illum, and Alpha. - A tab containing the active Mapping channels. - - - - - Get the face index into the mapping channel array. - - - Get the actual index into the mapping channel for the supplied face. - - TRUE if the channel was accessed correctly. False will mean that the channel was not present. - - The mapping channel to use - The face to use - An array of three indices to receive the indexing into the vertices - - - - Get all the smoothing groups found on a mesh. - - - A tab containing the smoothing groups. If the count is zero it means that no smoothing groups were found - - - - - Get all the material IDs found on a mesh. - - - A tab containing the IDs - - - - - Get the face for a particular smoothing group. - - - Get all the faces belonging to a particular smoothing group - A tab containing all the faces - - The smoothing group to use - - - - Get the face index for a particular smoothing group. - - - Get all the faces belonging to a particular smoothing group as a set of indexes into the main face list - A tab containing all the indexes - - The smoothing group to use - - - - Get the faces for a particular ID. - - - Get all the faces belonging to a particular material ID - A tab containing all the faces - - The material ID to use - - - - The actual material used by the . - - - This will provide access to the material used by the whose index is passed in. This means the mesh can be broken down into smaller meshes if the material is a subObject material. This can be used in conjunction with IGameMesh::GetFacesFromMatID to rebuild a face with the material assigned via a material ID. - A pointer to a material. The is the actual material, so in the case of the SubObject material the material whose mat ID matches. - - The index of the face whose material is needed. - - - - The actual material used by the . - - - This will provide access to the material used by the . This means the mesh can be broken down into smaller meshes if the material is a subObject material. This can be used in conjunction with IGameMesh::GetFacesFromMatID to rebuild a face with the material assigned via a material ID. - A pointer to a material. The is the actual material, so in the case of the SubObject material the material whose mat ID matches. - - A pointer to the face whose material is needed. - - - - The actual 3ds Max representation. - - - The pointer used by 3ds Max. This allows the developer further access if required to the mesh or data structures - A pointer - - - - - Access the color data for the face specified. - - - The surface color can be obtained from the RenderedSurface interface. Before this function can be used the Surface data needs to be initialised before hand. Please see the for more information - TRUE is successful. Possible errors include the object not being renderable or is hidden. - - The face index whose color is being evaluated - A pointer to a that receives the 3 vertices for the face. This should initialised as res[3] - - - - [METHOD IS RETIRED] Tell IGame to create a flattened Normals - - - IGame can create a flattened list of normals for export much like Vertices and Texture Coordinates. However this operation can be expensive especially on large objects with mixed smoothing groups. This method determines whether this is available for use. If it is not set, then vertex normals can only be looked up on a per face basis . - - Due to some internal changes, this method is not really needed. However some builds of IGame did require it so it has been kept in. - - - - - Simple wrapper for 3ds Max modifiers. - - - This is an IGame wrapper for the basic 3ds Max modifier class. This is provided so that the developer does not need to walk the modifier stack and look for derived objects. An instance of this class is obtained from class - - - - - Get type. - - - Return the Type of represents - The modifier type, corresponds to IGameModifier::ModType Enum - - - - - An IGame wrapper around the Morph Compound and the Morpher . - - - - - Get the number of morph targets. - - - The number of targets used by the morpher. There is a slight difference between the morph methods. The compound morpher include the original object as a target, where as the morpher modifier only show the actual physical targets. So to provide the same result the compound will show one more target - The number of morph targets - - - - - Get the morph target used by the morpher. - - - This method provides the actual morph target used by the system. In the case of the compound object, it does its best to find the node but, the compound morpher only exposes the actual "Object" and in 3ds Max the object could have multiple nodes. - An representing the target - - The index of the target to retrieve - - - - Get the weight associated with the target. - - - An . The actual value of the keys provides the weight value - this value can not be consider normalised - - The index of the target whose weight is being accessed - - - - Get the morpher type. - - - The type of morpher represented by this interface - The morpher type. It can be one of the following - MORPHER_OBJECT - MORPHER_MODIFIER - - - - - - A simple wrapper for max nodes. - - - provides simplified access to many of 3ds Max's standard Node. The user can use this class to gain access to Controllers and Objects, plus many basic node properties. An instance of this class is available through the interfaces. - - - - - Get the . - - - The provides access to the key frame data for the node - An pointer. - - - - - Get the actual object. - - - The is the object used by IGame, all the basic objects supported by IGame derive from IGameObject::GetIGameType should be used to determine how to cast the returned pointer. - An pointer - - - - - Release the obtained from GetIGameObject. - - - This will release all the memory used by the object, but it will not effect any controller or transfrom data. Remember to call GetIGameObject if you want to use it again. - Starting with IGame v 1.2 reference counter used internally, so will be released only in case of matching GetIGameObject/ReleaseIGameObject calls. - - - - - Get the node name. - - - The name of the node as used in max - The name of the object - - - - - Get the unique Node ID. - - - This provideds access to the node handle used in 3ds Max. This value will be unique for the file - The node ID (node handle) - - - - - Access to the 3ds Max node, if further processing is required. - - - if need be the node can be accessed here - this is so that IGame can be intergrated into existing pipelines - A pointer to a Max node - - - - - Get World TM. - - - A matrix containing the World TM - - the Time to retrieve the WorldTM. If no time is passed in then the global static frame is used - - - - Get Local TM. - - - A Matrix containing the local TM - - the Time to retrieve the LocalTM. If no time is passed in then the global static frame is used - - - - Get TM. - - - A Matrix containing the TM. This is the TM after any world space transforms have been applied - - the Time to retrieve the ObjectTM. If no time is passed in then the global static frame is used - - - - Get the nodes parent. - - - If this is a top level node, then it will not have any parents - If there is a parent a valid pointer will be returned, else NULL - - - - - Get the number of direct children to the parent. - - - This does not include children of children - The number of children - - - - - Access the n'th child node of the parent node. - - - pointer to the child - - The index to the child to retrieve - - - - Get the material index. - - - The index into the material array for this node's material - The index of material used by this node - - - - - Get the material. - - - Direct access to the actual material used by the node - The pointer for this node. - - - - - Get the wireframe color. - - - Access to the wireframe color used by this node. - An (r,g,b) color, with values in the range 0-255 - - - - - Check if a Target Node. - - - Can be used for exporting targets. Exporters often treat targets separately to standard nodes choosing to export them as part of the node that uses them as targets for example lights and cameras - TRUE if it is a target - - - - - Check if a Group Head. - - - A group in 3ds Max has an owner, a Group Head, this is a dummy node. The children of a Group Head are the members of the group. So when you encounter one of these, look for the children as these will be the members of the group. - TRUE if a "Group Head" - - - - - Check if the node hidden. - - - This allows access to the hidden property of the node. A developer may choose to ignore any node that is hidden. However this can be dangerous as many dummy objects get hidden but actually define animation - especially in IK situations - TRUE if hidden - - - - - Simple wrapper for 3ds Max objects. - - - This is heart of the interaction with 3ds Max objects. 3ds Max objects are converted to IGame objects to provide simpler interfaces. Specific support is given to Meshes, Splines, Helper (including bones) and Cameras. Any object that is not supported by IGame directly is supported as a generic object, so that properties can be extracted easily. At the present time IGame only supports Geom Objects that can be converted to a Tri . - A note about XRef items. IGame will search out XRef Objects and store them as IGameXrefObject. External file names and proxies can be accessed by casting IGameObject* to IGameXrefObject* - Some of the interfaces returned by require that the nodes be parsed by IGame first. - - - - - The bounding box of the object. - - - - The to receive the value - - - - Check if object renderable. - - - TRUE if it is renderable - - - - - The IGame object type. - - - Return the Type of it represents - The object type. Returned value corresponds to IGameObject::ObjectTypes Enum - - - - - Access to the actual 3ds Max object. - - - Access to the actual 3ds Max object, if further direct access needed - A pointer to a max class - - - - - The 3ds Max object type. - - - This lets the developer know what type of object - , Geom, Helper etc... This is different from the IGame types, as these may group more than one type of 3ds Max object together. The information can be used to cast returned from IGameObject::GetMaxObject to the appropriate class. - The type of max object. This is defined as the IGameObject::MaxType enum - - - - - The number of modifiers active on the object. - - - The number of modifiers - - - - - Access to IGame modifier. - - - Get a pointer to the IGame representation of the modifier - A pointer to the - - The index of the modifier to return - - - - Check if casts shadows. - - - TRUE if object casts shadows - - - - - Check if object skinned. - - - Is object skinned with either Physique of Skin - TRUE if skinned - - - - - Access to the Skin interface. - - - A pointer to or NULL if not present - - - - - Check if XRef object. - - - Indentify XRef objects - TRUE if it is an XRef - - - - - Access to the ObjectTM. - - - Get the ObjectTM. This is the matrix needed to calculate world space - A matrix containing the TM. Used to calculate world space. - - - - - Extract the 3ds Max data into IGame data. - - - Some extraction processes are time and memory consuming. This method allows the developer to specify when they want the data to be converted - this prevents any unwanted data being converted. This is important for class - if you are just after parameter data, you don't want the whole vertex array being sorted. Calling this tells the object that you want the data be converted. - It will return FALSE when data has not been converted, this object should not be exported. Usually this is due to a standin or in the case of a , it can't be converted to a Tri . - - - - - Main property definition. - - - provides a wrapper around the standard 3ds Max ParamBlock system. It works for both and , all paramblocks parameters are supported directly. It provides access to and also data access for floats, ints, strings, etc. It performs the type checking, so the Paramblock system will not assert in case of the wrong data type requested. The access to User Properties is provided by look up from the IGameProp.xml file. - - - - - The name of the Property. - - - The name as defined in MAXScript or User Property defined in IGameProp.xml file - The parameter name - - - - - Check if the parameter is a based. - - - TRUE if , FALSE if - - - - - Check if the parameter animated. - - - Use this check to determing whether or not to access the controller - TRUE if animated - - - - - The controller for the Property. - - - A pointer to - - - - - Direct access to the . - - - a pointer to - - - - - Direct access to the . - - - a pointer to - - - - - Check if the parameter is or based. - - - Specifies whether this parameter is based on either or . This is useful as some IGameProperties are based on Non paramblocks. For example node/user data is accessed as an IGame Property but in 3ds Max has no Paramblock representation - TRUE if it is based on a either or . - - - - - The data type of the Property. - - - This is used to find out the data type of the property, so the correct GetPropertyValue method can be used - The data type. Returned value corresponds to PropType enumeration. - - - - - Check if User Parameter has a entry in the IGameProp.xml file. - - - All parameter blocks parameters are supported directly. Use this check to decide whether a User Property is defined in the IGameProp.xml file - True if User Parameter has a entry in the IGameProp.xml file - - - - - The index of the parameter. - - - Replacement for the old GetParamBlockIndex method. This method gets the actual index of the parameter as used by the Parameter block system. The Parameter block system treats ParamID's and their related indexes very differently. Therefore incorrectly mixing Parameter integer index's and and ParamID's can cause very subtle and difficult to find bugs. Previous implementations of the old GetParamBlockIndex method returned a ParamID cast to an int which was incorrect (If the data was based off of Parameter Block 2). Fixing it would cause silent behavior changes which may have gone unnoticed. Therefore this method was introduced to forcefully clarify the difference between accessing the ParamID versus the index of the Parameter. - The index in the parameter block - - - - - The ParamID of the parameter. - - - This replaces the old method GetParamBlockIndex which previously had incorrect behavior. - The ParamID of the parameter, not the index. - - - - - Access to the actual Parameter Data. - - - TRUE if succesful - - The float to receive the data - The time to retrieve the value, defaulted to the static frame. This is set by - The flag indicating if percent fraction value (TYPE_PCNT_FRAC) should be converted (0.1 to 10), default:false - - - - Access to the actual Parameter Data. - - - TRUE if succesful - - The int to receive the data - The time to retrieve the value, defaulted to the static frame. This is set by - - - - Access to the actual Parameter Data. - - - TRUE if succesful - - The to receive the data - The time to retrieve the value, defaulted to the static frame. This is set by - - - - Access to the actual Parameter Data - - - TRUE if succesful - - The to receive the data - The time to retrieve the value, defaulted to the static frame. This is set by - - - - Access to the actual Parameter Data. - - - TRUE if successful - - The MCHAR to receive the data - The time to retrieve the value, defaulted to the static frame. This is set by - - - - class - - - Access to the main render surface interface. Methods are available to setup the system and define the lighting models used. Actual access to the data is provided through the class - - - - - Setup the database for rendering. - - - - - Clean it all up. - - - - - Define the type of model be used in the render. - - - - - Define the usage of Maps and shadows. - - - - - Define the usage of Maps and shadows. - - - - - A generic animation key wrapper class. - - - A generic Sample Key class for IGame. This is used for unknown controllers or controllers that simply need to be sampled, this can includes Biped - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POINT4 specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - Quaternion based value. - - - This would be accessed when using the IGameControlType::IGAME_ROT specifier - - - - - Scale based value. - - - This would be accessed when using the IGameControlType::IGAME_SCALE specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_TM specifier - - - - - Main scene access. - - - is the main entry point for an exporter. It contains the initialisation routines and access to the nodes and materials of the scene. The user can ask IGame to enumerate the whole scene, selected nodes or single nodes, with or with out hierarchy. - - - - - the Property File to use. - - - You can define the name of the file to use, including full path, that IGame uses to parse for the supported parameters. This means that you could have multiple configs depending on the various games in development. InitialiseIGame(). By default the the filename will be the maxroot/plugcfg/IGameProp.XML. - - The name of the property file to use inthis session. - - - - Initialise IGame. - - - IGame can be initialised specifying whether to search for selected nodes only - True if the scene was enumerated - A Possible reason for failure is that the Parameter IGameProp.XML file was not found or not parsed correctly - - True if selected are searched for - default false - - - - Initialise IGame with a specific node. - - - Developer can specify a single node to parse. - True if the scene was enumerated - A Possible reason for failure is that the Parameter IGameProp.XML file was not found or parsed correctly - - The actual node to parse - lets IGame know to initialise the children of the node - - - - Initialise IGame with a specific set of nodes. - - - Developer can specify a set of nodes to parse. This could be implemented by creating a using the 3ds Max sdk. Look at Interface::GetSelNodes() and Interface::GetSelNodeCount(). - True if the scene was enumerated - A Possible reason for failure is that the Parameter IGameProp.XML file was not found or parsed correctly - - The actual tab containing the nodes to parse - lets IGame know to initialise the children of the node - - - - Get the active filename. - - - The current filename - - - - - the static frame. - - - Specify the frame to use for Time access functions - - The static frame to use - Internally this will be converted to Ticks - - - - Get the start of the animation range. - - - This provides the animation start time in ticks - The start time in ticks - - - - - Get the end of the animation range. - - - This provides the animation end time in ticks - The end time in ticks - - - - - Get the number of ticks per frame. - - - The number of ticks per frame - - - - - All node access is provides by parent nodes. This does not include the Root node as in 3ds Max. This method can be used to traverse the scene - The number of parent nodes - - - - - Get the complete number of nodes. - - - The is useful for implementing a progress bar in the exporter - The total node count - - - - - Get the actual toplevel node. - - - A Top level node is a node at the top of the Hierarchy, i.e it has no Parent. - A pointer to a - - The index into the the toplevel parent list - - - - Get the total number of parent materials. - - - This does not include sub materials - just the number of actual material containers - The total number of parent materials - - - - - Access to the Root . - - - This is the parent material that is stored on the Node. The material will host any sub materials and access is provided by the interface. - A Pointer to an - - The root material to access - - - - Access the from the supplied . - - - Some IGame methods provide access to lists. You can use this method to retrieve the equivelent IGame must be initialised first, as the node must be in the Database - A pointer to , NULL if not found - - The 3ds node to find - - - - Access the from the supplied Node ID. - - - You can use this method to retrieve the based on a Node ID IGame must be initialised first, as the node must be in the Database - A pointer to , or NULL if not found - - The Node ID to find - - - - Access the set IGameNodes from the specified IGame Type. - - - You can use this method to retrieve the based on IGameObject::ObjectTypes. IGame must be initialised first, as the node must be in the Database - A of IGameNodes. The developer should check the Count() method to see if any were found - - The to find - - - - Access the from the supplied . - - - You can use this method to retrieve the equivelent IGame must be initialised first, doesn't have to be part of database - A pointer to - - The 3ds - - - - Access the from the supplied . - - - You can use this method to retrieve the equivelent IGame must be initialised first, Texture doesn't have to be part of database - A pointer to - - The 3ds Texture Map - - - - Releases IGame and free all associated memory. - - - This must be called after you have finished with IGame. It makes sure all data is freed and general clean up is performed. Without calling this there is the risk of corrupting memory, and causing incorrect data to returned the next time IGame is run - - - - - A skin wrapper Class. - - - This class provides an unified interface to the various skin options present in 3ds Max. This includes Physique and Skin. All the data from skin and physique are stored in the same way, but options exist to find out what skinning option was used. The vertex indexes used here are the same as those for the actual mesh, so this provides a one to one corelation. - The version of the Character Studio that is used for IGame is 3.2.1 - Anything earlier is unsupported - The bones need to be parsed by IGame before this interface can be used. - - - - - Get the numbers of vertices effected by this instance of the modifier. - - - If the modifier is attached to more than one node, then this will be the count of vertices on the current node - The number of vertices - - - - - Get the numbers of bones effecting the vertex. - - - The number of bones - - The index of the vertex - - - - Get the weight for the bone and vertex index passed in. - - - The weight - - The index of the vertex - The bone index - - - - Get the 3ds Max bone effecting the vertex. - - - A pointer to a 3ds Max for the bone - - The index of the vertex - The bone index - - - - Get the equivalent of the bone effecting the vertex. - - - A pointer to a for the bone - - The index of the vertex - The bone index - - - - Get the ID equivalent of the bone effecting the vertex. - - - The ID can be used if the nodes pass out first and use this value as an index when upon import - A Node ID - - The index of the vertex - The bone index - - - - Get Vertex Type. - - - Specifies whether the Vertex is either Rigid or blended - The vertex type. It can be one of the following - IGAME_RIGID - - IGAME_RIGID_BLENDED - - - The vertex to query - - - - Get the Skinning type. - - - This can be used to find out whether 3ds Max's Skin or Physique was used - The skinning type. It can be one of the following - IGAME_PHYSIQUE - - IGAME_SKIN - - - - - - Get the bone TM when skin was added. - - - This provides access to the intial Bone TM when the skin modifier was applied. - True if the bone was found - - THe bone whose matrix is needed - THe matrix to receive the intial TM - - - - Get the bone TM when skin was added. - - - This provides access to the intial Bone TM when the skin modifier was applied. - True if the bone was found - - The bone whose matrix is needed - The matrix to receive the intial TM - - - - Get the original TM for the node with skin. - - - This provides access to the intial node TM when the skin modifier was applied. - - The matrix to receive the intial TM - - - - Get the number of bones used by the skinning modifiers. - - - This provides the toal number of bones used by the modifiers. This shouldn't be confused with IGameSkin::GetNumberOfBones, which returns the numbers of bones associated with a vertex. - The total number of bones in the system - - - - - Receive the total number of bones used by the skinning system - this will include bones that are not assigned to any vertex. - - - - - Returns the mesh before the skin modifier was added. - - - - - use the usedList to define if you want to the search all the bones or just the bones actually effecting a vertex - - - - - use the usedList to define if you want to the search all the bones or just the bones actually effecting a vertex - - - - - use the usedList to define if you want to the search all the bones or just the bones actually effecting a vertex - - - - - use the usedList to define if you want to the search all the bones or just the bones actually effecting a vertex - - - - - Simple wrapper for Splines. - - - An IGame wrapper around the standard 3ds Max spline object. acts as a container for all the individual splines that make up the object - - - - - Get the number of splines. - - - The number of splines that make up this object - The total number of splines - - - - - Get an individual Spline. - - - Get a spline based on the index. - A pointer to the spline. - - The index of the spline to access - - - - Get the Max object. - - - The used by 3ds Max - - - - - A wrapper class for splines. - - - This provides information about the actual splines making up the spline object in 3ds Max. Access to the knot data is provided with this class - - - - - Access the individual knot. - - - The knot for the index passed in - - - - - The knot count. - - - The total number of knots in the spline - - - - - Base class for "support" objects, such as bone, helpers dummies etc.. - - - These types of objects are really supported for their parameter access. However a pointer to the representation is provided if for example bone geometry is needed. This class can be used to check for BONES, DUMMYS etc.. - - - - - Access to the mesh. - - - If required, access to the mesh is provided - A pointer to an object - - - - - Check for 3ds Max 4.0 version of bone. - - - TRUE if it is an 3ds Max 4.0 bone. - - - - - Simple wrapper for 3ds Max textures. - - - A generic class that wraps all the 3ds Max texture maps. This class directly supports the Texture. This can be tested for by calling IExportEntity::IsEntitySupported. If it is not supported then access to the paramblocks, if defined can be obtained by using the properties interface. The usual texture map properties including coordinate rollout access are provided. - - - - - Get the texture map name as seen in the Editor. - - - The name of the TextureMap as seen in the material editor/material browser. - The name of the texture map - - - - - Get the Texture class as seen in the Editor. - - - The name of the texture class - - - - - Access to the actual 3ds Max definition. - - - This allows the developer to get hold of extra data such as Texture Transforms, specified from the Coordinates rollout. 3ds Max method of GetUVGen or GetXYZGen can be used for more advanced access - A pointer to a max class - - - - - Access to the Coordinate . - - - If the developer needs access to the transforms applied to the texture, then this can be accessed here. - A pointer to - - - - - Get the map channel being used by the texture. - - - The map channel. Valid value is 1..99 - - - - - Get the slot that the bitmap was found in. - - - It uses the standard 3ds Max convention ID_BU for bump etc.. If this is -1 then it means either the hosting material was not a standard material and the channel conversion could not be performed based on the active shader. - The Slot definition. Return -1 for an unsupported material. - - - - - Get the filename of the bitmap used by the Texture. - - - The name of bitmap file - - - - - Get the Clip U Data from a the Texture. - - - A pointer to - - - - - Get the Clip V Data from a the Texture. - - - A pointer to - - - - - Get the Clip H Data from a the Texture. - - - A pointer to - - - - - Get the Clip W Data from a the Texture. - - - A pointer to - - - - - A generic animation key wrapper class. - - - A generic TCB key class for IGame - - - - - Access to basic TCB data. - - - This provides access to the Tension, continuity, bias and easein/out properties of a TCB Key - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_FLOAT specifier - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POS or IGameControlType::IGAME_POINT3 specifiers - - - - - based value. - - - This would be accessed when using the IGameControlType::IGAME_POINT4 specifiers - - - - - Ang Axis based value. - - - This would be accessed when using the IGameControlType::IGAME_ROT specifier - - - - - Scale based value. - - - This would be accessed when using the IGameControlType::IGAME_SCALE specifier - - - - - class IGameBitmapTex - - - An IGame wrapper class for basic Texture access. Properties such as tiling are also provided This is basically a helper class to access some data from the Coordinate panel. All data is extracted from the paramblock, and access is provided by support methods that handle the Property Container Access. This data is used to extract the actual Matrix used. However it can be animated, so using this data the matrix can be recontructed. - - - - - Get the U Offset Data. - - - A pointer to - - - - - Get the V Offset Data. - - - A pointer to - - - - - Get the U Tiling Data. - - - A pointer to - - - - - Get the V Tiling Data. - - - A pointer to - - - - - Get the U Angle Data. - - - A pointer to - - - - - Get the V Angle Data. - - - A pointer to - - - - - Get the W Angle Data. - - - A pointer to - - - - - Get the actual UV transform. - - - The UV transform that is the result of the Coordinate data. - - A representation of the matrix - - - - - An interface for an XRef . - - - - - Retrieve XRef File . - - - The name of XRef File - - - - - Base Class For Geometry Checkers. - - - The class is an abstract base class to be used to create Geometry Checkers GeometryCheckers are basically objects that perform analysis on some which then returns the results as a set of geometric indices. - - - - - Returns the string that should be displayed in the viewport, rather than the default text output. - - - - - Returns true if the geometry checker overrides the normal display otuput, which is usually highlighted vertices, edges, or faces. - - - - - The display override function used to draw a different display output. - - - - The time at which to draw the display - The node that was geometry checked - The window handle of the viewport where the display should get outputted. Usually the active viewport. - The last set of results returned by this checker. This may be helpful when drawing the display override. - - - - Returns whether or not a given node is valid for this geometry checker. - - - Return true if the node is valid, otherwise return false if it is not supported. - - The node that we will test to see if it is supported. - - - - The type that the geometry checker returns. For now we support vertices, edges and polys or tris. - - - Returns the type of geometric entity that the checker will output. May be IGeometryChecker::eVertices, IGeometryChecker::eEdges, or IGeometryChecker::eFaces - - - - - Perform the geometry check. - - - The ReturnVal of the check. If the check fails for some reason the returned value will be IGeometryChecker::eFail otherwise it will be one of the geometric types. - - The time to run the check - The node to run the check on - The output from the check. - - - - Return the name of the geometry checker. Note that geometry checker name's must be unique. - - - - - Returns the unique identifier of the geometry checker. - - - - - Returns true if the geometry checker has a property dialog, false otherwise. - - - - - Show the property dialog. - - - - - The interface to the geometry checker manager. - - - This manager is responsible for registering, activitating and displaying the results of the geometry checkers. You get this interface by calling GetIGeometryCheckerManager() - - - - - Unregister a geometry checker. - - - - The checker you want to unregister. - - - - Returns the number of registered geometry checkers. - - - - - Returns whether or not the geometry checker system is on. - - - - - Get whether or not the results should be seen through objects or not. - - - Return true if the results can be seen through objects, false if not. - - - - - Returns true if automatic updating of the geometry checker is on and false if not. - - - - - Returns true if the text is displayed on top of the viewport, false if displayed on the bottom. - - - - - Gets the number of indices in the current output. - - - - - Returns the output string that's shown as text display. - - - - - Get the nth GeometryChecker. - - - Returns the geometry checker at that index - - The index of the registered geoemtry checker - - - - Get the name of the nth Geometry Checker. - - - The name of the geometry checker at that index - - The index of the registered geoemtry checker - - - - Activate this geometry checker so that it is the one that's run. - - - Returns true if the function correctly sets that checker active, false otherwise. - - The index of the geometry checker that's being made active. - - - - Returns the index of the activated geometry checker. - - - - - Get whether or not the specified geometry checker has a property dialog. - - - Returns true if that geometry checker has a property dialog, false otherwise. - - The index which to check to see if the geometry checker has a dialog. - - - - Show the specified geometry checkers dialog. - - - - The index of the geometry checker that will show it's property dialog. - - - - Run the current geometry check based upon the active geometry checker and the current selection set. - - - - The time at which to run the check. - - - - Run the active geometry checker at this time and on this node. - - - The ReturnVal of the geometry check. May be IGeometryChecker::eVertices, IGeometryChecker::eEdges, or IGeometryChecker::eFaces. - - The time at which to run the check. - The node on which to run the check. - The output of the check. Currently a list of indices. - - - - Show the selection popup menu that lets you pick different checkers to be active and modify different geometry checker manager properties. - - - - - Select the results of the currently run geometry check on the currently selected node. Based upon the ReturnType it will select the correct vertices, edges or faces on that node, in the current active modifier or object. - - - - The time to perform the selection. - - - - Utility function to use the internal display mechanism to display a set of highlighted vertices, edges or faces. - - - - The color that you want the items to be displayed in. - The time you want the node to get queried at for display. - The node over which the display will be drawn over. - The window handle of the viewport where the display should get outputted. Usually the active viewport. - The type of geometric item that will get displayed, may be , , or - The indices of the geometric elements that will get highlighted. - - - - Utility function to get the next valid geometry checker id. New geometry checkers should use this function to get an id. - - - returns a valid geometry checker ID. - - - - - Description: - This class is used to copy and paste gizmo buffers. It is passed to the Gizmo Class which news and instance of its buffer and fills out it ClassID. - Data Members: - cid; - - The Class ID of the gizmo. - - - - - This interface provides the user control over how the viewport shaders are displayed in the viewport. - - - This interface provides the user control over how the viewport shaders are displayed in the viewport. is provided to turn of the display totally and use the original material in the viewport, or to display the shader only on the selected node. The new material options for viewport shaders use this interface to control the system. - Developers can control this themselves using this interface, you simply have to use GetGlobalDXDisplayManager() to get to the actual interface. - - - - - Sets a global overide to turn off display of Dx Shaders in the viewport. - - - - Sets the Force Software flag to true/false. If true default software rendering will be performed - - - - Sets the force display of Dx Effects when an object is selected. - - - Sets the force display of Dx Effects when an object is selected. This only works if SetForceSoftware is set to TRUE - - Turns Force selected to on/off - - - - Gets the state of the Force Software flag. - - - Whether the viewports are using software rendering or not - - - - - Gets the state of the Force Selected falg. - - - Whether hardware rendering of the selected object is active or not - - - - - Queries whether DX is available - useful for UI handlers. - - - Is DX active - if false it could either be OpenGL or Heidi - - - - - Provides methods to turn on DirectX based Scene effects. - - - - - - - Are Dx scene effects active. - - - True if scene effects are active - - - - - Enables of disables Scene effects. - - - - Turn on/off scene effects - - - - Represents a node in the schematic view graph and provides a few methods for querying information about the node. - - - - - - Returns the associated with this node. - - - - - Returns the "primary parent" of this node. Nodes can have multiple parents (objects referencing this node) so this function is not strictly accurate. That said, many nodes have the concept of an owner node, which is what this function returns. - - - - - Returns the "owner" of this node. Some nodes have multiple owners. When this is the case, this function returns the "first" owner (the object that first added this node to the schematic view). - - - - - Returns the ID of this node. When nodes are added to the schematic view (via the IGraphObjectManager::AddAnimatable() method), an integer is provided. This value is not used internally by the schematic view. Rather, it is available to implementers of the Animatable::Sv*() methods to aid in identifying the node. - - - - - Represents an instance of a schematic view window and provides methods for adding nodes and node pointers, refreshing the schematic view, accessing filter bits and updating and controlling the various editors within 3ds Max in ways that are not surfaced in the general interface. - - - - - - Push a level onto the animatable ownership stack. During traversal of the graph via SvTraverseAnimGraph(), this method (along with PopLevel()) should be called appropriately to maintain an ownership stack. This is required by the schematic view when nodes are added to the graph with the SV_DUPLICATE_INSTANCES flag set. Note: In 3ds Max 3.0, SV_DUPLICATE_INSTANCES is always on (i.e., the flag is ignored). Because of this, PushLevel() and PopLevel() should always be called in SvTraverseAnimGraph(). See the sample code in Animatable::SvStdTraverseAnimGraph() for an example of this. - - This is the that you are, in all likelihood, about to add to the graph via the call. - (default to SV_NO_ID) This is also the same "id" you'd pass into . The "id" is only required in cases where it's impossible for the schematic view to distinguish between two (or more) children in the tree that have the same but represent different sub-anims. For example, a box has both its width and height set to the same controller (instanced). In the schematic view, this is still shown in tree form so we need the ID to distinguish between the "width" and "height" children. - - - - Pops a level off the animatable ownership stack. - - - - - Adds an to the schematic view. Note that "owner" and "id" are actually arbitrary - they are used to provide context for this . This means that the plug-in developer can set them to any value. They are not used internally by the schematic view except in the "Sv*" methods (which the developer can override). So, when you add an to the schematic view, you would typically add the owner (parent) as well as the sub-anim id. This allows you to, for example, easily return the name of the object when queried by the SvGetName() call (whose default implementation is shown below): - A object. - - Points to the animatable to add. - Points to the owner of "anim" above (typically). - When nodes are added to the schematic view via this method this integer is provided. This value is not used internally by the schematic view. Rather, it is available to implementers of the Animatable::Sv*() methods to aid in identifying the node. - This flag is some combination of the bit flags in - - - - This method adds a reference from the specified "maker" node to the specified "target" node. - A pointer to an object. - Sample Code: - - Points to the 'maker' node in schematic view. - Points to the 'target' node in schematic view. - One of the following enum values: - - - - This method adds a relationship from the specified "maker" node to the specified "target" node. - A pointer to an object. - - Points to the 'maker' node in schematic view. - Points to the 'target' node in schematic view. - An arbitrary ID that the can use later to identify itself. - the type of the relationship - - - - Pops up the property editor dialog on the selected nodes in the schematic view. - - - - - Selects the given node in the material editor. Does nothing if "gNode" does not represent a material or map. - - Points to the node in schematic view. - - - - Selects the given node in the modifier panel. Does nothing if "gNode" does not represent an object. - - Points to the node in schematic view. - - - - Returns true if the given node is current in the modifier panel - - - - - Invokes the copy/instance controller dialog within schematic view. The controller referenced by gSrcNode will be either copied or instanced into gDestNode. This is typically called from within a link callback: - true if the controller is successfully applied, false if not. - - The node that supplies the controller to apply. - The node to apply the controller to. - - - - Invalidates the schematic view window. - - - - - Invalidates a node in the schematic view window. - - - Points to the node in schematic view. - - - - Forces the material editor to update. - - - - - Forces the modifier panel to update. - - - - - Sets the specified filter bits. - - See - - - - Clears the specified filter bits. - - See - - - - Tets the specified filter bits. Returns true if set; otherwise false. - - See - - - - Get a SV UI color given a color index. - - - - - Get HWnd for Schematic window. - - - - - Represents a node pointer and currently has no methods. - - - - - The interface to the functionality for using the Grip Manager. - - - This class contains key functionality for using grips. It contains functionality for setting which grip is active in addition to various options for how grips are displayed and manipulated. You get this interface by calling GetIGripManager(). This class is created by the system. - - - - - Make the grip active and show it. - - The grip that will turn active and have its displayed. If another grip was active, that grip becomes inactive. Only one grip may be active at a time. If the value is NULL this functions acts like SetGripsInactive. - - - - Inactivate the current active grip. If no grip is active, nothing happens. - - - - - Get the current active grip. - Returns the current active grip. If no grip is active, returns NULL. - - - - - whether or not a particular grip item of the active grip will be activated or not. By default, all grip items are activated and interactive. - true if the operation succeeded, false otherwise. - - The zero based index for the item for which we will be activate or not. If out of range of the number of grip items, on the active grip this function will do nothing. - If true the item is active and can get manipulated, if false, the item is disabled and greyed out in the viewport. - - - - Get whether or not a particular grip item of the active grip is active or not. - Returns true if the item is active, false if the item is not and it's been disabled. If the whichItem parameter is out of range or no grip is active then this function will return false. - - The zero based index for the item for which we are checking to see if it's active or not. - - - - whether or not a particular grip item of the active grip will be visible or not. By default, all grip items are visible. - true if the operation succeeded, false otherwise. - - The zero based index for the item for which we will display or hide. If out of range of the number of grip items, on the active grip this function will do nothing. - If true the item is hidden and is not displayed, if false, the item is displayed. Note that by default all grip items are visible. Note in order to see the change in the , you must call ResetAllGripUI(). - - - - Get whether or not a particular grip item of the active grip is visible or not. - Returns true if the item is visible, false if the item is not. If the whichItem parameter is out of range or no grip is active then this function will return false. - - The zero based index for the item for which we are checking to see if it's visible. - - - - Tell that grip item it should reset its UI, usually since some value has changed and needs to get refleced in the UI. When called that item will call the necessary functions, such as GetValue, to reset and recreate the UI, - Returns true if the item is active, false if the item is not. If the whichItem parameter is out of range or no grip is active then this function will do nothing and return false. - - The zero based index for the item for which needs to reset its . - - - - Convienence function to reset all of a grip's UI. Resetting the UI will cause the system to get the various values from each grip item. - - - - - Get if grips are shown. - If true grips will be shown,if false no grips will be shown even if active. - - - - - Get the location of the grip in screen space. - - The x location of the grip in screen space. - The y location of the grip in screen space. - - - - the location of the grip in screen space. - - The x location of the grip in screen space that you want the grip's upper right corner to be placed. - The y location of the grip in screen space that you want the grip's upper right corner to be placed. - - - - Get whether or not the grip stays centered around the current selection gizmo. return If true the grip stays centered around the current selection gizmo, if false the grip stays fixed at it's current viewport location. - - - - - the normalized x and y location of the grip in the active viewport. These values are used if GetCenterOnSelection returns false. - - The normalized [0-1] x location of the grip in the active viewport. So a value of 0.5 will place the grip in the center of viewport. - The normalized [0-1] y location of the grip in the active viewport. So a value of 0.5 will place the grip in the center of viewport. - - - - Get the normalized y location of the grip in the active viewport. These values are used if GetCenterOnSelection returns false. - The normalized [0-1] y location of the grip in the active viewport. So a value of 0.5 will place the grip in the center of viewport. - - - - - Get the normalized x location of the grip in the active viewport. These values are used if GetCenterOnSelection returns false. - The normalized [0-1] x location of the grip in the active viewport. So a value of 0.5 will place the grip in the center of viewport. - - - - - the x and y pixel offset from the current selection gizmo where the grip will get placed. These values are used if GetCenterOnSelection returns true. - - The x pixel offset off of the current selection where the grip will get placed. - The y pixel offset off of the current selection where the grip will get placed. - - - - Get the x pixel offset from the current selection gizmo where the grip will get placed. These values are used if GetCenterOnSelection returns true. - The x pixel offset off of the current selection where the grip will get placed. - - - - - Get the y pixel offset from the current selection gizmo where the grip will get placed. These values are used if GetCenterOnSelection returns true. - The y pixel offset off of the current selection where the grip will get placed. - - - - - Get the transparency of the grip items in the viewport. - Returns the transparency of the grip items in the viewport. Range is from 0, opaque to 1, fully transparent. - - - - - Get the hover transparency of the grip items in the viewport. - Returns the transparency of the grip items in the viewport. Range is from 0, opaque to 1, fully transparent. - - - - - Get the spacing in pixels between the main grip UI elements. - Returns the pacing in pixels between the main grip UI elements. - - - - - Register a callback that will get called when the active grip changes. - - - - - The callback that you are registering. If NULL this function does nothing. - - - - Unregister the grip changed ballback. - - - - - The callback that you are unregistering. If NULL or the callback is not registered this function does nothing.\ - - - - to recalculate the layout and position of all of the grip items. This usually just needs to get called by the system due to the fact that a window was moved or it's size changed or the selection changed. - - - - - Description: - This class is only available in release 5 or later. - - A pointer to this class is provided by IDXDataBridge::SetDXData(). The GFX layer will implement all these methods. Most of the methods are direct replicas of the DirectX API for SetRenderState and SetTextureStageState. - - The reason for this is that only one thread can access the graphics hardware at any one time. Using this interface means that the GFX driver can have its database initialized with the DirectX states required for this object, when it comes to access the graphics device. - - To use this class good knowledge of DirectX is needed, a copy of the DirectX documentation is also recommended. - - For an example usage of this class see MAXSDK/SAMPLES/HardwareShaders/LightMap/Lightmap.cpp - - - - - - - This is equivalent to the DirectX method SetRenderState(FILLMODE,mode) - - - Parameters: - DWORD mode - - A member of D3DFILLMODE - - - - - - - This is equivalent to DirectX method SetRenderState(SHADEMODE,mode) - - - Parameters: - DWORD mode - - A member of D3DSHADEMODE - - - - - - - Allows the Diffuse color to be set - - - Parameters: - c - - The diffuse color - - float alpha - - The colors alpha - - - - - - - Allows the Diffuse color to be set - - - Parameters: - c - - The diffuse color - - float alpha - - The colors alpha - - - - - Allows the Ambient color to be set - Parameters: - c - - The ambient color - - float alpha - - The colors alpha - - - - - - - Allows the Ambient color to set - Parameters: - c - - The ambient color - - float alpha - - The colors alpha - - - - - - - Allows the Specular color to be set - Parameters: - c - - The specular color - - float alpha - - The colors alpha - - - - - - - Allows the Specular color to set - Parameters: - c - - The specular color - - float alpha - - The colors alpha - - - - - - - Allows the Emissive color to be set - - - Parameters: - c - - The emissive color - - float alpha - - The colors alpha - - - - - - - Allows the Emissive color to be set - - - Parameters: - c - - The emissive color - - float alpha - - The colors alpha - - - - - - - Allows the specular exponent of the material to be set - Parameters: - float power - - The specular amount - - - - - - - This sets the internal size for the table that will hold the Texture information for the material. If you are not using any Texture stages then this should be set to zero, otherwise it should match exactly the number of textures being used. - Parameters: - DWORD numStages - - The number of Texture stages - - - - - This allows a texture to be loaded to the graphics device. In this case the texture is loaded/created by the GFX via calls to IHardwareRenderer::BuildTexture() which will return a DWORD_PTR, which is an internal representation of the texture. The texture was allocated it will return true. - - - Parameters: - DWORD stage - - The stage to hold the texture - - DWORD_PTR pTexture - - A texture pointer returned by IHardwareRenderer::BuildTexture() - - - - - - - This allows a texture to be loaded to the graphics device. The file is assumed to exist. If successful it will return true. - Parameters: - DWORD stage - - The stage to hold the texture - - LPCSTR filename - - A string containing the filename of the texture to load - - - - - - - This allows a texture to be loaded to the graphics device. In this case the texture is loaded/created by the GFX via calls to IHardwareRenderer::BuildTexture() which will return a DWORD_PTR, which is an internal representation of the texture. The texture was allocated it will return true. - - NOTE:If you want to take advantage of the new viewport display mechanism ,you should pass a valid MapUsageType other than MAPUSAGE_UNDEFINED for stage 0. Otherwise, it will use the old display mechanism. - TRUE if successful, FALSE otherwise. - - - The stage to hold the texture - - A texture pointer returned by - - A enum type that tell the rendering system the usage of the texture - - - - This method allows a texture to be loaded to the graphics device. - The file is assumed to exist. If successful it will return true. NOTE:If you want to take advantage of the new viewport display mechanism ,you should pass a valid MapUsageType other than MAPUSAGE_UNDEFINED for stage 0. Otherwise, it will use the old display mechanism. - - - TRUE if successful, FALSE otherwise. - - - The stage to hold the texture - - A string containing the filename of the texture to load - - A enum type that tell the rendering system the usage of this texture - - - - This specifies where the Texture Coordinates will be retrieved. Most of the time the mesh will supply them so the type would be UVSOURCE_HWGEN. However a Viewport could create them dynamically so would supply. If successful it will return true. - Parameters: - DWORD stage - - The stage to set - - DWORD type - - The UVW Source. It can be any of the following :- - - UVSOURCE_MESH - - UVSOURCE_XYZ - - UVSOURCE_MESH2 - - UVSOURCE_WORLDXYZ - - UVSOURCE_FACEMAP - - UVSOURCE_HWGEN - - - - - - - This specifies what mapping channel from the mesh the Texture Coordinates will be retrieved. This is used in the stripping code so that the is populated with the correct TVs. If successful it will return true. - Parameters: - DWORD stage - - The stage to set - - DWORD type - - The mapping channel to use - - - - - This specifies what texture coordinate the stage will use. This value is used in the DirectX call SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, index). If successful it will return true. - Parameters: - DWORD stage - - The stage to set - - DWORD index - - The texture coordinate index to use - - - - - This specifies what texture flag the stage will use. This value is used in the DirectX call SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, flag). If successful it will return true. - Parameters: - DWORD stage - - The stage to set - - DWORD flag - - The DirectX flag to set - - - - - This method is a direct replica if the DirectX color operators used with D3DTSS_COLOROP. Please refer to the DirectX documentation for further information - Parameters: - DWORD stage - - The stage to set - - DWORD colorOp - - A member of the DirectX enumerated type D3DTEXTUREOP - - - - - - - This method is a direct replica if the DirectX Texture Argument flag used with D3DTSS_COLOROPARG. The argNum defines which argument to set. Please refer to the DirectX documentation for further information - Parameters: - DWORD stage - - The stage to set - - DWORD argNum - - The argument index to set. If this is set to 1 then D3DTSS_COLORPARG1 will be addressed - - DWORD colorArg - - The Argument to set. - - - - - - - This method is a direct replica if the DirectX alpha blending operators used with D3DTSS_ALPHAOP. Please refer to the DirectX documentation for further information - Parameters: - DWORD stage - - The stage to set - - DWORD alphaArg - - A member of the DirectX enumerated type D3DTEXTUREOP - - - - - This method is a direct replica if the DirectX Texture Alpha Argument flag used with D3DTSS_APLHAPARG. The argNum defines which argument to set. Please refer to the DirectX documentation for further information - Parameters: - DWORD stage - - The stage to set - - DWORD argNum - - The alpha argument index to set. If this is set to 1 then D3DTSS_ALPHAARG1 will be addressed - - DWORD colorArg - - The Alpha Argument to set. - - - - - This method allows a DirectX vertex shader to be loaded. It is used in conjunction with IHardwareRenderer::LoadVertexShader which will return a DWORD_PTR of internal storage for the shader. There are methods in Class that provide a means to supply the constants used in the shader. - - - Parameters: - DWORD_PTR pVertexShader - - The vertex shader to load. - - - - - - - This method allows a DirectX pixel shader to be loaded. It is used in conjunction with IHardwareRenderer::LoadPixelShader which will return a DWORD_PTR of internal storage for the shader. There are methods Class that provide a means to supply the constants used in the shader. - - - Parameters: - DWORD_PTR pPixelShader - - The vertex shader to load - - - - - This method allows a DirectX effect. It is used in conjunction with IHardwareRenderer::LoadEffectFile which will return a DWORD_PTR of internal storage for the file. There are methods in Class that provide a means to connect the application to the effects file. - - - Parameters: - DWORD_PTR pEffect - - The effect file to load - - - - - This method sets color used for multiple-texture blending with the D3DTA_TFACTOR - - texture-blending argument or the D3DTOP_BLENDFACTORALPHA texture-blending operation. - - - Parameters: - DWORD factor - - "factor" is a D3DCOLOR variable. The default value is opaque white(0xFFFFFFFF). - - - - - This method sets the specular level. - This method sets the specular level value. The specular level information is used - to adjust the specular color when viewport is in best quality mode. - NOTE:If specular level map exists, this value will be ignored. - - - - - The specular level value. - - - - Extension of . This class extends the functionality of . To acquire this interface, simply call GetInterface(IHARDWARE_MATERIAL2_INTERFACE_ID). If failed, it will return NULL. - - - - - This method sets the self illumination mode. - - - - - If FALSE, the SelfIllumColor is off.Otherwise, the SelfIllumColor is on. - - - - Extension of . This class extends the functionality of . To acquire this interface, simply call GetInterface(IHARDWARE_MATERIAL3_INTERFACE_ID). If failed, it will return NULL. - - - - - This method sets the border color for the specified stage. - - - true if successful, otherwise false - - - The sampler stage whose border color you want to set - - The border color value - - - - Description: - This class is only available in release 5 or later. - - This interface provides access to the DirectX interfaces on the drawing thread of Max. This allows creation and loading of various DirectX objects such as Textures. This class has many interfaces not currently implemented, although they will compile and link correctly. This is due to support for DirectX 9, meaning that when a compatible driver is released these methods will be implemented. The documentation for this class only deals with methods that developers can and would normally use. - - The basic idea of this class is to provide the developer with access to the DirectX device without actually giving the developer total control, and thus possibility to de-stable the 3ds Max Viewports. - - A pointer to this class can be obtained with the following code snippet: For an example usage of this class see MAXSDK/SAMPLES/HardwareShaders/LightMap/Lightmap.cpp - - - - - This simple loads a texture from the supplied filename using the default options for D3DXCreateTextureFromFile. Please refer to the DirectX documentation for further information. - - - - - This tells the mesh / mnmesh classes whether a shader has performed the drawing already so it can simply ignore the draw call. - - - When a shader draws an object, in certain situations 3ds Max will also try to draw the object. This can produce a "double draw" situation. This method used to query if the object has been drawn by the shader already. If it has you can simply ignore your drawing code. However if you draw any support objects or subobject data, these can still be drawn, you simply want to avoid drawing the actual triangles of the object. - true if the object has already been drawn, false if not. - - - - - This method lets you update the vertex positions of the DirectX mesh cache. - - - This allow you to keep the DirectX mesh cache around without having to delete it on geometric changes. - - this is the handle of the DirectX mesh - this is a pointer to an array containing the new vertex positions - this is a pointer to an array containing the new vertex normals. This is the gfxnormals, ie the flattened list of the render normals - this is a pointer to an array containing the new face normals. This is to handle face with no smoothing group which default to the face normal instead of the render normals - this is a bitarray that marks all the vertices that have changed. This lets us know which sectors of the mesh we don;t have to change thus making the operation faster - this is the number of vertices in the vertexList - - - - This interface gives access to the HeightManager. The HeightManager has a list of heights for Metric, Imperial and Custom Units. All methods work on the currently selected display unit type If is selected, the System unit will be considered in regards to which height-list to use. All Heights are stored in the 3dsmax.ini/3dsviz.ini file. - - - - - Brings up a dialog, letting the user customize (add, delete, set current) the heights. - - - - - Gets the height for the given index - height for the given index - - - Index to get the height for. - - - - Gets the height, respecting the current unit setting in string form - height, respecting the current unit setting in string form - - - Index to get the height for. - - - - Gets the index of the current height - index of the current height. If no height is active, return value is -1 - - - - - Gets the number of heights - number of heights - - - - - this is the interface to use illumination by components this may be supported by a light object returned by lightObjDesc::GetInterface( IID_IIlluminationComponents ); - - - - - Description: - This class represents an abstract interface class for an image viewer. - - - - - This method will show the image viewer. In the class, the Display() method must initially be used to display the viewer; this method only displays the viewer after using Hide(). - - - - - This method will hide the image viewer. In the class, the UnDisplay() method should be used to close the viewer when done; use Hide() to temporarily hide the window. - - - - - This method returns the handle to the display window of the image viewer. - - - - - This method allows you to set the position of the image viewer window. - Parameters: - int x, y - - The position of the window. - - int w, h - - The width and height of the window. - - - - - This method will return the display style used by the image viewer window, which is either IV_FLOATING or IV_DOCKED. - - - - - This method returns the context help identifier. - - - - - This method returns a pointer to the pre-event handler callback function. - - - - - This method returns a pointer to the post display callback function. - - - - - This method provides a way to extend the class with interfaces. - Parameters: - id - - The interface ID. - Default Implementation: - { return NULL; } - - - - - The interface for an object to specify the ReferenceTargets it is dependent on, but doesn't hold a reference to (i.e., indirect references). - - - The owner of a RefTargMonitorRefMaker-like instance would implement this interface to cause the ReferenceTargets it is dependent on, but doesn't hold a reference to, to be saved when the owner is saved, and loaded when the owner is loaded. When the scene is loaded, SetIndirectReference is called to set the indirect reference. - Indirect references should typically implemented as weak references. Otherwise, if ref A holds a normal reference to B, and B holds an indirect reference to A, A would never be deleted because there is always at least one strong reference to it. - For an example, see the NodeTransformMonitor class in maxsdk\samples\controllers\nodetransformmonitor.cpp. - - - - - The number of indirect references. - - - The number of indirect references. - - - - - Retrieve the indexed indirect reference. - - - The reference handle of the 'i-th' indirect reference. - - - The virtual array index of the indirect reference to get. - - - - the indexed indirect reference. - - - - - The virtual array index of the indirect reference to set. - - The indirect reference. - - - - Specifies remapping of indirect references on load. - - - This method is used when you have modified a to add or delete indirect references, and are loading old files. This method is called during the reference mapping process, after the Load() method is called. You determine what version is loading in the Load(), and store the version in a variable which you can look at in RemapIndirectRefOnLoad() to determine how to remap indirect references. The default implementation of this method just returns the same value it is passed, so you don't need to implement it unless you have added or deleted indirect references from your class. - - The output index of the indirect reference. - - - The input index of the indirect reference. - - - - Specifies whether an indirect reference is persisted on a partial load or save. - - - This method specifies the partial load/save behavior of an indirect reference. If this method returns true, and the ref maker implementing this interface is loaded/saved, the indirect reference will be forced to be loaded/saved. If false, the indirect reference will not be forced to be loaded/saved, but will be hooked back up if it is loaded. - Since indirect references are typically implemented as weak references, the default implementation of this method is to return false. Typical cases where an implementation of this method would return true is if the indirect reference is to a node (such as in NodeTransformMonitor) or postload callbacks are used to check and process the indirect reference. - Whether to force the load/save of the indirect reference if the implementing reference maker is saved. - - - The indirect reference. - - - - The interface for a container of indirect references. - - - - - Manages instances of objects, modifiers, transformation controllers Use this interface to work with object instances in a Max scene. There are several criteria based on which two or more objects must be considered instances of each other. This interface abstracts the details of dealing with them and thus help client code focus on the specific tasks it needs to perform on object instances, rather than on the logic of finding them. Two or more objects are considered instances of each other if: - - - - - - - Retrieves state of automatic material propagation flag. - - - true if automatic material propagation is On, false otherwise. - - - - - Sets automatic material propagation flag. - - - The previous state of the automatic material propagation flag. - - pass true to turn On automatic material propagation, false otherwise. - - - - Determines whether the given objects can be made unique. - - - true if at least one object can be made unique. - - The nodes representing the objects to be made unique. - - - - Makes the given objects unique. - - - true if at least one object was made unique - - The nodes representing the objects to be made unique. - Specifies the to use when making objects unique. - - - - Determines whether the given modifiers can be made unique. - - - true if at least one modifier can be made unique. - - The nodes the modifiers are being applied to. - The modifiers to be made unique. - - - - Makes the given modifiers unique. - - - true if at least one modifier was made unique - - The nodes the modifiers are applied to. - The modifiers to be made unique. - Specifies the to use when making modifiers unique. - - - - Determines whether the given transform controllers can be made unique. - - - true if at least one controller can be made unique. - - The nodes the controller are applied to. - The controllers to be made unique. - - - - Makes the given transform controllers unique. - - - true if at least one controller was made unique - - The nodes the controllers are applied to. - The controllers to be made unique. - Specifies the to use when making controllers unique. - - - - Saves instance manager state. This method is called by the system. - - - - - Loads instance manager state. This method is called by the system. - - - - - Retrieves instances and references of an object. Instances of styles and blocks are collected only if and interfaces are available. - - - The number of instances found. There's always at least 1 instance found - - The node of the object whose instances are to be retrieved. For an object with multiple instances, any of the nodes representing an instance can be specified here as a parameter. - of nodes representing the instances of source The collection is cleared before this method starts filling it in. The source node is also included in this collection since every object can be thought of as having at least one instance. - - - - Sets the provided material on all instances of a given object. - - - The number of instances found. - - The node of the object whose instances should be set up with the specified material. For an object with multiple instances, any of the nodes representing an instance can be specified as this parameter. - The material to be set. If NULL, all instances of the source object will have their materials removed. - - - - Description: - This is the abstract class () for a a renderer supporting interactive rendering. - - With the likelihood of evolving rendering and shading techniques which are going to be markedly different from what is being used now, the 3ds Max SDK provides the infrastructure to support interactive rendering. Since renderers are a plugin to 3ds Max and since each renderer has a different set of resources and capabilities the interactive rendering and shading API has been made as general and independent as possible. The independence of the renderer also means that the renderer must do a fair amount of work that could be done by the system for all renderers. - - Interactive rendering and shading is a separate interface which can be optionally supported by 3rd party renderers and can be obtained by using the GetIInteractiveRender() method on the renderer. The renderer returns a pointer to a class instance if it supports interactive rendering, otherwise the default implementation will return NULL, indicating that interactive rendering is not supported. - - As it is, interactive renderers will reference any and all objects, as well as lights and materials in the scene that they can respond to changes from. Via the normal 3ds Max notification system the interactive shader will then receive messages whenever one of these referenced objects changes and it must then decide how best to update the scene for the user. - - - - - This method initiates the interactive rendering and will reference objects in the scene so the renderer receives the proper change notifications. The interactive renderer will automatically update the scene when these changes are received. - - This is called when the user first invokes interactive rendering. During the begin session call, the renderer should reference any object in the scene that it can respond to changes from. There are reference manager classes in the SDK to ease this referencing in the file referenceManager.h. many of the parameters of interactive reshading are set up prior to the call to BeginSession(), here is a code snippet from the interactive rendering manager: - - mIRenderInterface->SetOwnerWnd(mpIMaxBitmapViewer->GetHDisplayWindow()); - - mIRenderInterface->SetIIRenderMgr(this); - - GetBitmap()); - - mIRenderInterface->SetSceneINode(mpInterface->GetRootNode()); - - mIRenderInterface->SetUseViewINode(false); - - mIRenderInterface->SetViewINode(NULL); - - mIRenderInterface->SetViewExp(mpViewExp); - - mIRenderInterface->SetRegion(mSelectedRegion); - - mIRenderInterface->SetDefaultLights(mDefaultLights, mNumDefaultLights); - - mIRenderInterface->SetProgressCallback( - - *>(&mImageViewerCB) - - ); - - BeginSession(); - - Consequently, BeginSession() can rely on all these local attributes being valid. - - - - - This method will end an interactive rendering session and will remove all references placed on the scene. - - - - - This method allows you to retrieve the owner window. - - - - - This method sets a pointer to the controlling renderMgr, so that various states can be queried. - Parameters: - *pIIRenderMgr - - A pointer to the controlling interactive rendering manager. - - - - - This method allows you to retrieve a pointer to the controlling interactive render manager - Parameters: - *pIIRenderMgr - - A pointer to the render manager interface. - - Used internally. This should always be set to NULL. - - - - - This method allows you to set the destination bitmap to be rendered and re-rendered to. This destination bitmap is persistent between update renderings, basically the renderer holds the bitmap and updates the screen while the manager holds the reference to the bitmap and controls its lifetime. - Parameters: - *pDestBitmap - - A pointer to the destination bitmap to set. - - - - - This method allows you to retrieve the destination bitmap that's being redered and re-rendered to. - Parameters: - *pDestBitmap - - A pointer to the destination bitmap. - - Used internally. This should always be set to NULL. - - - - - This method returns a pointer to the scene's root node. - - - - - This method returns FALSE if the obtained from should be used. TRUE would indicate that this is not the case. - - - - - This method returns a pointer to the view node if this is used instead of . - - - - - This method returns a pointer to the which is used for the view specification for docked windows. - - - - - This method returns the region of the bitmap to be rendered. Note that if Box2::IsEmpty() returns TRUE, it indicates to render entire bitmap. - - - - - This method allows you to set the default lights to be used in absence of scene lights. These lights will be used when no user specified lights are in the scene. This should be noted when the scene is traversed in begin session, and of course altered if new user lights are created. - Parameters: - *pDefLights - - A pointer to a default light source. - - int numDefLights - - The number of default lights. - - - - - This method returns a pointer to the default lights and the number of default lights which are used in absence of scene lights. - Parameters: - int &numDefLights - - The number of default lights returned. - - - - - This method returns a pointer to the interactive rendering progress callback object. - - - - - This method renders the bitmap using default non-interactive rendering functionality. This is the only actual command to the interactive renderer. - Parameters: - *pDestBitmap - - The destination bitmap to render to. - - - - - This method returns the closest node handle for a given bitmap pixel location. This can be implemented with an item buffer, by using ray casting, or some other method and allows the interactive rendering manager to implement object selection. - Parameters: - int x, int y - - The x and y coordinate of the bitmap pixel. - The node handle or 0 if there is no node. - - - - - This method returns the screen bounding box of the corresponding , so the selection box corners can be drawn. - Parameters: - & sBBox - - The screen bounding box. - - *pINode - - The for which you wish to retrieve the screen bounding box. - TRUE if successful, otherwise FALSE. - - - - - This method returns the ActionTableId for any action items the renderer may implement. This method will return 0 if none are available. Action tables are used as context sensitive command system to generate quad menus and the like from the various objects in the scene. - - - - - This method returns a pointer to an for any action items the renderer may implement. This method will return NULL if none are available. - - - - - This method provides a general extension mechanism, access to additional method interfaces. - Default Implementation: - { return NULL; } - - - - - This method returns TRUE if the renderer is currently rendering, otherwise FALSE. - - When the interactive rendering manager gets a message to shut down or abort an interactive rendering, there is a potential race condition between the interactive renderer shutting down and the shutting down of the manager itself, which deletes the renderer. Since it is the renderer itself that decides when, what and how to re-render the image, it's not clear to the manager whether a delete is safe. This method allows the manager to inquire whether the renderer is recomputing the image. To abort a rendering, the progress/abort callback must be used. When the abort is complete, IsRendering will return FALSE. - - - - - This method returns TRUE if the renderer has not applied all pending scene updates yet, or FALSE if there are no updates pending and what is currently rendering or has been rendered is matching what the scene looks like. - - If the interactive renderer has the concept of an update queue, it can return its state here. This function is used by the GetActiveShadeBitmap wait:true MaxScript function to be certain that the image being rendered is final and the complete state of the rendering. The function waits until IsRendering() AND AnyUpdatesPending() return false, and then grabs the image. - Default Implementation: - { return FALSE; } - - - - - This method is called to abort the render operation. The implementation should stop the rendering process as quickly as possible and return only once the render has actually stopped rendering. - - - - - Factory for the Particle Flow creation from a OneClick plugin. This interface is implemented by 3ds Max. - - - - - Sets a new file path to the nCache file to be read by the File Birth object. - - - true if we could set the property, false otherwise. - - The File Birth node that will receive the new file path (new nCache). - The path of the nCache file that will be connected to this construct. - - - - Factory interface for the Particle Flow creation from a plugin. This is used to simplify the use of nCaches in 3ds Max when coming from Softimage XSI. This interface is implemented by 3ds Max. - - - - - Creates and adds to the scene a default ICE Flow particle structure. - - - It is mandatory to have in the nCache files the following attributes : position, id, color, size, and mass - the created - - The name of the instance to create. This name is usually coming from the Manifest from the Delegate. - The path of the nCache file that will be connected to this construct. - - - - Shape interface to change the shape of a given particle system. This is used to change the shape type of the shape action object from the particle flow simulation engine with the shape type coming from the nCache particle files generated from Softimage. This interface is implemented by 3ds Max. - - - - - Sets the shape type into the specified object. - - - 0 if the shape was changed - 1 if the shape was not changed (the same) - 2 if the shape is not support and defaulted to point - - the shape object whose shape will be changed - the number of the shape as specified in the nCache file. - - - - Description: - This class is only available in release 5 or later. - - The interface class to TM controller that the IK chain node employs. Suppose node is an IK chain node, following code obtains the interface pointer: - - From this pointer, we can get all properties pertinent to an IK Chain. - - - - - - - The start joint, end joint of the chain, and the node to that this IK chain controller belongs. - - - - - - - Please refer to StartJoint(). - - - - - - - Please refer to StartJoint(). - - - - - - - Preferred angles are used to start the IK iteration. Hence, the pose when joint angles assume the preferred angles is also called the Initial Pose in the context of IK. It is animatable, meaning that at different time, IK may start iteration from different poses. - - Let's call the plane that the joints of an IK chain the (IK) solver plane. InitPlane() and InitEEAxis() returns the normal to the solver plane and the axis from the start joint to the end joint (end-effector axis) at the initial (preferred angle) pose, at time of input argument. They are represented in the parent space of the start joint. ChainNormal() returns the normal in the object space, as - - InitPlane() * startIKCont->PrefRotation() - - where - - StartJoint()->GetController()->GetInterface(I_IKControl); - - Furthermore, ChainNormal() takes as an input argument a validity interval that will be intersected by the validity interval of the chain normal. - - - - - - - Please refer to ChainNormal(). - - - - - Please refer to ChainNormal(). - - - - - Please refer to ChainNormal(). - - - - - The swivel angle at time. The validity interval, valid, will be intersected. - - - - - - - The zero plane is the plane that, at each "start joint to end joint" axis, is used as a reference plane with regard to that the swivel angle is defined. The zero plane map maps an axis to a plane normal. The IK system offers as a possible default via DefaultZeroPlaneMap(). - - - - - - - Whether the zero plane is defined in the parent space of the start joint, kSAInStartJoint, or in the space of the IK goal, kSAInGoal. - - - - - - - The solver that is assigned to this chain. - - - - - - - Whether the solver is enabled (IK mode) or not (FK mode). - - - - - - - When the chain is in the FK mode, IK can still be invoked when the goal is moved interactively if CanAutoEnabled() is true. It is a PB2 parameter of index kAutoEnable. It is not animatable. - - - - - - - It is a transient state that is alive only at the time when joint angles are to be updated. Being true means that the Enabled state of the chain is off the IK is turned on by interactive manipulation. - - - - - - - Whether this chain is a valid one. It is valid if it is assigned a proper IK solver and it has valid start joint and end joint. - - - - - - - What IK goal interface this chain is prepaired for. For now, there are two interfaces: HI IK goal (IHIIKGoal) and Spline IK goal (ISplineIKGoal). An IK chain will admit of plugin solvers that support this goal interface (IKSolver::ExpectGoal()). - - - - - - - It returns an interface to the goal at the time. Validity interval is reconciled. The parent matrix of the start joint is also returned in the third argument. - - - - - Description: - This class represents the TM controller for IK Chains and is used for nodes that serve as IK joints. This class is closely knit together with the Class and form the IK system. An interface pointer to the IKControl class can be obtained by using Animatable::GetInterface(I_IKCONTROL). See the Inverse Kinematics section for more detailed information. - - - - - This method allows you to determine which degrees of freedom are active and inactive for the translational and rotational axes. - Parameters: - DofAxis - - The DOF axis to check, which is one of the following IKSys::TransX, . - TRUE if the specified DOF axis is active, otherwise FALSE. - - - - - This method allows you to determine which degrees of freedom are active and inactive for the translational axes. The returned DofSet can be tested for IKSys::DofX, and IKSys::DofX. - A DofSet structure containing the translational axes. - - - - - This method allows you to determine which degrees of freedom are active and inactive for the rotational axes. The returned DofSet can be tested for IKSys::DofX, and IKSys::DofX. - A DofSet structure containing the translational axes. - - - - - This method allows you to determine which degrees of freedom are active and inactive for the translational and rotational axes. The returned DofSet can be tested for IKSys::TransX, . - A DofSet structure containing the translational and rotational axes. - - - - - This method returns a list of IK Chain nodes. Note that nn IK chain starts at the rotational joint of the Start Joint and ends at the sliding joint of the End Joint. - Parameters: - JointType - - The joint type, either IKSys::SlidingJoint or IKSys::RotationalJoint. - The node table of IK Chain nodes. - - - - - This method allows you to check if a specific DOF axis has its lower bounds limited. - Parameters: - DofAxis - - The DOF axis to check, which is one of the following IKSys::TransX, . - TRUE if limited, otherwise FALSE. - - - - - This method allows you to check if a specific DOF axis has its upper bounds limited. - Parameters: - DofAxis - - The DOF axis to check, which is one of the following IKSys::TransX, . - TRUE if limited, otherwise FALSE. - - - - - This method allows you to check if a specific DOF axis has its upper and lower bounds limited. - Parameters: - DofAxis - - The DOF axis to check, which is one of the following IKSys::TransX, . - A where X and Y are the lower and upper limits, respectively. - - - - - This method allows you to retrieve the translation lower limits. - A where X, Y, and Z represents the actual limits. - - - - - This method allows you to retrieve the translation upper limits. - A where X, Y, and Z represents the actual limits. - - - - - This method allows you to retrieve the rotational lower limits. - A where X, Y, and Z represents the actual limits. - - - - - This method allows you to retrieve the rotational upper limits. - A where X, Y, and Z represents the actual limits. - - - - - The parameter that decides whether an individual degree of freedom is active is not animatable. There is an animatable variable of IK chain that decides whether the goal defined in the IK chain actually affects the joints it covers at a specific time. This method allows you to query that. - Parameters: - TimeValue t - - The time at which to test the joint type. - - JointType jt - - The joint type, either IKSys::SlidingJoint or IKSys::RotationalJoint. - TRUE if bound, otherwise FALSE. - - - - - This method allows you to obtain a pointer to the Forward Kinematics sub-controller. Note that the IK controller is not designed to be instanced. It is expected to have a unique node. - - - - - This method allows you to obtain a pointer to the node that holds the Forward Kinematics TM controller. - - - - - This method allows you to retrieve the preferred position of translation. - The X, Y, and Z, preferred position. - - - The time at which to retrieve the preferred position. - - The interval into which the validity of the evaluated parameters is intersected. - - - - This method allows you to retrieve the preferred angle of rotation. - Parameters: - The X, Y, and Z, preferred angles. - - - The time at which to retrieve the preferred angle. - - The interval into which the validity of the evaluated parameters is intersected. - - - - This method allows you to set the angles of translational joints. Note that this method does not adjust the validity interval. - Parameters: - & - - The joint angles. - - & - - The validity interval - - - - - This method allows you to set the angles of rotational joints. Note that this method does not adjust the validity interval. - Parameters: - & - - The joint angles. - - & - - The validity interval - - - - - This method allows you to set the angles of translational joints. Note that this method will skip those degrees of freedom that are not active and that this method will not adjust the validity interval. - Parameters: - & - - The joint angles. - - & - - The validity interval - - - - - This method allows you to set the angles of rotational joints. Note that this method will skip those degrees of freedom that are not active and that this method does not adjust the validity interval. - Parameters: - & - - The joint angles. - - & - - The validity interval - - - - - This method allows you to set the angles of translational joints. The active DOF's are given as the first argument of type DofSet and the new values are supplied as a float array whose size should be the same as the DofSet [DofSet::Count()].Note that this method does not adjust the validity interval. - Parameters: - const DofSet& - - The degrees of freedom. - - const float[] - - The new angles you wish to set. - - & - - The validity interval - - - - - This method allows you to set the angles of rotational joints. The active DOF's are given as the first argument of type DofSet and the new values are supplied as a float array whose size should be the same as the DofSet [DofSet::Count()].Note that this method does not adjust the validity interval. - Parameters: - const DofSet& - - The degrees of freedom. - - const float[] - - The new angles you wish to set. - - & - - The validity interval - - - - - This method allows you to set the validity interval for translational joint angles. - Parameters: - & valid - - The validity interval. - - - - - This method allows you to set the validity interval for rotational joint angles. - Parameters: - & valid - - The validity interval. - - - - - This method allows you to set the validity interval for both translational and rotational joint angles. - Parameters: - & valid - - The validity interval. - - - - - A solver may start off the solution process with joint angles being set to special values, preferred angles. This method allows you to set the preferred angles of the translational joints. - Parameters: - & val - - The preferred angles you wish to set. - - TimeValue t = 0 - - The time at which to set them. - - - - - A solver may start off the solution process with joint angles being set to special values, preferred angles. This method allows you to set the preferred angles of the rotational joints. - Parameters: - & val - - The preferred angles you wish to set. - - TimeValue t = 0 - - The time at which to set them. - - - - - A solver may start off the solution process with joint angles being set to special values, preferred angles. This method allows you to set the preferred angles of both the translational and rotational joints. - Parameters: - & trans - - The preferred translational angles you wish to set. - - & rot - - The preferred rotational angles you wish to set. - - TimeValue t = 0 - - The time at which to set them. - - - - - to the IK Key Property. - - - This class defines the interface to the IK key property. This property has a property ID of IKeyProperty::kIKProp. A pointer to whose propertyID is kIKProp can be safely cast to a pointer to an : - - - - - Get the IK Blend attribute of the property. It should be in the range of [0,1]. - - - - - Get the IK Space attribute of the property. - - - - - Get the Pivot On attribute of the property. - - - - - Get the World Pivot attribute of the property. - - - - - Get the Pivot Node attribute of the property. - - - - - When passed in IKeyControl2::SetKeyProp(), it tells whether to set value to the IK Blend attribute. If it is true, GetIKBlend() will be used as the target of the set value. - - - - - When passed in IKeyControl2::SetKeyProp(), it tells whether to set value to the IK Space attribute. If it is true, GetIKSpace() will be used as the target of the set value. - - - - - When passed in IKeyControl2::SetKeyProp(), it tells whether to set value to the Pivot On attribute. If it is true, GetPivotOn() will be used as the target of the set value. - - - - - When passed in IKeyControl2::SetKeyProp(), it tells whether to set value to the World Pivot attribute. If it is true, GetWorldPivot() will be used as the target of the set value. - - - - - When passed in IKeyControl2::SetKeyProp(), it tells whether to set value to the Pivot Node attribute. If it is true, GetPivotNode() will be used as the target of the set value. - - - - - Description: - This class represents the abstract (interface) for an interactive rendering manager. - - - - - This method will indicate the viewport has valid data and can execute. - - - - - This method allows you to activate and deactivate the current interactive rendering manager. - Parameters: - bool active - - TRUE to enable; FALSE to disable. - - - - - This method will return the name of the render manager. - - - - - This method returns TRUE if the current interactive rendering manager is active, otherwise FALSE. - - - - - This method returns a handle to the current window which is being rendered to. - - - - - This method returns a pointer to the associated with the current interactive rendering manager. - - - - - This method allows you to set the position and size of the window being rendered to. - Parameters: - int X, int Y - - The x and y screen coordinates of the window. - - int W, int H - - The width and height of the window. - - - - - This method will show the window currently being rendered to. - - - - - This method will hide the window currently being rendered to. - - - - - This method will issue an update of the current display. - - - - - This method starts the actual rendering process. - - - - - This method returns the delay time in milliseconds. - - - - - This method will close the window currently being rendered to. - - - - - This method will delete this render manager. - - - - - This method returns the command mode, which is one of the following; CMD_MODE_DRAW_REGION, or CMD_MODE_SELECT_OBJECT. - - - - - This method returns TRUE if the interactive rendering action and update should be issued when the mouse button is released upward, otherwise FALSE. - - - - - This method toggles the toolbar display mode (for docked windows). - - - - - This method returns the display style of the window being rendered in, which is one of the following; IV_FLOATING or IV_DOCKED. - - - - - This method returns TRUE if the renderer is currently rendering, otherwise FALSE. - - - - - This method returns TRUE if the renderer has not applied all pending scene updates yet, or FALSE if there are no updates pending and what is currently rendering (or has been rendered) is matching what the scene looks like. - - - - - - - This method returns TRUE if the rendering manager has any selected notes or FALSE if there are none. - - - - - This method allows you to get the interface that determines whether nodes are selected. - - - - - Description: - This class represents the abstract (interface) for an interactive rendering manager selector to assist in the process of determining the nodes that are selected by the interactive rendering manager. - - - - - This method returns whether the specified node is selected. By default all nodes are selected and should therefore be shaded. - Parameters: - INode* pINode - - The node to test. - Default Implementation: - { return TRUE; } - - - - - Description: - This class represents the interface to the Spring Controller and comes in two different flavors, the JIGGLE_POS_CLASS_ID for the position spring controller and JIGGLE_P3_CLASS_ID for the spring controller. - - All methods of this class are Implemented by the System. - - - Data Members: - SpringSys* partsys; - - A pointer to the spring system class. - - - - - This method returns the pointer to the associated spring system object. - - - - - This method returns the mass value. - - - - - This method allows you to set the mass value. - Parameters: - float mass - - The mass you wish to set. - - bool update=true - - This flag initiates an update if set to TRUE. - - - - - This method returns the drag value. - - - - - This method allows you to set the drag value. - Parameters: - float drag - - The drag you wish to set. - - bool update=true - - This flag initiates an update if set to TRUE. - - - - - This method returns the tension for the specified spring in the system. - Parameters: - int index - - The index of the spring in the system. - - - - - This method allows you to set the tension for the specified spring in the system. - Parameters: - int index - - The index of the spring in the system. - - float tension - - The tension you wish to set. - - int absolute=1 - - The flag defining whether the tension is absolute or relative. - - bool update=true - - This flag initiates an update if set to TRUE. - - - - - This method returns the dampening value for the specified spring in the system. - Parameters: - int index - - The index of the spring in the system. - - - - - This method allows you to set the dampening value for the specified spring in the system. - Parameters: - int index - - The index of the spring in the system. - - float dampening - - The tension you wish to set. - - int absolute=1 - - The flag defining whether the tension is absolute or relative. - - bool update=true - - This flag initiates an update if set to TRUE. - - - - - This method allows you to add a spring. - Parameters: - *node - - A pointer to the node. - TRUE if the spring was added, otherwise FALSE. - - - - - This method returns the current number of springs in the system. - - - - - This method allows you to remove a spring from the system. - Parameters: - int which - - The index of the spring in the system to remove. - - - - - This method allows you to remove a spring from the system. - Parameters: - *node - - A pointer to the node you wish to remove. - - - - - Description: - This is the base class for keys that are part of the controller interface. This class stores the time of the key, and some flags that describe the properties of the key. - Data Members: - TimeValue time; - - The time of the key. - - DWORD flags; - - The flag bits for keys. One or more of the following values: - - General flags - - IKEY_SELECTED - - The key is selected. - - IKEY_XSEL - - In the function curve editor X is selected. - - IKEY_YSEL - - In the function curve editor Y is selected. - - IKEY_ZSEL - - In the function curve editor Z is selected. - - IKEY_FLAGGED - - The key is flagged. See :: FlagKey(). - - IKEY_TIME_LOCK - - The key is locked in time so it won't move. - - TCB specific key flags: - - TCBKEY_QUATVALID - - The quaternion TCB key has inside it both a quaternion and an angle axis. When this bit is set the angle/axis is derived from the quaternion instead of vice/versa. - - Bezier specific key flags: - - BEZKEY_CONSTVELOCITY - - This key is interpolated using arclength as the interpolation parameter. - - BEZKEY_XBROKEN - - BEZKEY_YBROKEN - - BEZKEY_ZBROKEN - - Indicates if the tangent handles are locked together. Broken means not locked. - - The following macros may be used to test and set the tangent locks: - - TangentsLocked(f,j); - - SetTangentLick(f,j,l); - - The following macros may be used to access the hybrid tangent types: - - GetInTanType(f); - - GetOutTanType(f); - - SetINTanType(f,t); - - SetOutTanType(f,t); - - - - - Description: - This is an interface into the TCB, Linear, and Bezier keyframe controllers. It allows a developer to add, delete, retrieve and store the keys of the controller. This is for controllers that have made their keys accessible using this interface. 3ds Max has done this for its keyframe controllers. It is up to other third party developers to decide if they wish to make their keys available through this interface as well. See below for more details. - - It is up to the developer to make sure that the IKey* points to a key of the appropriate derived class based on the ClassID() of the controller. For the details of using these APIs see the Advanced Topics section ~{ Controller Data Access }~. - - All methods of this class are implemented by the system. - - To get a pointer to this interface given a pointer to a controller, use the following macro (defined in AnimatableInterfaceIDs.h). Using this macro, given any , it is easy to ask for the control interface. - - GetKeyControlInterface(anim)#define - - ((IKeyControl*)anim->GetInterface(I_KEYCONTROL)) - - A plug-in developer may use this macro as follows: - - ; - - This return value will either be NULL or a pointer to a valid controller interface. Here is an example of getting the controller interface from a node in the scene. First get the position controller from the node (see Class ) and then get the controller interface. - - *c; - - c = node->GetTMController()->GetPositionController(); - - ; - - With this controller interface you can use its methods to get information about the keys. - - GetNumKeys(); - - Developers should note that the values that are retrieved from this class may differ from the values that appear in Key Info in the 3ds Max user interface. For instance, the Intan and Outtan values are multiplied by the global function GetFrameRate() when displayed. Additionally, the sign of angles (+ or -) may be reversed from the what is found in the UI. For example, the following shows the values shown in Key Info versus the values retrieved from GetKey(): - - Motion branch Key Info: - - Key#1 - - X: -1.0 - - Y: 0.0 - - Z: 0.0 - - Ang: 0.0 - - Key#2 - - X: 0.0 - - Y: 1.0 - - Z: 0.0 - - Ang: 90.0 - - Key#3 - - X: 0.0 - - Y: 0.0 - - Z: 1.0 - - Ang: 90.0 - - key; - - ikc->GetKey(i, &key); - - Key#1 - - X: 1.0 - - Y: 0.0 - - Z: 0.0 - - Ang: 0.0 - - Key#2 - - X: 0.0 - - Y: -1.0 - - Z: 0.0 - - Ang: 1.57 - - Key#3 - - X: 0.0 - - Y: 0.0 - - Z: -1.0 - - Ang: 1.57 - - Sample code in the SDK that makes use of this interface is the 3D Studio Export plug-in. See /MAXSDK/SAMPLES/IMPEXP/3DSEXP.CPP. - Tension/Continuity/Bias: - Class - - Class - - Class , - - Class - - Class - Bezier: - Class - - Class - - Class - - Class - Linear: - Class - - Class - - Class - - Class - - Note: Developers creating controller plug-ins may wish to make their keys accessible to others through this interface. The way 3ds Max does this is by deriving the controllers from this class () in addition to class . So, multiple inheritance is used, and 3ds Max then implements the methods of this class to provide the interface. - - Below is the code from 3ds Max implementation of Animatable::GetInterface() (as part of a template). Note the cast of the this pointer to . - - - - - - - Returns the total number of keys. - - - - - Retrieves the 'i-th' key and stores the result in key. - Parameters: - int i - - The index of the key to retrieve. - - *key - - Storage for the key data. - - - - - Sets the 'i-th' key. The 'i-th' key must exist. - Parameters: - int i - - The index of the key to set. - - *key - - Pointer to the key data. - - - - - This method will append a new key onto the end of the key list. Note that the key list will ultimately be sorted by time. - Parameters: - *key - - Pointer to the key data to append. - The key's index. - - - - - This method should be called if any changes are made that would require the keys to be sorted. The keys are stored in order by TimeValue. - - - - - Retrieves the track flags. - One or more of the following values: - - TFLAG_CURVESEL - - Determines if the curve is selected in the track view in the function curve editor. - - TFLAG_RANGE_UNLOCKED - - Determines if the range is locked to the first key and the last key. If a user goes into Position Ranges mode and moves the range bar, the range becomes unlocked. - - TFLAG_LOOPEDIN - - This is set if the in out of range type is set to loop. - - TFLAG_LOOPEDOUT - - This is set if the out of range type is set to loop. - - TFLAG_COLOR - - for Bezier controllers that are color controllers. - - TFLAG_HSV - - for color controls that interpolate in HSV rather than RGB. - - - - - Retrieves the maximim size of a key in bytes. Implement only if size of is greater than the default value. - - 128 (default), or the value you specify in your implementation. - - - - - - - Extend to include interfaces to . Keys of a key controller may have extra properties that does not affect the interpolated value. These properties are accessed through interface . provides interface to the Key Property of individual keys. - The interface ID is I_KEYCONTROL2 defined in AnimatableInterfaceIDs.h. - - - - - Whether the key of this key controller has property of ID id. - true if it has the property of ID id. - - - the property ID being queried. - - - - Get the property of the i-th key. Use this method to get the property of the i-th key. - a pointer to the key property object. It may return null - if the property of the respected ID does not exist at the key - of this key frame controller. To get the actual attributes of the - properties, cast the returned pointer to the appropriate property interface. - The returned pointer must be deleted after use. - - - the property ID. - - the index of the key - - - - the property to the i-th key. - true if set the key property has actually affected. It can - be false if (a) this key controller does not have the property, or - (b) the values in prop are out of expected ranges. - - - the property ID. - the index for the key at which to set. - - the property object whose values are used for set-value. The implementation will cast it to appropriate property interface and call the get methods to extract values. The values will be checked against the expected range. An attribute of the key property won't be affected if the value of that particular attribute is out of range. - - - - to the Key Property. - - - This interface allows defining properties for keys. Properties are additional attributes that are not interpolated between keys. - - - - - Get the Property ID. - the property ID enum. - - - - - Description: - This class is only available in release 5 or later. The program interface to actions on IK chain nodes, which IKCmdOps::CreateIKChain() returns. An macro is defined to obtain a pointer to the interface: - - IKChainActions* ikchainAction = GET_IKCHAIN_FP_INTERFACE; - - It should be a valid pointer provided the IK system is successfully loaded. - - The methods are mainly designed to connect to the UI and script. However, they can be called programmatically as well. The action methods, those that return FPStatus, assume that a unique IK chain node is currently selected and apply action to it. Before an action method is called, IsSnapEnabled() must be called to test whether a unique IK chain node is being selected. Such as: - - - - - - - It applies IKSnapAction() if IK Enabled is currently off, and FKSnapAction() if IK Enabled is on. - - - - - - - Applies IK Snapping, which sets IK goal and other parameters, such as the swivel angle, according to the current state of the bone chain. Moreover, it invokes SetPreferredAngles(). - - - - - - - Applies FK Snapping, which assigns the currently active joint angles to the corresponding FK angles. Moreover, it invokes SetPreferredAngles(). - - - - - - - Toggles IK Enabled state. If the AutoSnap parameter of the IK chain is true, it will invoke SnapAction() before toggling the Enabled state. - - - - - - - It sets the preferred angles of all bones on the chain to the corresponding joint angles currently in force, which can be FK or IK depending the state of Enabled. - - - - - - - It assigns the preferred angles to the corresponding FK angles and then turn off IK Enabled. - - - - - Description: - This class is used to store IK parameters that have been copied to a clipboard. The plug-in derives a class from this class to store their data and implements the methods that describe the creator object. The plug-in should also implement the DeleteThis() method to delete the instance of the class. - - - - - Returns the super class ID of the creator of the clip object. - - - - - Returns the class ID of the creator of the clip object. - - - - - Description: - This class is only available in release 5 or later. The program interface to functions of the IK system. To obtain a pointer to the interface, use - - IKCmdOps* iksys = GetCoreInterface(IK_FP_INTERFACE_ID); - - It should be non-null if the plugin of the IK system is loaded. - - - - - - - This method assigns an IK solver from nodes start to end. To be successful, following conditions have to be met: - - Upon success, it will create an IK chain node that contains these pieces of information plus the IK goal and returns a pointer to it. Returning non-null pointer indicates failure. - - Example: - - - - - - - Returns the number of IK solvers that have been loaded in. - - - - - - - Returns the internal name of the i-th solver. This name is used in CreateIKChain() or the script. - - - - - - - Returns the UI name of the i-th solver. The UI names appear in the solver list on the Motion Panel, or the Animation menu. They are localized. - - - - - This interface extends interface by providing access to notification suspension for the IK system. - - - This class contains functionality for suspending and resuming IK system notification and for inquiring its status. If you have a large number of node parenting, you can expect a performance gain if you suspend IK link notifications. Be sure to match any call to SuspendLinkNotify() with one to ResumeLinkNotify() since they are nestable. You get this interface by calling GET_IKEX_OPS_INTERFACE - - - - - Temporarily suspend the IK link notification mechanism. - - - - - - - Resume the IK link notification mechanism. - - - - - - - Returns the status of the IK link notification mechanism. - - - - - - - Description: - This class provides method that a plug-in calls in its implementation of the method CompDerivs(). All methods of this class are implemented by the system. - - - - - This method returns the number of end effectors. There may be multiple end effectors if there is branching in the IK chain. For example if the plug-in is a controller controlling a torso there might be two end effectors - the two feet. The plug-ins implementation of CompDerivs() should loop through each end effector and call DP() and DR() for each end effector. Thus this method tells the plug-in how many times it needs to loop. - The number of end effectors - - - - - If a plug-in needs to know the position of an end effector to calculate its derivative it may call this method to retrieve it. This method is used to return the position of the end effector whose index is passed. - Parameters: - int index - - The index of the end effector whose position will be returned. - - - - - The plug-in calls this method to specify the derivative of the position of the end effector with respect to the parameter whose index is passed. - Parameters: - dp - - The derivative of the position of the end effector with respect to the parameter. - - int index - - The index of the end effector. - - - - - Allows the plug-in to specify the derivative of the orientation in terms of Euler angle of the end effector with respect to the parameter. - Parameters: - dr - - The derivative of the orientation in terms of Euler angles of the end effector with respect to the parameter. - - int index - - The index of the end effector. - - - - - This method is called after a plug-in has called the above methods DP() and DR() for one of its parameters and it needs to call them again for the next parameter. - - - - - Description: - The IK Controller requires that you use the Bones system. When you create the bones, a driven IK controller is assigned to each bone. All of the driven IK controllers in a single hierarchy are, in turn, controlled by a driver IK controller. This class provides access to the driven controller parameters. - - If you have a pointer to a TM controller you may test the against IKDRIVEN_CLASSID to determine if it is an IK Driven Controller. - - For an example the use of this class see /MAXSDK/SAMPLES/OBJECTS/BONES.CPP. - - - - - Returns a pointer to the that manages this IK driven controller. - - - - - Sets the specified degree of freedom to on or off. - Parameters: - int which - - Specifies which degree of freedom to modify. Pass a value between 1 and - - - - - Sets the initial position to the value passed. - Parameters: - pos - - The initial position to set. - - - - - Sets the initial rotation to the value passed. - Parameters: - rot - - The initial rotation to set. - - - - - For any IK solution you explicitly move one object. 3ds Max uses IK calculations to move and rotate all other objects in the kinematic chain to react to the object you moved. The object that you move is the end effector. There are two types of end effectors; Position and Rotation. This method create or deletes an end effector for position or rotation or both. - Parameters: - BOOL onOff - - Controls if the end effector is on or off (creates or deletes the end effector controller). TRUE to create; FALSE to delete. - - DWORD which - - Specifies which end effector(s) to modify. the low order bit for position, the second bit for rotation, or set both for position and rotation. - - pos - - The initial position set at time 0 for the position controller (CTRL_ABSOLUTE). - - rot - - The initial rotation set at time 0 for the rotation controller (CTRL_ABSOLUTE). - - - - - Description: - The IK Controller requires that you use the Bones system. When you create the bones, a driven IK controller is assigned to each bone. All of the driven IK controllers in a single hierarchy are, in turn, controlled by a driver IK controller. This class provides two methods to work with the driver controller. To get an interface to this class call GetInterface(I_DRIVER);on the controller in question. If the return value is non-NULL you can cast the pointer to an instance of this class. - - For an example the use of this class see /MAXSDK/SAMPLES/OBJECTS/BONES.CPP. - - - - - Adds the specified node to the list of driven nodes maintained. - Parameters: - *node - - The node to add. - - - - - Returns a pointer to the IK driver object. - - - - - This method is available in release 3.0 and later only. - - Returns the position threshold. - - - - - This method is available in release 3.0 and later only. - - Returns the rotation threshold. - - - - - This method is available in release 3.0 and later only. - - Returns the iterations setting. - - - - - This method is available in release 3.0 and later only. - - Returns the start time. - - - - - This method is available in release 3.0 and later only. - - Returns the end time. - - - - - Description: - This class is for enumerating IK parameters. This callback is called once for each parameter a controller has. This callback is implemented by the system and passed into the method EnumIKParams() of the controller. - - - - - Implemented by the System. - - The plug-in calls this method once for each parameter (degree of freedom it has). It passes a pointer to itself and the index of the parameter. - Parameters: - *c - - The controller itself is passed here. - - int index - - The index of the parameter. For example a position controller with three degrees of freedom (X, Y, Z) would call this method three times passing it and index of 0, then 1, then 2. - - - - - Description: - This class represents the base class that IK Solver plugins should derive from. - - The IK solver is a pure mathematical function and does not hold state, but instead just solves a given, self-contained, mathematical problem, e.g. the plugin solver does not have influence on when IK is invoked and what an IK problem is (what is the goal and what are the joints, etc.), but contributes to IK by providing an answer on how to solve. Structurally, it is independent of the SDK and, hence, can be built independently, except for some theoretically independent math library. See the Inverse Kinematics section for more detailed information. - - - - - Plugins derived from this class are supposed to have IK_SOLVER_CLASS_IDas their super class ID. This method should not be overridden. - Default Implementation: - { return IK_SOLVER_CLASS_ID; } - - - - - Returns the class ID of the IK Solver plugin. - - - - - This method returns the class name of the IK Solver plugin. This name will appear in the solver list from which users can pick or assign IK chains. - Parameters: - MSTR& s - - The class name string. - Default Implementation: - { s = MSTR(_M("IKSolver")); } - - - - - At a specific point in time, the history dependent solver will reach solutions not only based the state of the goal at the time, but also its previous states (i.e. history dependent). On the contrary, the history independent solver does its job based on the state of the goal just at the time. The procedural implication is that, when the goal is changed at time t, the IK system would have to invalidate joints at time t for the history independent solver, and at all times that are greater or equal to t for the history dependent solver. In R4, only history dependent solvers are used by the IK system. - TRUE if the IK Solver is history dependent, otherwise FALSE. - - - - - When two IK chains overlap, i.e., there is a joint belonging to both IK chains, some solvers are able to negotiate between the possibly contending goals and some are not. This method indicates if the IK Solver does a single chain only. For those IK Solvers that can only solve one chain at a time, the IK system will pass to the solvers one chain at a time in a definitive order. In R4, only solvers that "do one chain only" are used. - TRUE if the IK Solver does only one chain, otherwise FALSE. - - - - - This method indicates whether the IK Solver is a controller or an interactive manipulation tool. In the former, the relationship between the goal and the joints are permanent: joints are completely controlled by the goal. In the latter, the relationship is transient, existing only during interactive manipulation. In the end, IK solutions are registered at each joint, mostly likely as key-frames, and it no longer matters how joints have got their joint angles. Only non-interactive, or controller, IK solvers are supported in R4. Note that Interactive solvers do not need an initial pose, instead it needs a current pose. - TRUE if the IK Solver is an interactive tool, otherwise FALSE. - - - - - This method indicates whether the IK Solver intends to use the sliding joint (translational degrees of freedom) of the IK chain. - TRUE if the sliding joint of the IK chain is used, otherwise FALSE. - - - - - This method indicates whether the IK Solver intends to use the swivel angle parameter of the IK chain. - TRUE if the swivel angle of the IK chain is used, otherwise FALSE. - - - - - This method determines whether the IK Solver is analytic or needs to go through iterations. Solutions of an analytic IK Solver are not dependent on position and rotation thresholds or a maximum number of iterations. - TRUE if the IK Solver is analytic, otherwise FALSE. - Default Implementation: - { return false; } - - - - - This method determines whether the IK Solver handles root joint limits. If the IK Solver does not do joint limits, the result will be simply clamped into joint limits by the IK system. - TRUE if the IK Solver does root joint limits, otherwise FALSE. - Default Implementation: - { return false;} - - - - - This method determines whether the IK Solver handles joint limits. If the IK Solver does not do joint limits, the result will be simply clamped into joint limits by the IK system. - TRUE if the IK Solver does joint limits, otherwise FALSE. - Default Implementation: - { return false;} - - - - - This method determines whether the rotational part of the goal node will be used. - TRUE if the rotational part of the goal node will be used, otherwise FALSE to indicate that only the position of the goal node is taken as the IK goal while the rotation threshold will be irrelevant. - - - - - IK Solvers may have their own Zero Map. If so, they must override this method. The IK system will need it to perform IK snapping, which is setting the swivel angle based on the current pose so that the pose is consistent with the swivel angle. A Zero-Plane map can depend on the initial pose, which is when the joint angles take into account the respective preferred angles. In this method, a0 is to be substituted for by the end effector axis, which is a unit vector, and n0 by the solver plane normal, also a unit vector, when the chain is at the initial pose. The IK system will call this function using IIKChainControl::InitEEAxis() and IIKChainControl::InitPlane() for the two arguments. - Parameters: - & a0 - - The end effector axis unit vector. - - & n0 - - The solver plane normal. - A pointer to the ZeroPlaneMap. - Default Implementation: - { return NULL; } - - - - - This method allows you to retrieve the position threshold. - - - - - This method allows you to retrieve the rotation threshold. - - - - - This method allows you to retrieve the maximum number of iterations. - - - - - This is the method that the IK system will call when it's the time to update the joints according to the IK goal and other parameters. The derived class should override this method if DoesOneChainOnly() returns TRUE and HistoryDependent() returns FALSE. Note that the solver is not designed to be invoked recursively. The recursion logic existing among the IK chains is taken care of by the 3ds Max IK (sub-)System. The data structure passed to the Solver is transient and thus will be discarded once the solution is copied back to the joints. If the return condition indicates failure, (i.e. > 0xff) the result will not be copied back to the joint nodes in the 3ds Max scene database. - Parameters: - & - - A reference to the Link Chain. - The ReturnCondition bit-set with one or more of the following flags; - - bLimitReached - - The limit is reached. - - bLimitClamped - - The limit is clamped. - - bMaxIterationReached - - The maximum number of iterations is reached. - - bGoalTooCloseToEE - - The goal is too close to the end effector. - - bInvalidArgument - - An invalid argument is passed. - - bInvalidInitialValue - - An invalid initial value is passed. - - - - - to the layers functionality. - - - Description: - Layers govern (override) some properties of the nodes which are on the layer. For example, a Layer could be used to freeze all the nodes on it without having to set this property of each node individually. - - Some of the methods below are not functional in 3ds Max. Such cases are noted in the remarks for the method. - - - - - Returns the name of this layer. - - - - - Sets the wire frame color. - - - See . - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns the wire frame color. See . - - - - - Sets the hidden state. - - - Use true for hidden; false for not hidden. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if hidden; false if not hidden. - - - Use true to get "by layer" hidden state; false for the object permanent hidden state. A child layer is considered hidden by layer when his parent is hidden (by layer or permanently), regardless of its permanent state, which is preserved when hiding through a parent layer. - - - - Sets the frozen state. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if frozen; false if not frozen. - - - Use true to get "by layer" frozen state; false for the object permanent frozen state. A child layer is considered frozen by layer when his parent is frozen (by layer or permanently), regardless of its permanent state, which is preserved when freezing through a parent layer. - - - - Sets the See-through material property. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if See-through material is set; false if not. - - - - - Sets the box mode state. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if box mode is on; false if off. - - - - - Sets the backface culling state. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if backface culling is on; false if not. - - - - - Sets the all edges setting. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if all edges is on; false if off. - - - - - Sets the vertex ticks state. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if vertex ticks is on; false if off. - - - - - Sets the Trajectory flag state - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if the display trajectory flag for the layer is set. - - - - - Sets the ignore extents property. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if ignore extents is on; false if off. - - - - - Sets the Show Frozen with property. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Gets whether the objects on the layer are frozen in gray. - - - - - Sets the color per vertex display mode. - - - Use true for on; false for off. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if the color vertex display mode is on; otherwise false. - - - - - Returns true if the shaded color vertex mode is on; false if off. - - - - - Sets the visibility at the specified time - - - The time at which to set the value - - The new value for visibility - - - - Gets the visibility at the specified time - - - Unused. - - Unused. - - - - Gets the visibility at the specified time and viewport. Identical to GetVisibility. - - - Unused. - - Unused. - - Unused. - - - - Identical to GetVisibility. All params unused. - - - - - Always returns false - - - - - Sets the renderable state. - - - Use true for renderable; false for not renderable. - - Use true to pass the value to child layers, false to set just this one layer - - - - Returns true if renderable; false if not. - - - - - This method returns TRUE if the inherit visibility flag for the layer is set. - - - - - This method returns TRUE if the primary visibility flag for the layer is set. Otherwise known as Visible to . - - - - - This method returns TRUE if the secondary visibility flag for the layer is set. Otherwise known as Visible to Reflection and Refraction. - - - - - Returns true if cast shadow is on; false if off. - - - - - Returns true if receives shadow is on; false if off. - - - - - Returns true if Atmospherics apply to this layer, false if not. - - - - - Returns true if Render Occluded is on; false if off. - - - - - This method returns the state of the motion blur flag at the specified time. - - - The time at which to get the flag. - - - - This method allows you to set the state of the motion blur flag at the specified time. - - - The time at which to set the flag. - - TRUE to turn on; FALSE to turn off. - - - - This method allows you to set the motion blur multiplier for the layer. - - - The timevalue to get the motion blur multiplier for. - - - - This method allows you to set the image blur multiplier. - - - The timevalue to set the image blur multiplier for. - - The multiplier to set. - - - - Returns the type of motion blur used by the layer. One of the following values: - - 0: None. - - 1: Motion Blur. - - 2: Image Motion Blur. - - - - - This method allows you to set the display by layer flag for the specified node. - - - TRUE to set; FALSE to unset. - - The pointer to the node. - - - - This method allows you to set the render by layer flag for the specified node. - - - TRUE to set; FALSE to unset. - - The pointer to the node. - - - - This method allows you to set the motion by layer flag for the specified node. - - - TRUE to set; FALSE to unset. - - The pointer to the node. - - - - This method returns the state of the display by layer flag for the specified node. - - TRUE if set; FALSE if not set. - - - The pointer to the node. - - - - This method returns the state of the render by layer flag for the specified node. - - TRUE if set; FALSE if not set. - - - The pointer to the node. - - - - This method returns the state of the motion by layer flag for the specified node. - TRUE if set; FALSE if not set. - - - The pointer to the node. - - - - Adds the specified node to this layer. - - - The node to add. - - - - Deletes the specified node from this layer. Note: This method does nothing in 3ds Max. - - - The node to delete from this layer. - - - - Returns true if the layer is used (nodes have been added); otherwise false. - - - - - Returns true if the layer is used (nodes have been added); otherwise false. - - - - - This method will select the objects of the layer. - - - - - Returns the parent Layer. This could be NULL meaning the layer is at the top level. - - - - - Sets the parent layer for this layer. - Returns TRUE if set; FALSE if not set. There are some cases where you cannot set, for example, you cannot set yourself as your parent. Another example is you cannot set one of your childs as your parent (no cycles). - - - The layer that will become the parent layer. - - - - Returns a pointer to the Nth child Layer for this layer. - Returns a pointer to the Nth child layer. - - - The index of the child layer. - - - - Returns the number of child layers in this layer. - The number of child layers in this layer. - - - - - This method is for internal use in VIZ. Note: This method does nothing in 3ds Max. - - - - - This method returns the render flags associated with the layer. - - - - - provides API access to layer control functionality. - - - The interface is returned by calling GetILayerControlInterface. - - - - - Return the total number of layers on this layer control - The total number of layers. - - - - - Returns which layer is active. - The active layer. - - - - - Delete the specified layer. Note since layers are synchronized on a node, other layers on the same node will also get deleted. - - The layer to delete. - - - - Copy the specified layer so that it may be pasted. Note since layers are synchronized on a node, other layers on the same node will also get cut. - - The layer to cut. - - - - Paste the copied layer to the specified index. Note since layers are synchronized on a node, other layers on the same node will also get pasted. If no layer is copied, then nothing happens. - - Where the pasted layer will go. - - - - the name of the specified layer. - - Which layer to rename. - The new name of the layer. Remember layer names are unique so if a layer exists with this name, nothing happens. - - - - Get the name of the specified layer. - Returns the layer's name. If the index is invalid, returns an empty string. - - Which layer's name to get. - - - - Get the layer weight for the specified layer at the specified time. - Returns the layer weight. - - Where to get the layer weight. - At what time to get the layer weight. - - - - the layer weight for the specified layer at the specified time. - - Where to set the layer weight. - At what time to set the layer weight. - The weight to set. - - - - Get whether or not a particular layer is muted or not. - Whether or not the layer is muted or not. - - Which layer to see if it's muted. - - - - whether or not a particular layer is muted or not. - - Which layer to mute or not. - The mute value for the specified layer. - - - - Get a subcontroller from its index. - - a pointer to a , or NULL if the index is invalid. - - Index of the list controller subcontroller - - - - Collapse the layer at the specified index so that it gets deleted and it's keys and values are baked down to the previous layer. - - - Where to collapse. The index must be greater than zero since we can't collapse the first layer. - - - - Nothing will happen if the layer controller has more than one layer. - - - Disables and remove the layer controller, and replace it with the first, base layer. Note that doing this may delete the layer control also, thus making this interface invalid. - - - - - Get whether or not the layer is locked. A locked layer cannot be animated nor collapsed, or pasted over and an object with a locked layer cannot get disabled. - Whether or not the layer is locked or not. - - Which layer to see if it's locked. - - - - whether or not a particular layer is locked. A locked layer cannot be animated nor collapsed, or pasted over and an object with a locked layer cannot get disabled. - - the locked value for the specified layer. If true the layer is locked if false it is unlocked. - Which layer output to lock or unlock. - - - - Returns TRUE if the layer is set to never degrade; FALSE if not . - - - - - Extended interface to the layers functionality. Added for 3dsMax 2016. - - - - - Returns true if the layer or one if its child layers contains a scene selected node. - - - - - Returns the maximum value node handle of the nodes held by the layer. For example, if the layer has nodes with handles 12, 32, and 101, this method will return 101. - - the maximum value node handle of nodes held by the layer, 0 if no nodes held. - - - if true, includes nodes in children layers. - - - - Returns true if the layer or one if its child layers contains an xref scene node. - - - - - This class is an interface to the layer manager. - - - Note that some methods of this class are not functional in 3ds Max (only in 3D Studio VIZ). To get a pointer to the global instance of this class use the following code: - - - - - Adds the specified layer. - Returns true if the layer was added; false if not. - - - Points to the layer to add. - - - - Creates and adds a layer. The name is based on the incremented layer count. - The new layer - - - - - Creates and adds a layer. - - The new layer if a layer with the specified name could be created, null if not. - - - The name of the new layer. The name must be case-insensitive unique - - - - Deletes the layer whose name is passed. - TRUE if the layer was deleted, otherwise FALSE. A layer cannot be deleted if it is the current layer or contains nodes. - - - The name for the layer. - - - - Sets the layer whose name is passed as current. - - - The name for the new current layer. - - - - Sets the current layer based on the selection set (the common layer). - - - - - Returns an interface to the current layer. - - - - - Edits the layer whose name is passed. Note: This method does nothing in 3ds Max. - - - The name of the layer to edit. - - - - Brings up the layer property dialog. Note: This method does nothing in 3ds Max. - - - The parent window handle. - - - - Returns the number of layers. - - - - - Gets the specified layer by index - The layer if the layer index is valid, null if not. - - - The index of the layer to get. - - - - Returns a pointer to a layer interface for the named layer. - The layer if a layer with the specified name exists, null if not. - - - The name of the layer to get. - - - - Sets up the dropdown list in the Layer toolbar. - - - The dropdown list window handle. - - The dropdown list's parent window handle. - - - - Gets the layer saved in the right menu stack. Note: This method does nothing in 3ds Max. - The layer name if the layer index is valid, null string if not. - - - The index of the layer to get. - - - - Returns an interface to the 0 layer. - - - - - Resets the layer manager. - - - This parameter is ignored. - - - - gets whether Unhide/Unfreeze of objects is automatically propagated to hidden/frozen layers. - - - - - This class is an extended interface to the layer manager. - - - To get a pointer to the global instance of this class use the following code: - - - - - Returns the behavior of handling layers when merging a scene file. - - - - - Sets the behavior of handling layers when merging a scene file. - - - The merge type behavior. - - Whether to persist the new setting to 3dsmax.ini - - - - Returns whether to rename the merged layer or combine its content when an existing layer of the same name already exists. - - - - - Sets whether to rename the merged layer or combine its content when an existing layer of the same name already exists. - - - If true, renames the merged layer if an existing layer with the same name already exists. - - Whether to persist the new setting to 3dsmax.ini - - - - Sets the layer passed as the current layer. - - - The new current layer. - - - - Tests if the specified layer can be deleted. A layer can be deleted if it is not the current layer, it is not layer "0", and the layer contains no nodes - true if the specified layer can be deleted. - - - The layer to test. - - - - Deletes the specified layer. - true if the layer was deleted, otherwise false. - - - The layer to delete. - - - - Deletes the specified layer and its child layers. - the number of layers deleted. - - - The layer to test. - - If false, any layers containing nodes, and their parent layers recursively, are not deleted. If true, any nodes found are moved to the parent of the specified layer, or layer "0" if no parent layer, and the layers are deleted. - - - - Tests if the specified layer, or one of its descendant layers, contains a node. - true if the specified layer, or one of its descendant layers, contains a node. - - - The layer to test. - - - - Extracts all the nodes for a particular layer. - - - a reference to a to be filled with the layers nodes. - - - - Returns the parent Layer. This could be NULL meaning the layer is at the top level. - - - - - Sets the parent layer properties for this layer - Parameters: - FPInterface* parentLayerProp - - The layer properties that will become the parent layer. - Returns TRUE if set; FALSE if not set. There are some cases where you cannot set, for example, you cannot set yourself as your parent. Another example is you cannot set one of your childs as your parent (no cycles). - - - - - Returns a pointer to the Nth child Layer properties for this layer. - Parameters: - int n - - The index of the child layer properties. - Returns a pointer to the Nth child layer properties. - - - - - Returns the number of child layer properties in this layer. - The number of child layer properties in this layer. - - - - - Access Lighting data from 3ds Max lights. - - - This is the main access to the lights. The user would request the light data from the LightManager based on the D3DHANDLE - - - - - Get the current falloff value - A float representing the value. - - - - - Get the current Hotspot value - A float representing the value. - - - - - Provides access to the lighting unit system for converting and displaying luminance and illuminance values. - - - - - For internal use. - - - - - For internal use. - - - - - Returns the unit system currently being used for display. - - - - - Returns the unit suffix as a text string, to be used for displaying luminance values. - - - - - Returns the unit suffix as a text string, to be used for displaying illuminance values. - - - - - Converts a luminance or illuminance unit, from one system to the other. - - - - - Converts a luminance or illuminance unit, from the given system to the one used for display. - - - - - Converts a luminance or illuminance unit, from the display system to the given one. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Retrieves the display unit currently in use for lighting quantities. - - - - - A basic light container. - - - The user would use this to access the light data for a specific light. The system maintains the light list so the user does not need to worry about the maintenance. - - - - - Access the Data. - - - Access the light data based on the handle supplied. The handle is based on the parameter found in the File - A pointer to the light data - - The parameter to find in the File - - - - provides access to the limit controller methods. - - - Base Limit Controller InterfaceA limit controller is used to restrict the range of values produced by other controllers. - The controller whose range of value is being restricted is called the limited controller. Its presence is optional. - This interface can be used to gain access to the limit controller's enable state and limited controller, and to set the upper or lower limits of - the controller. - Limit controllers can be disabled, in which case they just let the limited controller pass through. - - - - - the upper limit of the controller at a given time. - - - time for which the upper limit is to be set - - pointer to a variable of type according to the limit controller type - - - - the lower limit of the controller at a given time. - - - time for which the lower limit is to be set - - pointer to a variable of type according to the limit controller type - - - - Description: - This class represents the interface to the Link Controller. You can obtain a pointer to the link controller interface by calling GetInterface(Interface_ID id) on the controller instance, as in this example: - Developers may use the following values to access the references of the Link controller: - All methods of this class are Implemented by the System. - - - - - This method is available in release 4.0 and later only. - - This method returns the number of parents (links). - - - - - Returns the start time associated with the 'i-th' link. - Parameters: - int i - - Specifies which parent (link). - - - - - Sets the start time associated with the 'i-th' link. See LinkTimeChanged() below. Note: This method also sorts the indices according to increasing time values. - Parameters: - int i - - Specifies which parent (link). - - TimeValue t - - The time to set. - - - - - This method should be called after changing link times. Note: This method also sorts the indices according to increasing time values. - - - - - Adds a new link at the specified time. - Parameters: - *node - - Points to the node of the link to add. - - TimeValue t - - The time to change to this link. - - - - - This method will delete the specified link. - Parameters: - int frameNo - - Specifies which link to delete. - - - - - This method returns the start frame of the specified target. - Parameters: - int targetNumber - - The target number for which to get the start frame. - - - - - This method is available in release 4.0 and later only. - - This method allows you to set the start frame of the specified target. - Parameters: - int targetNumber - - The target number for which to set the start frame. - - int frameNumber - - The time value. - TRUE if the start frame is set, otherwise FALSE. - - - - - This method is available in release 4.0 and later only. - - This method allows you to append a target. - Parameters: - *target - - The target node to append. - - int frameNo - - The frame time. - TRUE if the target was appended, otherwise FALSE. - - - - - This method is available in release 4.0 and later only. - - This method returns one of the link nodes that the link constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the link target list to be obtained. - - - - - This method returns the parent transformation matrix containing the combined link TM for a given time - Parameters: - TimeValue t - - The time at which to get the TM. *valid - - The interval to get the TM. - - - - - Description: - This class stores a Linear floating point key. - Data Members: - float val; - - The value of the key. - - - - - Description: - This class stores a Linear key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class stores a Linear rotation key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class stores a Linear scale key. - Data Members: - val; - - The value of the key. - - - - - provides API access to list control functionality. - - - The interface is returned by calling GetIListControlInterface. - Description: - This class represents the interface to the list controller. You can obtain a pointer to the list control interface using; GetIListControlInterface(cd). This macro will return (IListControl*)(CD)->GetFPInterface(LIST_CONTROLLER_INTERFACE). - - The Class ID's of individual controllers are; FLOATLIST_CONTROL_CLASS_ID, POINT3LIST_CONTROL_CLASS_ID, POSLIST_CONTROL_CLASS_ID, ROTLIST_CONTROL_CLASS_ID, SCALELIST_CONTROL_CLASS_ID, DUMMY_CONTROL_CLASS_ID, DRIVERBLOCKLIST_CONTROL_CLASS_ID, TMLIST_CONTROL_CLASS_ID. - - All methods of this class are Implemented by the System. - - - - - This method returns the number of items that appear in the List controllers list box. - - - - - When in weight mode, this method returns the index of the currently active item. When in index mode, this returns the current active index. - - - - - the Index mode index property using the list entry name that is the best match - - True if a match was found and the index was set. - - - The case insensitive search string. Best match closest to beginning of the name is chosen. - - - - This method allows you to delete the indexed sub controller from the list. - Parameters: - int index - - The index of the item to delete from the list. - - - - - This method allows you to cutsthe index sub controller from the list and stores it in the buffer to paste later. - Parameters: - int index - - The index of the item you wish to cut. - - - - - This method allows you to paste the sub-controller from the buffer into the indexed slot in the - - list. - Parameters: - int index - - The index of the slot to paste into. - - - - - This method allows you to set the name of an indexed item. - Parameters: - int index - - The index of the item. - - MSTR name - - The name to set it to. - - - - - This method returns the class name of the indexed sub-controller if a user defined name doesn't exist. - Parameters: - int index - - The index of the item for which to get the name. - - - - - Get a subcontroller from its index. - - a pointer to a , or NULL if the index is invalid. - - - index of the list controller subcontroller - - - - Get the weight of a subcontroller at a given time. - - the weight of the subcontroller (non-percent, typically 0.0f to 1.0f), or -1.0f if the index is invalid. - - - time of the weight evaluation (in case of an animated weight) - - index of the list controller subcontroller - - - - Getter for wether or not the list controller is in weight mode or index mode. Default is false, weight mode. - - - - True if the list control is in index mode. - - - - - Description: - This class provides methods to load data from disk and to register post load callbacks. - - Note: It is not valid, to write two CStrs in the same chunk of a 3ds Max file, since ILoad::ReadCStringChunk() sets the size for the string to the ChunkSize. However it is possible to write other data, such as two ints, into the same chunk. - - All methods of this class are implemented by the system. - - - - - This method may be used to load a pointer from disk. It returns the memory address of the specified object Scene stream. This may be nullptr if the address is not available. See RecordBackpatch() above for a work around. - - This is the index returned from . that was used to save the pointer. - - - - This method may be used to load a pointer from disk. This is a pointer that was saved using ISave::GetRefID(). You pass the index returned from GetRefID() and a pointer to a pointer that will get set. This method will patch the address immediately if it is available, otherwise it will happen later when it is known. During the load process if you need to work with this information you'll have to use a post load callback since all the addresses are not updated immediately. See RegisterPostLoadCallback() above. - - This is the index returned from . - This is a pointer to the pointer you want patched. - This flag indicates that backpatches (and their subsequent references) should be merged as well. - - - - This method is used internally. - - - - - This method is used to open a chunk. If OpenChunk() returns IO_OK, use the following 3 functions to get the info about the chunk. If it returns IO_END this indicates there are no more chunks at this level. - IO_OK - The result was acceptable - no errors. - - IO_END - This is returned from ILoad::OpenChunk() when the end of the chunks at a certain level have been reached. It is used as a signal to terminates the processing of chunks at that level. - - IO_ERROR - This is returned if an error occurred. Note that the plug-in should not put up a message box if a read error occurred. It should simply return the error status. This prevents a overabundance of messages from appearing. - - - - - This method returns the ID of the most recently opened chunk. - - - - - This method returns the type of the most recently opened chunk. This may be one of the following values: - - NEW_CHUNK - - CONTAINER_CHUNK - - DATA_CHUNK - - - - - This method returns the chunk length NOT including the header. - - - - - of data bytes remaining in chunk NOT including header. - - - - - This method is used internally for checking for balanced OpenChunk/CloseChunk pairs. - - - - - This method is used to close the currently opened chunk, and position at the next chunk. - A return value of IO_ERROR indicates there is no open chunk to close; otherwise IO_OK. - - - - - This method returns the ID of the next chunk without opening it. It returns 0 if there are no more chunks. - - - - - This method is used to read a block of bytes from the output stream. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - A pointer to the buffer to read. - The number of bytes to read. - The number of bytes that were read. - - - - This method read a string that was stored as Wide characters. Note: This method reads a string from a string chunk. It is assumed the chunk is already open, it will NOT close the chunk. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - A pointer to an array of characters. - - - - This method read a string that was stored as Wide chars. Note: This method reads a string from a string chunk. It is assumed the chunk is already open, it will NOT close the chunk. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - A pointer to an array of wide characters. - - - - This method reads a string that was stored as single byte characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - A pointer to an array of single byte characters. This method will allocate an internal buffer, stored in the ILoadImp class that is big enough to hold the string chunk read in. You must then copy or parse out the data and store it in your own area: you can't hang on to the string pointer it hands back because it will not be valid. - - - - This method may be used to read a string that was stored as single byte characters. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - A pointer to an array of wide characters. This method will allocate an internal buffer, stored in the ILoadImp class that is big enough to hold the string chunk read in. You must then copy or parse out the data and store it in your own area: you can't hang on to the string pointer it hands back because it will not be valid. - - - - You may call this if you encounter obsolete data to cause a message to be displayed after loading. - - - - - Registers a procedure to be called after loading. These will be called in the order that they are registered. It is assumed that if the callback needs to be deleted, the proc will do it. - - Points to the callback object. - - - - Retrieves the specified standard 3ds Max directory name (fonts, scenes, images, ...). - The name of the specified directory. - - Specifies the directory name to retrieve. See . The constants are defined in - - - - Determines if we are loading a standard 3ds Max file (.MAX) or a material library (.MAT). - One of the following values: - - IOTYPE_MAX - - IOTYPE_MATLIB - - - - - Returns the root node to attach to when loading a node with no parent. - - - - - This method is available in release 3.0 and later only. - - Returns a pointer to the corresponding to the specified reference ID in the stream. - Default Implementation: - { return nullptr; } - - The reference ID in the stream. - - - - Retrieves the version and build number of 3ds Max used to save the file being loaded. - - - Plugins can call this method when loading a max file is being loaded. - A value describing the version of 3ds Max used to save the file. The value is composed of a LOWORD(value)= Build number, and a HIWORD(value) = MAX_RELEASE. For example, 41 for build #41, and 4000 for 3ds Max version 4.0 - Plugins should not rely on the value returned by this function for versioning their own data saved to the max file. Plugins should rather use either: - - - - - Records information needed to remap a reference to a node. References to nodes held by object-xrefed reference makers need to be remapped when updating xref records. In most cases, Max will automatically record data required to remap node references when xrefing objects. Plug-ins that save node pointers into the max file need to be modified to indirectly reference the node, in order for that plug-in to be xref-able. For the legacy version of the plugin to be xref-able, the plugin must record in a information needed for remapping the indirect reference it makes to nodes. This can be done by calling this method. - - true if a node-ref-remap entry was recorded successfully, false otherwise - - - A scene entity that makes a reference to a node - - The index of the reference aRefMaker makes to a node - - The node being referenced - - If true, the reference to the node is indirect, otherwise it's a regular reference - - - - Returns the name of the scene file being loaded. - - - - - This method is used by Asset Manager to load from the scene file all asset meta data. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - - - - the 3dsmax language id when the file was saved - kFileSaveAsVersionNotSpecified if not loaded from file - - - - - the 'Save As' version number when the file was saved - kFileSaveAsVersionNotSpecified if not loaded from file - - - - - the Active Code Page when the file was saved - kFileSaveAsVersionNotSpecified if not loaded from file - - - - - The interface to the functionality for loading saving XML animation files. - - - This class contains key functionality for saving and creating both animation and map files and for loading in animation. You get this interface by calling GetILoadSaveAnimation() - - - - - Brings up the Save Animation dialog. - - - The name of the file if a file gets saved, otherwise returns NULL - - - - - Brings up the Load Animation dialog. - - - The name of the file if a file gets loaded, otherwise returns NULL - - - - - Brings up the Load Animation dialog and returns the fileName and the mapFileName in the passed in parameters. - - - TRUE if a file name is selected in the dialog, otherwise returns FALSE. - - The name of the animation file returned. Note that the character array passed in should have a size of MAX_PATH. - The name of the map file returned. Note that the character array passed in should have a size of MAX_PATH. - - - - Brings up the Load Animation dialog and returns a list of possible multiple file names in the passed in parameters. - - - param[out] names The list of animation files. param[out] mapFileName The name of the map file. Note that the character array passed in should have a size of MAX_PATH. - TRUE if one or more file names are selected, false otherwise - - - - - Save the animation from the current nodes into the specified file. - - - This function will save out an animation file given the passed in nodes and user attributes, based upon the saveFlags and possible segment interval. - TRUE if a file gets saved, otherwise FALSE - - The file to save the animation to. - The nodes whose animation you would like to save. - A of strings that specify the names of the user attributes to be saved out. The values of these attributes are found in the next parameter. Thus the userAttributes and the userValues need to be the same size or the function will return FALSE. - A of strings that specify the names of the user values to be saved out. Each user value corresponds to a user attribute that's passed in the previous parameter. - Determines which tracks under the specified nodes will be saved. The possible values of the saveFlag are found in the SaveFlags enum. The possible vales are eAnimatedTracks, if this value is set, then only animated tracks only will be saved, otherwise non-animated tracks will also be saved. eIncludeConstraints, if set and eAnimatedTracks is set, then constraints will also be saved out, otherwise if eAnimatedTracks is set and this value isn't set, they won't be saved out. If eAnimatedTracks isn't set this parameter is unused since constraints will be automatically saved out. eKeyableTracks, if set keyable tracks only will be saved, otherwise non-keyable tracks will also be saved. eSaveSegment, if set a segment will be saved specified by the segInterval and eSegKeyPerFrame flag. eSegKeyPerFrame, which if set will save out a key per frame when saving out a segment, otherwise only the keys will be saved out. - The interval over which to save the segment. - - - - Save the animation from the current nodeAnim tracks into the specified file. - - - This function saves out the animation file given the passed in nodeAnim array and user attributes, based upon the saveFlags and possible segment interval. - TRUE if a file gets saved, otherwise FALSE - - The file to save the animation to. - The nodeAnim list whose animation you would like to save. Should have been created via SetUpAnimsForSave. - - - - Load the animation from the current file onto the specified nodes using any mapping that's specified. - - - This function loads in the specified file onto the passed in nodes based upon the the passed in flags, insertion time and possible mapFileName. - TRUE if a file gets loaded, otherwise FALSE. - - The file to load the animation from. - The nodes where the animation will be loaded onto. - Determines which tracks under the specified nodes will be loaded onto. The possible values of the loadFlag are found in the LoadFlags enum. The possible vales are: eRelative, if this value is set, the animation will be loaded at the current position and orientation of a node, if it's parent is the root, if not set the animation will be loaded in absolutely. eInsert, if this value is set, the existing animation will be moved to the left when the animation is loaded, otherwise is not set the animation will overwrite the existing animation. eStripLayers, if this value is set, then any layer controller name will be removed from the current controller names, otherwise it won't. - The time where the animation is loaded. - If TRUE the mapFileName file name parameter will be used to specify what map file to use. If FALSE then default mapping is used. - The file name of the map file to use if the useMapFile parameter is TRUE. Note that the character array passed in should have a size of MAX_PATH. - - - - Load the animation from the current file onto the specified nodeAnim tracks using any mapping that's specified. - - - This function loads in the specified file onto the passed in nodeAndAnim tracks based upon the the passed in flags, insertion time and possible mapFileName. - TRUE if a file gets loaded, otherwise FALSE. - - The file to load the animation from. - The nodeAnim list whose animation you would like to save. Should have been created via SetUpAnimsForLoad. - - - - Create a map file based upon nodes to map to, the animation file that will be loaded, and the specific mapping protocols. - - - TRUE if a map file gets created, otherwise FALSE - - The file to save the map file to. - The nodes which will be mapped to the specified incoming Animation File. - The file from which to map from. The controllers in this file will map to the controllers of the current nodes. - A of strings that specify the names of the user attributes to be saved out. The values of these attributes are found in the next parameter. Thus the userAttributes and the userValues need to be the same size or the function will return FALSE. - A of strings that specify the names of the user values to be saved out. Each user value corresponds to a user attribute that's passed in the previous parameter. - A of values that specify how specific nodes that get mapped should be retargeted. - The type of node mapping to perform. If the value is eMatchExactName, the nodes will map if the nodes have the same exact name. If the value is eMatchClosestName, the nodes will match based off of which nodes have the closest names. If the value is eMatchHierarchy, the nodes will try to match by matching their hierarchies. - Determines how the controller mapping will occur once the nodes are mapped. The possible values of the mapFlag are found in the MapFlags enum. The possible vales are: eMapControllerExactName, if set the controllers of the mapped nodes will try to map to each other by matching their names exactly, if not set the controllers will map by their subanim ordering. eMapControllerType, if set, the controllers will check to see if they have the same exact type, that is the same ClassID and SuperClassID, otherwise they won't map, if not set then the controllers only need to be have the same SuperClassID. eStripLayersinMap, if set, will strip the layer controller name from any active layers on the current nodes. - - - - Create a map file based upon nodeAnim tracks to map to, the animation file that will be loaded, and the specific mapping protocols. - - - TRUE if a map file gets created, otherwise FALSE - - The file to save the map file to. - The nodeAnim list whose animation you would like to map. Should have been created via SetUpAnimsForMap. - - - - Get the extension used for the animation files. - - - The animation file extension (xaf). - - - - - Get the extension used for the animation map files. - - - The animation map file extension (xmm). - - - - - Get the current directory for finding animation files. - - - The animation file directory - - - - - Get all of the anim file directories in the load/save UI. - - - - A of MSTR strings containing all of recently used directories. The caller of this function is responsible for deleting the valid MSTR * pointers. - - - - Get all of the recently used map files in the load/save UI. - - - - A of MSTR strings containing all of recently used map files. The caller of this function is responsible for deleting the valid MSTR * pointers. - - - - Get the current map file. - - - The name of the current animation map file being used in the load/save UI. - - - - - Sets up the anim list to be used for saving out an xml animation file. - - - - Nodes you want to save out - If TRUE will only included animated tracks in the list, - If animatedTracks is TRUE and this is TRUE, constraints will be considered to be animated and thus also in the list. - If TRUE will only include keyable tracks in the list. - The returned list of nodes and their anim tracks based upon the flags passed into the function. - - - - Sets up the anim list to be used for loading in an xml animation file or putting nodes and their tracks into the mixer. - - - - Nodes you want to load - Whether or not to include param block2 tracks when loading in the animation. - The returned list of nodes and their anim tracks based upon the flags passed into the function. - - - - Sets up the anim list to be used for mapping an xml animation file. - - - - Nodes you want to map - The returned list of nodes and their anim tracks - - - - Get the user attributes that are present out of the corresponding animation or map file. - - - TRUE if operation was successful, FALSE if otherwise. - - The name of the animation or map file that you are getting user attributes from. - A of MSTR strings of the user defined attributes found in the file. There is a one to one correspondence between the number of attributes and number of values in the file. The callee of this function is responsible for deleting the valid MSTR * pointers. - A of MSTR strings of the user defined values found in the file. There is one string value for each attribute. The caller of this function is responsible for deleting the valid MSTR * pointers - - - - An extension to that exposes additional functionality. - - - This class contains key functionality for saving and creating both animation and map files and for loading in animation. You get this interface by calling GetILoadSaveAnimation10() - - - - - Creates a list of items to be used for saving animation. Use as a replacement for ILoadSaveAnimation::SetUpAnimsForSave. - - - - Nodes whose tracks you want to save out. - Determines which tracks under the specified nodes will be present in the resulting nodeAnims tab. The possible values of the saveFlag are found in the enum. The possible vales are eAnimatedTracks, if this value is set, then only animated tracks only will be saved, otherwise non-animated tracks will also be saved. eIncludeConstraints, if set and eAnimatedTracks is set, then constraints will also be saved out, otherwise if eAnimatedTracks is set and this value isn't set, they won't be saved out. If eAnimatedTracks isn't set this parameter is unused since constraints will be automatically saved out. eKeyableTracks, if set keyable tracks only will be saved, otherwise non-keyable tracks will also be saved. Not that we don't use the eSaveSeg or eSegPerFrame flags with this function - The returned list of nodes and their anim tracks based upon the flags passed into the function. This can then be passed to in order to save the animation. - - - - Creates a list of items to be used for saving animation based upon a specified list of items. Use this function instead of ILoadInterface10::SetUpAnimsForSaveExt when you want to save animation from specific tracks. - - - - A of items, each of which specifies a single animatable track, usually from a dlg. - - - - Creates a list of items to be used for loading animation or for putting tracks into the mixer. - - - - Nodes whose tracks you want to load onto. - Determines which tracks under the specified nodes will be loaded onto. The possible values of the loadFlag are found in the enum. The possible vales are: eStripLayers, if this value is set, then any layer controller name will be removed from the incoming controller names, otherwise it won't. eIncludePB2s, if set then we will include any ParamBlock2 tracks. Note that we don't use the eRelative or eInsert flags. - The returned list of nodes and their anim tracks based upon the flags passed into the function. This can then be sent to either or IMixer8::AddMaxMixxer. - - - - Creates a list of items to be used for loading animation based upon a specified list of items. Use this function instead of ILoadInterface10::SetUpAnimsForLoadExt when you want to load animation upon specific tracks. - - - - A of items, each of which specifies a single animatable track, usually from a dlg. - - - - Creates a list of items to be used for mapping animation. - - - - Nodes whose tracks you want to map onto. - Determines which tracks under the specified nodes will be mapped onto. The possible values of the mapFlag are found in the enum. The possible vales are: eStripLayersInMap, if this value is set, then any layer controller name will be removed from the incoming controller names, otherwise it won't. Note that we don't use eMapControllerExactName or eMapControllerType flags. - The returned list of nodes and their anim tracks based upon the flags passed into this function. This can then be sent to . - - - - Creates a items to be used for mapping animation based upon a list of items. Use this function instead of ILoadInterface10::SetUpAnimsForMapExt when you want to map animation from specific tracks. - - - - A of items, each of which specifies a single animatable track, usually from a dlg. - - - - Bring up a load animation dialog that will load animation to the each track that's specified in the tab of items. - - - The name of the file if a file gets loaded, otherwise returns NULL. - - A of items, each of which specifies a single animatable track, usually from a dlg. - - - - Bring up a save animation dialog that will save animation from the each track that's specified in the tab of items. - - - The name of the file if a file gets saved, otherwise returns NULL. - - A of items, each of which specifies a single animatable track, usually from a dlg. - - - - Given a specified map file, it will replace all specified string attributes with the new string attributes, and a create a new map file with those new strings. - - - TRUE if we had strings to replace and we were able to create the new map file. If we return FALSE, no new map file was created. - - The name of the map file that you want to search and replace attribute strings from. - The name of the new map file that will be created with the replaced attribute strings. - The list of old string values you wish to replace - The list of new string values that will replace the corresponding old string value. - If true it will replace the 'mapName' attribute in the map xml file, otherwise it will change the 'name' attribute value. - - - - Given a set of nodes it will create a map file that maps the nodes tracks onto themselves, which is the same as doing 'default' mapping. - - - TRUE if the map file is created, FALSE if for some reason we couldn't create the map file. - - Nodes you want to map to themselves. - The name of the map file you to create with the default mapping. - - - - This class provides an interface for classes that may need to augment the new container update process that was introduced in 3ds Max 2011. During this update process, locked items from the source are merged into the main file and replace their corresponding locked counterpart in the main if one exists. This process is automatic but sometimes the item in question needs to augment this process since some information may get lost during this merge and copy process. Note there may be some other cases where the source item is merged in, for example unlocked modifiers may get copied in from the source if that modifier doesn't exist in the main. An example of a class that needs to implement this is the skin modifier. When a skin modifier is put onto the modifier stack on some node, any existing weight information on the specific vertices are automatically lost, since they are stored in the local mod data for modifier instance, even though that skin modifier has the correct nodes in its node list, which is the case during the container update process. So what the skin modifier needs to do is provide an implementation of interface. In the ILockedContainerUpdate::PreReplacement function it copies and saves out it's weight information, and then in the ILockedContainerUpdate::PostReplacement function it pastes these weights back onto itself, since this function is called after the replacement has happened. You can see this example at maxsdk\samples\bondesdef. - Note that the container update process does handle the transferring of node references during the process, that's why the skin modifier doesn't need to worry about having the correct nodes it's node list. However external non-node references aren't automatically handled so an item has one and this reference isn't locked, it will need to make sure that the correct one is found and the reference replaced. For example we do this internally with our wire parameters, if the object that's controlling the wire isn't locked we make sure that this existing main item replaces the merged item that's coming in from the source. - - - - - that's called before the source item replaces the main item during a container update. - - - Returns true if the function succeeds, false otherwise. - - The merged node from the source, that may be needed to find a modifier's , etc.. Note that the sourceNode doesn't replace the mainNode, only the sourceAnim replaces the mainAnim on the mainNode. - The merged from the source that replaces the mainAnim parameter. Note that this value may be the same as the object that implements this function. - The mainNode that the mainAnim exists under. It may be needed to find a modifier's , etc.. Note that the sourceNode doesn't replace the mainNode, only the sourceAnim replaces the mainAnim on the mainNode. - The that will get replaced. - An interface that lets you query for a node currently in the scene what node, if any, will be replacing it after the update process. As noted the references to these nodes are automatically transferred but it still may be useful to the client to know exactly what's getting replaced, in case for some reason they aren't using reference to keep track of a node. - A string to place any pertinent error messages that the container update system may output as an error log during the update process. - - - - that's called after the source item replaces the main item during a container update. - - - Returns true if the function succeeds, false otherwise. - - The merged node from the source, that may be needed to find a modifier's , etc.. Note that the sourceNode doesn't replace the mainNode, only the sourceAnim replaces the mainAnim on the mainNode. - The merged from the source that replaces the mainAnim parameter. Note that this value may be the same as the object that implements this function. - The mainNode that the main anim exists under. It may be needed to find a modifier's , etc.. Note that the sourceNode doesn't replace the mainNode. - An interface that lets you query for a node currently in the scene what node, if any, will be replacing it after the update process. As noted the references to these nodes are automatically transferred but it still may be useful to the client to know exactly what's getting replaced, in case for some reason they aren't using reference to keep track of a node. - A string to place any pertinent error messages that the container update system may output as an error log during the update process. - - - - An interface to a track that can get locked. Your animatable class should inherit from this class if it wants to support itself getting locked. Remember only items which can get locked can support local edits with containers. To get from an existing object, call GetLockedTrackInterface(anim) which is defined AnimatableInterfaceIDs.h. - - - - - to lock or unlock this track This function will be called to lock or unlock this item. The implementer of this function is responsible for setting and saving the locked state of the track based upon the value of the passed in flag. Also it's the responsible of the implementer to lock it's sub anims if the flag is set to also lock it's subanims. The system itself is responsible to making sure all of it's parents are unlocked when it gets unlocked. - - - - If true the track gets locked, if false the track gets unlocked - If true, then also lock the children of the item that you are locking. - A pointer to the reference target that contains this interface. - A pointer to the parent of this interface. - The subanim index of this track. - - - - Return whether or not the track is locked. - - - Returns true if the track is locked, false if it is not. Also take note that this track takes into account whether or not any overrides are active and if it's inside a container or not. - - If true we check the overrides first before testing to see if the track is locked, if false then we don't check the override state and rather just check the state of the locked item by itself. - - - - Returns whether or not the object is a component Returns whether or not an object is a component. A component is an object that when locked gets replaced by a wrapper object that hides the existing object inside it. Lockable Modifiers and Materials may be examples of components. Most basic 'tracks' and controllers aren't components. Thus the default returns false. - - - return true if a component false otherwise - - - - - Locked Track Manager This class provides an interface for managing and setting locks on acceptable tracks. - - To get a pointer to this class simply call. - - - - - - - to set or unset a lock on a list of possible tracks. This function is used to lock or unlock a list of possible tracks. The tracks are represented by a pointer to the track, a pointer to their parent, and it's parent sub anim number. You can specify if you want to propagate the locking or unlocking to the tracks children. - - - - If true we lock, if false we unlock. - The list of tracks that you want to lock or unlock - The list of the tracks parents. - The list of the subAnim id's for each of the track for each parent. - If true then we also lock or unlock the tracks subanims, if false then we don't. - - - - to toggle a lock on a list of possible tracks. This function is used to toggle a lock on a list of possible tracks. The tracks are represented by a pointer to the track , a pointer to their parent, and it's parent sub anim number. You can specify if you want to propagate the locking or unlocking to the tracks children. - - - - The list of tracks that you want to toggle the lock on. - The list of the tracks parents. - The list of the subAnim id's for each of the track for each parent. - If true then we also toggle the locks on the tracks sub anims, if false we don't. - - - - to get the state of the unlock override. - - - Returns the value of the current state of the unlock override. If true then all locked items, not in an imported container, are unlocked. - - - - - to override all locked tracks, even those in containers. This function will push an unlock override state that will let you override and unlock all tracks, including those that locked in a container. Useful usually when you want to have a script, like a script controller, still be able to drive locked tracks. Note that you need to call PopUberUnLockOverride to when you are done with this override and it should be used in a limited, local manner. - - - - - to pop the uber unlock override state. This function will pop an unlock override state that will let you override and unlock all tracks, including those that locked in a container. This function needs to be called at some point after every PushUberUnLockOverride function call. If called before PushUberUnLockOverride an error may occur. - - - - - to get the state of the uber unlock override. This function will return the value of how many existing pushes of the uber unlock override state exist. So, if this value is greater or equal to one then we have an active uber unlock override occurring, if the value is zero then we don't have this override, if this value is less than zero, then we have an error since a PopUberUnLockOverride(), was called without first calling PushUberUnLockOverride. - - - - - to find all locked or unlocked anims on a node. - - - - If true we find locked items, if false we find unlocked items. If an item is not lockable, it is not included with either option. - If true we check the overrides first before testing to see if the item is locked, - The reference target we will find the anims on. - The list of anims that are locked or unlocked. - The parents of the anims that are locked or unlocked. - The subanim index of the anims that are locked or unlocked - - - - to test whether or not a particular anim is overridden unlocked or not. - - - If true the item is overridden unlocked and a locked item should now return false when queried for it's locked state. - - The anim we are testing to see if it's overridden unlocked or not. - - - - to see if a particular track is lockable. This function is used to see if a particular track may get locked and unlocked. - - - Returns true if a track can get locked and unlocked, false if it can't get locked or unlocked. - - The track that we are checking to see if it's lockable. - The parent of the track that we are testing to see if it's lockable. - The subanim number of the anim related to it's client. - - - - to see if a particular track is locked or unlocked. This function is used to see if a track is locked or unlocked. - - - Returns true if a track is locked, false if it's unlocked or if it's unlockable. - - The track that we are checking to see if it's locked - The parent of the track that we are testing to see if it's locked. - The subanim number of the anim related to it's client. - If true we check the overrides first before testing to see if the item is locked, if false then we don't check the override state and rather just check the state of the locked item by itself. - - - - An interface to an object who is a client that has subanims that may get locked. Your animatable class should inherit from this class if it wants to support subanims, that don't return an interface when GetLockedTrackInterface(anim) is called, but can still get locked. In particularly, and objects will return this interface since they will control the locking and unlocking of their parameter entries. To get from an existing object, call GetLockedTrackClientInterface(anim) which is defined AnimatableInterfaceIDs.h. - - - - - to lock or unlock this track's subanim This function will be called to lock or unlock this clients subanim . The implementer of this function is responsible for setting and saving the locked state of the subanim track based upon the value of the passed in flag. Also it's the responsible of the implementer to lock it's subanim subanims if the flag is set to also lock it's subanims. The system itself is responsible to making sure all of it's parents are unlocked when it gets unlocked also. - - - - If true the subanim track gets locked, if false the track gets unlocked - If true then also lock the children of the anim that you are locking. Usually this is not needed since the anim is almost always a leaf. - A pointer to the reference target that contains this interface. - A pointer to the reference target of this interface. It's the client that contains the subanim we will lock. - The subanim index of this track. - - - - Return whether or not one if it's subanim tracks are locked. - - - Returns true if the subanim track is locked, false if it is not. Also take note that this track takes into account whether or not any overrides are active and if it's inside a container or not. - - This is the SubAnim number for the track we want to check to see if it's locked. - If true we check the overrides first before testing to see if the track is locked, if false then we don't check the override state and rather just check the state of the locked item by itself. - - - - Return whether or not one if its subanim tracks or lockable or not. - - - Returns true if the subanim track is lockable false if it is not. - - This is the SubAnim number for the track we want to check to see if it's lockable or not. - - - - This class provides an implementation of base class, including a local variable that's used for the persisting the lock. - - - - - Description: - This class provides access to the LookAt Controller parameters. - - Developers may use the following values to access the references of the Look At controller. - - LOOKAT_TARGET_REF - - LOOKAT_POS_REF - - LOOKAT_ROLL_REF - - LOOKAT_SCL_REF - - All methods of this class are implemented by the system. - - - - - Returns the state of the flip setting. TRUE if on; FALSE if off. - - - - - Returns the axis setting. - One of the following values: - - 0: X axis. - - 1: Y axis. - - 2: Z axis. - - - - - Description: - This class is an interface to the LookAt Constraint rotation controller. You can obtain a pointer to the list control interface using; GetILookAtConstInterface(cd). This macro will return (ILookAtConstRotation*)(CD)->GetFPInterface(LOOKAT_CONSTRAINT_INTERFACE). - - LOOKAT_ROT_PBLOCK_REF may be used to access the look-at controller's references: - - All methods of this class are Implemented by the System. - - - - - Returns the number of nodes in the list of nodes to look at. - - - - - Gets the weight of one of the Look-At nodes that the Look-At constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the Look-At target list whose weight is to be obtained. - - - - - Sets the weight of one of the Look-At nodes that the Look-At constraint controller follows, specified by targetNumber. - Parameters: - targetNumber - - The node number in the Look-At target list whose weight is to be set. float weight - - The weight to set. - - - TRUE if there is more than one Look-At targets in the list and you are trying to set weight, FALSE otherwise. - - - - - Appends the current Look-At target list by one and appends the current Look-At target weightlist by one. - Parameters: - *target - - The node that is to be appended to the current Look-At target list. - - float weight=50.0 - - This is the weight that is to be assigned to the newly appended Look-At target. The default weight is 50.0. - TRUE if the target was appended, otherwise FALSE. - - - - - This method allows you to delete a specified target. - Parameters: - int selection - - The zero based node number in the list of nodes the controller looks at. - - - - - Gets the relative/absolute mode corresponding to the "Keep Initial Offset" checkbox in the UI. - - - - - Gets the ViewLine relative/absolute mode corresponding to the "Keep ViewLine Length Absolute" checkbox in the UI. When Viewline Length is absolute, the "ViewLine Length" spinner sets the length of the ViewLine. A negative length implies that starting from the source object the line travels opposite to the direction of the target object. The source/target distance has no effect on the ViewLine length in this mode. If the "Keep ViewLine Length Absolute" checkbox is unchecked, the ViewLine length is determined from the spinner value, which is interpreted as a percentage of the source/target distance. - TRUE if the ViewLine length is absolute, FALSE otherwise. - - - - - Returns TRUE if the "World" checkbox is on; FALSE if off. - - - - - Returns TRUE if the "selected" axis flip checkbox is on; FALSE if off. - - - - - Returns TRUE if the "source" axis flip checkbox is on; FALSE if off. - - - - - Returns TRUE if the orientation flag is set, FALSE if off. - - - - - Gets the selection corresponding to the "Select LookAtAxis" button in the UI. Obtains which of the source axes is required to coincide with the target axis. - (0) if the target axis coincides with the x axis of the source object. (1) if the target axis coincides with the y axis of the source object. (2) if the target axis coincides with the z axis of the source object. - - - - - Gets the selection corresponding to the "Source/UpnodeAlignment: Aligned to UpNode Axis:" radiobutton in the UI. Obtains which of the upnode axes is required to align with a specified source axis. - (0) if the upnode x axis coincides with a specified source object. (1) if the upnode y axis coincides with a specified source object. (2) if the upnode z axis coincides with a specified source object. - - - - - Gets the selection corresponding to the "Source/UpnodeAlignment: Aligned to UpNode Axis:" radiobutton in the UI. Obtains which of the source axes is required to align with a specified upnode axis. - (0) if the source x axis coincides with a specified upnode axis. (1) if the source y axis coincides with a specified upnode axis. (2) if the source z axis coincides with a specified upnode axis. - - - - - Resets to zero the amount of orientation offset, effected through the "Set Orientation" feature. - - - - - Gets the vector line length of one of the Look-At nodes that the Look-At constraint controller follows. - - - - - - - This class allows a plugin to post a Task to be executed on 3DS Max main thread. It is necessary for example to modify 3DS MaxUI controls which can only be done from 3DS Max main thread. - - - - - Call this method to execute a task on 3DS Max main thread. - - - - the Task to be executed (see Task), will be freed by the system. - - - - This will execute all the pending tasks. This should only be called from the main thread, the call is ignored otherwise. - - - - - Returns true if there are pending tasks. - - - - - Description: - This is the abstract interface class for Manager Objects - - The ID of this class is MANIP_MGR_INTERFACE. - - - - - This method allows you to create a spherical mesh gizmo. - Parameters: - & pos - - The position of the sphere. - - float radius - - The radius of the sphere - - int segments - - The number of segments in the sphere. - A pointer to the resulting mesh. - - - - - This method allows you to create a torus mesh gizmo. - Parameters: - & pos - - The position of the torus. - - float radius - - The radius of the torus. - - float radius2 - - The second radius of the torus. - - int segs - - The number of segments in the torus. - - int sides - - The number of sides of the torus. - A pointer to the resulting mesh. - - - - - This method allows you to create a box mesh gizmo. - Parameters: - & pos - - The position of the box. - - float l - - The length of the box. - - float w - - The width of the box. - - float h - - The height of the box. - - int lsegs - - The length segments of the box. - - int wsegs - - The width segments of the box. - - int hsegs - - The height segments of the box. - A pointer to the resulting mesh. - - - - - This method creates a default plane gizmo. - - - - - This method creates a plane gizmo. - Parameters: - & p1 - - The first point of the plane. - - & p2 - - The second point of the plane. - - & p3 - - The third point of the plane. - - - - - This method creates a plane gizmo. - Parameters: - & normal - - The normal of the plane - - & point - - The center point in space of the plane. - - - - - This method returns the XY plane. - - - - - This method returns the XZ plane. - - - - - This method returns the YZ plane. - - - - - This method will create a default gizmo shape. - - - - - This method will make a circular gizmo shape. - Parameters: - & center - - The center of the circle. - - float radius - - The radius of the circle. - - int segments - - The number of segments of the circle. - A pointer to the resulting gizmo shape. - - - - - This method will get the current state of the Mode. - The current object manipulator display mode. - - - - - This method will set the current state of the Mode. - Parameters: - int newMode - - The new mode to use. - The previous object manipulator display mode. - - - - - Description: - This class represents the material extension interface with the interface ID IMATERIAL_INTERFACE_ID. - - - - - This method returns a pointer to the material base. - - - - - This method returns a pointer to the node associated with the material interface. - - - - - This interface allows materials and textures to customize their appearance in the Browser. - - - This class is optional, and may be provided by plug-ins of superclass MATERIAL_CLASS_ID or TEXMAP_CLASS_ID. There is no obligation to implement it, and no guarantee it will be provided by internal materials or textures. If implemented, the plug-in class should return its instance of this interface in response to ClassDesc::GetInterface(IMATERIAL_BROWSER_ENTRY_INFO_INTERFACE). The system fetches the interface from the . The interface allows a plug-in to customize the default appearance of its entries, as shown in the Browser. This includes the display name, the thumbnail, and the location (or category) of entries. The user may further customize the appearance of the Browser; those customizations are saved in a configuration file, and may override values provided by this class. The class is implemented by the plug-in. - - - - - Get the UI name of the entry. This name will be displayed in the Browser, instead of the class name from the class descriptor. - - - The UI name of the entry. - - - - - The category under which the entry will appear in the material/map browser. The category is formatted as a path, with multiple levels of categorization being delimited by backslashes ("\\"). - - - The base level should be one of the standard categories used by system materials and maps - i.e. "Maps", "Materials", etc. The next level could be a categorization based on the target use case or renderer - e.g. "Standard", "XYZRenderer", etc. Further levels of categorization are up to the developer. - The category string, formatted as described above. - - - - - Get the UI thumbnail of the entry, if any. This thumbnail will be displayed in the Browser, instead of a rendered sample. This improves performance by avoiding a render, and allows a customized display in the browser. The system automatically displays a scaled image according to the current thumbnail size, but the preferred size is 100x100 pixels, to accommodate large thumbnails without upscaling. - - - The thumbnail bitmap of the entry, or NULL if none. - - - - - Returns whether the entry supports a custom thumbnail via GetThumbnail(). If this returns false, the system will render a thumbnail for display in the Browser. - - - true if a thumbnail can be provided, false otherwise. - - - - - A new interface for 3ds Max 2008. - - - This interface is used for manipulating material shading model in the viewport. A material would implement this interface so as to control the "Show map in viewport" (SMIV) button. In 3dsmax 2008 the SMIV button can now show as a flyoff, for regular shading (Blue) and Hardware shading (Pink). If a material supports a Hardware representation then it can implement this interface and return the correct level support in IsShadingModelSupported. This will mean the UI is reflective of the support available. This interface DOES NOT provide any support for the actual Hardware implementation - purely the UI synchronisation. - An implementation for this interface can be found at \maxsdk\samples\materials\StdMaterialViewportShading.cpp where it support the case where the material deals with plugin hardware shaders as well. Currently in 3ds max 2008, only two materials implement a Hardware version, and they are the Standard and Mental Images's Architectural and Design . - - - - - Does the material support a specific shading model in viewport. This will be used to enable\disable the SMIV options. - if the shading model is supported, return true; otherwise return false - - The shading model, for now it must be Standard or Hardware. - - - - Used to query the material for its current level of viewport rendering - current shading model. - - - - - the shading model of the material in viewport. - If the shading model is set successfully, return true; otherwise return false. - - The shading model, must be Standard or Hardware. - - - - The map levels needs to be defined by the material, it will tell the various shader compilers how far to go in the search of materials/maps. Most materials will stop searching after one level, as the shader becomes too complex. For example specifiying 1 will mean the first map found will be used e.g a in a diffuse slot. The compiler will not search any further for maps to support. In this case it will probably bake the submaps to textures and will not try to generate - shader code for these submaps. - How deep the shader compilers will go in the search of material/Maps in the tree. - - - - - Description: - This class represents an abstract interface class for a default bitmap viewer. - - The following functions are available for use but are not part of the class . - - Note that the minimum size of the floating window is 390 x 325. - - - - - This method returns a pointer to the bitmap that is being displayed by the bitmap viewer. - - - - - This method returns a pointer to the crop callback function used by the bitmap viewer. - - - - - This method returns TRUE if the viewer is autonomous, otherwise FALSE. When the bitmap viewer is set in autonomous mode, the viewer will not have a clone button, although the viewer will not display a clone button unless the save button is also displayed. - - - - - This method returns the current position of the bitmap viewer. - - - - - This method returns TRUE if the save button is shown as part of the bitmap viewer window, otherwise FALSE. - - - - - This method will display the bitmap image viewer. Note that the Show() and Hide() methods have no effect until the window is initialized by a call to Display(). This method should not be called when the window is already open and this method can't be used to create a docked viewer. - - You should also not call this twice on this interface. The second time the function is called, the viewer will loose all references to the previoulsy opened window. To switch images using the same bitmap viewer, a call to "UnDisplay" should be made to close the previous window before calling this method again. - - - Parameters: - MCHAR *title - - The title of the window to set. - - WindowPosition position = WPos_Center - - The window position you wish to set, which is one of the following enum values; WPos_NULL, WPos_UpperLeft, WPos_LowerLeft, WPos_UpperRight, WPos_LowerRight, WPos_Center. - TRUE if successful, otherwise FALSE. - - - - - This method will display the bitmap image viewer. Note that the Show() and Hide() methods have no effect until the window is initialized by a call to Display(). For docked viewers, the hParent parameter is the window into which te viewer will be docked. For floating viewers, the parameter has no effect. - - You should also not call this twice on this interface. The second time the function is called, the viewer will loose all references to the previoulsy opened window. To switch images using the same bitmap viewer, a call to "UnDisplay" should be made to close the previous window before calling this method again. - Parameters: - MCHAR *title - - The title of the window to set. - - HWND hParent - - A handle to the parent window. - - int x, y, h, w - - The position and dimensions of the window. - - Note that these parameters will be ignored unless 'Current Position' is WPos_NULL. - TRUE if successful, otherwise FALSE. - - - - - This method will undisplay the current bitmap image. The Show() and Hide() methods will no longer function after the window is destroyed. - - - - - This method will clear the bitmap image viewer window contents. This will not delete the window as it would using the Delete button on the viewer toolbar which actually deletes the contents of the bitmap. - - - - - This method will transform a specified point between the window's client coordinates and the bitmap coordinates and return the result. - Parameters: - const POINT &pt - - The point on screen. - - - - - This method will transform a specified point between the window's client coordinates and the bitmap coordinates and return the result. - Parameters: - const POINT &pt - - The point on the bitmap. - - - - - This method will transform a specified rectangle between the window's client coordinates and the bitmap coordinates and return the result. - Parameters: - const Rect &rect - - The screen rectangle. - - - - - This method will transform a specified rectangle between the window's client coordinates and the bitmap coordinates and return the result. - Parameters: - const Rect &rect - - The bitmap rectangle. - - - - - This method allows you to set whether the toolbar should be shown as part of the bitmap image viewer window. - Parameters: - bool show - - TRUE to show; FALSE to hide. - - - - - This method allows you to toggle the toolbar of the bitmap image viewer window on and off. - - - - - This method will retrieve the portion of the window's client area that is safe to draw in (in client coordinates and below the toolbar). This method can return a value larger than the displayed bitmap if the window size is large enough. - Parameters: - Rect& drawableRect - - The client area. - - - - - This method will refresh the region of the window, or the entire window if region is NULL - Parameters: - Rect* pRefreshRegion = NULL - - The region of the window you wish to refresh. - - - - - Description: - This abstract class represents an interface for all general menu settings. Methods that are marked as internal should not be used. - - - - - This method is used internally. - - This method checks if a token is valid. - Parameters: - ValidityToken& token - - A reference to a token for which to check its validity. - TRUE if the token is valid, otherwise FALSE. - - - - - This method is used internally. - - This method updates the validity token. - Parameters: - ValidityToken& token - - A reference to a token to update. - - - - - This method will reset the menu settings to their defaults. - - - - - This method returns the menu border size. - - - - - This method returns the menu's horizontal margin size (in points). - - - - - This method returns the menu's vertical margin size (in points). - - - - - This method returns the menu's horizontal margin, in pixels. - Parameters: - HDC hDC - - A handle to a device context. - - - - - This method returns the menu's vertical margin, in pixels. - - - Parameters: - HDC hDC - - A handle to a device context. - - - - - This method returns the name of the menu item's font typeface. - - - - - This method returns the name of the menu title's font typeface. - - - - - This method returns the menu item's font size, in points. - - - - - This method returns the menu title's font size, in points. - - - - - This method returns TRUE or FALSE if the menu item's uniform height flag is set or not set, respectively. - - - - - This method returns TRUE or FALSE if the menu item's uniform height flag is set or not set, respectively. This version of GetUniformItemHeight() is provided for the function publishing system. - - - - - This method returns the menu's opacity value. - - - - - This method returns the menu's display method, which is either of the following; DM_NORMAL, DM_STRETCH, DM_FADE, DM_NUM_METHODS - - - - - This method returns the menu's number of animated steps used for the 'growing' effect. - - - - - This method returns the menu's animated step time, in milliseconds. - - - - - This method returns the delay before a submenu is displayed, in milliseconds. - - - - - This method returns whether the "last executed item" flag is set (TRUE) or not set (FALSE). The flag determines whether to use the menu's last executed item when the user clicks on the menu's titlebar. - - - - - This method returns whether the "last executed item" flag is set (TRUE) or not set (FALSE). The flag determines whether to use the menu's last executed item when the user clicks on the menu's titlebar. This version of GetUseLastExecutedItem() is provided for the function publishing system. - - - - - This method returns the status of the flag which controls and determines whether the menu is repositioned when near the edge of the screen. - TRUE if the flag is ON, otherwise FALSE. - - - - - This method returns the status of the flag which controls and determines whether the menu is repositioned when near the edge of the screen. This version of GetRepositionWhenClipped() is provided for the function publishing system. - TRUE if the flag is ON, otherwise FALSE. - - - - - This method returns the status of the flag which controls and determines whether the menu should remove redundant separators. - TRUE if the flag is ON, otherwise FALSE. - - - - - This method returns the status of the flag which controls and determines whether the menu should remove redundant separators. This version of GetRemoveRedundantSeparators() is provided for the function publishing system. - TRUE if the flag is ON, otherwise FALSE. - - - - - Description: - This class facilitates taking care of node handles when merging and xref'ing scenes. - - When nodes are merged, their handles will be reassigned so that their handles will not conflict with existing nodes in the scene. After the merge process has completed, all merged objects will receive a reference notification; REFMSG_NODE_HANDLE_CHANGED. The PartID (see PartID) will be a pointer to a merge manager interface that you can use to see if a specific handle was converted and convert between the old and the new handle. IMergeManager* pMergeManager = (IMergeManager*)partID; If a plug-in uses node handles in a persistent manner it has to intercept this reference message and convert the previous handles to the newly generated handles. - - - - - This method allows you to obtain a new handle. - Parameters: - ULONG oldHandle - - The old handle you wish to obtain a new one for. - The new handle. - - - - - This method allows you to check if a handle already exists. - Parameters: - ULONG handle - - The handle you wish to check for. - TRUE if the handle exists; otherwise FALSE. - - - - - is the interface into the Skin Wrap(Mesh) modifier - - - - - This selects the control point cage vertices. - - - - - this is which wrap mesh you are getting the selection from each wrap mesh keeps it own selection list - - the bitarray representing the selection - - whether to update the view and the modifier - - - - This returns the current selected control points on the cage. - - - - - this is which wrap mesh you are setting the selection to each wrap mesh keeps it own selection list - - - - This returns the number of control points on the cage. - - - - - this is which wrap mesh you are getting the number of control pointss from - - - - This returns the local scale factor for a control point. - - - The total influence area is equal to the control points distance * global distance * local scale - - - this is which wrap mesh you are getting the info from - - this is which control point you want to get - - - - This lets you set a control points local scale. - - - - - this is which wrap mesh you are setting the info to - - this is the index of the point you want to set - - this is the scale of the point - - - - this returns the strength of a control point - - - - - this is which wrap mesh you are getting the info from - - this is the index of the control point you want to get - - - - This lets you set the strength of a control point. - - - - - this is which wrap mesh you are setting the info to - - this is the index of the control point you want to set - - this is the strength - - - - This returns the initial tm of the control point. - - - - - this is which wrap mesh you are getting the info from - - the control point index - - - - This returns the current tm of the control point. - - - - - this is which wrap mesh you are getting the info from - - the control point index - - - - This returns the size of the envelope of a control point. - - - - - this is which wrap mesh you are getting the info from - - the control point index - - - - this is the vertex that forms the x axis, the z axis is the normal - - - - - this is which wrap mesh you are getting the info from - - the control point index - - - - This mirrors the current selected control points. - - - This is identical to pushing the Mirro button in the UI - - - - - This bakes the control point data into the app data of the node that is the control mesh. - - - This is identical to pushing the Bake button in the UI - - - - - This retrieves the control point data from the app data of the node that is the control mesh. - - - This is identical to pushing the Retrieve button in the UI - - - - - This forces the modifier to resample itself. This will force all weights to be recomputed. - - - - - same as Resample - - - - - Update the neighbouring weight lists on selection change. - - - The system keep tracks of a potential weight lists by using neighbor data. Any time a selection is changed this potential weight list needs to be updated use this function to update that list. - This should be called after any control point selection change. - - - - - This forces the selected control points to have their weights rebuilt this should be called when you change the str/scaling etc of a control point. - - - - - returns the number of deformed vertices - - - - - the node that owns the local data - - - - this returns the number of weights of a vertex - - - - - the node that owns the local data - - the vertex index that you want to get the number of weights from - - - - this returns a particular weight of a vertex - - - - - the node that owns the local data - - the vertex index that you want to get the weight - - the weight index you want to get - - - - this returns a particular distance of a vertex - - - - - the node that owns the local data - - the vertex index that you want to get the weight - - the weight index you want to get - - - - this returns the control point that owns this weight - - - - - the node that owns the local data - - the vertex index that you want to get the weight - - the weight index you want to get - - - - this returns the wrap node that owns this weight - - - - - the node that owns the local data - - the vertex index that you want to get the weight - - the weight index you want to get - - - - This forces the modifier to reset itself. - - - This is identical to pressing the reset button in the UI. This will force all weights and param space to be recomputed - - - - - This takes the weighting generated from a wrap modifier and turns it into a skin modifier. - - - This requires that the modifier not be instances and all the wrap objects be driven by skin - - - this suppresses any warning/error message boxes - - - - Description: - This class provides access to selection data for the Select , Editable and Edit modifier. - - To get a pointer to this interface given a pointer to a modifier or editable mesh object, use the following macro (defined in AnimatableInterfaceIDs.h ). Using this macro, given any , it is easy to ask for the interface. - - GetMeshSelectInterface(anim) ((IMeshSelect*)anim->GetInterface(I_MESHSELECT)) - - A plug-in developer may use this macro as follows: - - ; - - This return value will either be NULL or a pointer to a valid Select interface. - - - - - Returns the current level of selection for the modifier. - One of the following values: - - IMESHSEL_OBJECT: level. - - IMESHSEL_VERTEX: Vertex level. - - IMESHSEL_FACE: level. - - IMESHSEL_EDGE: level. - - - - - This method must be called when the of the modifier is changed. Developers can use the methods of to get and set the actual selection for vertex, face and edge. When a developers does set any of these selection sets this method must be called when done. - - - - - Returns TRUE if this modifier or object has weighted vertex selection data (Soft Selection data), FALSE if not. - Default Implementation: - { return FALSE; } - - - - - Returns TRUE if this modifier or object can assign weighted vertex selection data; FALSE if it cannot. - Default Implementation: - { return FALSE; } - - - - - Description: - When a developer gets the from the of the Select or Edit , they may cast it to this class and use these methods. They may be used to get/set the vert/face/edge selection state of the modifier. This class also provides access to the named sub-object selection sets. - - To get a pointer to this interface given a pointer to a modifier use the following macro (defined in AnimatableInterfaceIDs.h ). Using this macro, given any , it is easy to ask for the interface. - - GetMeshSelectDataInterface(anim) ((IMeshSelectData*)anim->GetInterface(I_MESHSELECTDATA)) - - A plug-in developer may use this macro as follows: - - ; - - This return value will either be NULL or a pointer to a valid Select Data interface. - - - - - Returns a that reflects the current vertex selection. There is one bit for each vertex. Bits that are 1 indicate the vertex is selected. - - - - - Returns a that reflects the current face selection. There is one bit for each face. Bits that are 1 indicate the face is selected. - - - - - Returns a that reflects the current edge selection. There is one bit for each edge. Bits that are 1 indicate the edge is selected. - - - - - Sets the vertex selection of the modifier. - Parameters: - &set - - There is one bit for each vertex. Bits that are 1 indicate the vertex is selected. - - *imod - - This parameter is available in release 3.0 and later only. - - Points to the instance (generally this is a modifier). - - TimeValue t - - This parameter is available in release 3.0 and later only. - - The current time at which the call is made. - - - - - Sets the face selection of the modifier. - Parameters: - &set - - There is one bit for each face. Bits that are 1 indicate the face is selected. - - *imod - - This parameter is available in release 3.0 and later only. - - Points to the instance (generally this is a modifier). - - TimeValue t - - This parameter is available in release 3.0 and later only. - - The current time at which the call is made. - - - - - Sets the edge selection of the modifier. - Parameters: - &set - - There is one bit for each edge. Bits that are 1 indicate the edge is selected. - - *imod - - This parameter is available in release 3.0 and later only. - - Points to the instance (generally this is a modifier). - - TimeValue t - - This parameter is available in release 3.0 and later only. - - The current time at which the call is made. - - - - - Returns a reference to an instance of used for storing vertex level named selection sets. This class provides access to and the ability to manipulate a list of named selection sets. - - - - - Returns a reference to an instance of used for storing edge level named selection sets. This class provides access to and the ability to manipulate a list of named selection sets. - - - - - Returns a reference to an instance of used for storing face level named selection sets. This class provides access to and the ability to manipulate a list of named selection sets. - - - - - Retrieves the weighted vertex selections data (Soft Selection data). - Parameters: - int nv - - The number of vertices. - - float *sel - - An array of floats to store the results. - Default Implementation: - {} - - - - - Sets the weighted vertex selection data (Soft Selection data) to the values passed. - Parameters: - int nv - - The number of vertices. - - float *sel - - An array of floats with the data. - - *imod - - Points to the object. - - TimeValue t - - The time at which to set the data. - Default Implementation: - {} - - - - - The interface for creating, adding, removing and keeping track of meta-data on max Animatables. - - - Meta-data are custom attributes that contain only a parameter block. In order to create meta-data, you have to create its definition by specify the parameters first. This will give you a meta-data ID. You can then use that ID to add, remove or list meta-data in the scene. - - - - - Create a meta-data definition for further use in meta-data manager functions. - - - The ID returned will allow the user to add or remove meta-data in the scene and to keep track of them. - EmptyMetaDataID if for any reason the definition cannot be created: - - - a name for the custom attribute set. - - a name for an eventual rollout. - - an array of descriptions for each parameter in the param block. - - (optional): pointer to a MSTR. If non-null and the definition cannot be created, will contain a description of the reason. - - - - Create a meta-data instance and add it to the custom attribute container of an animatable. - - - If the meta-data already exists for an animatable, it will not get added. - the MetaData if created successfully, NULL otherwise - - - the meta-data ID of the custom attribute set to be created. - - the to which the custom attribute set will be added. - - the insertion index of the custom attribute. Default is to append - - - - Create meta-data instances and add it to the custom attribute container of animatables. - - - If the meta-data already exists for an animatable, it will not get added. - - - the meta-data ID of the custom attribute set to be created. - - an array of Animatables to which the custom attribute set will be added. - - an array of MetaData that were created successfully. - - if true, a single instance will be created and shared by all animatables. - - the insertion index of the custom attribute. Default is to append - - - - Remove a meta-data from the custom attribute container of an animatable. - - - true if the MetaData was removed - - - the meta-data ID of the custom attribute to be removed. - - the from which the custom attribute set will be removed. - - - - Returns the number of meta-data in the scene. - - - - - Finds all owners of meta-data of a given meta-data ID. - - - - - the meta-data ID of the meta-data. - - an array of Animatables that own meta-data of the given ID. - - - - Returns whether a definition exists for a given meta-data ID. - - - true if the MetaData was defined. - - - the meta-data ID to be checked. - - - - Checks the existence of meta-data of a given ID on an animatable. - - - the meta-data if it exists. - - - the animatable to be checked for meta-data. - - the meta-data ID to be checked. - - - - Finds all meta-data on an animatable. - - - - - the animatable to be checked for meta-data. - - an array of the meta-data on the . - - - - An interface to the new functionality for max 8 for the mixer. In particularly, new information for max mixers. - - - Contains functionality relating to the new functionality for max mixers, including setting and getting the name and the nodes in a max mixer. The interface is accessed via TheMaxMixerManager.GetNthMaxMixer or TheMaxMixerManger.GetMaxMixer /see MaxMixerManager::GetNthMaxMixer /see MaxMixerManager::GetMaxMixer - - - - - Whether or not a max mixer or a biped mixer. - - - Returns true if it's a max mixer, false if it's a biped mixer. - - - - - Returns the interface for the specified clip. - - - The new trackgroup interface for this clip. May return NULL if an invalid index is passed in. - - The index of the trackgroup. - - - - the nodes for the max mixer. This function does nothing for biped mixers. - - - - The nodes that the mixer will now contain. Note that a node may only be in one mix at a time. The nodes that the new max mix now contains will be returned in this tab. - If TRUE than any node that is no longer part of the max mixer will collapse the animation thats in the mixer onto it's mixed tracks. If FALSE than the original animation that was on these nodes when the node was added to the mixer will now revert back onto the node. - - - - Get the nodes for this max mixer. This function does nothing for biped mixers. - - - - The nodes that make up this max mixer. - - - - Get the name of the mixer. - - - The name of the mixer. - - - - - the name of the mixer. - - - Returns truue if the name was changed correctly, returns false if the name wasn't changed either because the mix is a biped mix or the name of the mix already exists in the mixer. - - The name of the mix. Note that you can only set the name name of max mixes and not biped mixes since their name cames from the name of the biped root node. - - - - INTERNAL USE. - - - - - Description: - This is the interface into the Skin Morph modifier. It contains methods to get access to the Skin Morph UI actions and the data in the Skin Morph modifier. - - - - - void fnAddBone(INode *node)=0; This adds a bone to the system *node the bone to add - - - - - void fnRemoveBone(INode *node) This removes a bone from the system *node the bone to remove - - - - - void fnSelectBone(node,const MCHAR morphName) This selects a bone and/or morph in the selection list. If the morphName is null only the bone will be selected. node this is the node to be selected MCHAR morphName this is the morph to be selected - - - - - INode* fnGetSelectedBone() This returns the current active bone - - - - - MCHAR* fnGetSelectedMorph() This returns the name of the current selected morph - - - - - void fnSelectVertices(INode *node,BitArray *sel) This lets you select vertices. *node this is the node that owns the modifier, this is used to find a specific instance of the modifier and apply it to the right local data *sel the selection array - - - - - BOOL fnIsSelectedVertex(INode *node,int index) *node this is the node that owns the modifier, this is used to find a specific instance of the modifier and apply it to the right local data int index this the index of the vertex that you want to check - - - - - void fnResetGraph() this is equivalent to pressing the reset graph button in the UI which resets the the soft selection graph to a sinual graph - - - - - void fnShrink() This contracts your vertex selection - - - - - void fnGrow() This expands your vertex selection - - - - - void fnRing() This turns your current selection into a ring selection - - - - - void fnLoop() This turns your current selection into a loop selection - - - - - void fnCreateMorph(INode *node) This creates a new morph for a bone *node this is the bone that you want to create the morph on - - - - - void fnRemoveMorph(INode *node, const MCHAR *name) This removes a morph target *node this is the bone that owns the morph that you want to remove MCHAR *name this is the name of the morph that you want to remove - - - - - fnEdit(BOOL edit) This toggles on/off the edit morph mode. The current active morph is the one that will be edited BOOL edit the edit mode state - - - - - void fnClearSelectedVertices() This ie equivalent to press the clear verts button in the UI which takes the selected vertices and sets their delta to zero - - - - - void fnDeleteSelectedVertices() This ie equivalent to press the delet verts button in the UI which takes the selected vertices and removes them from the current morph - - - - - void fnResetOrientation(INode *node, const MCHAR *name) This resets the orientation of morph to the current orientation of the bone that owns it *node this is the bone that owns the morph to be reset MCHAR *name this is the name of the morph to be reset - - - - - void fnReloadTarget(INode *node, const MCHAR *name) This reloads the external mesh for a morph if there is one *node this is the bone that owns the morph to be reloaded MCHAR *name this is the name of the morph to be reloaded - - - - - fnMirrorPaste(INode *node) This mirror pastes the node to its mirror target based on the mirror parameters *node this is the node that is to be mirrored - - - - - void fnEditFalloffGraph(INode *node, const MCHAR *name) This brings up the falloff graph of a morph if there is one *node this is the bone that owns the morph MCHAR *name this is the name of the morph to to have its graph brought up - - - - - void fnSetExternalNode(INode *node, const MCHAR *name,INode *exnode) This lets you set the external mesh node for a morph *node this is the bone that owns the morph MCHAR *name this is the name of the morph to to have its external node set - - - - - void fnMoveVerts(Point3 vec) This moves the selected vertices along a vec which is applied to an active morph if there is one vec this is the vec which the vertices are moved. - - - - - void fnTransFormVerts(Matrix3 a, Matrix3 b) This transforms the selected vertices which is applied to an active morph if there is one Matrix a this is matrix transformation Matrix b this is the space? - - - - - int fnNumberOfBones() This is the number of bones in the system - - - - - Matrix3* fnBoneGetInitialNodeTM(INode *node) This returns the initial node tm of bone. This is the tm of the bone when it is added to the system the initial node tm is used to determine the actual deformation *node this is the bone that you want get the tm from - - - - - void fnBoneSetInitialNodeTM(INode *node, Matrix3 tm) This lets you set the initial node tm of a bone *node this is the bone that you want set the tm on tm this is the initial tm - - - - - Matrix3* fnBoneGetInitialObjectTM(INode *node) This returns the initial object tm of bone. This is the tm of the bone when it is added to the system the initial object tm is used only for display *node this is the bone that you want get the tm from - - - - - void fnBoneSetInitialObjectTM(INode *node, Matrix3 tm) This lets you set the initial object tm of a bone *node this is the bone that you want set the tm on tm this is the initial tm - - - - - Matrix3* fnBoneGetInitialParentTM(INode *node) This returns the initial node tm parent that owns bone. - *node this is the bone that you want get the parent tm from - - - - - void fnBoneSetInitialParentTM(INode *node, Matrix3 tm) This lets you set the parent tm of a bone. - *node this is the bone that you want set the tm on tm this is the parent tm - - - - - int fnBoneGetNumberOfMorphs(INode *node) This returns the number of morphs that a bone owns *node this the bone to get the number of morphs from - - - - - the follow le get/set properties of individual morphs they all follow the same format *node is the bone that owns the morph int morphIndex is the index of the morph - - - - - These let you get access to the morph vertex properties every morph contains a list of vertices and properties *node is the bone that owns the morph int morphIndex is the index of the morph int ithIndex is which vertex you want to get info about the index back into the mesh vertex list - - - - - the vector in local bone space - - - - - the vector in parent space - - - - - the original point before any deformation - - - - - this returns which node owns the vertex if ther modifier is instanced - - - - - void fnUpdate() This forces a system to update - - - - - This return the weight of particular morph is contributing *node is the bone that owns the morph MCHAR*name this is the name of the morph - - - - - - - - - Returns the name of the filter. - - - - - Returns if this filter is enabled. The filter manager will not call disabled filters. - - - true if this filter should be applied - - - - - Used to enable/disable this filter. - - - - - if false, disable this filter by returning false from Enabled - - - - Called when this filter is added to the manager. - - - - - Called when a filter is removed from the manager. - - - - - Returns whether the given material/map should be included in the browser, when browsing for existing materials/maps. - - - true if this material should be included in the browser - - - The material/texmap to be filtered - - See . - - - - Returns whether the given material/map should be included in the browser, when browsing for 'new'. - - - true if this material should be included in the browser - - - The material/map class descriptor to be filtered - - See . - - - - Description - This is the manager for the material and texture map browser filters. It is used to add, remove and access filters for the browser. - - - - - Adds a filter to the list. - - - false if filter could not be added because duplicate. - - - A new filter to add to the browser - - - - Remove a filter from the list. - - - false if filter could not be removed because not found. - - The filter to be removed - - - - Query the list of filters currently assigned. - - - the number of applied filters - - - - - Query the list of filters currently assigned. - - - The filter at index i - - - the index of the filter to return - - - - Returns whether the i-th filter is enabled. - - - - - Enables/disables the i-th filter. - - - - - Get the name of the i-th filter. - - - - - Run the given material/map through all the filters in the list. - - - Returns true if and only if all filters accept to include that material/map. - true if every filter accepts mtlBase - - - the to be filtered - - See . - - - - Run the given through all the filters in the list. - - - Returns true if and only if all filters accept to include that . - true if every filter accepts mtlBase - - - The material/map class descriptor to be filtered - - See . - - - - Description: - This class represents the interface to the Editor. You can obtain a pointer to the Editor interface using; IMtlEditInterface* GetMtlEditInterface (). This macro will return - - *)GetCOREInterface(MTLEDIT_INTERFACE). - - All methods of this class are Implemented by the System. - - - - - This method returns a material base pointer for the current material. - - - - - This method allows you to set the active material slot. - Parameters: - int i - - The material slot index. - - BOOL forceUpdate = FALSE - - this to TRUE to update the slot contents. - - - - - This method returns the index of the active material slot. - - - - - This method allows you to put the specified material to the specified material editor slot. - Parameters: - *mtlBase - - The material you want to put. - - int slot - - The index of the material slot you wish to put the material into. - - - - - This method returns a pointer to the material base from the specified slot. - Parameters: - int slot - - The index of the material slot for which you wish to obtain the material. - - - - - Before assigning material to scene, call this to avoid duplicate names. - Parameters: - *m - - The pointer to the material. - - - - - This method makes sure the Materials Editor slots correctly reflect which materials are used in the scene, which are used by selected objects, etc. This is used internally for the drag-and-drop of materials to nodes - there is no reason why a plug-in developer should need to call it. - - - - - Description: - This is the interface that is passed in to the material or texture map when it is in the material editor. All methods of this class are implemented by the system. - - - - - This method may be called to causes the viewports to be redrawn. It should be called when any parameter that affects the look of the material in the viewport has been altered. If the material is not on a visible node in a shaded view, nothing will happen. This method should NOT be called as a spinner is being dragged, but only upon release of the mouse button. - - - - - This method may be called to add a rollup page to the material editor dialog. It returns the window handle of the dialog that makes up the rollup page. - Parameters: - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the message sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar. - - LPARAM param=0 - - Any specific data to pass along may be stored here. This may be later retrieved using the GetWindowLong() call from the Windows API. - - DWORD flags=0 - - The following flag is defined: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The window handle of the rollup page. - - - - - This method is used to replace the rollup page whose index is passed. - Parameters: - HWND hOldRollup - - The handle to the rollup to replace. - - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the message sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar. - - LPARAM param=0 - - Any specific data to pass along may be stored here. - - DWORD flags=0 - - Append rollup page flags: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The handle of the replacement page is returned. - - - - - This method may be called to remove a rollup page and destroy it. - Parameters: - HWND hRollup - - The handle of the rollup window. This is the handle returned from AddRollupPage(). - - - - - This method allows hand cursor scrolling when the user clicks the mouse in an unused area of the dialog. When the user mouses down in dead area of the material editor, the plug-in should pass mouse messages to this function. - - Note: In 3ds Max 2.0 and later only use of this method is no longer required - the functionality happens automatically. - Parameters: - HWND hDlg - - The window handle of the dialog. - - UINT message - - The message sent to the dialog proc. - - WPARAM wParam - - Passed in to the dialog proc. Pass along to this method. - - LPARAM lParam - - Passed in to the dialog proc. Pass along to this method. - Example: - case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: - - im->iMtlParams->RollupMouseMessage(hDlg,message,wParam,lParam); - - - - - Returns nonzero if the rollup page whose handle is passed is open; otherwise zero. - Parameters: - HWND hwnd - - The window handle of the rollup page to check. - - - - - Returns the rollup scroll position. This is used, for example, by the Standard material because it saves and restores the rollup page positions with the material. This is just a convenience for the user. - - - - - Registers a callback object that will get called every time the current animation time is changed. - Parameters: - *tc - - The callback called when the time changes. See Class . - - - - - This method un-registers the time change callback. - Parameters: - *tc - - The callback called when the time changes. See Class . - - - - - This is called automatically in AddRollupPage(), so a plug-in doesn't need to do it. It is now obsolete. - Parameters: - HWND hDlg - - The handle of the dialog window. - - - - - This method is called automatically and is now obsolete. - Parameters: - HWND hDlg - - The handle of the dialog window. - - - - - Returns the current time (the frame slider position). - The current time. - - Pick an object from the scene - - - - - Calling this methods puts the user into a pick mode where they can select items in the scene. - Parameters: - *proc - - This is the callback object for the picking. Its methods allow for filtering the picks, changing cursors over valid hits, and allowing multiple picks. See Class . - - - - - This method is called to terminate the pick mode. - - - - - This method returns an interface to Materials Editor rollup. - - - - - Description: - This interface is used to determine whether a material/map flags itself as being compatible with a specific renderer plugin. If the material/map flags itself as being compatible with a renderer, then it is deemed compatible with that renderer regardless of what class might say. - Implementation: - To be inherited by a or of a or plugin. The child class needs to call Init(*this) in its constructor. - Default compatibility: - If neither the renderer nor the material/map implements the compatibility interface, they are considered compatible by default. - Material/map browser icon: - The interface also provides a way of defining an icon that appears in the material browser - GetCustomMtlBrowserIcon. This can be used to provide an Enabled/Disabled color. In mental ray enabled uses a yellow icon, the DirextX 9 uses a pink icon. Developers can use this to highlight special materials or textures. - - - - - Initialization method. MUST be called from the constructor of the child class. i.e. "Init(*this);". - - - Reference to sub-class instance - - - - Returns whether this material/map is compatible with the given renderer. (Use the class ID of the renderer to determine compatibility). - - - Class descriptor of a plugin - - - - Provides custom icons for the material/map browser. Returns true if custom icons are provided. - - When using this method, the developer should keep a single instance of the imagelist used, and it is the developers responsibility to release the memory - true if custom icons are provided - - - The image list from which the icons are extracted. The images should have a mask. - - Index (into image list) of icon to be displayed when the material/map has the "Show Maps in Viewport" flag turned OFF. - - Index (into image list) of icon to be displayed when the material/map has the "Show Maps in Viewport" flag turned ON. - - Index (into image list) of icon to be displayed when the material/map is NOT COMPATIBLE with the current renderer. - - - - Description: - This interface is used to determine whether a flags itself as being compatible with a specific material/map plugin. If the flags itself as being compatible with a material/map, then it is deemed compatible with that material/map regardless of what class might say. - Implementation instructions: - To be inherited by a or of a plugin. The child class needs to call Init(*this) in its constructor. - Default compatibility: - If neither the renderer nor the material/map implements the compatibility interface, they are considered compatible by default. - - - - - Initialization method. MUST be called from the constructor of the child class. i.e. "Init(*this);". - - - Reference to sub-class instance - - - - Returns whether this material/map is compatible with the given renderer. (Use the class ID of the renderer to determine compatibility). - true if this renderer is compatible with the given material - - - Class descriptor of or plugin - - - - The multipass camera effect allows modification of viewpoints and view directions or time for each pass of a multipass rendering. Algorithms such as Depth of Field, Scene motion blur can be implemented using multipass techniques. A multipass camera effect is a plug-in to camera objects. It allows the renderer to query the camera for the view params for each pass of the rendering, and provides a dithered combining function to combine the bitmaps produced by each pass into the final bitmap. It also allows time to be manipulated for each rendering pass, providing effects such as motion blur. - - - - - Some cameras are not compatible with some render effects, this method allows cameras to list compatible effects in the UI and as such allows the effect to declare its compatibility with the current camera object. - TRUE if compatible, otherwise FALSE. - - A pointer to a camera object. - - - - There is a UI option on multipass effects that indicates whether the renderer should display each pass as it is rendered. Note this is not used by viewport renderer, because of the hardware involvement. This method returns whether to display individual passes as they are computed. - TRUE if display is on, otherwise FALSE. - - The rendertime at which to check the display passes. - - - - The multipass effect also has a variable number of passes. This method tells the renderer how many passes to render per final output frame and as such returns the total number of passes to be rendered - - The rendertime at which to check the display passes. - - - - This method will modify the camera, camera node, or time value to affect each pass. This is the modify function called for each pass of the frame. The effect can alter the camera node, camera object, or override the render time in the course of this call. 3ds Max renderers take an optional parameter viewParams* that when not NULL overrides the normal rendering camera. When this is called the override render time will be set to the current frame time. If the value is changed, this will be the time value used for the pass. Note that at the time that apply is called, the renderer has not yet been called, hence it is possible, with care, to alter the scene in a general way, not just the camera & time parameters. Apply should return NULL if the normal unmodified camera is to be used. - The viewparams returned by apply which are supplied to the renderer. - - A pointer to the node of the camera. - A pointer to the camera object. - The number of the pass. - The time if you wish to override the render time. - - - - This method will blend each pass (src) into the final accumulator (dest). After each pass is rendered, it needs to be combined into the final output bitmap. The current multipass effects use a dithered combiner, so that hard edges from the passes are more smoothly blended. There are many ways to do this, with varying quality, so this method allows different future implementations. Note that this is not used by the viewport renderer, as there's no way to tell the hardware to do this. Hardware is for fast & edgy, software is for slow and smooth. - - The destination bitmap. - The source bitmap. - The number of the pass. - The render time. - - - - This method is called after all passes have been rendered. After all passes have been rendered & accumulated, this method will be called so that the effect can do any final cleanup. Currently unused, it can be ignored by multipass effects if they wish. - - - - - Description: - This interface defines methods that manipulate the MultiTile map. It is derived by MultiTileMap - - - - - Get TilePatternFormat enum from the MultiTile map. - Current TilePatternFormat value. - - - - - Get pattern format through specified file path. - Return one of the pattern format if the file path match its regulation, return Custom if match none of them. return Invalid if file path is null string. - - The patterned file path to check. - - - - Get ViewportQuality enum from the MultiTile map. - Current ViewportQuality value. - - - - - a patterned image file to the MultiTile map. It first verifies file name pattern with current pattern format, return false if the file name pattern is invalid. If the pattern is ok, it searches the directory where file resides to find other image files that match the pattern, and load all of them and return true. The MultiTile map creates a tile list with these patterned image files. - Return true if current pattern format is one of the 3 valid formats of TilePatternFormat, and file name is matched with current pattern format. Otherwise, return false. - - The patterned file path to be set. - - - - an image file to the specified tile of a MultiTile map. If current tile pattern format is one of the 3 valid foramts of TilePatternFormat, the tile index must be zero. Otherwise return false and do nothing. It then follows same work flow as SetPatternedImageFile. If current tile pattern format is Custom format, the tile index could be zero, or value other than zero. It sets image file path as it is without verification and matching. - Return true if current pattern format is one of the 3 valid formats of TilePatternFormat, and file name is matched with current pattern format. Otherwise, return false. - - The tile index to be set with new image file. - The image file path to be set. - - - - Return file prefix of current pattern format. - Return file prefix if current pattern format is one of the 3 valid formats of TilePatternFormat, return nullptr if current pattern format is Custom, or patterned image file has not been set. - - - - - UV offset to specified tile. It only works in Custom format. - If current format is Custom and tile index is valid, return true. Otherwise, return false. - - The tile to be set UV offset. - The U offset to be set. - The V offset to be set. - - - - Get UV offset with specified tile. The returned UV offset are truncated to integer. If the texmap is 3D, return X, Y axis offset instead. - If the tile index is valid, return true. Otherwise, return false. - - The tile to be set UV offset. - The returned U offset, truncated to integer. - The returned V offset, truncated to integer. - - - - Append a new tile to existing list. - - - - - Delete specified tile. If index is invalid, or this is the last layer, no action occurred - - The tile index to be deleted. - - - - The interface for Image Motion Blur. - - - This interface is implemented in the plug-in MotionBlur.dlv, which must be present to use it. This interface is does NOT support scripting, only direct calling. The sample code below shows how this is done: - - - - - Sets the channels required for the image motion blur. - Parameters: - ULONG flags=0 - - The following flag may be set: - - IMB_TRANSP - - Controls whether motion blur works through transparency. Setting it to 0 saves memory, runs faster. - - - - - Applies the motion blur process to the specified bitmap. - Parameters: - *bm - - The bitmap to apply the motion blur to. - - *progCallback=NULL - - A pointer to a callback, allowing an abort check during the progress. - - float duration=1.0f - - The motion blur duration. - - ULONG flags=IMB_TRANSP - - The following flag may be set: - - IMB_TRANSP - - Controls whether motion blur works through transparency. Setting it to 0 saves memory, runs faster. - - Bitmap* extraBM=NULL - - If the extraBM bitmap is supplied, then that is used as the target color bitmap, but the gbuffer information still comes from the other, main, bitmap. this is used to apply motion blur to render lements. - TRUE if success, otherwise FALSE. - - - - - Description: - This is an interface into the motion capture manager. This interface is passed to plug-ins derived from class . All methods of this class are implemented by the system. - - - - - This method is obsolete. - - - - - This method returns the current time at which it is called. This is an aide for devices where interaction is happening asynchronously (the MIDI interface is an example of this). The MIDI motion capture device uses a separate thread to track the MIDI keyboard. When the user presses a key, the MIDI device plug-in needs to record which key was pressed and when. It calls this method to grab the current 3ds Max time at which it happened. - - - - - Description: - If a motion capture controller has one of the following class IDs, then it can be cast into this class to give access to the controller's parameters. - - POS_MOTION_CLASS_ID - - ROT_MOTION_CLASS_ID - - SCALE_MOTION_CLASS_ID - - FLOAT_MOTION_CLASS_ID - - POINT3_MOTION_CLASS_ID - - Note that normally a developer will not call these methods. - - All methods of this class are implemented by the system. - - - - - Returns TRUE if Live mode is on; otherwise FALSE. Live mode is invoked by pressing the 'Test' button in the Motion Capture user interface. - - - - - Returns TRUE if Record mode is on; otherwise FALSE. Record mode is set by pressin the 'Start' button in the Motion Capture user interface. - - - - - Returns the number of device bindings. - - - - - Returns a pointer to the 'i-th' device binding. - Parameters: - int i - - Specifies which device binding to return. - - - - - Sets the 'i-th' device bindings. - Parameters: - int i - - Specifies which device binding to set. - - *b - - Points to the device binding to set. - - - - - This method retrieves the value based on the current state of the device (not the value of the controller). For instance, say you have done some motion capture using a joystick plugged into a position motion capture controller. You can call GetValue() on the controller to get its recorded value (just like a keyframe controller), or you can call this method to get the actual state of the joystick. - Parameters: - TimeValue t - - Specifies the time to update the value. - - void *val - - Points to the value that is updated. See for the data types returned here. - - GetSetMethod method - - One of the following values: - - CTRL_RELATIVE - - Indicates the plug-in should apply the value of the controller to *val. - - CTRL_ABSOLUTE - - Indicates the controller should simply store its value in *val. - - - - - Description: - This class is an interface to allow the plug-in to provide a user interface in the command panel. It has two data members. - Data Members: - *binding; - - Returns a pointer to the device binding. - - *iRoll; - - This is an interface into the command panel. Its methods may be used to work with rollup pages and alter UI controls. - - - - - class for handling interactive face extrude operations, such as the shift-drag face extrude implemented in Editable Poly and Edit Poly. - Usage: - - - - - Performs the topology changes for the face extrude operation, following the approach of MNMesh::ExtrudeFaceClusters, for the faces flagged with faceFlag, and sets up the data structures required to perform further processing in UpdateFaceExtrude and EndFaceExtrude. - - the MN_XXX selection flag used to faces to be extrude - - - - Performs intermediate postprocessing after extruded faces have been moved or scaled. Guaranteed not to alter geometry or topology of entities existing in the mesh prior to the first call to this function for a particular extrude operation, but may alter flags. - flag indicating whether topology was altered - - - - - Finalizes postprocessing of the extrude operation. May alter vertex MN_WHATEVER flags. - flag indicating whether topology was altered - - - - - Extends the class, adding new functionality applied on a . Usage: - See for details on using this interface. - - - - - Chamfers mesh edges like MNMesh::ChamferEdges. - true if the chamfer operation was successful - false if the chamfer operation failed - the mesh geometry is valid, even if the operation failed - - the edge flag used. See for a description of flag values. - the chamfer data. - If true, the newly created faces are removed, creating a hole between chamfered edges. - The number of new edges to create per selected edge. If in_segments < 1, then behave as though in_segments = 1. - - - - Constrains the positional offsets given for each vertex so that they are limited to travel along each corresponding vertex normal. - Returns true if the function succeeds false if it doesn't for any reason. - - A tab of positional changes for each vertex in the mesh. If the count of deltaIn is different than the number of vertices in the mesh, the function will return false. - A tab of the resulting positional changes for each vertex in the mesh after the incoming changes in deltaIn are constrained by the vertex normal. The deltaOut parameter maybe equal to deltaIn parameter. The count of the deltaOut parameter will get modified so that it's the same as number of vertices in the mesh. - - - - Extends the class, adding new functionality applied on a . The added functions are used for selecting subobject loops or rings when the Shift key is pressed. See for details on using this interface. - Usage: - - - - - Finds a vertex loop based on the newly selected vertex and the currently selected vertices. If a loop is found the loop vertices are added to the hitSel . - true if a loop was found - false if no loop was found - - the newly selected vertices that are about to get added to the selection. - the currently selected vertices. - - - - Finds an edge loop or ring based on the newly selected edge and the currently selected edges. If a loop or ring is found the loop/ring edges are added to the hitSel . - true if a loop or ring was found - false if no loop or ring was found - - the newly selected edges that are about to get added to the selection. - the currently selected edges. - - - - Finds a face loop based on the newly selected face and the currently selected faces. If a loop is found the loop faces are added to the hitSel . - true if a loop was found - false if no loop was found - - the newly selected faces that are about to get added to the selection. - the currently selected faces. - - - - Extends the class for 2018 Update 4, adding new functionality applied on a . The added functions are a new GetExtrudeDirection that allows for distance to be computed from surface instead of along normal. - NOTE should only be used now for support of loading older file less than 2019.1 - Usage: - - - - - This improves the GetExtrudeDirection instead of just using the length applied to the normal it computes the distance perpendicular from the surface and uses that to compute the distance along the normal. - - The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well - defined way to modify mapping values during an extrusion drag.) - which flag to uses that defines the extrusion. - is the blend along the normal and distance from tha surface - - - - Extends the class for 2019.1. Fixes various issues with extruding. - Usage: - - - - - This improves the GetExtrudeDirection instead of just using the length applied to the normal it computes the distance perpendicular from the surface and uses that to compute the distance along the normal. - - The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well - defined way to modify mapping values during an extrusion drag.) - which flag to uses that defines the extrusion. - is the blend along the normal and distance from tha surface - - - - Extends the class for 2020. - Usage: - - - - - Performs chamfers on a mesh, with varying versions - true if mesh altered; false otherwise - - The Quad Chamfer parameter data (See ) - - - - This improves the GetExtrudeDirection instead of just using the length applied to the normal it computes the distance perpendicular from the surface and uses that to compute the distance along the normal. - - The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well - defined way to modify mapping values during an extrusion drag.) - which flag to uses that defines the extrusion. - is the blend along the normal and distance from the surface - if true use pre-2026 behavior which returned a instead of a - - - - Extends the class for 2020 Update 1. - Usage: - - - - - Performs chamfers on a mesh, with varying versions - true if mesh altered; false otherwise - - The Quad Chamfer parameter data (See ) - - - - Extends the class for 2020 Update 2. - Usage: - - - - - Performs vertex chamfers on a mesh, using the new segmented quad chamfer approach. - true if mesh altered; false otherwise - - The quad vertex chamfer parameter data (See ) - - - - Chamfers mesh edges like MNMesh::ChamferEdges. - true if the chamfer operation was successful - false if the chamfer operation failed - the mesh geometry is valid, even if the operation failed - - the edge flag used. See for a description of flag values. - the chamfer data. - Either everything, chamfered edges only (inverted), or without chamfered edges (opened). - The number of new edges to create per selected edge. If in_segments < 1, then behave as though in_segments = 1. - - - - Chamfers mesh vertices like MNMesh::ChamferVertices. - true if the chamfer operation was successful - false if the chamfer operation failed - the mesh geometry is valid, even if the operation failed - - the vertive flag used. See for a description of flag values. - the chamfer data. - Either everything, chamfered vertices only (inverted), or without chamfered vertices (opened). - - - - extends the class, adding new functionality applied on a . Such an interface is obtained through the call to GetInterface, using the class id: IMNMESHUTILITIES8_INTERFACE_ID on an instance of an . usage is : IMNMeshUtilities8* l_meshToBridge = static_cast<IMNMeshUtilities8*>(mesh.GetInterface( IMNMESHUTILITIES8_INTERFACE_ID )); - bridging: This is an extension of the existing bridge border method. It bridges 2 sets od edges of different size. you can bridge 4 edges with 5 edges. Limitations. the 2 edge lists must be disjoint, or at least separated by a sharp angle. this angular threshold can be adjusted by using the in_adjacentAngle parameter, Connectedges: 2 new parameters are added for better precision: in_pinch and in_slide. SelectEdgeRingShift: selects edges in the ring direction - - - - - Check if a face's cache is invalid. The function first checks if the whole mesh or the face have been flagged as cache invalid (MN_CACHEINVALID). If none of these is true, it then cycles through the face's vertices and returns true as soon as it finds a vertex flagged with MN_CACHEINVALID. - faceIndex must be a valid index in the faces (f) array. - true if the face is invalid, else false. - - The index of the face for which you want to determine cache validity - - - - Invalidates a single vertex's cache indicating it needs to be rebuilt. The function flags the specified vertex with the MN_CACHEINVALID flag, telling the rebuild functions that this vertex, the faces surrounding it and the other vertices of those faces need to have their normals recomputed. It also sets normalsBuilt to 0 to trigger normals' rebuild. This function should be called when one to several vertices have been modified. If all or almost all vertices of the mesh have been invalidated, it's more efficient to call InvalidateGeomCache() instead. - vertex must be a valid index in the vertex (v) array. - - The index of the vertex that needs to be invalidated. - - - - Bridges 2 edges - true if the bridging operation was successful - false if the bridging operation failed - in_sourceEdge and in_targetEdge must be different - in_sourceEdge and in_targetEdge must on border - the mesh geometry is valid, even if the operation failed - - 1st edge index to bridge - 2nd edge index to bridge - number of polys between the edges - internal value, do not use - new face smoothing Group index - new face material id - internal value, do not use - algorithm to be employed when triangulating generated faces - - - - Bridges edge selection - true if the bridging operation was successful - false if the bridging operation failed - in_sourceEdge and in_targetEdge must be different - in_sourceEdge and in_targetEdge must on border - the mesh geometry is valid, even if the operation failed - - edge cluster flag. - threshold angle, in radians, for smoothing successive columns of the bridge. - number of polys between the edges - angular threshold in radians for splitting one contiguous edge list in 2 in order to perform the bridging on 2 separate edge lists - reverse triangle's position: if true, triangles will be added at the end of the bridge, if they are needed ( when bridging 4 edges with 5 edges - algorithm to be employed when triangulating generated faces - - - - Creates new connections between opposing edges of the specified type. If two edges are opposed they will each be split into a number (specified by in_segements) of equally sized segments. New edges will be created from the new vertexes created on each edge - true if the connection operation was successful - false if the connection operation failed - in_segments must be greater than 1 - in_pinch and in_slide must be between -100 and 100 - the mesh geometry is valid, even if the operation failed - - edge cluster flag - number of connection edges between successive selected edges - distance between successive new connection edges. Can be < 0. - position of the new connection edges, relative to the existing edges. Can be < 0. - triangulation algorithm to employ - - - - selection shifting routine: shifts the current edge selection in the ring direction - the io_edgeSel , must exist with the proper size - the io_edgeSel contains the list of the shifted edges - - shifting value, can be positive or negative - the new edge selection list - - - - selection shifting routine: shifts the current edge selection in the loop direction - the io_edgeSel must exist with the proper size - the io_edgeSel contains the list of the shifted edges - - shifting value, can be positive or negative - the new edge selection list - - - - Vertex splitting method, using a distance value for specifying the distance between the split vertices. - the MNmesh is valid, with the selected vertices ,split apart, using the in_distance. - - the vertex flag used - to split the vertices apart - - - - splitting method, using a distance value for specifying the distance between the split edges. - the MNmesh is valid with the selected vertices ,split apart, using the in_distance. - - the vertex flag used - to split the selected edges apart - - - - Creates a bitArray indicating the directions of the 's edges relative to 2 arbitrary edges: the 2 first edges of the first face of the . For a MNesh made of quads ( like a converted plane), they are the 2 first edges of the lower left face. - the array io_edgeFlip does not need to exist - the array exists and contains number of edges entries. - - - array of flipped edges - if this is true, only selected edges will be tested against the 2 original edges. - - - - New chamfer method: A new parameter is added, allowing the creation of holes when chamfering. - true if the chamfer operation was successful - false if the chamfer operation failed - the mesh geometry is valid, even if the operation failed - - the edge flag used - the chamfer data - If true, the newly created faces are removed, creating a hole between chamfered edges. - - - - New Vertex chamfer method : A new parameter is added, allowing the creation of holes when chamfering. - true if the chamfer operation was successful - false if the chamfer operation failed - the mesh geometry is valid, even if the operation failed - - the vertices flag used - the chamfer data - If true, the newly created faces are removed, creating a hole between chamfered vertices. - - - - for changes made to in version 9.5. For use with . Usage: - - - - - Returns pointer to object. owns the memory. - pointer to allocated object - - - - - Deallocates data allocated by ChamferData(). MNTempData::freeChamferData calls this function. - - - - - Description: - This class represents the interface to the MAXScript Zip Package Manager. You can obtain a pointer to the Browser Manager interface using; GetMSZipMgr()IMSZipMgr* . This macro will return (IMSZipMgr*)GetCOREInterface(MSZIP_MGR_INTERFACE). - - All methods of this class are Implemented by the System. - - - - - This method will unload and run a zip package and return the extract_dir. - Parameters: - MCHAR* file_name - - The file name of the ZIP script package. - - MSTR& extract_dir - - The directory in which the files were extracted. - TRUE if successful, otherwise FALSE. - - - - - This method will unload the package while ignoring any drop or run commands and return the extract_dir and any primary drop file. If the primary dropFile is a *.ds, compile it in context of the package and return the in dropScript. - Parameters: - MCHAR* file_name - - The file name of the ZIP script package. - - MSTR& extract_dir - - The directory in which the files were extracted. - - MSTR& dropFile - - The primary drop file. - - MacroEntry*& dropScript - - The resulting . - TRUE if successful, otherwise FALSE. - - - - - An interface to the new functionality for max 8 for clips in the mixer. - - - Contains functionality relating to the new functionality for max clips, including the name of the max map file, and the particular transition information needed to transition max clips. Inherits from . The interface is accessed via IMXclip::GetClip8 or IMXclip::GetTransClip8 /see IMXtrack8::GetClip8 /see IMXtrack8::GetTransClip8 - - - - - Get the nodes that make up the velocity blended nodes for a transition. Only works with max clips. - - - - The nodes whose positions and orientations are accumulated and blended via velocity for this clips transition - - - - the nodes that make up the velocity blended nodes. Only works with max clips. - - - - The nodes whose positions and orientations are accumulated and bleneded via their velocities in this clip - - - - Get the nodes that make up the the sub blended nodes. Only works with max clips. - - - - Nodes who will get their positions and orientations blended in the coordinate space of their corresponding subBlendNode parent thats found by calling GetSubBlendNodesParents. - - - - the nodes that make up the sub blended nodes. Only works with max clips. - - - - Nodes who will get their positions and orientations blended in the coordinate space of their corresponding subBlendNode parent. You should call this functions first before calling SetSubBlendNodesParents. - - - - Get the nodes that make up the sub blended nodes parents. Only works with max clips. - - - - An array of 'parent' nodes whose coordinate space the sub blend nodes will blend in. - - - - the nodes that make up the sub blended parent nodes. Only works with max clips. - - - - The nodes whose coordinate space the sub blend nodes will blend in . Should be called after SetSubBlendNodeParents, and there's a 1-1 correspondance between the the two arrays. - - - - Whether or not a max clip or a biped clip. - - - Returns True if it's a max clip, false if it's a biped clip - - - - - The name of the possible map file for a max clip. - - - the name of the map file if one exists, otherwise returns empty string - - - - - Loads the clip with the given options and animation files. Only works with max clips. - - - True if the file was loaded successfully, else returns false - - Must be one of the following defined in . RE_SOURCE_CLIP_ONLY, RE_SOURCE_INSTANCES, RE_SOURCE_FILEGROUP. RE_SOURCE_CLIP_ONLY: the file will be loaded into just this single clip. RE_SOURCE_INSTANCES: the file will be loaded into this clip and all instances of this clip. RE_SOURCE_FILEGROUP: the file will be loaded into this clip and all instances and adaptations of this clip. - The name of the max animation file(.xaf) to be loaded. It valid .xaf file must be supplied or the load will fail and the function will return false - The name of the possible animation map file(.xmm) used for mapping the clip. This value may be NULL. - - - - whether or not velocity blended nodes yaw,pitch and roll angles will get accumulated or not. Only works with max clips. - - - - If true the yaw orientation (angle about local z)will get velocity blended, otherwise it will get blended normally. - If true the pitch orientation(angle about local x) will get velocity blended, otherwise it will get blended normally. - If true the roll orientation(angle about local y) will get velocity blended, otherwise it will get blended normally. - - - - Get whether or not velocity blended nodes yaw,pitch and roll angles will get accumulated or not. Only works with max clips. - - - - If true the yaw orientation (angle about local z)gets velocity blended, otherwise it will get blended normally. - If true the pitch orientation(angle about local x) gets velocity blended, otherwise it will get blended normally. - If true the roll orientation(angle about local y) gets velocity blended, otherwise it will get blended normally. - - - - the transition yaw,pitch and roll angles. - - - - The additional yaw angle the clip will transition around - The additional pitch angle the clip with transition around - The additional roll angel the clip will transition around - - - - Get the transition yaw,pitch and roll angles. - - - - The additional yaw angle of the current transition. - The additional pitch angle of the curren transition. - The additional roll angel of the current transition - - - - whether or not velocity blended nodes x,y, and z positions will get accumulated or not. Only works with max clips. - - - - If true the x position, will get velocity blended, otherwise it will get blended normally. - If true the y position, will get velocity blended, otherwise it will get blended normally. - If true the z position, will get velocity blended, otherwise it will get blended normally. - - - - Get whether or not velocity blended nodes x,y and z positions will get accumulated. - - - - If true the x position gets velocity blended, otherwise it will get blended normally. - If true the y position gets velocity blended, otherwise it will get blended normally. - If true the z position gets velocity blended, otherwise it will get blended normally. - - - - An interface to the new functionality for max 8 for tracks in the mixer. - - - Contains functionality relating to the new functionality for max tracks, mainly the ability to get or append new clips. Inherits from . The interface is accessed via IMXtrackgroup8::GetTrack8. /see IMXtrackgroup8::GetTrack8 - - - - - Returns the interface for the specified clip. - - - The new clip interface for this clip. May return NULL if an invalid parameter,either improper row or index, is passed in. - - Which clip you want to get, >=0. - Which row the clip you want to get is in, value may be BOT_ROW or TOP_ROW defined in For layer tracks, only BOT_ROW is a valid input. - - - - Returns the interface for the specified clip. - - - The new clip interface for this clip. May return NULL if an invalid parameter is passed in. - - The index of the sorted clips in the transition track. Takes into account both rows when indexing the clips. - - - - Whether or not a max track or a biped track. - - - Returns true if it's a max track, false if it's a biped track. - - - - - Loads the specified max animation file as a clip onto the track. Only works for max tracks. - - - false if the files can't be loaded or the mapping isn't correct. If the clip is created properly, returns true. - - The filename of the .xaf file to be loaded. - The filename of the .xmm map file to be loaded. Defaults to NULL, - The number of frames from the end of the last clipin the track that the new clip will be appended in layer tracks. The interval must be >=0. Not that for transistion tracks, this parameter is ingnored and the start of the new clip will be at theinpoint of the last clip in the track, and it will be on the opposite row of the last clip. Also the parameter is ignored if there are no clips in the track, the clip will automatically start at frame 0. - - - - An interface to the new functionality for max 8 for trackgroups in the mixer. In particularly, new information for max trackgroups. - - - Contains functionality relating to the new functionality for max trackgrouops, mainly the new filter for max mixes. Inherits from . The interface is accessed via IMXclip::GetTrackgroup8 /see IMixer8::GetTrackgroup8 - - - - - Whether or not a max trackgroup or a biped trackgroup. - - - Returns true if it's a max trackgroup, false if it's a biped trackgroup. - - - - - Returns the interface for the specified clip. - - - The new track interface for this clip. May return NULL if an invalid index is passed in. - - The index of the track. - - - - Get the nodes that are filtered in the current max mix. Only works with max trackgroups. - - - - The nodes which are filtered in the max mix. - - - - the filtered nodes for this trackgroup. Only works with max trackgroups. - - - - The nodes that you want to be filtered in this trackgroup. - - - - The non-maxscript-version of particle container in the Init/Proceed/Release calls for operator and test. - - - - - The particle system in the Init/Proceed/Release calls for operator and test. - - - - - The particle system node in the Init/Proceed/Release calls for operator and test. - - - - - The list of actions during initialization in the Init/Proceed/Release calls for operator and test. - - - - - The list of action nodes during initialization in the Init/Proceed/Release calls for operator and test. - - - - - Start of the proceed interval in the Init/Proceed/Release calls for operator and test. - - - - - End of the proceed interval in the Init/Proceed/Release calls for operator and test. - - - - - the end time if the test can't proceed particles to the given time end in the Init/Proceed/Release calls for test. - - - - - The node of the action in the Init/Proceed/Release calls for operator and test. - - - - - Update cycle integrator in the Init/Proceed/Release calls for operator and test. - - - - - Get random sign { -1, 1 }. - - - - - Get random number between 0.0f and 1.0f. - - - - - Get random number between -1.0f and 1.0f. - - - - - Get random number between -0.5f and 0.5f. - - - - - Get integer random number between 0 and maxnum. - - - - - Get random point from sphere surface of radius 1. - - - - - Returns a vector with the same length as a given vector but the direction differs from the given for no more than maxAngle. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Used to define whether particle channel will be used by the operator/test. - - - - - Method to get/set properties of the particle in the container. - - - - - Add a single particle to particle system. Returns true if the operation was completed successfully. - - - - - Add "num" particles into the particle system. Returns true if the operation was completed successfully. - - - - - Delete a single particle with the given index. Returns true if the operation was completed successfully. - - - - - List-type delete of "num" particles starting with "start". Returns true if the operation was completed successfully. - - - - - Each particle is given a unique ID (consecutive) upon its birth. The method allows us to distinguish physically different particles even if they are using the same particle index (because of the "index reusing"). - - - - index of the particle in the range of [0, NumParticles-1] - - - - Implemented by the Plug-In. The methods verifies if a particle with a given particle id (born index) is present in the particle container. The methods returns index in the container. If there is no such particle, the method returns false. - - - - particle born index - particle index in the particle group or particle system - - - - Defines "current" index, used to get the property without specifying the index. - - - - - Defines "current" bornIndex, used to get the property without specifying the index. - - - - - Defines if a particle just arrived into the current event. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle container - - - - See IsParticleNewByIndex(). - - - - particle born index - - - - See IsParticleNewByIndex(). - - - - - Defines time for the current state for a particle. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. Modification of the time is only accessible for tests, and only for particles that satisfy the test. - - - - int, particle index in the particle container - - - - See GetParticleTimeByIndex(). - - - - int, particle born index - - - - See GetParticleTimeByIndex(). - - - - int, particle index in the particle container - TimeValue, time of the current state for the particle - - - - See GetParticleTimeByIndex(). - - - - int, particle index in the particle container - TimeValue, time of the current state for the particle - float, if you need more precision to set time value then use the timeDelta parameter - - - - See GetParticleTimeByIndex(). - - - - int, particle born index - TimeValue, time of the current state for the particle - - - - See GetParticleTimeByIndex(). - - - - int, particle born index - TimeValue, time of the current state for the particle - float, if you need more precision to set time value then use the timeDelta parameter - - - - See GetParticleTimeByIndex(). - - - - - Defines age of the specified particle. Particle is specified by either its index in the particle group or particle system, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleAgeByIndex(). - - - - particle born index - - - - See GetParticleAgeByIndex(). - - - - particle index in the particle group - new age value to set for a particle - - - - See GetParticleAgeByIndex(). - - - - particle born index - new age value to set for a particle - - - - See GetParticleAgeByIndex(). - - - - - Defines lifespan of the specified particle. Particle is specified by either its index in the particle group or particle system, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleLifespanByIndex(). - - - - particle born index - - - - See GetParticleLifespanByIndex(). - - - - particle index in the particle group - new lifespan value to set for a particle - - - - See GetParticleLifespanByIndex(). - - - - particle born index - new lifespan value to set for a particle - - - - See GetParticleLifespanByIndex(). - - - - - Defines for how long the specified particle was staying in the current action list (event). Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle container - - - - See GetParticleEventTimeByIndex(). - - - - particle born index - - - - See GetParticleEventTimeByIndex(). - - - - particle index in the particle container - how long particle was staying in the current action list (event) - - - - See GetParticleEventTimeByIndex(). - - - - particle born index - how long particle was staying in the current action list (event) - - - - See GetParticleEventTimeByIndex(). - - - - - Defines position of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticlePositionByIndex(). - - - - particle born index - - - - See GetParticlePositionByIndex(). - - - - particle index in the particle group - position of the particle - - - - See GetParticlePositionByIndex(). - - - - particle born index - position of the particle - - - - See GetParticlePositionByIndex(). - - - - - Defines speed of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleSpeedByIndex(). - - - - particle born index - - - - See GetParticleSpeedByIndex(). - - - - particle index in the particle group - speed of the particle in units per frame - - - - See GetParticleSpeedByIndex(). - - - - particle born index - speed of the particle in units per frame - - - - See GetParticleSpeedByIndex(). - - - - - Defines acceleration of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. The acceleration is reset in the each update cycle so the operator/test should update it for each particle in each proceed call. - - - - particle index in the particle group - - - - See GetParticleAccelerationByIndex(). - - - - particle born index - - - - See GetParticleAccelerationByIndex(). - - - - particle index in the particle group - acceleration of the particle in units per frame squared - - - - See GetParticleAccelerationByIndex(). - - - - particle born index - acceleration of the particle in units per frame squared - - - - See GetParticleAccelerationByIndex(). - - - - - Defines orientation of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleOrientationByIndex(). - - - - particle born index - - - - See GetParticleOrientationByIndex(). - - - - particle index in the particle group - orientation of the particle. The orientation is defined by incremental rotations by world axes X, Y and Z. The rotation values are in degrees. - - - - See GetParticleOrientationByIndex(). - - - - particle born index - orientation of the particle. The orientation is defined by incremental rotations by world axes X, Y and Z. The rotation values are in degrees. - - - - See GetParticleOrientationByIndex(). - - - - - Defines angular speed of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleSpinByIndex(). - - - - particle born index - - - - See GetParticleSpinByIndex(). - - - - particle index in the particle group - angular speed of the particle in rotation per frame, axis defines rotation axis, angle defines rotation amount per frame - - - - See GetParticleSpinByIndex(). - - - - particle born index - angular speed of the particle in rotation per frame, axis defines rotation axis, angle defines rotation amount per frame - - - - See GetParticleSpinByIndex(). - - - - - Defines scale factor of the specified particle in the current state. The XYZ form is used for non-uniform scaling. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleScaleByIndex(). - - - - particle born index - - - - See GetParticleScaleByIndex(). - - - - particle index in the particle group - uniform scale factor - - - - See GetParticleScaleByIndex(). - - - - particle born index - uniform scale factor - - - - See GetParticleScaleByIndex(). - - - - - See GetParticleScaleByIndex(). - - - - particle index in the particle group - - - - See GetParticleScaleByIndex(). - - - - particle born index - - - - See GetParticleScaleByIndex(). - - - - particle index in the particle group - scale factor for each local axis of the particle - - - - See GetParticleScaleByIndex(). - - - - particle born index - scale factor for each local axis of the particle - - - - See GetParticleScaleByIndex(). - - - - - Defines transformation matrix of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleTMByIndex(). - - - - particle born index - - - - See GetParticleTMByIndex(). - - - - particle index in the particle group - transformation matrix of the particle - - - - See GetParticleTMByIndex(). - - - - particle born index - transformation matrix of the particle - - - - See GetParticleTMByIndex(). - - - - - Defines selection status of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleSelectedByIndex(). - - - - particle born index - - - - See GetParticleSelectedByIndex(). - - - - particle index in the particle group - selection status of the particle - - - - See GetParticleSelectedByIndex(). - - - - particle born index - selection status of the particle - - - - See GetParticleSelectedByIndex(). - - - - - Defines shape of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. if no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleShapeByIndex(). - - - - particle born index - - - - See GetParticleShapeByIndex(). - - - - particle index in the particle group - shape of the particle - - - - See GetParticleShapeByIndex(). - - - - particle born index - shape of the particle - - - - See GetParticleShapeByIndex(). - - - - - the same shape for all particles. See GetParticleShapeByIndex(). - - - - shape of the particle - - - - Defines material index of the specified particle in the current state. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - material index of the particle - - - - See SetParticleMtlIndexByIndex(). - - - - particle born index - material index of the particle - - - - See SetParticleMtlIndexByIndex(). - - - - material index of the particle - - - - Defines mapping of the specified particle in the current state. All vertices of the particle are assigned the same map value. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - mapping channel; range from 0 to MAX_MESHMAPS-1 - mapping value of the particle - - - - See SetParticleMappingByIndex(). - - - - particle born index - mapping channel; range from 0 to MAX_MESHMAPS-1 - mapping value of the particle - - - - See SetParticleMappingByIndex(). - - - - mapping channel; range from 0 to MAX_MESHMAPS-1 - mapping value of the particle - - - - Defines integer value of the specified particle. The methods can be used to keep integer data with the particle, and to be used later. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleIntByIndex(). - - - - particle born index - - - - See GetParticleIntByIndex(). - - - - particle index in the particle group - integer value of the particle - - - - See GetParticleIntByIndex(). - - - - particle born index - integer value of the particle - - - - See GetParticleIntByIndex(). - - - - - Defines float value of the specified particle. The methods can be used to keep float data with the particle, and to be used later. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleFloatByIndex(). - - - - particle born index - - - - See GetParticleFloatByIndex(). - - - - particle index in the particle group - float value of the particle - - - - See GetParticleFloatByIndex(). - - - - particle born index - float value of the particle - - - - See GetParticleFloatByIndex(). - - - - - Defines vector value of the specified particle. Can be used to keep vector data with the particle, and to be used later. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - int, particle index in the particle group - - - - See GetParticleVectorByIndex(). - - - - int, particle born index - - - - See GetParticleVectorByIndex(). - - - - int, particle index in the particle group - vector value of the particle - - - - See GetParticleVectorByIndex(). - - - - int, particle born index - vector value of the particle - - - - See GetParticleVectorByIndex(). - - - - - Defines matrix value of the specified particle. Can be used to keep matrix data with the particle, and to be used later. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - - - - See GetParticleMatrixByIndex(). - - - - particle born index - - - - See GetParticleMatrixByIndex(). - - - - particle index in the particle group - matrix value of the particle - - - - See GetParticleMatrixByIndex(). - - - - particle born index - matrix value of the particle - - - - See GetParticleMatrixByIndex(). - - - - - Defines test status (true or false) for particles while testing. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - particle index in the particle group - test status - - - - See SetParticleTestStatusByIndex() - - - - particle born index - test status - - - - See SetParticleTestStatusByIndex() - - - - - the same test status for all particles. - - - - test status - - - - Defines the time when a particle satisfies the test. Particle is specified by either its index in the particle container, or by its born index. If no index is specified then the "current" index is used. - - - - int, particle index in the particle group - TimeValue; time when a particle satisfies the test - - - - See SetParticleTestTimeByIndex(). - - - - int, particle index in the particle group - TimeValue; time when a particle satisfies the test - float, if testTime parameter doesn't have enough precision then use the delta for fine tuning the test time - - - - See SetParticleTestTimeByIndex(). - - - - int, particle born index - TimeValue; time when a particle satisfies the test - - - - See SetParticleTestTimeByIndex(). - - - - int, particle born index - TimeValue; time when a particle satisfies the test - float, if testTime parameter doesn't have enough precision then use the delta for fine tuning the test time - - - - See SetParticleTestTimeByIndex(). - - - - - See SetParticleTestTimeByIndex(). - - - - TimeValue; time when a particle satisfies the test - float, if testTime parameter doesn't have enough precision then use the delta for fine tuning the test time - - - - set the same test status for all particles - - - - TimeValue; time when a particle satisfies the test - - - - set the same test status for all particles - - - - TimeValue; time when a particle satisfies the test - float, if testTime parameter doesn't have enough precision then use the delta for fine tuning the test time - - - - The Named Selection Sets management class. - - - The user may use functions exposed by this class to manage all the named selection sets of objects. - This class DOES NOT deal with named selection sets of sub-objects but only named selection sets of objects. - - - - - Get the name of the named selection set whose index is passed. - - - the name of the named selection set if the given index is valid, NULL otherwise. - - - The index of the named selection set. - - - - Adds a new named selection set to those already available in the drop down list in the MAX toolbar. - - - TRUE if the named selection set is successfully added,FALSE otherwise. - - - The table of nodes making up the selection set. - - The name for the set. - - - - Removes the specified named selection set those already available in the drop down list in the MAX toolbar. - - - TRUE if the named selection set is successfully removed,FALSE otherwise. - - - The name for the set to remove. - - - - Removes the specified named selection set those already available in the drop down list in the MAX toolbar. - - - TRUE if the named selection set is successfully removed,FALSE otherwise. - - - The index of the specified named selection set. - - - - Get a specified named selection set by its index. - - - TRUE if the specified named set index is valid,FALSE otherwise. - - - The node set of the specified named selection set that is to be fatched.This node set will be filled only if the specified index is valid. - - The index of the specified named selection set. If the index is invalid, an empty nodes set is to be returned. - - - - Sets node named selection set's name. Returns TRUE if successful. - - - TRUE if the specified named selection set is found with its name set, FALSE otherwise. - - - The selection set index. - - The new name for the selection set. - - - - Get the number of items in the named selection set whose index is passed. - - - the number of items in the named selection set if the given index is valid, 0 otherwise. - - The index of the named selection set. - - - - Get the specified node of a specified named selection set. - - - This method may be used to retrieve the pointer of the 'i-th' item in the named selection set whose index is passed. - the specified node if the given set index and node index is valid, NULL otherwise. - - - The index of the selection set whose 'i-th' pointer is returned. - - The index into the selection set. - - - - Replace the specified named selection set with given nodes. - - - TRUE if the specified selection set is found and replaced, FALSE otherwise. - - - The given nodes to be filled into the named selection set. - - The index of the specified named selection set. - - - - Replace the specified named selection set with given nodes. - - - TRUE if the specified selection set is found and replaced, FALSE otherwise. - - - The given nodes to be filled into the named selection set. - - The name of the specified named selection set. - - - - Get the count of all the named selection sets. - - - the count of all the named selection sets. - - - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - is a static interface that is attached to the class descriptors for light classes that wish to advertise that they represent either skylight or sunlight on the surface of the earth. - - It is used by the Daylight System, to populate it's UI with the classes that describe themselves as naturalLight. This is an example of the way it is used. - - void addClassToCombo(ClassDesc* pCd, HWND sunCombo, HWND skyCombo) - - { - - INaturalLightClass* pNC; - - pNC = GetNaturalLightClassInterface(pCd); - - if (pNC != NULL) { - - IsSun()) { - - addLightToCombo(sunCombo, pCd->ClassName(), pCd); - - } - - IsSky()) { - - addLightToCombo(skyCombo, pCd->ClassName(), pCd); - - } - - } - - } - - - - - - - Returns whether the light is a "Sun" light. - - - - - - - Returns whether the light is a "Sky" light - - - - - Description: - The class is the interface to nodes in the scene. It provides methods to access various parts of a node such as its name, transformation matrices, parents and children, display status, etc. All methods of this class are implemented by the system. - - - - - If this was a temporary (like an ) then this method will delete it. Also see the method Interface::GetModContexts(). - - - - - In the case of , this method retrieves a pointer to the real node. - Example - A pointer to the node. - - - - - Returns the name of the node. - - - - - Builds a string representing the object's hierachy path. - - Place quotes around each level name. - Determines whether root node is to be included in path name. - - - - This method returns the unique node handle. Each node is assigned a unique node handle. - Zero. - For additional information regarding transformation matrices, see the Advanced Topics section on ~{ Transformation and Rotation }~ . - - - - - This method returns the world space transformation matrix of the node at the specified time. This matrix contains its parents transformation. This matrix does not include the object-offset transformation, or any world space modifier (Space Warp) affects. If you select a single node and change the reference coordinate system to 'Local', you'll see the node's axes tripod displayed. This tripod graphically depicts the nodes transformation matrix. The Node TM may be considered the world space transformation as far as kinematics is concerned. This is almost the complete world space transformation as far as the geometry of the object is concerned, except it does not include the object-offset transformation. See the method INode::GetObjectTM() for the complete world space transformation of the geometry of the object. The Node TM is inherited. When a node asks to retrieve its parents TM, it gets its parents Node TM. It does not get its parents TM. The object-offset transformation is not inherited. - Example - The node's world space transform matrix. - - Specifies the time to retrieve the TM. - Points to storage for the validity interval of the transformation matrix. The interval, if passed, is intersected with the validity interval of the NodeTM. - - - - This methods sets the node's world space transformation matrix (without the object-offset transformation or world space modifier affect). This method will perform the appropriate operation to the node's transform controller. For example, if the node has a parent, this method will take the parent's transformation into consideration when it calls SetValue() on the controller. This method can be used to set the world space position of the node. - Example - - Specifies the time to set the transformation matrix. - The node's world space transformation matrix. - - - - This method returns the transformation matrix the object needs to be multiplied by to transform it into world space. At times, this matrix may be the identity. For example, a deformable object that has a Space Warp applied to it would already have been translated into world space by the space warp. Since the object is already in world space the matrix needed to get it there is the identity. This matrix would not be the identity for a deformable object with only object space modifiers applied. This object would indeed need to be transformed. In this case the TM returned would include the NodeTM plus the object-offset transformation. So, GetObjectTM() is dependent on the context when it is called - it will either be equal to GetObjTMAfterWSM() or GetObjTMBeforeWSM(). Developers should use GetObjTMBeforeWSM() if what is wanted is the object TM and not the identity matrix. For non-deformable objects this matrix may include the NodeTM, the object-offset transformation and the world space modifier affect. This matrix could be used, for example, if you have a and wanted to get the world space coordinate of one of its vertices. You could do this by taking the vertex coordinate in object space and multiplying it by the matrix returned from this method. This matrix is also often used inside an object's Display() and HitTest() methods. When an object goes to draw itself (in its BaseObject::Display() method) it is given a node pointer. What the object normally does is use the node pointer and calls GetObjectTM(). It then takes the matrix returned and sets it into the graphics window (using GraphicsWindow::setTransform()). In this way, when the object starts drawing points in object space, they will be transformed with this matrix. This will transform the points into world space when they are drawn. The TM is not inherited. - The object's transformation matrix. - - Specifies the time to retrieve the object's transform matrix. - Points to storage for the validity interval of the transformation matrix. - - - - This method explicitly retrieves the pipeline TM before any world space modifiers have been applied. This includes the node's TM and the object-offset transformation (but not any world space modifier affect). See the section on the ~{ Geometry Pipeline System }~ for additional details on this method. - - Specifies the time to retrieve the transform matrix. - Points to storage for the validity interval of the transformation matrix. - - - - This method explicitly retrieves the pipeline TM after any world space modifiers have been applied. This includes the Node TM, the object-offset transformation, and any world space modifier affects. In some cases a world space modifier can actually deform the TM itself if it cannot deform the object. Examples of this are cameras and lights. These objects do not have any 'object' to deform, so the space warp deforms the TM instead. See the section on the ~{ Geometry Pipeline System }~ for additional details on this method. Note: Beware of calling this method from inside a function that performs a mesh traversal as doing so can invalidate the mesh. - - Specifies the time to retrieve the object's transform matrix. - Points to storage for the validity interval of the transformation matrix. - - - - Retrieves the specified transform lock state of the node. When the user is doing interactive Moving / Rotating / Scaling these locks simply remove one of the components. - TRUE if the lock is set; otherwise FALSE. - - See transformLockTypes. - See . - - - - Sets the specified transform lock state of the node. When the user is doing interactive Moving / Rotating / Scaling these locks simply remove one of the components. - - See . - See . - TRUE sets the lock on; FALSE sets the lock off. - - - - This method may be called to move the node about the specified axis system. Either the pivot point, or the geometry of the object, or both the pivot and the object may be transformed. Optionally, any children of the node can be counter transformed so they don't move. - - The time to transform the node. - The axis system about which the node is transformed. - The amount of the transformation relative to the axis system. - If TRUE the transformation takes place about the nodes local origin; otherwise about the world origin. - TRUE If TRUE any child nodes are transformed along with the parent node. If FALSE any children of the node are counter transformed so they don't move. - One of the following values: Move both the pivot point and the geometry of the object. Move the pivot point only. Move the geometry of the object only. - If TRUE any transform locks associated with the node are ignored; otherwise the locks govern the application of the transformation. - - - - This method may be called to rotate the node about the specified axis system. Either the pivot point, or the geometry of the object, or both the pivot and the object may be transformed. Optionally, any children of the node can be counter transformed so they don't rotate. - - The time to transform the node. - The axis system about which the node is transformed. - The amount of the transformation. - If TRUE the transformation takes place about the nodes local origin; otherwise about the world origin. - If TRUE any child nodes are transformed along with the parent node. If FALSE any children of the node are counter transformed so they don't rotate. - One of the following values: Move both the pivot point and the geometry of the object. Move the pivot point only. Move the geometry of the object only. - If TRUE any transform locks associated with the node are ignored; otherwise the locks govern the application of the transformation. - - - - This method may be called to rotate the node about the specified axis system. Either the pivot point, or the geometry of the object, or both the pivot and the object may be transformed. Optionally, any children of the node can be counter transformed so they don't rotate. - - The time to transform the node. - The axis system about which the node is transformed. - The amount of the transformation. - If TRUE the transformation takes place about the nodes local origin; otherwise about the world origin. - If TRUE any child nodes are transformed along with the parent node. If FALSE any children of the node are counter transformed so they don't rotate. - One of the following values: Move both the pivot point and the geometry of the object. Move the pivot point only. Move the geometry of the object only. - If TRUE any transform locks associated with the node are ignored; otherwise the locks govern the application of the transformation. - - - - This method may be called to scale the node about the specified axis system. Either the pivot point, or the geometry of the object, or both the pivot and the object may be transformed. Optionally, any children of the node can be counter transformed so they don't scale. - - The time to transform the node. - The axis system about which the node is transformed. - The amount of the transformation. - If TRUE the transformation takes place about the nodes local origin; otherwise about the world origin. - If TRUE any child nodes are transformed along with the parent node. If FALSE any children of the node are counter transformed so they don't scale. - One of the following values: Move both the pivot point and the geometry of the object. Move the pivot point only. Move the geometry of the object only. - If TRUE any transform locks associated with the node are ignored; otherwise the locks govern the application of the transformation. - - - - This method will notify the node's subtree that the transformation matrix has changed. NotifyDependents() is called with the message REFMSG_CHANGE. - - - - - This method will invalidate the node's transformation matrix cache. - - - - - This method will invalidate the node's world space cache. - - - - - This method should be called when a developer needs to work with an object that is the result of the node's pipeline. This is the object that the appears in the scene. - - This may not be an object that anyone has a reference to - it may just be an object that has flowed down the pipeline. For example, if there is a Sphere in the scene that has a Bend and Taper applied, EvalWorldState() would return an containing a . This is the result of the sphere turning into a and being bent and tapered (just as it appeared in the scene). - - If a developer needs to access the object that the node in the scene references, then the method INode::GetObjectRef() should be used instead. - The that is the result of the pipeline. See Class . The following code shows how a can be retrieved from a node. Note on the code that if you call ConvertToType() on an object and it returns a pointer other than itself, you are responsible for deleting that object. - - Specifies the time to retrieve the object state. - If FALSE and the node is hidden, the pipeline will not actually be evaluated (however the TM will). - - - - Retrieves the parent node of this node. If the node is not linked, its parent is the root node. This may be checked using INode::IsRootNode(). - Example - - - - - Makes the specified node a child of this node. - - Specifies the node to attach. - If nonzero, the world transform matrix of the specified (child) node is unchanged after the attach operation, i.e. returns the same matrix both before and after the attach operation. Otherwise, the world transform of the specified (child) node is affected by the parent node's transform. - - - - Detaches this node from its parent. - The node is detached from its current parent and attached to the scene's root node. - - Specifies the time at which to detach the node. - If nonzero, the world transform matrix of the detached node is unchanged, i.e. returns the same matrix both before and after the detach operation. Otherwise, the world transform of the detached node may change as a result of the detach operation since the node stops inheriting its parent node's transform. - - - - Returns the number of children of this node. - - - - - Retrieves the 'i-th' child node of this node. - - Specifies the child node to retrieve. - - - - Determines if this node is the root node (does not have a parent node). - Example - Non-zero if the node is the root node; otherwise 0. - - - - - This method will delete the node, handle removing it from the hierarchy, and handle undo. - - - The time for the deletion. - If TRUE the position of any children of this node are kept the same; otherwise linked children may move due to the deletion. - - - - Controls the hidden state of the node in the scene. - - - - Pass TRUE to hide the node in the scene; pass FALSE to make the node visible. - - - - Determines if the node is hidden in the scene. - - - Nonzero if the node is hidden; otherwise 0. - - If you pass 0, you will get the hidden state of the node. If you pass one or more of the flags shown below, the method checks the of the node to see if it's hidden by the specified category. You may specify one or more of the following values: See the method for how to retrieve the currently set values to use as the flags for this method. - If true, test to see if the node is hidden for the render, else if it is hidden in the viewport - - - - Returns nonzero if the node is hidden in any way. - - - This method takes into account both the node hidden attribute and the 'Hide By Category' flags. - - If true, test to see if the node is hidden for the render, else if it is hidden in the viewport returns zero. - - - - Determines if the node is frozen in any way in the scene. - - - A node can have the frozen property set, or be frozen by 'ghosting' - Nonzero if the node is frozen; otherwise 0. - - - - - This method returns the state of the NODE_SHOW_FRZN_WITH_MTL flag in the node and whether it is enabled or disabled. - - - - - Returns nonzero if the X-Ray display property is on for the node; otherwise zero. - - - - - Determines if the node is displayed in box mode in the scene. - Nonzero if the node is displayed in box mode; otherwise 0. - - - - - Determines if all the edges of the node are displayed. - Nonzero if all the edges (including "hidden" ones) are displayed; otherwise 0. - - - - - This method returns the state of the vertex ticks display. TRUE if enabled; FALSE if disabled. - - - - - Determines if back-face culling is being used to draw the node. - Nonzero if back-face culling is used; otherwise 0. - - - - - Returns non-zero if the trajectory display is on; zero if the trajectory display is off. - - - - - Controls the display of Bones in the scene. A bone is just the link (or line) connecting the node to its parent. These are the same options as available in the 3ds Max user interface in the Display branch, under Link Display, i.e. Display Links and Link Replaces . - - Specifies the display state:: Bones are not drawn.: Bones are drawn.: Only bones are shown. - - - - Controls the display of Bones as simple lines in the scene. - - Non-zero if bones should be shown as lines only; 0 for normal display. - - - - Returns TRUE if the node's bone is turned on; otherwise FALSE. - - - - - Returns TRUE if the bone is showing but the object is hidden; FALSE if both the bone and the node is hidden. - - - - - Retrieves the node's wire-frame color. See . - - - - - Determines if the node is selected. - Non-zero if the node is selected; otherwise 0. - - - - - Returns non-zero if the node has its dependent flag set; otherwise 0. This is dependent in the sense of 3ds Max's Views/Show Dependencies mode. When in the Modify branch, Show Dependencies will show all the nodes that are dependent on the current modifier or object being editing by highlighting them in green. It also set a flag in the node. This method allows a developer to check this flag. - - - - - Retrieves the shadow casting attribute of the node. - Nonzero indicates the node casts shadows; zero if the node does not cast shadows. - - - - - Retrieves the shadow receiving attribute of the node. - Nonzero indicates the node receives shadows; zero if the node does not receive shadows. - - - - - Retrieves the type of motion blur used by the node. - One of the following values: - - 0: None - 1: Motion Blur. - 2: Image Motion Blur. - - - - - Returns the image motion blur multiplier value at the specified time. - - The time to retrieve the value. - - - - Sets the image blur multiplier value for the node. This is used to increase or decrease the length of the blur 'streak'. - - The time to set the value. - The value to set. - - - - Returns a pointer to the controller for the image blur multiplier value. - - - - - Returns TRUE if the object motion blur controller is 'on' at the specified time; otherwise FALSE. - Default Implementation: - { return 1; } - - The time to check. - - - - Sets the state of the object motion blur controller to on or off at the specified time. - Default Implementation: - {} - - The time to set the value. - TRUE for on; FALSE for off. - - - - Returns a pointer to the controller handling the object motion blur on / off setting. - Default Implementation: - { return NULL;} - - - - - Returns non-zero if the renderable flag is on; zero if off. - - - - - This method returns the on/off state of the "apply atmospherics" flag. - - - - - This method returns the on/off state of the primary visibility to determine whether or not the node is visible to the camera. - - - - - This method returns the on/off state of the secondary visibility to determine whether or not the node is visible to reflections and refractions. - - - - - Returns TRUE if the node's 'Render Occluded ' flag is set; otherwise FALSE. - - - - - Returns non-zero if the vertex color flag if on; otherwise zero. - - - - - Returns non-zero if the vertex color shaded flag is on; zero if off. - - - - - Get the node's vertex color "type". This is one of the nodeVertexColorType enums above. - - - - - get the map channel to be displayed as vertex color. - - - - - Calling this method copies the various display, rendering, bone and other general parameters from the "from" object. This is used in Edit(able) Spline and Edit(able) to copy node settings into new nodes created by the "Detach" operations. - Parameters: - *frame A pointer to the to copy the properties from. - - - - - This method is used for hit-testing and selecting node and target as a single unit. In 3ds Max 2.0 and later you can click on the line connecting, say, a camera to its target and drag that around in the viewports. Doing so moves both the camera and its target as a locked pair. To accomplish this, the camera, light, and tape measure objects (those with two nodes linked by a Look At controller) check for a hit on the object-target line. If they get there (but not at the object or target itself), then they call this method passing TRUE. Then, when a hit is registered, 3ds Max checks the value of this variable (by calling GetTargetNodePair()), and, if it is TRUE, selects both the target and the node. If it's FALSE, then either the target or the node, but not both, gets selected, as with 3ds Max 1.x. For sample code see /MAXSDK/SAMPLES/OBJECTS/LIGHT.CPP or TAPEHELP.CPP. - Example - Default Implementation: - {} - - TRUE for on; FALSE for off. - - - - Returns the target/node pair setting stored by 3ds Max. See SetTargetNodePair() above for details. - Default Implementation: - { return 0; } - - - - - Determines if the node is a target node of a lookat controller. - Non-zero if the node is a target; otherwise 0. - - - - - Retrieves this node's target node if any. - NULL if this node has no target. - - - - - If this node is a target of a lookat controller, this method finds the node that looks at it. - The node that looks at this node or NULL if the node is not a target. - - - - - Retrieves the parent node's transformation matrix. This is simply for convenience. It is the equivalent to the following code: GetParentNode(); - The parent node's transformation matrix. - - Specifies the time to retrieve the transformation matrix. - - - - Retrieves the target node's transformation matrix. This is simply for convenience. It is the equivalent to the following code: - - GetTarget(); - Nonzero if the target matrix was retrieved (the node had a target); otherwise 0. - - Specifies the time to retrieve the transformation matrix. - The result is stored here. - - - - Returns the object that this node references unless the node has been bound to a Space Warp. In that case this method will not return the WSM derived object even though the node's object reference points at it. Instead it will return the item that the WSM derived object references. Thus, this method will always return essentially the object space portion of the pipeline. In contrast, see GetObjOrWSMRef() below. See the ~{ Geometry Pipeline System }~ section for additional details. - - - - - This method returns the actual object reference of the node directly. So if this node is bound to a Space Warp this method will return a WSM derived object. If you want the object space portion of the pipeline see GetObjectRef() above. - - - - - Retrieves the node's transform controller. The standard 3ds Max transform controllers each have sub-controllers for position, rotation and scale. To access the data of the node's transform controller you may use Class . The following code fragment shows an example of how this may be done for a PRS controller. With this controller interface you can use its methods to get information about the keys. For example: - Example - - - - - Sets the node's transform controller. - TRUE if the controller was a valid transform controller for this node, and the reference was successfully created, else FALSE. - - The transform controller to use. This controller must return a SuperClassID of CTRL_MATRIX3_CLASS_ID - - - - Returns the visibility controller for this node. - - - - - Retrieves the visibility of the node at the time passed and updates the validity interval passed. Values < 0 indicate off while values > 0 indicate on. The node is fully visible (opaque) when 1.0 and fully invisible (transparent) when 0.0. - this value may be inherited by the children of this node - Example - - The time to get the visibility value. - The validity interval to update based on the validity of the visibility. - - - - Gets the visibility for the node within the specified view at the time passed, and updates the validity. The visibility calculated includes the view dependent Level Of Detail visibility calculated by the Nodes visibility controller. See also Control::EvalVisibility for more info. - The visibility of the node as rendered. Values <= 0 are invisible, and values >= 1 are fully opaque. - - The time to get the visibility value. - This is the view to calculate the view-dependent LOD visibility from. - The validity interval to update based on the validity of the visibility. - - - - Sets the visibility of the node to the value passed at the time passed. - - The time to set the visibility value. - The visibility of the node to set. This is treated like a boolean value where < 0 means off and > 0 means on. - - - - Returns the local visibility of the node. The value returned from this method is treated like a boolean value where < 0 means off and > 0 means on. If a node returns TRUE from GetInheritVisibility() then its visibility is determined by this method. If GetInheritVisibility() method returns FALSE then the visibility of the node is determined by GetVisibility(). - This value does not take into account the parent nodes visibility, and is not inherited by the children of this node - - The time to get the local visibility value. - The validity interval to update based on the validity of the local visibility controller. - - - - Returns TRUE if the node's visibility is determined by the visibility of the parent of the node; otherwise returns FALSE. - - - - - Returns a pointer to the renderer material for the node. If the value returned is NULL the user has not assigned a material yet. See Class , ~{ Materials, Textures and Maps }~. - Example - - - - - Returns a pointer to the materials. See NumMtls() below for the number of entries in this array. - - - - - Returns the number of entries in the array of Materials returned by Mtls() above. - - - - - Returns the position portion of the object-offset from the node as a . See the Advanced Topics section on ~{ Transformation and Rotation }~ for an overview of the object offset transformation. - - - - - Returns the rotation portion of the object-offset from the node. See the Advanced Topics section on ~{ Transformation and Rotation }~ for an overview of the object offset transformation. - - - - - Returns the scale portion of the object-offset from the node. See Class . See the Advanced Topics section on ~{ Transformation and Rotation }~ for an overview of the object offset transformation. - - - - - Centers the pivot to the object. The effect is the same as Hierarchy Panel/Pivot - [Center to or Center to Pivot] - - - not used - - If true, the object is moved to be centered on the pivot. If false, the pivot is centered on the object - - - - Resets the pivot alignment. The effect is the same as Hierarchy Panel/Pivot - [Align to or Align to Pivot] - - - not used - - If true, the object is rotated to be aligned with the pivot. If false, the pivot rotation is reset to be realigned with the object - - - - Aligns the object to the world . The effect is the same as Hierarchy Panel/Pivot/[Affect Pivot Only or Affect Only]/ - Align to World - - - not used - - If true, the object is rotated to be aligned with the world. If false, the pivot rotation is set to be aligned with the world - - - - Aligns the pivot to the node's parent's pivot, or to world if no parent. - - - not used - - - - Aligns the pivot to the to world - - - not used - - - - Resets the pivot offset transform. The effect is the same as Hierarchy Panel/Pivot/[Reset Transform or Reset Scale] - - - not used - - If true, reset only the offset scale. Else reset the rotation and scale parts - - - - Resets the pivot transform. The effect is the same as Hierarchy Panel/Pivot/Reset Pivot - - - not used - - - - Flags the node to put it in the foreground. For additional information see ~{ Foreground / Background Planes }~. - - The time to put the node in the foreground. - If TRUE, the reference message with is sent. - - - - Determines if this node is the active grid object. - Nonzero indicates the node is the active grid object; zero indicates it is not. - - - - - Returns the value set by SetNodeLong - - - - - Returns the render data for the node. See Class . - - - - - This method allows access to the entire user defined property text buffer. - - The buffer to hold the user defined property text. - - - - This method allows a developer to set to the entire user defined property text buffer. - - The buffer containing the user defined property text. - - - - This method retrieves a string based on the key passed. - TRUE if the key was found; otherwise FALSE. - - The key (or name) of the user defined property text. - Storage for the string to retrieve. - - - - Retrieves an integer value from the node based on the key passed. - TRUE if the key was found; otherwise FALSE. - - The key (or name) of the data to retrieve. - Storage for the integer value. - - - - Retrieves a floating point value from the node based on the key passed. - TRUE if the key was found; otherwise FALSE. - - The key (or name) of the data to retrieve. - Storage for the float value. - - - - Retrieves a boolean value from the node based on the key passed. - TRUE if the key was found; otherwise FALSE. - - The key (or name) of the data to retrieve. - Storage for the boolean value. - - - - Stores a string in the node using the key passed. If the key name already exists it is overwritten; otherwise it is created. - - The key (or name) of the data to store. - The string to store. - - - - Stores an integer value in the node using the key passed. If the key name already exists it is overwritten; otherwise it is created. - - The key (or name) of the data to store. - The value to store. - - - - Stores a floating point value in the node using the key passed. If the key name already exists it is overwritten; otherwise it is created. - - The key (or name) of the data to store. - The value to store. - - - - Stores a boolean value in the node using the key passed. If the key name already exists it is overwritten; otherwise it is created. - - The key (or name) of the data to store. - The value to store. - - - - This method simply checks to see if a key exists. - TRUE if the key was found; otherwise FALSE. - - The key string to search for. - - - - This method returns an array of key/value pairs. - - - - - Returns the G-Buffer ID of this node. This is the ID available in the BMM_CHAN_NODE_ID channel. See ~{ Working with Bitmaps }~(G-Buffer) for additional details. - - - - - Returns the G-Buffer render ID of the node. This is set by the renderer during a video post render when the BMM_CHAN_NODE_RENDER_ID is requested. - - - - - Returns TRUE if this node is a member of a group; otherwise FALSE. - - - - - Returns TRUE if this node is the head of a group; otherwise FALSE. - - - - - Returns TRUE if this node is a member of an open group; otherwise FALSE. - Default Implementation: - {return 0; } - - - - - Returns TRUE if this node is the head of a group and that group is open; otherwise FALSE. - Default Implementation: - {return 0; } - - - - - A node is marked as a group member or not. This method sets this state. - - TRUE to mark the node as a group member; FALSE to indicate it's not in a group. - - - - A node is marked as the group head or not. This method sets this state. - - TRUE to mark the node as a group head; FALSE to indicate it's not a group head. - - - - A node is marked as an open group member or not. This method sets this state. - - TRUE to mark the node as a open; FALSE to indicate it's not open. - - - - A node is marked as being the head of a group and being open or not. This method sets this state. - - TRUE to mark the node as an open group head; FALSE to indicate it's not an open group head. - - - - This method returns the position weight for the node. - - - - - This method returns the rotation weight for the node. - - - - - Returns TRUE of FALSE to indicate if the specified axis is set for position or rotation. - - Indicates if the method returns the position state or the rotation state:: specifies position;: specifies rotation. - The axis to check. Values are as follows:: specifies X: specifies Y: specifies Z. - - - - Sets the specified axis state for position or rotation. - - Indicates if the method returns the position state or the rotation state:: specifies position: specifies rotation. - The axis to check. Values are as follows:: specifies X specifies Y specifies Z - TRUE for on; FALSE for off. - - - - This method returns the same information as GetTaskAxisState() above. - The first three bits indicate position X, Y and Z. Then the next three bits indicate rotation X, Y, Z. - - - - - Calling this method will create a WSM derived object for this node if one doesn't already exist. - Default Implementation: - {} - - - - - This method pointer to the WSM Derived object for this node. Note that there is at most one WSM derived object per node. - Default Implementation: - {return NULL;} - - - - - Returns the file asset of the scene xref whose index is passed. - - The zero based index of the scene xref ( to ). - - - - Sets the file asset of the scene xref whose index is passed. - Default Implementation: - {} - - The zero based index of the scene xref ( to ). - The file to set. - TRUE to reload; FALSE to not reload. - - - - Returns the number of scene xrefs. - Default Implementation: - {return 0;} - Example - - - - - Adds the specified file to the scene and optionally updates the scene now. - TRUE if the XRef was loaded; otherwise FALSE. - Default Implementation: - {return FALSE;} - Example - - The file asset to load. - If TRUE the file is loaded immediately and the scene updated; if FALSE the scene is now updated until the user requests it. - If TRUE (default value is FALSE) the scene xref flag XREF_SCENE_HIDEINMANAGERUI will be set, so that the scene xref will not be listed in the scene XRef manager . - - - - This method removes the 'i-th' Scene XRef. - TRUE if the file was deleted from the scene; otherwise FALSE. - Default Implementation: - {return FALSE;} - - The zero based index of the Scene XRef to load. - - - - This methods binds the specified XRef. This deletes the XRef after merging it into the scene. - TRUE if the file was deleted; otherwise FALSE. - Default Implementation: - {return FALSE;} - Example - See GetXRefFileCount() - - The zero based index of the XRef to bind. - - - - This method deletes all the XRefs from the scene. This is called when loading a new file, resetting or clearing the scene. - Default Implementation: - {} - - - - - This method will reload (updates from disk) the specified XRef. - TRUE if the XRef was reloaded; otherwise FALSE. - Default Implementation: - {return FALSE;} - Example - - The zero based index of the XRef to reload. - - - - This method indicates that the specified XRef has been changed and should be updated. - Default Implementation: - {} - - The zero based index of the XRef to flag. - - - - This method updates all XRefs which have their changed flag set. - TRUE if the XRefs were loaded okay; otherwise FALSE. - Default Implementation: - {return FALSE;} - - TRUE to redraw the scene; otherwise FALSE. - - - - Returns the root node of the tree for the specified XRef. This method, when called on a root node, will access the various XRef scenes. Note that these can be nested so calling this on the root node of the scene will return the root node of one of the scene XRefs. Calling it on the root node of the scene XRef will get the root node of a nested XRef and so on. Note that this is not the parent of the XRef (see GetXRefParent() below). - Default Implementation: - {return NULL;} - - The zero based index of the XRef. - - - - Returns the parent node of the specified XRef. This is the node in the scene (if any) which the scene XRef is linked to through the special bind function in the scene XRef dialog. - Default Implementation: - {return NULL;} - - The zero based index of the XRef. - - - - Sets the parent of the specified XRef to the node passed. - Default Implementation: - {} - - The zero based index of the XRef. - The parent node to set. - Automatically offset XRef so that it keeps its world TM. - - - - Generates a table of names for the unresolved XRefs in the scene. - Returns TRUE if there are still unresolved XRefs; otherwise FALSE. - Default Implementation: - {return FALSE;} - - The table of names. See Class . - - - - This method tries to load any XRefs that are currently unresolved. - Default Implementation: - {} - - - - - Returns the state of flags for the specified XRef. - See XRef Flag Bits. - Default Implementation: - {return 0;} - - The zero based index of the XRef whose flags are returned. - - - - Sets the state of the specified flags in the specified XRef to on or off. - Default Implementation: - {} - - The zero based index of the XRef whose flags are set. - See . - TRUE for on; FALSE for off. - - - - This method tells if the is a scene XRef node or not. - true if the node is a scene XRef node, false otherwise. - - - - - This method tells if the is a scene node or not. - true if the node is a scene node, false otherwise. - - - - - Sets the bone on/off property of the node. - Default Implementation: - {} - - Pass TRUE for on; FALSE for off. - The time at which to set the property. - - - - Returns TRUE if the bone property is on; FALSE if off. - Default Implementation: - {return FALSE;} - - - - - Returns TRUE if the bone property is on at a specfied time; FALSE if off. - Default Implementation: - {return FALSE;} - - The time value at which to check the bond node. - - - - Returns TRUE if the bone auto-align property is on; FALSE if off. - Default Implementation: - {return FALSE;} - - - - - Returns TRUE if the freeze length property is on; FALSE if off. - Default Implementation: - {return FALSE;} - - - - - Returns a value which indicates the bone scale type. - One of the following values: - - BONE_SCALETYPE_SCALE - BONE_SCALETYPE_SQUASH - BONE_SCALETYPE_NONE - Default Implementation: - {return 0;} - - - - - Returns a value which indicates the bone axis. - One of the following values: - - BONE_AXIS_X - BONE_AXIS_Y - BONE_AXIS_Z - Default Implementation: - {return 0;} - - - - - Returns TRUE if the axis flip toggle is on; FALSE if off. - Default Implementation: - {return FALSE;} - - - - - Calling this method is the equivalent of pressing the Realign button in the UI. - Default Implementation: - {} - - The time at which to reset the initial child position. - - - - Calling this method is the equivalent of pressing the Reset Stretch button in the UI. This will cause the X-axis of the bone to realign to point at the child bone (or average pivot of multiple children). - Default Implementation: - {} - - The time at which to reset the bone stretch. - - - - This method returns the strechTM without the object offset included. Normally matrix concatenation occurs in the following manner: - objectTM = objectOffsetTM * stretchTM * nodeTM - A plug-in that uses the objectTM will transparently inherit the effects of the stretchTM. However if a plug-in (such as skin) wants the stretchTM included but not the object offset, this method will return the stretchTM alone. If the node is not a bone or has no stretching, this method will return the identity. - Default Implementation: - ;} - - The time at which to obtain the strechtTM. - The interval. - - - - Determines if this node was loaded during last merge - true if the node was loaded during last merge; otherwise false. - - - - - This method invalidates the rectangle in the viewports that the node occupies. Rectangles flagged as invalid will be updated on the next screen redraw. Each node caches the rectangle in the viewports that the node occupies. These caches are updated when the node is drawn in the viewports. - Example - - - The time to invalidate the node's rectangle - - If true, the cached viewport rectangles of the node are invalidated. This would be the case when a node property that doesn't affect the size or position of the node's viewport rectangles, such as wireframe color, is changed. Otherwise, the node's current rectangle in each viewport is invalidated. If the node's world space cache is not valid, the node's world state at time t will be evaluated, from which its current viewport rectangles are calculated. - - - - Makes the node, and optionally the layer, visible in the scene. - - - - Pass TRUE to unhide the node in the scene; pass FALSE to make the node visible. - - - - Returns the hidden state of this node in the scene. - - - non-zero if this node is hidden, else false - - - - - Unfreeze the node, and optionally its layer. - - - - if true, unfreeze the layer - - - - Test the frozen property of this node. - - - non-zero if this node is frozen, else zero - - - - - Get the X-Ray node property. - - - The X-Ray display property allows you to quickly make objects transparent. - TRUE if X-Ray materials are enabled; else FALSE - - - - - Is this node ignored during zoom extents. - - - true if this node is to be ignored during zoom extents. - - - - - Indicates whether a call to ResetTransform() will succeed. The ResetTransform() method also checks this internally, so it's not necessary to check beforehand. - true if ResetTransform will succeed, false if no change would occur - - - - - Description: - This class defines an interface for accessing a node's texture baking properties. An instance of this interface can be retrieved using the following line of code (assuming 'node' is of type INode*): Description of the node's texture baking properties: - General Properties: - Enable:Baking Channel:List of Baking Render Elements: - - - - - Get the flag to identify if the baking is enabled. - The baker can query the flag to perform the baking or not. - The flag to identify if the baking is enabled. - - - - - Get the mapping channel to use for baking level. - The baker can query the mapping channel, then apply it for baking. - The mapping channel for baking. - - - - - Get the number of dilations after rendering, affects seaming. - The baker can query the number of dilations, then apply it for baking. - The number of dilations for baking. - - - - - Get the surface area for baking. - The baker can query the surface area, then apply it for baking. - The surface area for baking. - - - - - Get the area scale for baking. - The baker can query the area scale, then apply it for baking. - The area scale for baking. - - - - - Get total number of the bake elements. - The total number of the bake elements. - - - - - Get the bake element by the index. - The pointer to the bake element. - - The index of the bake element. - - - - returns a object holding the list of Texture Bake elements assigned to the node. - - - Developers should not try to set BakeElements by altering the contents of this ; use the methods AddBakeElement() and RemoveBakeElement() instead - a object holding the list of Texture Bake elements assigned to the node. - - - - - Add bake element by the pointer. - The flag to identify if the operation is successful. - - The pointer to the bake element. - - - - Remove bake element by the pointer. - The flag to identify if the operation is successful. - - The pointer to the bake element. - - - - Remove bake element by name. - The flag to identify if the operation is successful. - - The name of the bake element. - - - - Remove bake element by index. - The flag to identify if the operation is successful. - - The index of the bake element. - - - - Remove all bake elements hold by this entity. - - - - - Reset params to default, toss render elements. - - - - - Get the flag to identify if there's anything effective to bake. - The result depends on if the node is bake enabled & has some elements & sz not 0. - The flag to identify if there's anything effective to bake. - - - - - Get the render size for baking. - It returns the largest size of enabled baking elements. - The baker can query the render size, then render to target with that size. - The the render size for baking. - - - - - Get the active region for baking. - The region is a rectangle area. - The baker can query the active region, then bake everything in that region. - The active region for baking. - - - - - Get the active uv tile for baking. - In UDIM baking workflow, the tile to bake could be , uOffset/vOffset means the offset in u/v space. - The default value is , which represents the main/default tile or tile u0v0/1001. - The baker can query the active uv tile, then bake everything in that uv tile. - The active uv tile for baking. - - - - - Description: - This class is an interface that is used to register the node display callback. To get a pointer to this interface the developer should use the following macro: - - GetNodeDisplayControl(i) ((INodeDisplayControl*)i->GetInterface(I_NODEDISPLAYCONTROL)) - - - - - Register a node display callback which can be used to control the display of nodes in the scene. - Parameters: - *cb - - Points to the callback object. - - - - - Un-registers the node display callback. - Parameters: - *cb - - Points to the callback object. - - - - - Sets the current current callback. The callback must be previously registered. - Parameters: - NodeDisplayCallback* hook - - Points to the node display callback to set. - Returns true if the callback was set; otherwise false. - - - - - Returns a pointer to the current current callback. The callback must be previously registered. - - - - - Viewport refresh routine. Tthis function only invalidates the display, it's up to the callback to select the correct redraw technique. - - - - - class : public - - - Description: - This class is only available in release 10 or later. - - This class defines an interface for accessing a node's new display properties dealing with degradation and bundling. - - An instance of this interface can be retrieved using the following line of code (assuming 'node' is of type INode*): - - - - - Nodes deleted from the scene. - - - - The node list, provided as AnimHandles. Node that, if already flushed from the undo buffer, nodes pointers will not be available via . - - - - Node linked or unlinked from another parent node. Only the linked or unlinked child nodes are listed in the notification, not the parent nodes. - - - - The node list, provided as AnimHandles. - - - - Nodes added or removed from a layer, or moved between layers. - - - - The node list, provided as AnimHandles. - - - - Nodes added or removed from a group, or its group was opened or closed. - - - - The node list, provided as AnimHandles. - - - - All other change to the scene structure of nodes. - - - - The node list, provided as AnimHandles. - - - - Nodes changed in their geometry channel. - - - - The node list, provided as AnimHandles. - - - - Nodes changed in their topology channel. - - - - The node list, provided as AnimHandles. - - - - Nodes changed in their UV mapping channel, or vertex color channel. Also includes ID changes. - - - - The node list, provided as AnimHandles. - - - - Nodes changed in any of their extention channels. - - - - The node list, provided as AnimHandles. - - - - All other change to the geometry or parameters of an object. This includes settings on lights, cameras and helper objects. - - - - The node list, provided as AnimHandles. - - - - All other change to the settings of a node's material. - - - - The node list, provided as AnimHandles. - - - - All other changes to node transform controller values, including nodes moved/rotated/scaled, or transform animation keys set. Pertains only to a node's transform controller, not to other animated aspects of the object. - - - - The node list, provided as AnimHandles. - - - - Node wire color changed. - - - - The node list, provided as AnimHandles. - - - - Node render-related object properties changed. From the Properties dialog, this includes Rendering and Motion Blur items, and the Advanced Lighting and mental ray tabs. Also includes changes to displacement approximation and render elements. - - - - The node list, provided as AnimHandles. - - - - Node display-related object properties changed. From the Properties dialog, this includes Interactivity and Display Properties items. Also includes changes to viewport shader data, as per PART_GFX_DATA. - - - - The node list, provided as AnimHandles. - - - - Node used-defined object properties changed. From the Properties dialog, this is the User Defined tab. - - - - The node list, provided as AnimHandles. - - - - All other changes to node property values. - - - - The node list, provided as AnimHandles. - - - - Nodes selected or deselected. - - - - The node list, provided as AnimHandles. - - - - Nodes hidden or unhidden. - - - - The node list, provided as AnimHandles. - - - - Nodes frozen or unfrozen. - - - - The node list, provided as AnimHandles. - - - - All other display or interaction node events. For example, turning on trajectory mode or link display mode. - - - - The node list, provided as AnimHandles. - - - - Called when messages are being triggered for the callback, before event methods. - - - - - Called when messages are being triggered for the callback, after all event methods. - - - - - Verbose Deleted mode, for extra information about deleted object If verbose is false, messages are never sent for objects which are deleted from the scene (and on the undo stack). Also the Add or Delete messages are treated as all-encompassing messages, and will never be accompanied by other messages. If verbose is true, all messages are sent, even for deleted objects, and even accompanying Add and Delete messages. Do not change this value dynamically. The method is called only once by the system, when the callback is registered. - - - The Verbose Deleted setting to use for the callback - - - - - class : public - Description: - This class is only available in release 5 or later. - - This interface provides the ability for a node to define whether it is visible in any of max's dialog boxes. This interface will be extended and used by more of 3ds Max's core utilities, but currently ONLY TrackView and the Select Object/HideObject dialog box use this interface. By default this interface is not available through the default nodes, it needs to be added. - - To get a pointer to this interface from a node the following code can be used. - This will add a new interface to the node if it is not present. The next time you use this technique it will only return the interface and not create another new interface. - - - Data Members: - enum { - - kSelectObjects, kSchematicView, kMaxscript, - - kMerge, kMergeAnimation, kReplace, - - kKeyEditor, kCurveEditor, kRangeEditor, - - kUpdates - - }; - - This enum provides access to the different supported UI elements. It is used with various methods of the class to get/set the UI flags. kUpdates is used when you want to temporarily remove a ref from updating the scene graph. This is for performance reason for instance if you wanted to cache a bunch nodes for display purposes after you built the cache you could turn off this flag and these not will not participate in scene updates. - - - - - This will return the exposure state of the UI element being queried - - - Parameters: - int ui - - The UI flag to query. This should be a value from the UI enum - See data members section - - - - - - - This will set the state of all the UI elements to the state passed into the method - - NOTE kUpdates is not set or cleared by this. You have to individually set/unset that flag - - Parameters: - bool state - - The state to set the nodes UI exposure - - - - - - - This will set the state of the individual UI element to the state passed into the method - - - Parameters: - bool state - - The state to set the nodes UI exposure - - int ui - - The UI element to set - - - - - This will return true if it is visible in Selected Objects/HideObjects Dialog box otherwise false - - - - - - - This will return true if it is visible in TrackView or false if it is not. This will return TRUE is the node is exposed in ANY of the TrackView states, kKeyEditor, kCurveEditor and kRangeEditor. It will return FALSE if ALL are set to false. - - - - - - - Specifies whether the node is visible in the Key Editor of TrackView - - - - - Specifies whether the node is visible in the Curve Editor of Track - - - - - Specifies whether the node is visible in the Key Range Editor of Track - - - - - This will set the flag for the exposure in Selected Objects/HideObjects dialog box - - - Parameters: - bool state - - The value to set the flag - - - - - - - This allows the state of the TrackView exposure flag to be set by the user. This will set the flag for all three TrackView flags. See comment in IsExposedInTrackView(). - - - - - - - This allows the state of the Key Editor of Trackview exposure flag to be set by the user. - - - - - - - This allows the state of the Curve Editor of Track view exposure flag to be set by the user. - - - - - - - This allows the state of the Key Range Editor of Track view exposure flag to be set by the user. - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - This class defines an interface for accessing a node's global illumination properties. - - An instance of this interface can be retrieved using the following line of code (assuming 'node' is of type INode*): - - static_cast<INodeGIProperties*>(node->GetInterface(NODEGIPROPERTIES_INTERFACE)) - - Geometric and object objects have different properties. Accessing/setting geometric properties of non-geometric objects is safe, but will have no effect in the global illumination solution. - - Here is a description of the global illumination properties: - - GENERAL PROPERTIES (all types of objects) GEOMETRIC OBJECTS (affects only geometric objects): - - LIGHT OBJECTS (affects only light sources): - - - - - K Prototype - - Clones the properties from a source - - - - - K Prototype - - Saves local properties - to be called on every node - - - - - K Prototype - - Saves local properties - to be called on every node. See also GIGetIsExcluded() - - - - - K Prototype - - Geometry object property - retrieves the current mesh size for the node. - - - - - K Prototype - - Geometry object property - query for whether the node is an occluder object in the global illumination computations. - - - - - K Prototype - - Geometry object property - query for whether the node is a receiver for global illumination. - - - - - K Prototype - - Geometry object property - query for whether the node has diffuse properties for usage in global illumination. - - - - - K Prototype - - Geometry object property - query for whether the node has specular properties for usage in global illumination. - - - - - K Prototype - - Geometry object property - set usage of global rendering context mesh refinement settings.. - - - - - K Prototype - - Geometry object property - set whether mesh refinement is enabled for this pass. - - - - - K Prototype - - Geometry object property - set the number of mesh refinement steps for the regathering pass. - - - - - K Prototype - - Geometry object property - query the number of steps performed thus far during the mesh refinement stage. - - - - - K Prototype - - Geometry object property - query for the refinement mesh size for the regathering pass. - - - - - K Prototype - - Geometry object property - query whether this node is to be excluded from the regathering pass. - - - - - K Prototype - - Geometry object property - set whether this node is to be excluded from the regathering pass. - - - - - K Prototype - - Get light object property. - - - - - K Prototype - - light object property. - - - - - K Prototype - - Get 'by layer' flag for radiosity properties. - - - - - K Prototype - - the 'by layer' flag for radiosity properties. - - - - - K Prototype - - Getting regathering ray multiplier node property - - - - - K Prototype - - Setting regathering ray multiplier node property. - - - - - This interace accesses the adaptive subdivision properties. - - - An instance of this interface can be retrieved using the following line of code (assuming 'node' is of type INode*): - static_cast<INodeGIProperties2*>(node->GetInterface(NODEGIPROPERTIES2_INTERFACE)) - - The adaptive subdivision properties are only used when the object is not using the global mesh settings. When an object is using the global settings, these will also be used for adaptive subdivision. - Here is a description of the adaptive subdivision properties: - GEOMETRIC OBJECTS (affects only geometric objects): - - - - - - Copy properties from another interface. - - - - - The interface the properties are copied from. - - - - Returns whether the use adaptive subdivision property is turned on. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - TRUE if the object can be adaptively subdivided. FALSE otherwise. - - - - - Returns the minimum mesh size set for the object. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - The minimum mesh size that adaptive subdivision will produce. The size of a face is the length of the longest side. - - - - - Returns the initial mesh size set for the object. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - The size of the smallest face that the initial meshing code will subdivide to improve the face shape. The size of a face in this case is the square-root of the area. - - - - - Returns the contrast threshold for subdivision. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - The threshold, which can be from 0 to 1, used to determine when a face is subdivided. The contrast is calculated for each light searately. The contrast on a face is effectively calculated like this: - max = max brightness of light shining on the vertices of the face - min = min brightness of light shining on the vertices of the face - contrast = log(max * (max - min) / (max + min) - 0.02 + 1.0) / log(1000.0 - 0.02 + 1) if max is 0 the the contrast is 0. - - - - - whether the use adaptive subdivision property is turned on. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - - - TRUE if the object can be adaptively subdivided. FALSE otherwise. - - - - the minimum mesh size set for the object. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - - - The minimum mesh size that adaptive subdivision will produce. The size of a face is the length of the longest side. - - - - the initial mesh size set for the object. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - - - The size of the smallest face that the initial meshing code will subdivide to improve the face shape. The size of a face in this case is the square-root of the area. - - - - the contrast threshold for subdivision. - - - This property should be ignored if INodeGIProperties::GIGetUseGlobalMeshSettings() returns TRUE. - - - The threshold, which can be from 0 to 1, used to determine when a face is subdivided. The contrast is calculated for each light searately. The contrast on a face is effectively calculated like this: max = max brightness of light shining on the vertices of the face min = min brightness of light shining on the vertices of the face contrast = log(max * (max - min) / (max + min) - 0.02 + 1.0) / log(1000.0 - 0.02 + 1) if max is 0 the the contrast is 0. - - - - class : public - - - Description: - This class is only available in release 5 or later. - - This class defines an interface for accessing a node's global illumination properties. - - An instance of this interface can be retrieved using the following line of code (assuming 'node' is of type INode*): - - - - - Extension to for accessing mental ray properties. - This interface class defines a set of methods for accessing mental ray properties on an . To get a pointer to this interface from an , call: - The properties exposed by this class to the SDK are also exposed to MaxScript through the function publishing system. - - - - - Copy properties from another interface - - - The properties to be copied. - - - - Gets the value of the "Use global displacement settings" flag. - The value of the flag. - - - - - Sets the value fo the "Use global displacement settings" flag. - - - The value to be set. - - - - Gets the displacement method to be used. - The displacement method to be used. - - - - - Sets the displacement method to be used. - - - The displacement method. - - - - Gets the value of the "View-Dependent Displacement" flag. - The value of the flag. - - - - - Sets the value of the "View-Dependent Displacement" flag. - - - The value to be set. - - - - Gets the value of the "Edge Length" property. Note: this value should be interpreted as pixels if the "view-dependent" flag is ON, and as object-space units if the "view-dependent" flag is OFF. - The value of the "Edge Length" parameter. - - - - - Sets the value of the "Edge Length" property. Note: this value should be interpreted as pixels if the "view-dependent" flag is ON, and as object-space units if the "view-dependent" flag is OFF. - - - The value to be set. - - - - Gets the value of the "Max. Displace" property. - The value of the "Max. Displace" property. - - - - - Sets the value of the "Max. Displace" property. - - - The value to be set. - - - - Gets the value of the "Displacement Max. Level" property. - The value of the "Displacement Max. Level" property. - - - - - Sets the value of the "Displacement Max. Level" property. - - - The value to bet set. - - - - Gets the value of the "Receive Illumination from Final Gather" flag. - The value of the flag. - - - - - Sets the value of the "Receive Illumination from Final Gather" flag. - - - The value to be set. - - - - Gets the mode for the "Cast Illumination from Final Gather" to be used. - The mode to be used for FG Rays that hit the object. - - - - - Sets the mode for the "Cast Illumination from Final Gather" to be used. - - - The mode to be used for FG Rays that hit the object. - - - - Gets the value of the "Exclude from Global Illumination Calculations" flag. - The value of the flag. - - - - - Sets the value of the "Exclude from Global Illumination Calculations" flag. - - - The value to be set. - - - - Gets the value of the "Exclude from Caustics Calculations" flag. - The value of the flag. - - - - - Sets the value of the "Exclude from Caustics Calculations" flag. - - - The value to be set. - - - - The interface for working with NodeMonitor class. - - - The NodeMonitor class (defined in ctrl.dlc) is used to monitor a node for its - REFMSG_TARGET_DELETED messages. The NodeMonitor class creates a instance pointing at a node, and allows only the REFMSG_TARGET_DELETED message to propagate to the NodeMonitor's dependents. To prevent circular message loops, the messages are not propagated if that message type is already being propagated. - - - - - Retrieves the node being watched. - - - pointer to the node being watched. - - - - - A node based interface to support new Viewport Rendering features. - - - The new interface for 3ds max 10 provides access to the new viewport rendering features. This includes the ability for any number of lights to illuminate the scene. A light can now cast shadows in the viewport and provide illumination which are properties stored at the node level. The interacts with this interface to give the user some control over these light node properties. These properties only have an effect if Viewport Shading is turned on. The developer can access this interface directly from the node. - - - - - Retrieves the shadow casting flag. - TRUE if it is shadow casting, FALSE if this is turned off - - - - - Retrieves the illumination flag. - TRUE if it is turned on for illumination, FALSE if this is turned off - - - - - Retrieves the locked state of the light. - - - A locked light means that it is not affected by changes of other properties. For example if the user locks the sun light, it will not be affected by a group "turn of shadows". - The locked lighting flag - - - - - Class representing a dynamic array of INodes. - - - - - Deletes all temporary nodes, such as those of type , from the array. - - - - - - - Finds the specified node in the array and returns its index. - - - int - The index of the node in this array, or -1 if the node is not found - - - The node to find - - - - Checks whether the specified node is in the array. - - - bool - true if the node is in the array, otherwise false - - - The node to find - - - - Adds a node to the end of the array. - - - - The number of nodes in the array prior to adding the specified node - - - The node to add to the array - - If true, the specified node is added to the array without checking whether it's contained already in it. If false, the node is added to the array only if it doesn't exist in it yet. - - The number of extra items by which the array should be enlarged if all its items have been filled with nodes. - - - - Inserts a node into the array at the specified position. - - - - The array index at which the node was inserted, or -1 if the node was not inserted into the array - - - The node to add to the array - - index where to insert the specified node. If a negative value is specified, the node will be appended to the array. - - If true, the specified node is added to the array without checking whether it's contained already in it. If false, the node is added to the array only if it doesn't exist in it yet. - - - - Removes the supplied node from the array - true if the node was found and removed, false otherwise - - Node to remove - - - - A version of that automatically calls INodeTab::DisposeTemporary() when it gets destroyed. This is useful when placed on the stack in order to call Interface::GetModContexts(ModContextList&, INodeTab&) safely. For example, an might contain entries which are temporary and need cleaning up. - - - - - Description: - This class provides a layer that will add in a transformation to the node's objectTM. Most methods pass through to the , except for the objectTM methods which pre-multiply in the given matrix. The methods of this class are the same as . See Class for details. Specifically see the methods related to in . All methods of this class are implemented by the system. - Data Members: - *node; - - The original pointer. - - tm; - - The additional transformation. - - BOOL deleteMe; - - If set to FALSE this will not get deleted. This may be used if the object is not allocated dynamically. If you create an on the stack you'll want to set deleteMe to FALSE. - - - - - The interface for working with NodeTransformMonitor class. - - - The NodeTransformMonitor class (defined in ctrl.dlc) is used to monitor a node for its REFMSG_CHANGE / PART_TM and REFMSG_TARGET_DELETED messages. The NodeTransformMonitor class creates a instance pointing at a node, and allows only the REFMSG_TARGET_DELETED message and the REFMSG_CHANGE message when PartID is PART_TM to propagate to the NodeTransformMonitor's dependents. To prevent circular message loops, the messages are not propagated if that message type is already being propagated. - - - - - Retrieves the node being watched. - - - pointer to the node being watched. - - - - - Retrieves whether to monitor for REFMSG_CHANGE / PART_TM messages. - - - True if to monitor for REFMSG_CHANGE / PART_TM messages. - - - - - Retrieves whether to monitor for REFMSG_FLAG_NODES_WITH_SEL_DEPENDENTS messages. - - - True if to monitor for REFMSG_FLAG_NODES_WITH_SEL_DEPENDENTS messages. - - - - - Retrieves whether to monitor for EnumDependentImp calls. - - - True if to monitor for EnumDependentImp calls. - - - - - This interface provides access to the node's geometry pipeline, transform and whole world state validity intervals. Client code can retrieve this interface from an instance as follows: - - - - - Returns the cached validity interval of the node's geometry pipeline, including world space modifiers. Calling this method does not cause an evaluation of the node's geometry pipeline. - - - - - Returns the cached validity interval of the node's world state, which includes the validity of its geometry pipeline, transform, material and visibility controller. Calling this method does not cause an evaluation of the node's transform. - - - - - Returns the cached validity interval of the node's transform controller. Calling this method does not cause an evaluation of the node's transform. - - - - - Description: - This class provides access to noise controller's parameters. All noise controllers are derived from this class. - - All methods of this class are implemented by the system. - - - - - Returns the seed value. - - - - - Returns the frequency value. - - - - - Returns the state of the fractal setting. TRUE if on; FALSE if off. - - - - - Returns the roughness setting. - - - - - Returns the ramp in setting. - - - - - Returns the ramp out setting. - - - - - Sets the positive only setting (>0) for the specified axis to the specified value. - Parameters: - int which - - Specifes the axis. One of the following values: - - 0: X, 1: y, 2: Z. - - BOOL onOff - - TRUE for on; FALSE for off. - - - - - Returns the positive only setting (>0) for the specified axis to the specified value. - Parameters: - int which - - Specifes the axis. One of the following values: - - 0: X, 1: y, 2: Z. - - - - - Returns a pointer to the controller for the strength parameter. - - - - - Description: - This class provides an interface for working with NVIDIA Renderers. MAXScript and 3DS Max SDK developers can query whether mental ray dll is present or not and do things like grey out buttons in their UI if it is not present. - Usage in C++ Max SDK : - Usage in Maxscript : - - - - - Used to know if NVIDIA mental ray dll is present in 3DS Max. - - - true if the dll is present - - - - - Description: - This is the base class used to publish functions from those objects not derived from . A developer inherits from this class and implements the methods of this class to provide information about the interfaces published by the class. - - There is a corresponding ParamType2 type code, TYPE_IOBJECT, that allows instances of these classes to be passed and returned in methods. This provides a simple form of user-defined type, in the sense that these instance collections are passed as interfaces rather than pointers. MAXScript has wrapper value classes for IObjects and so this mechanism provides a light-weight alternative to the MAXScript SDK facilities for adding new wrapper value classes to the scripter. - - MAXScript also calls the AcquireInterface() and ReleaseInterface() methods on IObjects as it creates and collects these wrappers, so that objects can keep track of MAXScript's extant references to them. - - - - Example - - - - - Returns the object/class name. - Default Implementation: - { return _M(""); } - - - - - This method is called when MAXScript makes a reference to this object. This is part of the reference management and can be implemented by dynamically allocated IObjects for ref-count based lifetime control. - Default Implementation: - { } - - - - - This method is called when MAXScript deletes a reference to this object. This is part of the reference management and can be implemented by dynamically allocated IObjects for ref-count based lifetime control. - Default Implementation: - { } - - - - - This method is the virtual destructor for the . - Default Implementation: - { } - - - - - Description: - This class is identical to Class . Refer to that section for a description of the methods. - - - - - Description: - This class is identical to Class . Refer to that section for a description of the methods. - - - - - Legacy interface for managing object xrefs. - - - This interface should be considered obsolete. Please use instead. Note that this interface does not provide full support for multiple object xref records/links created from the same source file. - Description: - This class represents the interface to the XRef Manager. You can obtain a pointer to the XRef Manager interface using; GetObjXRefManager()IObjXRefManager* . This macro will return - - (IObjXRefManager*)GetCOREInterface(OBJXREFMANAGER_INTERFACE). - - All methods of this class are Implemented by the System. - - - - - This method allows you to add an XRef object to the scene by providing the file and object name. - Parameters: - &asset - - The file asset of the scene containing the object to add. - - MCHAR *obname - - The name of the object in the scene. - - int xFlags - - The merge behavior is controlled by the bits set in xFlags: Bit: 0 - Add as proxy (XREF_AS_PROXY) Bit: 1 - Drop (ignore) modifiers (XREF_DROP_MODIFIERS) Bit: 2 - Merge modifiers (XREF_XREF_MODIFIERS) Bit: 3 - Merge manipulators (XREF_MERGE_MANIPULATORS) Duplicate material names action: Bit: 8 - Prompt Bit: 9 - Use Scene Bit: 10 - Use Merged Bit: 11 - Merge material and automatically rename them Reparent Action: Bit: 12 - Prompt Bit: 13 - Always Reparent Bit: 14 - Never Reparent The default behavior (flags = 0) is XRef the modifiers, XRef the manipulators, when duplicate material names are encountered use option specified by objXRefMgr.dupMtlNameAction (defaults to Merge and Rename), Always Reparent - A pointer to the newly added xref object, or NULL in case the file or name were invalid. - - - - - This method returns the number if IXRefObjects that reference a certain file name. It is possible to iterate over the IXRefObjects of a certain file by using GetXRefObject. - Parameters: - &asset - - The file name you wish to check references for. - - - - - This method returns a pointer to the I-th that references a certain file. - Parameters: - &asset - - The file you wish to check references for. - - int i - - The index of the object. - - - - - This method will return the number of files that contain object XRef's. - - - - - This method returns the file asset of the file that contains the specified object XRef. - Parameters: - int fidx - - The index of the object XRef for which to get the file. - - - - - This method will reload the file represented by the specified asset. - Parameters: - &asset - - The file name to reload. - TRUE if the reload was successful, otherwise FALSE. - - - - - This method returns whether or not the specified file asset is unresolved. - Parameters: - &asset - - The file name to check. - TRUE if the file is unresolved, otherwise FALSE. - - - - - This method returns whether or not the specified file name is disabled. - Parameters: - &asset - - The file name to check. - TRUE if the file is disabled, otherwise FALSE. - - - - - This method fills the table with all XrefObjects that are in the scene. - Parameters: - <IXRefObject*> &objs - - The table in which to receive all 's in the scene. - - - - - This interface extends interface. This interface is implemented by the system (3ds max). To obtain a pointer to the object xref manager, call IObjXRefManager18::GetInstace() - - - - - get the status of EnableUseLocalProxySettings ForXRefObj - - - EnableUseLocalProxySettings means while creating XRef objects, whether we turn its proxy's Enable/Use Local setting on by default. - bool - if EnableUseLocalProxySettings is enabled or not. - - - - - set the status of EnableUseLocalProxySettings - - - EnableUseLocalProxySettings means while creating XRef objects, whether we turn its proxy's Enable/Use Local setting on by default. - - - true to enable , false otherwise. - - - - gets the status of object's track. - - - 's track may inherit the source or become local for editing. - int - if XREF_TRACKS_XREF, it means track will inherit the source. if XREF_TRACKS_LOCAL, it means track will be local for editing. - - - - - Returns the option of whether to duplicate matching Layers without an identical parent hierarchy. - - - - - Class for managing object xrefs. - - - This interface allows for creating, destroying and managing xref records and xref items. Scene entities such as objects and materials must be xrefed using methods of this interface. Information related to xref operation and the xref items () themselves are stored in xref records (). The object xref manager must also be used for modifying and deleting xref items and records, in order to ensure the consistency and validity of the remaining xref data. This interface is implemented by the system (3ds max). To obtain a pointer to the object xref manager, call IObjXRefManager8::GetInstace() - Terms used with xrefs: - This interface should be used instead of . - - - - - - the number of object xref records - - - - - Retrieves the i-th xref record. - - - - Pointer to the i-th xref record. NULL if parameter i is greater than the number of currently stored xref records. - - - The index of the xref record to retrieve. - - - - Retrieves an xref record based on its unique handle. - - - - The record with the specified handle, or NULL if no record with the specified handle exists. - - - The xref record handle based on which to retrieve an xref record. - - - - Determines whether two xref records can be combined. - - - The specified xref records must meet the following criteria: - - - - - Combines several xref records into one single record. - - - The xref items of all xref records that meet the criteria described at IObjXRefManager8::CanCombineRecords will be combined into the first xref record in the list that is a top level xref record. All resulting empty xref records will be deleted. - The xref record that holds the xref items of all combined records, or NULL if none of the records was combined. - - - The xref records to be combined. - - - - Removes an xref record from the scene. - - - All xref items of this record are removed from the scene and the record is destroyed. - - true if the operation was successful, false otherwise - - - The xref record to be removed - - - - Merges an xref record into the scene. - - - All xref items of this record are merged into the scene and the record is destroyed. - - true if the operation was successful, false otherwise - - - The xref record to be merged - - - - Sets a new file path and name for the specified xref record. - - - Call this method in order to change the source file of all xref items within a top-level (non-nested) xref record. - - true if the xref record has been successfully updated, false otherwise. - - - The top-level xref record to be changed. This xref record becomes invalid once this method returns, thus client code should not try to use it. - - The path and name of the new source file. Must be a non-empty string. This method checks that the supplied file path and name is valid for xrefing. - - - - Updates all xref records. - - - This method updates the up-to-date state of all xref records that are enabled and not auto-updating. Then it reloads all the records that are out-of-date, bringing them all up-to-date. Nested records are also reloaded. - - true if at least one xref record has been reloaded, false otherwise. - - - - - Adds new xref items to an existent xref record from the record's source file. - - - In order to xref only certain objects, specify their name via the objNames parameter. In order to xref all objects not xrefed yet, leave the objNames parameter NULL. The xref options and the source file name of the specified xref record are used to create the new xref objects. New xref items can be added only to top-level xref records that are resolved (not unresolved). See for a discussion of nested xref records. - - true if the operation was successful, false otherwise. - - The xref record to which the new xref objects will be added - - If true, the user can interactively specify the objects to get xrefed, and the objNames parameter is ignored. If false, the objNames parameter controls what gets xrefed. - - A list with names of objects (nodes) to xref. If no names are specified or this parameter is NULL, all objects in the source file that aren't xrefed yet will get xrefed. Otherwise, the specified objects are xrefed only, whether already xrefed or not. - - - - Removes the specified xref items from the scene. - - - This method simplifies the task of removing several xref items at once. - - - - - Merges the specified xref items into the scene. - - - This method merges the source scene entities of the specified xref items into the current scene by. - - - - - Applies or re-applies an xref material to a list of xref objects and reset its overide material. - - - This method iterates through the list of xref objects and applies/re-applies an xref material on each node that references each object. The override material of xref material is reset as well. The xref material that is applied will reference the material on the xref object's source. If an appropriate xref material already exists in the record that contains the xref object, it is re-used; otherwise, a new xref material is created and added to the record. Note: If the source object has no material, then this method will remove any existing material on the xref object's nodes. - - - The xref objects on which the xref material is to be applied. - - - - Applies or re-applies an xref controller to a list of xref objects. - - - This method iterates through the list of xref objects and applies/re-applies an xref controller on each node that references each object. The xref controller that is applied will reference the controller on the xref object's source. If an appropriate xref controller already exists in the record that contains the xref object, it is re-used; otherwise, a new xref controller is created and added to the record. - - - The xref objects on which the xref controller is to be applied. - - - - Determines whether an Item can have its Offset matrix being reset. - - - For this to be true, the given xref item must meet the following criteria: - - - - - XRef controllers' offset matrix back to identity, and if any, set the corresponding source controller's transformation matrix accordingly. - - - This method iterates through the list of XRef items, and for any non-nested XRef controller that is found, it will set its offset matrix back to identity. If the XRef controller is resolved, i.e. it has a source controller, it will also set this one's transformation matrix accordingly. - true if at least one XRef controller has its offset been reset, false otherwise. - - - Collected set of XRef items. - - - - Sets a new scene entity for the specified xref item. - - - Call this method in order to change the source scene entity being xrefed by an xref item. The specified scene entity will be xrefed from the scene the xref record owning the the specified xref item is pointing to. - XRef Atmospherics are should not be modified using this method since they are xrefed and updated when their xrefed gizmos are modified. Thus, this method ignores XRef Atmospherics and return false. - - true if the xref item has been successfully updated, false otherwise. If the xref item has not been successfully updated, IXRefItem::GetSrcItem will return NULL. - - - The xref item to be changed. XRef Atmospherics should not be passed as parameter. - - The name of the new source entity. Must be a non-empty string - - - - Sets a new scene entity for the specified xref proxy. - - - Call this method in order to change the proxy scene entity being xrefed by an xref proxy. The specified scene entity will be xrefed from the scene the xref record owning the the specified xref proxy is pointing to. - - true if the proxy has been successfully updated, false otherwise. If the proxy has not been successfully updated, IXRefItem::GetSrcItem will return NULL. - - - The xref proxy to be changed. - - The name of the new proxy scene entity. Must be a non-empty string - - - - Sets a new file for the specified xref item. - - - Call this method in order to change the source file a scene entity is xrefed from. Xref records could be removed if they become empty as a result of executing this method. - - true if the source item has been successfully updated, false otherwise. If the source item has not been successfully updated, IXRefItem::GetSrcItem will return NULL. - - - The xref item to be changed. - - The new source file. This method checks that the supplied file is valid for xrefing. - - - - Sets a new file for the specified xref proxy. - - - Call this method in order to change the file a proxy scene entity is xrefed from. Xref records could be removed if they become empty as a result of executing this method. - - true if the xref proxy has been successfully updated, false otherwise. If the source item has not been successfully updated, IXRefItem::GetSrcItem will return NULL. - - - The xref proxy to be changed. - - The new proxy file. This method checks that the supplied file is valid for xrefing. - - - - One of the action values listed under Duplicate Node Name Actions - - - - - Gets the action taken during xrefing when a source material has a name that is already used by a main scene material. - - - One of the action values listed under Duplicate Material Name Actions - - - - - Determines if a node is xrefed. - - - A node is considered to be xrefed if any part of it's geometry pipeline is xrefed. - - Pointer to the first xref object in the geometry pipeline of the node. Use IXRefObject8::GetInterface(InterfaceServer& is) to get an pointer from the returned interface pointer. - - - The node to be checked whether it's an xref - - - - Returns the current setting of whether the transform controllers of nodes are merged when xrefing objects. - - - - - Returns the option of merging the material of nodes when xrefing objects. - - - - - Returns the option of merging manipulators when xrefing objects. - - - - - Sets the handling of modifiers of nodes when xrefing objects. - - - - - Returns the option of whether all nodes of a file will be added to a new xref record. - - - - - Returns the option of whether the content of the xref record will update on source file update. - - - - - Class for managing an object xref record. - - - Xref records store xref items and information regarding the xref operation/transaction that created them. Xref records are created by and can be retrieved from the Xref Manager (see class ). Xref records are not created when xrefing a whole scene via the scene xref feature. - - - - - - The number of xrefed items of the specified type. - - - One of the predefined xref item types - - - - Retrieves all the xref items of the specified type. - - - Note that any xref atmospheric item returned by this method will become invalid if all other types of items are removed from this record. Also, any of of the xref items returned by this method could become invalid after an operation that modifies the contents of the xref record. - - The number of returned xref items - - - A combination of predefined xref item types - - An array where the xref items will be returned. The array is not cleared, so its existent elements will be preserved. - - - - Retrieves the i-th xref item of the specified type. - - - - Pointer to the xref item. NULL if the supplied index (i) is out of range, or if the supplied item type is unsupported - - - The index of the xref item to retrieve. - - One of the predefined xref item types - - - - Allows to verify whether this record contains any xref items. - - - Note that empty xref records are automatically deleted by the system, so this method should never return true, except when called before the system had a chance to delete empty xref records. Also note that xref records containing only xref atmospherics will be deleted automatically by the system. - - true if the record does not contain any xref items of any type, otherwise false - - - - - Retrieves all child xref records of this record. - - - - The number of child xref records. - - - of xref records where the child records are retured. The supplied array is not cleared out before the xref records are added to it. The array is guaranteed not to contain duplicate xref records. - - - - Retrieves all parent xref records of this record. - - - - The number of parent xref records. - - - of xref records where the parent records are returned. The supplied array is not cleared out before the xref records are added to it. The array is guaranteed not to contain duplicate xref records. - - - - Retrieves all root (top-level) xref records of this record. - - - - The number of root xref records. - - - of xref records where the root records are returned. The supplied array cleared out before the xref records are added to it. The array is guaranteed not to contain duplicate xref records. - - - - Retrives whether this xref record has parent records or not. - - - This method uses a more efficient way of determining whether this xref record is nested or not than calling GetParentRecords. - - true if this xref record is nested, i.e. has at least one parent record, otherwise false. - - - - - Retrives the options used to create this xref record. - - - These options cannot be modifed once the xref record has been created. - The options used to create the xref record. See Object Xref Options for a full list of available options. - - - - - Retrieves whether all scene entities are xrefed from this record's source file. - - - When this option is turned on, the next update operation of this xref record will xref all scene entities that have not been xrefed yet from the its source file. - - true if this should be xrefing all scene entities from its source file, otherwise false - - - - - Sets the xrefing of all scene entities from this record's source file. - - - - - If true, the include-all option is enabled, otherwise it's disabled - - - - Retrieves the enabled state of this xref record. - - - Enabled xref records can be updated, while disabled xref records cannot. - - true if this xref record is enabled, otherwise false - - - - - Sets the enabled state of this xref record. - - - When disabling an xref record, the source items of its xref items are un-loaded from memory. Note that opening a main file containing disabled xref records results in unresolved xref items. Re-enabling and updating the record, re-resolves the xref items. - - - If true, the xref record is enabled, otherwise it's disabled - - - - Retrieves whether auto-update is enabled for this xref record. - - - When Auto-update is enabled, the xref record is automatically updated as soon as the source file changes. - - true if this xref record is has auto-update turned on, otherwise false - - - - - Sets the state of the auto-upate for this xref record. - - - - - If true, auto-update is enabled for this xref record, otherwise it's disabled. - - - - Allows to verify whether the xref record is up-to-date. - - - The xref record is up-to-date if it's been updated with the source items from the latest version of the source file. This method will report the current value of the up-to-date state of this xref record. To trigger a verification of whether the source file of this xref record has changed, use CheckSrcFileChanged. - - true if the record is up-to-date, otherwise false - - - - - Verifies whether the source file of this xref record has changed since the record was last updated. - - - Calling this method checks whether the source file is unresolved. If it isn't, it updates the up-to-date flag of this xref record by comparing the date and time of the source file with the date and time the xref record was last updated. - - true if the unresolved state, or the up-to-date state have changed, false if neither have changed - - - - - Allows to verify whether the xref record is unresolved. - - - An xref record is unresolved if the source file name and path is not valid. Unresolved xref records are not discarded by the system because they may get re-resolved on a subsequent update of the xref record if the source file path and name becomes valid. - - true if this is an unresolved xref record, otherwise false - - - - - Retrieves the asset Id of the source file. - - - The source file of an xref record is the file from where the source scene entities xrefed via this xref record come from. - - The asset user of the file that the source scene entity comes from or or NULL if there's no source file specified. - - - - - Returns the parent Xref record source file name. - - - the parent source file name. - - - - - The xref entities are reloaded according to the currently set options. For example, the xref record will not be updated if it is disabled. - - Updating an xref record will trigger the updating of all nested xref records. - Updating an xref record with the Include All flag On for itself and all its child records, will not result in xrefing scene entities newly added to nested source files. The child xref records saved with the intermediate main files must be update first, starting with the deepest child or intermediate file. - - true if the operation succeeded, otherwise false. - - - - - Retrieves the record's unique handle. - - - Each xref record is identified by a unique handle. The handle value is unique only within the current scene. Reseting the scene is considered to start a new scene. The handle of the xref records is not persisted. - - The handle of this xref record. - - - - - This interface extends interface. - - - - - Returns the option of whether to duplicate matching Layers without an identical parent hierarchy. - - - - - Retrieves the record's "unique" identifier. - - - - - Description: - This control provides an off screen buffer which the developer may draw into, then quickly blit onto the actual display for flicker free image updates. - - To initialize the pointer to the control call: - - - - - Returns a handle to the display device context (DC) for the off screen buffer. The display device context can be used in subsequent GDI functions to draw in the buffer. - - - - - This method is used to erase the buffer. - Parameters: - Rect *rct=NULL - - Specifies the rectangular region to erase. If NULL the entire buffer is erased. - - - - - This method blits (transfers the image from) the buffer to the display. - Parameters: - Rect *rct=NULL - - Specifies the rectangular region to blit. If NULL the entire buffer is blitted. - - - - - This method is used to resize the buffer. - - - - - This methods retrieves the background color of the buffer. - The background color of the buffer. - - - - - Description: - The Orientation Constraint matches the orientation of an object to its target without affecting its position. Multiple weighted targets are supported. This class is an interface to the parameters of this controllers. You can obtain a pointer to the list control interface using; GetIOrientConstInterface(cd). This macro will return (IOrientConstRotation*)(CD)->GetFPInterface(ORIENT_CONSTRAINT_INTERFACE). - - ORIENT_ROT_PBLOCK_REF may be used to access the orientation constraint controller's references: - - All methods of this class are Implemented by the System. - - - - - Returns the number of target nodes in the orientation target list. - - - - - Gets one of the orientation nodes that the orientation constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the orientation target list to be obtained. - - - - - Gets the weight of one of the orientation nodes that the orientation constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the orientation target list to set. - Returns the orientation target weight if the targetNumber is relevant, 0.0f otherwise. - - - - - Sets the weight of one of the orientation nodes that the orientation constraint controller follows, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the orientation target list whose weight is to be set. - - float weight - - The weight to set. - TRUE if there is more than one orientation target in the list and you are trying to set weight, FALSE otherwise. - - - - - Appends the current orientation target list by one and appends the current orient_targ_wtlist (orientation target weightlist) by one. - Parameters: - *target - - The node that is to be appended to the current orientation target list. - - float weight=50.0 - - This is the weight that is to be assigned to the newly appended orientation target. The default weight is 50.0. - TRUE if the target was appended, otherwise FALSE. - - - - - This method allows you to delete a specified target. - Parameters: - int selection - - The node number in the orientation target list to delete. - TRUE if successful, otherwise FALSE. - - - - - Description: - This class provides an interface to the OsnapManager. Developers who implement osnaps need to record hits with the osnap manager. Developers implementing command modes are responsible for getting the snap preview done and may be responsible for initializing and closing point sequences. See the Advanced Topics section on ~{ Snapping }~ for more details. - - - - - This method is used internally but may be called to determine if the OsnapManager is currently on. - - - - - This method is used internally but may be called to determine if the OsnapManager will use the system level axis constraints when performing translation. - - - - - When a plugin osnap finds a hit, it should call this method to record it with the manager. This will enter the hit in a stack which is sorted based on proximity to the cursor position. When multiple hits are recorded with the manager, the user has the ability to cycle throught the stack. - Parameters: - OsnapHit* somehit - - A pointer to the hit to record. The plugin should instantiate the hits and the manager is responsible for freeing them. - - - - - Some snaps only make sense relative to a reference point. Consider, for example, the tangent snap which looks for points of tangency on splines. You can only find a tangent point relative to a second point. As objects are created and manipulated, the OsnapManager maintains a list of the Points that have been input to the current command mode. This method tells you if the first point has been recorded. - - - - - This method tells you if the point on the top of the reference stack was actually snapped. - - - - - This method retrieves the Point on the top of the reference stack. The point returned is in world space. Note that calling this method when the stack is empty will crash the program. Remember to call OKForRelativeSnap() first. Here are the first few lines of the tangent snap's main method. - - - Parameters: - BOOL top = TRUE - - The default is to return the top of the stack, i.e. the last point which was input to the command mode. If you pass FALSE, the bottom of the stack will be returned. - - - - - This method is used internally. This method tells if the any hits were recorded with the OsnapManager during the last scene traversal. - - - - - This method is used internally. It returns the current hit i.e. the hit which the manager is currently displaying. - - - - - Returns a pointer to a . This is only valid for the duration of the current scene traversal. It is guaranteed to be valid while in a plugin's Snap() method. - - - - - Returns a pointer to the node which is currently being snapped. - - - - - Returns the current snap strength. This is the radius of a circular area about the cursor. It is the plugin's responsibility to determine if any "interesting" parts of the object lie within this area. For testing points, see the method OsnapManager::CheckPotentialHit(). - - - - - Returns the object transformation matrix of the node which is currently being snapped. - - - - - Returns the animation time of the current scene traversal. - - - - - This method is not currently used. The method transforms a point in the current node's object space into screen space. - Parameters: - *inpt - - A pointer to the object space point. - - *outpt - - A pointer to storage for the screen space point. - - - - - This method may be called to clear out the OsnapManager's reference point stack. Typically this is handled internally. However, objects which implement their own creation processes may need to call this method upon completion of a creation cycle. - - - - - Description: - Updated canvas interface for Max 2024.1. This variant allows the canvas to report whether the brush operation it defines can change the geometry or transformation of a node. Note that if a particular canvas does not implement this version of the interface, it will be assumed that the operation can indeed alter node geoemtry, retaining legacy behavior. - - - - - Returns a flag indicating whether the present brush operation leaves. - - - - - Description: - This is the Max5 version of a PainterCanvas. Any plugin that wants to be able to be painted on must sub class from this class or a later version of it. Basically this calls contains all the methods that deal with a paint stroke. - - - - - This is called when the user start a pen stroke. - - - - - This is called as the user strokes across the mesh or screen with the mouse down. - - - This only gets called if the interactive mode is off (the user has turned off Update on Mouse Up) - - - if this is a hit or not, since the user can paint off a mesh - - this is mouse coords of the current hit in view space - - this is the hit point on the painted mesh in world space - - this is the normal of the hit point on the painted mesh in world space - - this is the hit point on the painted mesh in local space of the mesh that was hit - - this is the normal of the hit point on the painted mesh in local space of the mesh that was hit - - this the barcentric coords of the hit point based on the face that was hit this may or may not be valid depending on the state of the stack. For instance if a paint modifier was below a MeshSmooth, the barycentric coords would be based on the MeshSmooth'ed mesh and not the mesh at the point of the paint modifier - - the index of the face that was hit. See the warning in bary above. - - the state of the shift, alt, and ctrl keys when the point was hit - - of the radius of the brush when the point was hit, this is after all modifiers have been applied like pressure or predefined radius etc - - of the strength of the brush when the point was hit, this is after all modifiers have been applied like pressure or predefined radius etc - - if a pressure sensitive tablet is used this value will be the pressure of the stroke ranging from 0 to 1 - - this node that got hit - - whther the user had mirror on for the stroke, you can ignore the next for params if false - - the mirrored world stroke pos - - the mirrored world stroke normal - - the mirros local stroke pos - - the mirros local stroke normal - - - - This is called as the user ends a strokes when the users has it set to always update. - - - - - This is called as the user ends a strokes when the users has it set to update on mouse up only. - - - the canvas gets a list of all points, normals etc instead of one at a time - - - the number of elements in the following arrays - - - - - This is called as the user cancels a stroke by right clicking. - - - - - This is called when the painter want to end a paint session for some reason. - - - - - this is called when the painter updates the view ports this will let you do custom drawing if you need to - - - - - Description: - This is the Max5.1 version of a PainterCanvas. - This interface changes how the command mode behaves It adds the ability to send back to the canvas whether to start or end the paint mode This bacially replaces the SystemEndPaintSession and also - - - - - Called on painting start. - - - the painter interface will call this when it wants to start the painter an example of this is when the user scrubs the time slider when in a paint session the system will turn off the paint mode while scrubbing so you will get a CanvasEndPaint then when the user stops scrubbing it will try to turn it back on using CanvasStartPaint. so if you use this interface after you call StartPaintSession() you will imediately get a CanvasStartPaint callback where all your setup code and UI code should be handled - - - - - Called on painting end. - - - the painter interface will call this when it wants to stop the painter an example of this is when the user scrubs the time slider when in a paint session the system will turn off the paint mode while scrubbing so you will get a CanvasEndPaint then when the user stops scrubbing it will try to turn it back on using CanvasStartPaint. so if you use this interface after you call StartPaintSession() you will imediately get a CanvasStartPaint callback where all your setup code and UI code should be handled - - - - - This is the additional functionality in the Max7.0 version of the PainterCanvas. - - - - - This method indicates that the paintbrush used to paint has changed. - - - (This usually cues applications to refresh their dialogs.) - - - - - Description: - It adds functionality for constraining the brush to a spline - - - - - This checks if constraining the brush to a spline is turned on. - - - - - This sets the spline node to use for constraining the brush. Returns false if the node is not a shape object. - - - - - This checks if a valid node has been assigned and is in the scene. - - - - - description - Any plugin that wants to be able to be painted on must sub class from this class or a later version of it. - - - - - The canvas passes a pointer of itself to the painter. - - - This is so the painter knows where to send the stroke messages - - - is the pointer to the canvas - - - - this loads of the nodes that you want to paint on - - - Anytime you want to add delete a node this must be called - - - not yet implemented does nothing but there to allow flags per node for special conditions - - a table of nodes that you want to paint on - - - - This forces the quadtree to rebuilt. - - - Any time you change a geometry or togopology of a node you passed to the InitializedNodes methode this must be called. Ideally I could listen to the notifyremessage changed and rebuild on that but the since rebuilding the quad tree is inetensive, I leave it up to the canvas as to when to rebuild so we can better control the amount of stack re-evals - - - determines whether the pointGather data gets updated also normally if your mesh does not change shape or topology you dont need to update the pointgather. For instance if you rotate a view your quad tree needs to get updated but not the point list - - - - This is called when the a canvas wants to start a paint session. - - - - - This is called when the a canvas wants to end a paint session. - - - - - This return whether the user is in the paint mode, so a plugin can determine how to paint the UI paint button. - - - - - This brings up the Painter Options dialog that lets the users sets various setting of the painter system. - - - - - This lets you access the time stamp of each sample of a stroke. - - - This lets you look at the acceleration of the mouse as it moves if say you wanted to paint a stroke and use it for an animation path. - - - - - this function lets you hit test against the quad tree given a mouse coord - - - TRUE if that point insterects the quad tree - - - the position in screen space that you want to hit test agains - - the world hit point position - - the world hit point normal - - the local hit point position - - the local hit point normal - - the barycentry coord of the face that was hit - - the index of the face that was hit - - the node that was hit - - whether mirroring was on or off - - the world hit point position after it was mirrored - - the world hit point normal after it was mirrored - - the local hit point position after it was mirrored - - the local hit point normal after it was mirrored - - - - Retrieves a random hit point around the last hit point or a specified hit point within the brush. - - - Useful if you want to do airbrush type effects or to just sample around the hit point - FALSE if a hit point was not found - - - the world hit point position - - the world hit point normal - - the local hit point position - - the local hit point normal - - the barycentry coord of the face that was hit - - the index of the face that was hit - - the strength of the point based on the fall off of the brush - - the node that was hit - - whether mirroring was on or off - - the world hit point position after it was mirrored - - the world hit point normal after it was mirrored - - the local hit point position after it was mirrored - - the local hit point normal after it was mirrored - - What hit you want to sample around if 0 or less it will hit around the last hit test - - - - This will do random hit point along the stroke segment. - - - FALSE if it does not find a hit - - - the world hit point position - - the world hit point normal - - the local hit point position - - the local hit point normal - - the barycentry coord of the face that was hit - - the index of the face that was hit - - the strength of the point based on the fall off of the brush - - the node that was hit - - whether mirroring was on or off - - the world hit point position after it was mirrored - - the world hit point normal after it was mirrored - - the local hit point position after it was mirrored - - the local hit point normal after it was mirrored - is what segment you want to sample around if 0 or less it will hit around the last segment - - - - this clears out all the stroke data for the current stroke - - - This method is used if you want to do a custom stroke. Say for instance you wanted to just stroke a straight line, by default the painter uses a path stroke. so what you do on the PaintStroke method record the first and last mousePos, clear all the stroke data and then Add your custom stroke to the system. - - - - - this adds a hit test to the current stroke - - - This method is used if you want to do a custom stroke. Say for instance you wanted to just stroke a straight line, by default the painter uses a path stroke. so what you do on the PaintStroke method record the first and last mousePos, clear all the stroke data and then Add your custom stroke to the system. - - - the point that want to test to add - - this determines whether the poing gather data get rebuilt this allows you to delay the building of the data if you are addding mulitple points at once - - determines if the viewports get updated after this call - - - - returns the number of sample points in the current stroke - - - - - this returns a pointer to an array of floats where each entry is the str of a point sample - - - - - this returns a pointer to an array of floats where each entry is the radius of a point sample - - - - - this returns a pointer to an array of point3s where each entry is the world space hit point of the sample - - - - - this returns a pointer to an array of point3s where each entry is the world space normal of the sample - - - - - this returns a pointer to an array of point3s where each entry is the world space hit point of the sample after it has been mirrored - - - - - this returns a pointer to an array of point3s where each entry is the world space normal of the sample after it has been mirrored - - - - - this returns a pointer to an array of floats where each entry is the pressure of a point sample either from a pressure sensitive tablet or from a predefined presssure graph - - - - - this returns a pointer to an array of point3s where each entry is the local space hit point of the sample - - - - - this returns a pointer to an array of point3s where each entry is the local space normal of the sample - - - - - this returns a pointer to an array of point3s where each entry is the local space hit point of the sample after it has been mirrored - - - - - this returns a pointer to an array of point3s where each entry is the world space normal of the sample after it has been mirrored - - - - - this returns a pointer to an array of Ipoint2s where each entry is the mouse pos in screen space for the sample - - - - - this returns a pointer to an array of s where each entry is whether the sample hit the mesh or not - - - the system allows the user to paint off the mesh, where all hitpoint are projected onto a plane based on the last hit point and normal - - - - - this returns a pointer to an array of point3s where each entry is the barycentri coords of the sample - - - - - this returns a pointer to an array of ints where each entry is the index of the face of the sample - - - - - this returns a pointer to an array of bools where each entry is the state of the shift of the sample - - - - - this returns a pointer to an array of bools where each entry is the state of the ctrl of the sample - - - - - this returns a pointer to an array of bools where each entry is the state of the alt of the sample - - - - - this returns a pointer to an array of where each entry is the of the sample - - - - - this returns a pointer to an array of ints where each entry is the time stamp of the sample - - - - - given a point in world space it returns the str of that point based on the current stroke - - - - - Lets you interogate and set the state of the options dialog. - - - this is used to ask the system if a stroke str changes as it is painted the user can set predetermined shapes graphs and attach them to the str of brush based on the position of the in the curve it is. If you are in an interactive mode this data will always be changing so you can use this to get the current str/sizes of the hit points. If you are in a non interactive mode you do not need to call this since all the correct sizes/str are sent to the end stroke arrays. If the user has not specified any predetermined graphs the arrays will be NULL - - - count of the arrays - - - - Lets you interogate and set the state of the options dialog. - - - this is used to ask the system if a stroke size changes as it is painted the user can set predetermined shapes graphs and attach them to the size of brush based on the position of the in the curve it is. If you are in an interactive mode this data will always be changing so you can use this to get the current str/sizes of the hit points. If you are in a non interactive mode you do not need to call this since all the correct sizes/str are sent to the end stroke arrays. If the user has not specified any predetermined graphs the arrays will be NULL - - - count of the arrays - - - - Access to the BuildNormalData property. - - - This will build a vertex normal list that you can access through RetrievePointGatherNormals This is by default is off to save memory. Also if you use a custom point list through LoadCustomPointGather no normals will be built since there is no topo data to build them from - whether we build normal data or not - - - - - Gets the state of point gathering. - - - If this is enabled, the points of the mesh will be used as your points - TRUE if point gather is enabled - - - - - This lets you set up a custom list of points to weight to override the currentlist. - - - for instance if you have a non mesh you will need to do this since by default the point gather uses the mesh points to weight - - - the number of points that you want to add - - the points you want to add in world space - - which node you want to assign them to - - - - This retrieves the weight of the points based on the current stroke. - - - a pointer to an array of weights - - - the node that you want to inspect - - the number of points in the array - - - - This retrieves the strength of the points based on the current stroke. - - - a pointer to an array of point strengths - - - the node that you want to inspect - - the number of points in the array - - - - This retrieves the whether the point was affected by a mirror stroke. - - - an pointer to an array of bools indicating if points were mirrored - - - the node that you want to inspect - - the number of points in the array - - - - This retrieves the the array of the points. - - - a pointer to an array of gather points - - - the node that you want to inspect - - the number of points in the array - - - - This retrieves the the array of the normals. - - - An array of normals in local space. Note that these are only valid if you do not use a CustomPointGather - - - the node that you want to inspect - - the number of points in the array - - - - This retrieves the the array of the U vals, this is how far along the stroke that point is. - - - a pointer to an array of float U values - - - the node that you want to inspect - - the number of points in the array - - - - returns if the mirror plane is on or off - - - - - returns the center of the mirror plane in world space coords - - - the mirror plane is always aligned to the world axis - The center of the mirror plane in world space - - - - - returns which mirror axis is active - - - One of the following values: - - - - - - Returns the mirror offset. - - - - - Lets you get the quad tree depth. - - - The deeper the quad tree the more memory you consume, but the more memory you consume (the memory consumption is exponential so be careful) - the current quad tree depth - - - - - Lets you get the Update on Mouse Up option. - - - When this is enabled you will not get PaintStroke calls. Instead you will get all the points at the end through the endStoke function - the current Update on Mouse Up state - - - - - These 2 function let you get and set the lag rate. - - - When this is enabled you get PaintStroke delayed by the lag rate calls. every x(lagrate) stroke points you willget the strokes. - The current lag rate - - - - - Let you get the min strength for a brush. - - - If there is no pressure sensitive device attached only the max str is used - The current min strength - - - - - lets you get the max strength for a brush. - - - If there is no pressure sensitive device attached only the max str is used - The current max strength - - - - - lets you get the min radius for a brush. - - - If there is no pressure sensitive device attached only the max radius is used - the current min radius - - - - - lets you get the max radius for a brush. - - - If there is no pressure sensitive device attached only the max radius is used - the current max radius - - - - - Gets the aditive mode. - - - When additive mode is off the weight is absolutely set based on the current stroke hit. Previous stroke data is over written. In Additive mode the strength is added to current strength and is not capped. - True if we are in additive mode - - - - - This returns the brush falloff curve if you want to handle the doing the brush falloff yourself. - - - - - This lets you get whether the ring is drawn around the hit point. - - - - - - - This lets you get whether the normal vector is drawn at the hit point. - - - - - - - This lets you get whether the a line is left behind a stroke as it is drawn. - - - - - - - let you get whether pressure sensistivity is turned on - - - when Pressure is enabled it can affect Str, Radius, Both Str and Radius or Nothing You would nothing fr instance if you wanted to do a custom affect for pressure. - TRUE if pressure is enabled - - - - - Get what the pressure of a brush affects. - - - You can effect Str. Radius, Str and Radius or None - - - - - what the pressure of a brush affects. - - - You can effect Str. Radius, Str and Radius or None - - - One of the in - - - - get whether a predefined str is enabled for a stroke. - - - A predefined str stroke lets the user graph the str of stroke over the length of stroke - - - - - get whether a predefined radius is enabled for a stroke. - - - A predefined radius stroke lets the user graph the radius of stroke over the length of stroke - - - - - get the predefined radius graph set for a stroke. - - - A predefined radius stroke lets the user graph the radius of stroke over the length of stroke - - - - - get the predefined strength graph set for a stroke. - - - A predefined strength stroke lets the user graph the strength of stroke over the length of stroke - - - - - Returns the mesh hit type. - - - One of the following values: - - - - - - Description: - Any plugin that wants to be able to be painted on must sub class from this class or a later version of it. - - - - - this loads of the nodes that you want to paint on - - - anytime you want to add delete a node this must be called. This use the object state passed to it instead of the one gotten from the node to get the hit mesh. NOTE I do not hang onto any of the data in the . I just get the a copy of the mesh from it. - - - not yet implemented does nothing but there to allow flags per node for special conditions - - a table of nodes that you want to paint on - - a table of objects states one per node to use as your hit node - - - - This forces the quadtree to rebuilt. - - - Any time you change a geometry or togopology of a node you passed to the InitializedNodes methode this must be called. Ideally I could listen to the notifyremessage changed and rebuild on that but the since rebuilding the quad tree is inetensive, I leave it up to the canvas as to when to rebuild so we can better control the amount of stack reevals NOTE I do not hang onto any of the data in the . I just get the a copy of the mesh from it. - - - determines whether the pointGather data gets updated also normally if your mesh does not change shape or topo you dont need to update the pointgather. For instance ifyou rotate a view your quad tree needs to get updated but not the point list - - a table of objects states one per node to use as your hit node - - - - This lets you take a patch and get a list or tri mesh faces wher each tri has an owning patch index and the UVW space of that face. This lets you get patch UVW space. - - - - - This overload of the method used to start a paint session allows you to submit a class which will handle right-click events in the paint mouse proc. - - - This allows you to end the paint proc however you need to. If rightClicker is NULL, or if the no-argument version of StartPaintSession is used, nothing will happen on right-click. - - - The handler class to be notified on a right click, or NULL - - - - this get the str limit min for while dragging to chnage the str - - - - - this get the str limit max for while dragging to chnage the str - - - - - Description: - This class is used to get right-click events when the painting mode is exited. Implement your own local version of this virtual class, and submit it to IPainterInterface_V7::StartPaintSession to be notified if the user right-clicks to exit painting. - - - - - This method cues you that the user has right-clicked to exit painting. Handle as desired. - - - - - A data management class for accessing data required for displaying real time effects. - - - An instance of this class is maintained by the DirectX 9 material and is passed into the IEffectParser::PreRender() method. This allows the Parsers to format the data accordingly based on the runtime active for the shader - - - - - The total number of parameters maintained by the manager. - - - The number of parameters - - - - - The semantic for the parameter. - - - This will be the semantic usage found in the shader file when it is parsed by the system - An item from MaxSemantics representing the semantic found in the file - - The index of the parameter to query - - - - Retireve the name of the parameter. - - - This will be the name of the parameter found in the shader file - A string containing the name - - The index of the parameter to query - - - - Access to the actual data stored by the manager. - - - This is the main access point for data retrieval. It is the calling code's responsibility to make sure there is enough space allocated to receive the data. This can be determined by calling GetParamType, which will return the data type. If it is a kPtype_Matrix, then internally this is stored as an 4x4 float array - True/False depending if the parameter was found, and the data copied correctly - - A pointer to a buffer to receive the data - THe index of the parameter to query - - - - Access to the actual data stored by the manager. - - - This is an access point for data retrieval. It is the calling code's responsibility to make sure there is enough space allocated to receive the data. This can be determined by calling GetParamType, which will return the data type. If it is a kPtype_Matrix, then internally this is stored as an 4x4 float array - True/False depending if the parameter was found, and the data copied correctly - - A pointer to a buffer to receive the data - The name of the parameter to query - - - - Access the data type of the parameter. - - - This method returns the type of parameter. This will be one of the enumerated types define in , kPType_Matrix etc.. - The parameter type - - The index of the parameter to query - - - - Access the data type of the parameter. - - - This method returns the type of parameter. This will be one of the enumerated types define in , kPType_Matrix etc.. - The parameter type - - The name of the parameter to query - - - - Access the data size of the parameter (mainly designed for kPType_Struct type) - - - This method returns the size of the parameter, in D3DXVECTOR4 (upper rounded to), or number of textures. - - The parameter size - - The index of the parameter to query - - - - Description: - This class represents a virtual array of parameters. Parameter are accessed using an integer index and GetValue() and SetValue() methods. Parameter blocks are one such implementation of this class, but it can also be useful to implement a class that abstracts non-parameter block variables. The ParamMap class uses this base class so that a ParamMap can be used to control UI for not only parameter blocks but also variables stored outside of parameter blocks. The Advanced Topics section on ~{ Parameter Maps }~ discusses how this is done. - Default implementation of these methods are provided which simply return FALSE. - - - - - This method is called when the system needs to store a value into a variable. There are overloaded functions for each type of value to set (int, float, and ). Each method has three parameters. Below is the float version - the others are similar. - Parameters: - int i - - This is the index into the virtual array of the value to set. - - TimeValue t - - This is the time at which to set the value. - - float v - - This is the value to set. - This is not currently used. - - - - - This is the integer version of above. - - - - - This is the version of above. - - - - - Whenever the developer needs to retrieve a value from the parameter block, the GetValue() method is used. There are overloaded functions for each type of value to retrieve (int, float, , and ). Each method has four parameters: - If the value was retrieved TRUE is returned; otherwise FALSE is returned. - - - This is the index into the virtual array of the value to retrieve. - - This is the time at which to retrieve the value. For constants pass 0. - - This is the value to retrieve. - - The interval into which the validity of the evaluated parameters is intersected. - - - - This is the integer version of above. - - - - - This is the version of above. - - - - - Implemented by the System. - - If the array uses a parameter block, this method will return a pointer to it, otherwise it will return NULL. Note that casting won't work because of multiple inheritance. - Returns a pointer to the parameter block if one is used; NULL otherwise. - - - - - This method is available in release 2.0 and later only. - - Checks to see if a keyframe exists for the given parameter at the given time. Returns TRUE if a keyframe exists at the specified time; otherwise FALSE. - Parameters: - int i - - Zero based index of the parameter to check. - - TimeValue t - - The time to check. - Default Implementation: - {return FALSE;} - - - - - Description: - This class provides methods to work with parameter blocks. For more details on parameter blocks see ~{ Parameter Blocks }~. - - - - - Returns the super class ID of a parameters controller. - Parameters: - int anim - - Specifies the parameter whose controller super class ID is returned. - - - - - Returns the type of the 'i-th' parameter. - Parameters: - int i - - The zero based index of the parameter to retrieve. See ParamType and ParamType2. - - - - - This is the version of above. - - - - - This is the version of above. - - - - - Implemented by the System. - - Returns the parameter block version. - - - - - Implemented by the System. - - Removes the 'i-th' controller. - Parameters: - int i - - The parameter index of the controller to remove. - - - - - Implemented by the System. - - Returns the controller of the 'i-th' parameter. - Parameters: - int i - - The parameter index of the controller to return. - - - - - Implemented by the System. - - Sets the 'i-th' parameter controller to c. - Parameters: - int i - - The index of the parameter to set. - - *c - - The controller to set. - - BOOL preserveFrame0Value=TRUE - - If TRUE the controllers value at frame 0 is preserved. - - - - - Implemented by the System. - - Swaps the two controllers of the parameters whose indices are passed. - Parameters: - int j, int k - - The parameter indices whose controllers should be swapped. - - - - - Implemented by the System. - - Given a parameter index this method will return the reference number of that parameter. - Parameters: - int paramNum - - The parameter index. - - - - - Implemented by the System. - - Given a parameter index this method will return the anim number. - Parameters: - int paramNum - - The parameter index. - - - - - Implemented by the System. - - Given an anim number this method will return the parameter index. - Parameters: - int animNum - - The anim number. - - - - - This method is available in release 2.0 and later only. - - This is only for use in a ReferenceMaker::RescaleWorldUnits() implementation: The parameter block implementation of RescaleWorldUnits() scales only tracks that have dimension type = stdWorldDim. If letting the parameter block handle the rescaling is not sufficient, call this on just the parameters you need to rescale. - Parameters: - int paramNum - - The index into the parmeter block of the parameter to rescale. - - float f - - The value to scale by. - - - - - This method is available in release 2.0 and later only. Returns the index into a parameter block of the parameter that generated a notification. You can call this method when you get a NotifyRefChanged() message from your parameter block to determine exactly which parameter it was that changed. When you have a very complicated dialog, for instance the Standard material, you can use this to selectively update controls in the dialog instead of updating all of them, which can feel pretty slow to the user. For smaller dialogs it's not worth the trouble. - Sample Code: - - - - - Description: - This class provides an interface for working with parameter block2s. There are methods for getting and setting parameters, descriptor access, parameter map access, etc. - - - - - Returns the version of this parameter block. - - - - - Returns the number of parameters in this parameter block. - - - - - Returns the localized name for the parameter block. - - - - - Returns a reference to the structure for this parameter block. - - The parameter ID. - - - - Returns the BlockID of the parameter block. Note: typedef short BlockID; - - - - - Returns a pointer to the owner of this parameter block. - - - - - Returns the parameter definition for the parameter with the given index. - A pointer to the parameter definition for the given index, or null if the index is invalid. - - Index of the parameter to be fetched. - - - - Acquires the descriptor for this parameter block. Call ReleaseDesc() when done. - - - - - Releases the descriptor for this parameter block. See GetDesc() above. - - - - - Returns the zero based index of the parameter into the parameter definitions array of the given parameter ID or -1 if not found. - - The parameter ID whose index to return. - - - - Returns the parameter ID of the parameter given its index into the parameter definitions array. - - The index of the parameter whose ID is to be returned. - - - - Returns the Super Class ID of the parameter's controller (specified by sub-anim number). - - The sub-anim index of the parameter. - - - - Returns the Super Class ID of the parameter's controller (specified by parameter ID). - - The ID of the parameter. - - - - Returns the type of the specified parameter. - - The ID of the parameter. - - - - Returns the local name for the specified parameter or <> parameter entry. - - The permanent ID of the parameter. - If the parameter is a table this is the zero based index into the table of the parameter. - If true, then the name returned should be localized in the language 3ds is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - - - - Sets the floating point value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_FLOAT, TYPE_ANGLE, TYPE_PCNT_FRAC, TYPE_WORLD, TYPE_COLOR_CHANNEL - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the integer value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_POINT2, TYPE_INT2, TYPE_BOOL2 - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the string value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_FILENAME or TYPE_STRING - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the Mtl* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_MTL - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the Texmap* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_TEXMAP - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the PBBitmap* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_BITMAP - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the INode* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_INODE - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the ReferenceTarget* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_MTL, TYPE_TEXMAP, TYPE_INODE, TYPE_REFTARG, TYPE_PBLOCK2, TYPE_OBJECT, TYPE_CONTROL - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the IParamBlock2* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_PBLOCK2 - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_MATRIX3 - TYPE_MATRIX3 items cannot be animated. - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Sets the AssetId value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no set occurs: TYPE_FILENAME - - The permanent ID of the parameter. - The time at which to set the value. - The value to set. - If the parameter is a <> this is the zero based index into the table of the value to set. - - - - Retrieves the floating point value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain 0.0f: TYPE_FLOAT, TYPE_ANGLE, TYPE_PCNT_FRAC, TYPE_WORLD, TYPE_COLOR_CHANNEL - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the integer value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain 0: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain Point2::Origin: TYPE_POINT2, TYPE_INT2, TYPE_BOOL2 - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain Point3::Origin: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain Point4::Origin: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain black: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain black: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the string value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will not be modified: TYPE_FILENAME or TYPE_STRING - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the Mtl* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_MTL - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the Texmap* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_TEXMAP - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the PBBitmap* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_BITMAP - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the INode* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_INODE - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - Validity interval of the node parameter. It's updated (intersected) by the validity of certain aspects of the node, such as geometry and transform, as specified in the parameter descriptor. See P_USE_NODE_OS_VALIDITY and P_USE_NODE_TM_VALIDITY for more details. This validity interval does not pertain to the validity of the node pointer. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the ReferenceTarget* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_MTL, TYPE_TEXMAP, TYPE_INODE, TYPE_REFTARG, TYPE_PBLOCK2, TYPE_OBJECT, TYPE_CONTROL - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the IParamBlock2* value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain NULL: TYPE_PBLOCK2 - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain IdentityMatrix: TYPE_MATRIX3 - TYPE_MATRIX3 items cannot be animated. - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the AssetUser value of the specified parameter at the specified time. - TRUE on success; otherwise FALSE. - The ParamType must be one of the following, otherwise no get occurs and v will contain IdentityMatrix: TYPE_FILENAME - - The permanent ID of the parameter. - The time at which to get the value. - The value to retrieve is returned here. - This is the validity interval which is updated by the validity of the retrieved parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of black returned: TYPE_POINT3, TYPE_RGBA - Starting in 3ds Max 2016, please use IParamBlock2::GetColor(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of black returned: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of black returned: TYPE_POINT4, TYPE_FRGBA - Starting in 3ds Max 2016, please use IParamBlock2::GetAColor(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of black returned: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point2::Origin returned: TYPE_POINT2, TYPE_INT2, TYPE_BOOL2 - Please use IParamBlock2::GetPoint2(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point3::Origin returned: TYPE_POINT2, TYPE_INT2, TYPE_BOOL2 - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point3::Origin returned: TYPE_POINT3, TYPE_RGBA - Starting in 3ds Max 2016, please use IParamBlock2::GetPoint3(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point3::Origin returned: TYPE_POINT3, TYPE_RGBA - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point4::Origin returned: TYPE_POINT4, TYPE_FRGBA - Starting in 3ds Max 2016, please use IParamBlock2::GetPoint4(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of Point4::Origin returned: TYPE_POINT4, TYPE_FRGBA - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the integer value of the specified parameter at the specified time. - The integer value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0 will be returned: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - Starting in 3ds Max 2016, please use IParamBlock2::GetInt(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the integer value of the specified parameter at the specified time. - The integer value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0 will be returned: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the floating point value of the specified parameter at the specified time. - The floating point value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0.0f will be returned: TYPE_FLOAT, TYPE_ANGLE, TYPE_PCNT_FRAC, TYPE_WORLD, TYPE_COLOR_CHANNEL - Starting in 3ds Max 2016, please use IParamBlock2::GetFloat(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the floating point value of the specified parameter at the specified time. - The floating point value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0.0f will be returned: TYPE_FLOAT, TYPE_ANGLE, TYPE_PCNT_FRAC, TYPE_WORLD, TYPE_COLOR_CHANNEL - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the TimeValue value of the specified parameter at the specified time. - The TimeValue value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0 will be returned: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - Starting in 3ds Max 2016, please use IParamBlock2::GetTimeValue(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the TimeValue value of the specified parameter at the specified time. - The TimeValue value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of 0 will be returned: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the string pointer value of the specified parameter at the specified time. - The string pointer value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_FILENAME or TYPE_STRING - Starting in 3ds Max 2016, please use IParamBlock2::GetStr(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the string pointer value of the specified parameter at the specified time. - The string pointer value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_FILENAME or TYPE_STRING - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the Mtl* value of the specified parameter at the specified time. - The Mtl* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_MTL - Starting in 3ds Max 2016, please use IParamBlock2::GetMtl(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the Mtl* value of the specified parameter at the specified time. - The Mtl* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_MTL - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the Texmap* value of the specified parameter at the specified time. - The Texmap* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_TEXMAP - Starting in 3ds Max 2016, please use IParamBlock2::GetTexmap(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the Texmap* value of the specified parameter at the specified time. - The Texmap* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_TEXMAP - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the PBBitmap* value of the specified parameter at the specified time. - The PBBitmap* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_BITMAP - Starting in 3ds Max 2016, please use IParamBlock2::GetBitmap(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the PBBitmap* value of the specified parameter at the specified time. - The PBBitmap* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_BITMAP - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the INode* value of the specified parameter at the specified time. - The INode* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_INODE - Starting in 3ds Max 2016, please use IParamBlock2::GetINode(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the INode* value of the specified parameter at the specified time. - The INode* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_INODE - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the ReferenceTarget* value of the specified parameter at the specified time. - The ReferenceTarget* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_MTL, TYPE_TEXMAP, TYPE_INODE, TYPE_REFTARG, TYPE_PBLOCK2, TYPE_OBJECT, TYPE_CONTROL - Starting in 3ds Max 2016, please use IParamBlock2::GetReferenceTarget(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the ReferenceTarget* value of the specified parameter at the specified time. - The ReferenceTarget* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_MTL, TYPE_TEXMAP, TYPE_INODE, TYPE_REFTARG, TYPE_PBLOCK2, TYPE_OBJECT, TYPE_CONTROL - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the IParamBlock2* value of the specified parameter at the specified time. - The IParamBlock2* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_PBLOCK2 - Starting in 3ds Max 2016, please use IParamBlock2::GetParamBlock2(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the IParamBlock2* value of the specified parameter at the specified time. - The IParamBlock2* value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of NULL will be returned: TYPE_PBLOCK2 - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of IdentityMatrix will be returned: TYPE_MATRIX3 - TYPE_MATRIX3 items cannot be animated. - Starting in 3ds Max 2016, please use IParamBlock2::GetMatrix3(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Retrieves the value of the specified parameter at the specified time. - The value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of IdentityMatrix will be returned: TYPE_MATRIX3 - TYPE_MATRIX3 items cannot be animated. - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the AssetUser of the specified parameter at the specified time. - The AssetUser value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of kInvalid will be returned: TYPE_FILENAME - Starting in 3ds Max 2016, please use IParamBlock2::GetAssetUser(ParamID,TimeValue,Interval&,int) instead; it supports a validity interval and is more robust in case of invalid parameter IDs. - - The permanent ID of the parameter. - The time at which to get the value. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the AssetUser of the specified parameter at the specified time. - The AssetUser value retrieved. - The ParamType must be one of the following, otherwise no get occurs and a value of kInvalid will be returned: TYPE_FILENAME - - The permanent ID of the parameter. - The time at which to get the value. - The validity of the returned value is intersected into the input value of this parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - This methods is used for getting a parameter value as a reference. - The value retrieved. - - The permanent ID of the parameter. - If the parameter is a <> this is the zero based index into the table of the value to get. - - - - Returns the number of entries being used in the table. - - The permanent ID of the parameter. - - - - the number of elements in the table that are actually used to zero. - - The permanent ID of the parameter. - - - - the number of elements in the table that are actually used to n. - - The permanent ID of the parameter. - The number of elements to set. - - - - List-type delete of num elements starting with start - Returns the number of items left in the table. - - The permanent ID of the parameter. - The start position for element deletion. - The number of elements to delete. - - - - Changes the number of allocated items to num. - Nonzero if the array was resized; otherwise 0. - - The permanent ID of the parameter. - The new size of the table. - - - - Reallocate so there is no wasted space. - - The permanent ID of the parameter. - - - - Sorts the array using the compare function. - Sample Code: - - The permanent ID of the parameter. - Type of function to pass to . Note: just uses the C library function. The developer must implement the CompareFnc function. The return value of is show below in the relationship of to : < 0 if less than 0 if identical to > 0 if greater than - - - - Insert num float elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num Point2* \ Point3* \ Point4* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num Color* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num TimeValue elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num string (MCHAR*) elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num Mtl* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num Texmap* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - - of elements to insert. - - - - Insert num PBBitmap* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num INode* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num ReferenceTarget* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Insert num Matrix3* elements at position at. - Returns at. - - The permanent ID of the parameter. - Zero based array index where to insert the elements. - of elements to insert. - of elements to insert. - - - - Append num float elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num Point2* \ Point3* \ Point4* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num Color* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num TimeValue elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num string (MCHAR*) elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num Mtl* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num Texmap* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num PBBitmap* elements at the end of the array. - The number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num INode* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num ReferenceTarget* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Append num Matrix3* elements at the end of the array. - Returns the number of elements in use prior to appending. - - The permanent ID of the parameter. - The number of elements to append to the end of the array. - The elements to append. - If you need to enlarge the array specify an non-zero value and this many extra slots will be allocated. - - - - Checks to see if a keyframe exists for the given parameter at the given time. - TRUE if a keyframe exists at the specified time; otherwise FALSE. - - Zero based index of the parameter to check. - The time to check. - If the parameter is a table this is the zero based index of the element in the table to check. - - - - Checks to see if a keyframe exists for the given parameter at the given time. Note this method is slower than KeyFrameAtTimeByIndex. - TRUE if a keyframe exists at the specified time; otherwise FALSE. - - The permanent ID of the parameter. - The time to check. - If the parameter is a table this is the zero based index of the element in the table to check. - - - - Removes the 'i-th' controller. - - Specifies which controller using the zero based index of the parameter in the block. - If the parameter is a table this is the zero based index of the element in the table whose controller is removed. - - - - Gets a pointer to the controller of the specified parameter. Note this method is slower than GetControllerByIndex. - - The permanent ID of the parameter. - If the parameter is a table this is the zero based index of the element in the table whose controller is returned. - - - - Gets a pointer to the controller of the specified parameter. - - Specifies which controller using the zero based index of the parameter in the block. - If the parameter is a table this is the zero based index of the element in the table whose controller is returned. - - - - Sets the indexed parameter controller to the one specified. - - Specifies which controller using the zero based index of the parameter in the block. - If the parameter is a table this is the zero based index of the element in the table. - The controller to set. - If TRUE the controllers value at frame 0 is preserved. - - - - Sets the parameter with the given id to the specified controller. Note that this is slower than calling SetControllerByIndex. - - The parameter id of the controller to be set. - If the parameter is a table this is the zero based index of the element in the table. - The controller to set. - If TRUE the controllers value at frame 0 is preserved. - - - - Swaps the two controllers of the parameters whose indices are passed. - - The zero based index of one of the parameters in the parameter block. - If the parameter is a table this is the zero based index of the element in the table. - The zero based index of one of the other parameters in the parameter block. - If the parameter is a table this is the zero based index of the element in the table. - - - - Given a parameter index this method will return the reference number of that parameter. - - The zero based index of the parameter in the parameter block. - If the parameter is a table this is the zero based index of the element in the table. - - - - Returns the reference number of the specified parameter's controller or -1 if not found. - - The zero based index into the parameter definitions array of the parameter. - If the parameter is a <> this is the zero based index in the table of the parameter. - - - - Returns the sub-anim number of the parameter whose ID is passed or -1 if not found. - - The parameter ID of the parameter. - If the parameter is a <> this is the zero based index in the table of the parameter. - - - - Returns the index into the parameter definitions array of the parameter whose sub-anim index is specified or -1 if not found. - - The zero based sub-anim index of the parameter. - If the parameter is a <> this is the zero based index into the table of the parameter. - - - - This is only for use in a RescaleWorldUnits() implementation: The parameter block implementation of RescaleWorldUnits scales only tracks that have dimension type = stdWorldDim. If letting the parameter block handle the rescaling is not sufficient, call this on just the parameters you need to rescale. - - The index into the parameter block of the parameter to rescale. - If the parameter is a <> this is the zero based index into the table of the parameter. - The value to scale by. - - - - Like LastNotifyParamID(), but takes an int& tabIndex argument so that it can return both the ID of the changing parameter (as the result) and the changing element index for <> parameters. - - If the ParamID returns -1 because no parameter is currently changing, tabIndex is not updated. If the change to a <> parameter is not to a single element (such as a sort), the tabIndex is set to -1. For multiple inserts, appends, deletes, the tabIndex returned is the index of the first element inserted, appended, deleted. - - The index of the changing element for parameters is returned here. - - - - Controls whether NotifyDependents() messages are sent when a parameter is changed, such as through - - a SetValue() call. For example: - - Notifications are enabled by default. Note that this is a GLOBAL enable/disable, ALL paramblocks will be prevented from sending notifications while EnableNotifications(FALSE) is in effect. - - TRUE to enable notifications, FALSE to disable them. - - - - This method returns a BOOL value to indicate whether the notifications are globally enabled. - - - TRUE if the notifications are enabled, FALSE otherwise. - - - - - This method sets the parameter map2 associated with this parameter block2. - - Points to the parameter map. - Specifies the ID of the map to set. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Returns a pointer to the parameter map2 associated with this parameter block. - - Specifies the ID of the map to get. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Sets the rollout state to open or closed. - - Note: Normally, developers don't need to call this method (or the related ones below) explicitly; they are used internally to keep track of rollouts states. Instead, use the method RestoreRolloutState() at the end of a BeginEditParams() or CreateParamDlg() to reset the rollouts to the state last used for the current object. - - TRUE for open; FALSE for closed. - Specifies the ID of the map/rollout to set open/closed state for. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Returns TRUE if the rollout is open; FALSE if closed. This is normally used internally - see the note above in SetRolloutOpen(). - - Specifies the ID of the map/rollout to get open/closed state for. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Sets the rollout scroll position. This is normally used internally - see the note above in SetRolloutOpen(). - - The position to set. - Specifies the ID of the map/rollout to set scroll position for. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Returns the rollout scroll position. This is normally used internally - see the note above in SetRolloutOpen(). - - Specifies the ID of the map/rollout to get scroll position for. If the parameter block is not a multimap parameter block (the P_MULTIMAP flag of its descriptor is false) and you pass a nonzero map_id, the map_id will be converted to zero because the parameter block only contains one map. - - - - Returns a pointer to the automatic parameter dialog object for a plug-in material or texmap (which has its interface in the materials editor). See Class . - - - - - Returns a pointer to the automatic parameter dialog object for the rendering effects plug-in. See Class . - - - - - This method initializes the parameters with MAXScript defaults. - - The descriptor lets you specify default values for parameters (using the tag p_default), and these get installed when you first create an object and its paramblocks. Sometimes, the default value needed for interactive creation is not the one you want when creating an object via the scripter. For example, a sphere should start out with radius 0 when you create it interactively, but you want a non-zero default if you create it in the scripter, say with sphere(), otherwise it would be invisible. There is another tag, p_ms_default, that lets you set a separate default for scripter-based creation (the p_ms_default for sphere radius is 25). This method is used internally by the scripter to set the p_ms_default values in after a script-based creation. It is not normally used by plug-in developers. - - - - - This is used to allow parameter 'aliases' to be set up for MAXScript use. Individual <> parameter elements can have aliases. This is used to set up dynamically-varying parameters, such as the texture maps in the new Standard material, which sets up aliases for elements in the texture map arrays. - - The name of the alias. - The permanent ID of the parameter. - If the parameter is a <> this is the zero based index of the parameter in the table. - - - - Returns a pointer to a Structure object which describes the parameter alias whose name is passed. This includes the name, ParamID and <> index. - - The name of the alias to find. - - - - Finds the name of a parameter alias using the ID and <> index passed. - The name of the alias or NULL if not found. - - The permanent ID of the parameter. - If the parameter is a <> this is the zero based index into the table. If not a <> use the default of -1. - - - - Breaks the association between the aliases and their parameters in this block. The method ParamAliasCount() below will return 0 following this call. - - - - - Returns the number of aliases currently defined. - - - - - Returns a pointer to the 'i-th' alias. See Structure . - - The zero based index of the alias to return. - - - - This method allows for the arbitrary ordering of sub-anim numbers for parameters and <> parameter elements. It sets the sub-anim number for the specified parameter. - - This call lets you set arbitrary sub-anim number ordering for the subAnim parameters and <> parameter elements in the block. You must set numbers for ALL subAnims and take care that all numbers are used. Note that in the case of the various ReferenceTarget* parameter types, NULL values for any parameter or <> elements are not included the subAnim count, so if such a parameter is made non-NULL (or vice-versa), you need to reassign the subanim numbers to take that change into account. - - The permanent parameter ID - The zero based sub-anim number. - The zero based index into the table of the parameter. - - - - This method clears any sub-anim map used to allow arbitrary ordering of sub-anim numbers for parameters. - - - - - This method is used for copying parameter values between parameter blocks (which is useful during old-version updating). This method copies from the 'src' block 'src_id' parameter into this parameter block's 'id' parameter. Developers are responsible for making sure the types are the same, otherwise an assert() may occur. - - This ID specifies the destination parameter. - Points to the source parameter block 2. - The source parameter ID. - - - - This method that takes a reference target object ref stored somewhere in this parameter block and returns the ParamID and tabIndex of the containing parameter, or -1 if not found in the parameter block. - - The reference target to find. - The table index if the parameter is a <>. - - - - This method resets all the parameters in the block to their default values and optionally updates any associated ParamMap2 UI that is currently displaying the contents of the block. It also optionally causing all the methods to be called after the reset. - - TRUE to update the user interface; FALSE to not update. - TRUE to call for all the parameters; otherwise FALSE. - - - - This method resets the single parameter specified to its default value. If the parameter is a <> and the tabIndex is -1, all the elements in the table are reset. - - The ID of the parameter to reset. - If the parameter is a <> this is the index into the table of the parameter to reset. A value of -1 causes all the elements in the table to be reset. - Determines if the user interface is updated for the parameter. TRUE to update; FALSE to not update. - Determines if the method should be called on the parameter. TRUE to call it; FALSE to not call it. - - - - This method forces a call to the PBAccessor::Set() method for the specified parameter. If the parameter is a <> parameter and the tabIndex is -1, all the elements have the appropriate functions called. - - The ID of the parameter. - If the parameter is a <> parameter this is the zero based index into the table of the element. A value of -1 causes all the appropriate methods to be called. - - - - This method forces a call to the PBAccessor::Get() method for the specified parameter. If the parameter is a <> parameter and the tabIndex is -1, all the elements have the appropriate functions called. - - The ID of the parameter. - If the parameter is a <> parameter this is the zero based index into the table of the element. A value of -1 causes all the appropriate methods to be called. - - - - This method forces a call to the PBAccessor::Set() method for every parameter in the block. Any parameters which are <> parameters will have call for every appropriate element. - - - - - This method forces a call to the PBAccessor::Get() method for every parameter in the block. Any parameters which are <> parameters will have Get() call for every appropriate element. - - - - - This method updates the validity interval passed with the cumulative interval for every parameter in the parameter block. - - The time about which the interval is computed. - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - This method should be called when the parameter block owner has deleted the reference to a reference target parameter. This sets the value to NULL and invalidates the UI associated with the pblock. Note that this must only be called on P_OWNERS_REF parameters. - - The ID of the reference target parameter. - If the parameter is a <> this is the zero based index into the table of the parameter. - - - - Informational class about ParamBlock2 objects loaded from file. - - - This allows a plugin to detect when an obsolete version of itself has been loaded, so the plugin can migrate obsolete parameters to the newer version. The information is available only under the following conditions, indicating that an obsolete file was loaded: 1) The current version of the ParamBlock2 uses the P_VERSION tag 2) The loaded version either did not use P_VERSION, or the version numbers don't match 3) The information is available only during a ; it is deleted after load. To obtain a pointer to this class, query the plugin's as follows: postLoadInfo = (IParamBlock2PostLoadInfo*)desc->GetInterface(IPARAMBLOCK2POSTLOADINFO_ID); - - - - - Returns the current which this information is associated with. - - - - - Returns the version number of the ParamBlock2 loaded from file. - - - This is either the P_VERSION number from the obsolete plugin, or if the plugin did not use P_VERSION it is equal to the value 3DSMAX_VERSION when the file was saved - - - - - Returns the ID numbers of the parameters in the ParamBlock2 loaded from file. - - - The numbers are in their original order used by the obsolete plugin. - - - - - Returns a mapping from old parameter indices to current parameter indices. - - - Each entry is an index into the current ParamBlock2; the number of entries equals the current number of parameters. The parameters are listed in an order that matches the order from the obsolete plugin. This is used internally during load. The reference numbering of the current ParamBlock2 is temporarily reordered, allowing objects and controllers referenced by the ParamBlock2 to load correctly even when the parameter order changes between plugin versions. - - - - - Description: - This class provides methods to work with parameter maps. These are things like invalidating the parameter map so it gets redrawn, working with the parameter blocks associated with the parameter map, and establishing an optional dialog proc to handle controls not directly handled by the pmap. This section also documents several functions that are available for creating and destroying parameter maps but are not part of this class. - - Note: The use of this class requires the explicit inclusion the IPARAMM.H header file. - - - - - Implemented by the System. - - Call this method to update (redraw) the user interface controls. This marks the UI controls as needing to be updated and the parameter map will take care of it. - - - - - Implemented by the System. - - This method changes a parameter map entry to refer to a different item in the parameter block. This is used for example by the Optimize modifier. This modifier has two sets of parameters that may be adjusted (L1 and L2). Optimize only maintains a single parameter block however. This pblock contains both sets of parameters. When the user switches between these two sets, this method is called to point the UI controls at different indices in the parameter block. - Parameters: - int mapIndex - - The map entry to change. - - int blockIndex - - The new parameter block index. - - - - - Implemented by the System. - - Returns the window handle of the rollup page (or dialog). - - - - - Implemented by the System. - - Returns a pointer to the parameter block managed by the parameter map. - - - - - Description: - This class provides methods to work with parameter map2s. Methods are provided for things like invalidating the parameter map so it gets redrawn, working with the parameter blocks associated with the parameter map, and establishing an optional dialog proc to handle controls not directly handled by the parameter map. This section also documents several functions that are available for creating and destroying parameter maps but are not part of this class. - - Note: The use of this class requires the explicit inclusion the IPARAMM2.H header file. - - - - - This method marks the user interface as needing to be updated. This affects the entire UI for the parameter map. - - - - - This methods un-invalidates the entire user interface. - - - - - This methods marks a specific control in the UI as requiring an update. - - The permanent ID of the control requiring an update. - If the control is a <> then this is the zero-based index into the table of the value to be invalidated. - - - - This method will update the user interface if the current settings are not valid at the given time (i.e., if anything is animated at that time). - - The time to check for the update. - - - - This method may be called to cause the viewports to be redrawn. - - The time at which to redraw the viewports. - You may specify one of the following: Call this before you redraw. This allows the view quality to degrade to maintain interactively. If during interactive redraw the state degraded, this will redraw the views in the undegraded state. This redraws the views in the undegraded state. - - - - Provides access to pmap's validity interval. Returns a refernce to the actual interval so it can be modified if desired. - - - - - Makes the parameter map point to a new parameter block, updating the user interface in the process. - - The new parameter block to use with the parameter map. - The owner the parameter block. In most cases, this should be . But in the case of class parameter block (see P_CLASS_PARAMS), where the parameter block does not have an owner, then this should point to the object for which the UI is currently being edited. - - - - Returns the parameter map's ID. - - - - - Returns a pointer to the user dialog proc for the parameter map (or NULL if none is defined). See SetUserDlgProc() above. - - - - - This method changes a parameter map entry to refer to a different item in the parameter block. - - The parameter ID of the item to change. - The new parameter ID. - - - - Returns the dialog window handle of the parameter map. - - - - - Returns a pointer to the parameter block2 used by this parameter map. - - - - - Returns TRUE if the parameter map dialog proc is active; otherwise FALSE. - - - - - Returns a pointer to the instance for this parameter map. - - - - - This method is called to indicate the dialog is going inactive or is becoming active. - - TRUE if becoming active; FALSE for inactive. - - - - This method is sent to a Editor map to find the SubTex index corresponding to the control handle. It should return the index of the sub-texmap corresponding to the window whose handle is passed. If the handle is not valid return -1. - - The window handle of the control. - - - - This method is used to enable of disable an individual user interface control. - - The parameter ID of the control to enable/disable. - TRUE to enable; FALSE to disable. - If the control is a <> then this is the zero-based index in the table of the item to enable/disable. - - - - This method sets the text of a parameter user interface control. - - The ID of the parameter whose user interface text to change. - The new string to display. - If the parameter is a <> this is the zero-based index of the parameter in the table. - - - - tooltip of param UI control. - - - This method allows for turning on or off the tooltip for a parameter user interface control. - - - The ID of the parameter whose user interface tooltip to set. - - if true, the tooltip is enabled, otherwise disabled. When disabled, the tooltip won't be displayed when the the mouse hovers on top of the control. Enabling the tooltip repeatedly will have the same effect as enabling it once. - - pointer to a string representing the text to be displayed in the tooltip window. This parameter is ignored when the tooltip is being disabled. - If the parameter is a <> this is the zero-based index of the parameter in the table. - - - - This method sets the range of parameter for a spinner or slider control. - - The ID of the parameter. - The low range for the spinner / slider. - The high range for the spinner / slider. - If the parameter is a <> this is the zero-based index of the parameter in the table. - - - - This method sets the range of parameter for a spinner or slider control. - - The ID of the parameter. - The low range for the spinner / slider. - The high range for the spinner / slider. - If the parameter is a <> this is the zero-based index of the parameter in the table. - - - - This method will show or hide the specified control. - - The ID of the parameter. - TRUE to show; FALSE to hide. - If the parameter is a Tab<> this is the zero-based index of the parameter in the table. - - - - This method is called by any IAutoXXParamDlg when it receives a SetThing(). - - The item which was set. - - - - This method removes all existing parameter UI connections held by the ParamMap. - - - The internal pointer to the old widget will be released, the widget will not be deleted. - - - - - Description: - This class represents the interface that provides general access to the parameter publish functions. You can obtain a pointer to the Parameter Publish Manager interface using; . All methods of this class are Implemented by the System. - - - - - This method will launch the parameter publish UI mode. - - - - - This method will add parameter into ready-to-publish parameter list. Only publishable parameters will be added successfully, and they'll be published when StartParamPublish() is called. - Parameters: - ReferenceTarget* parent - - Parent of the selected animatable parameter in track view. - - int subNum - - SubNum of the selected animatable parameter in track view. - Description: - The method can be used by MaxScript code like: . parent and subNum is obtained from track view, similar to Parameter Collector. Then StartParamPublish() will publish parameter added by AddParameter(). - - - - - Description: - This class represents the interface that provides general access to the parameter wiring functions. You can obtain a pointer to the Parameter Wire Manager interface using; . This macro will return All methods of this class are Implemented by the System. - - - - - This method will launch the parameter wiring UI mode. - - - - - This method will open up the parameter wiring dialog on the selected objects. - - - - - This method allows you to edit the left- and right-hand parameters and opens the parameter wiring dialog using the provided parameters. - - - A pointer to the left-hand reference target. - - The sub-animatable of the left-hand reference target. - - A pointer to the right-hand reference target. - - The sub-animatable of the right-hand reference target. - - - - This method allows you to setup the two controllers for the left- and right-hand to edit. - - - A pointer to the controller for the left-hand wire. - - A pointer to the controller for the right-hand wire. - - - - This method is identical to the EditControllers() but accepts a single wire controller for the left-hand. This method effectively calls EditControllers(wire, NULL). - - - A pointer to the controller being edited. - - - - This method allows you to set up a one-way wire. - TRUE if the connection can be made, otherwise FALSE. - - - A pointer to the reference target to wire from. - - The sub-animatable to wire from. - - A pointer to the reference target to wire to. - - The sub-animatable to wire to. - - A string containing the expression on the "to wire". - - - - This method allows you to set up a two-way wire. - TRUE if the connection can be made, otherwise FALSE. - - - A pointer to the left-hand reference target. - - The sub-animatable of the left-hand reference target. - - A pointer to the right-hand reference target. - - The sub-animatable of the right-hand reference target. - - A string containing the expression for the left-hand target. - = NULL - A string containing the expression for the right-hand target. - - - - This method allows you to disconnect a one-way wire. - TRUE if the disconnect was successful, otherwise FALSE. - - - A pointer to the wire controller you wish to disconnect. - - - - This method allows you to disconnect a two-way wire. - TRUE if the disconnect was successful, otherwise FALSE. - - - A pointer to the first wire controller you wish to disconnect. - - A pointer to the second wire controller you wish to disconnect. - - - - The ParamWireMenu method allows a plugin to host the parameter wiring context menus, typically found in the viewport, into any window. - The animatable that derived the context menu, or NULL if no menu was displayed - - - The parent of the target animatable that the context menu will be derived from. pTarget should support the I_WIRECONTROL interface. - - The SubAnim number in pTarget of the target animatable that the context menu will be derived from. If iSubNum is negative, pTarget will be used. - - one of the . This sets which which action to take. - - used as the parent window for the context menus and parameter wiring dialog. - - If iFlags is not PWMF_HAS_MENU, pPt should specify the position of the context menu in screen coordinates - - - - A core interface used to store parser DLLs found in the system. - - - - - The total number of parsers found at startup - The number of parsers - - - - - Get a parser based on parser ID. - - - An instance of the parser - - The ID of the parser you are requesting - - - - used by the system to load the parser DLLs from disk - - - - - Used by the system to unload the DLLs. - - - - - Get the filter name. THis will be used in the open dialog boxes. - - - A string with the extension. It will be in the form "Microsoft Direct3D Effects" - - The index to the parser. Use GetNumberOfParsers to find the total number in the system - - - - Get the file extension for the parser. THis will be used in the open dialog boxes. - - - A string with the extension. It will be in the form *.fx - - The index to the parser. Use GetNumberOfParsers to find the total number in the system - - - - Returns the unique ID for the channel class. The ID is used for constructing the channel when loading since the channel class is not inherited from class . - - - - - cloning; make a copy of the channel - - - - - saving content of the channel to file - - - - - loading content of the channel from file - - - - - checks if the given is a similar particle channel - - - - - Get "transferable" status. If particle channel is transferable then it is transferred from one event to another; the data in the channel are glued to particles if particle channel is not transferable then while particles moves to another event, the particle channel is not. - - - - - "transferable" status. - - - - - A channel can be declared "private" by an action. when a channel is declared as a "private" a reference on a "private owner" is given then only the "private owner" action will be given access to this channel. the technique allows creating several channels with the same data-type (for example, position) in the container by different "private owner" actions Because of access to particle container, onle an action that created the channel can declare itself as a private owner. - - - - - returns a "private owner" action of the channel - - - - - channel data can be viewed by different actions. however an action that created the channel is responsible for data initialization. therefore the action has to keep track how (by what action) the channel was created - - - - - Set/get a concrete channel ID for a generic data particle channel. Access read-interface ID of the wrapping channel. - - - - - Set/get a concrete channel ID for a generic data particle channel. Access read-interface ID of the wrapping channel. - - - - - access write-interface ID of the wrapping channel - - - - - access write-interface ID of the wrapping channel - - - - - set up read-interface ID of the wrapping channel - - - - - set up write-interface ID of the wrapping channel - - - - - methods that are not in FnPub interface. Access read-interface ID of the wrapping channel. - - - - - access write-interface ID of the wrapping channel - - - - - when cloning a channel, data about transferable, privateOwner, creatorAction, readID & write ID should be cloned. the following method does that: it clones the core data from the given channel - - - - - when cached channel data are merged the stored action creator handle could be invalid. the method lets the channel to update the action handle to the proper one - - - - - returns amount of memory used (in bytes) by the channel to store the information - - - - - Particle count management; number of particles in the channel. - - - - - set number of particles in the channel to zero - - - - - set number of particles in the channel to n - - - - - Delete num particles from start index. Returns number of particles left in the channel. - - - - - Delete particles according to the (bit set == remove). Returns number of particles left in the channel. - - - - - To new "split" particle channel. Returns new particle channel; type is chosen to be compatible with the available return types. All "bit-set" particles are moved. - - - - - Spawn particles according to the spawnTable. Returns true if the operation is successful. Size of the table equals to number of particles in the channel. Table value is how many particles are cloned from the index particle. - - - - - Append num particles to the channel(s). Returns true if the operation is successful. - - - - - Append all particles of another channel/container, then the input channel/container is deleted. Returns true if the operation is successful. - - - - - For internal use; no need to implement. - - - - - For internal use; no need to implement. - - - - - Get property for particle with index. - - - - - Verify if the channel is global. - - - - - If channel is global returns the global value. If channel is not global returns value of the first particle. Returns bounding box for all particles. - - - - - property for particle with index. - - - - - property for all particles at once thus making the channel global. - - - - - get property for particle with index - - - - - verify if the channel is global - - - - - if channel is global returns the global value. if channel is not global returns value of the first particle - - - - - set property for particle with index - - - - - set property for all particles at once thus making the channel global - - - - - Copy all particle data from another channel of the same type. Returns true if the operation is successful. - - - - - Make the data not to be global in the particle channel. This is mostly done to allow multi-threaded read/write access to the data Returns true if the operation is successful. It may return false if there is zero or one data item in the channel. - - - - - Gets a property for a particle by index. - - - - - Verifies that the channel is global. - - - - - If the channel is global, returns the global value. If channel is not global, returns value of the first particle. - - - - - Sets a property for the particle with the specified index. - - - - - Sets a property for all particles at once, thus making the channel global. - - - - - Gets a property for the particle by index. - - - - - Verifies that the channel is global. - - - - - If the channel is global, returns the global value. If the channel is not global, returns the value of the first particle. - - - - - Sets a property for particle by index. - - - - - Sets a property for all particles at once, thus making the channel global. - - - - - Returns particleIndex. - - - - - Returns particleBorn. - - - - - Methods not in the mapped interface. - - - - - particle property. - - - - - Methods not in the mapped interface. - - - - - Gets a property for a particle by index. - - - - - Verifies that the channel is global. - - - - - If the channel is global, returns the global value. If channel is not global, returns value of the first particle. - - - - - Sets a property for the particle with the specified index. - - - - - Sets a property for all particles at once, thus making the channel global. - - - - - check out if some particles have shared mapping data. if it's true then there is no need to get a mapping for each particle - - - - - check out if some particles have shared UVVert data. if it's true then there is no need to get a UVVert data for each particle - - - - - check out if some particles have shared data. if it's true then there is no need to get a data for each particle - - - - - get total number of actual TabUVVert values in the channel - - - - - get the TabUVVert value index of a particle - - - - - get TabUVVert of the valueIndex-th value - - - - - get TabUVVert of a particle with the specified index - - - - - get global TabUVVert value for all particles. the method returns the TabUVVert value of the first particle if it is local or shared - - - - - get total number of actual TabTVFace values in the channel - - - - - may return NULL. for different TabUVVert values it has different meanings. if TabUVVert has a single UVVert value then the particle has a planar data and all vertices of the particles have the same UVVert value. if TabUVVert has the same number of UVVert values as the particle mesh vertices number then the particle has a planar data and there is one-to-one correspondence between UVVerts and vertices of the particle. get the TabTVFace value index of a particle. - - - - - get TabTVFace of the valueIndex-th value. See GetTVFaceIndex(int particleIndex). - - - - - get TabTVFace of a particle with the specified index. See GetTVFaceIndex(int particleIndex). - - - - - get global TabTVFace value for all particles. the method returns the TabTVFace value of the first particle if it is local or shared. See GetTVFaceIndex(int particleIndex). - - - - - apply content of the channel to the mesh [mesh] at mapping channel [mp] - - - - - sets all vertices of the particle have the same UVVert value. returns true if successful. - - - - - copies UVVert data to be a shared value with indices in "particleIndeces" - - - - - copies UVVert data to a global value for all particles - - - - - copy UVVert data from fromParticle to toParticle - - - - - copy UVVert data from fromParticle to toParticles - - - - - copy UVVert data from fromParticle to all particles - - - - - copy data from fromParticle to toParticle - - - - - copy data from fromParticle to toParticles - - - - - copy data from fromParticle to all particles - - - - - returns an object of TabUVVert channel - - - - - returns an object of TabTVFace channel - - - - - sets all vertices of the particle have the same map value. returns true if successful. - - - - - copies map data to be a shared value with indices in "particleIndeces" - - - - - copies map data to a global value for all particles - - - - - copy map data from fromParticle to toParticle - - - - - copy map data from fromParticle to toParticles - - - - - copy map data from fromParticle to all particles - - - - - Gets a property for the particle by index. - - - - - Verify if the channel is global. - - - - - If the channel is global, returns the global value. If the channel is not global, returns the value of the first particle. Returns bounding box for all particles. - - - - - Sets a property for particle by index. - - - - - Sets a property for all particles at once, thus making the channel global. - - - - - Returns the number of mapping channels in use. - - - - - Returns true if the specified mapping channel is supported; otherwise false. - - - - Specifies the channel. See List of Mapping Channel Index Values. - - - - Returns an interface if the specified mapping channel is supported; otherwise NULL. - - - - Specifies the channel. See List of Mapping Channel Index Values. - - - - Sets the number of texture maps used. Note that this call is made automatically if SetMapSupport() is called. - - - - The number of texture maps to use. This is a value between 0 and MAX_MESHMAPS-1. - True to keep the old mapping information after the resize; false to discard it. - - - - Sets whether the specified mapping channels is supported or not. - - - - Specifies the channel. See List of Mapping Channel Index Values. - True to indicate the channel is supported; otherwise false. - - - - Returns an interface if the specified mapping channel is supported; otherwise NULL. - - - - Specifies the channel. See List of Mapping Channel Index Values. - - - - returns an object if the specified mapping channel is supported; otherwise NULL - - - - Specifies the channel. See List of Mapping Channel Index Values. - - - - Checks whether the particle specified by index is new. - - - - - Checks whether all particles are new. - - - - - Checks whether all particles are old. - - - - - Sets particle as new, returns true on success. - - - - - Sets particle as old, returns true on success. - - - - - Sets all particles as "new". - - - - - Sets all particles as "old". - - - - - Get particle property. - - - - - Returns true if "index" particle exists. - - - - - Returns true if all particles have the same time. - - - - - Methods not in the mapped interface. - - - - - Get synchronized time for all particles; if timing isn't synchronized then return time for the first particle in the container. - - - - - Gets the property for a particle by index. - - - - - Verifies that the channel is global. - - - - - If the channel is global, returns the global value. If the channel is not global, returns the value of the first particle. - - - - - Sets the property for a particle by index. - - - - - Sets the property for all particles at once thus making the channel global. - - - - - Checks whether some particles have shared . If it's true then there is no need to get a for each particle. - - - - - Gets the total number of actual Tabs (values) in the channel. - - - - - Gets the value index of a particle. - - - - - Gets the of the valueIndex-th value. - - - - - Gets the for the particle specified by particleIndex. - - - - - Gets the global for all particles. This method returns the of the first particle if it is local or shared. - - - - - Copies tab value from fromParticle to toParticle. - - - - - Copies tab value from fromParticle to toParticles. - - - - - Copies tab value from fromParticle to all particles. - - - - - Check whether some particles have shared Tab<UVVert>. If true, then there is no need to get a for each particle. - - - - - Gets the total number of actual Tabs (values) in the channel. - - - - - Gets the value index of a particle. - - - - - Gets the of the valueIndex-th value virtual const TabUVVert* GetValueByIndex(int valueIndex) const = 0;. - - - Gets the for a particle with index particleIndex. - - - - - Gets the global Tab<UVVert> for all particles. This method returns the of the first particle if it is local or shared. - - - - - Copies to be a local value for particle with index "particleIndex". Returns true if successful. - - - - - Creates a of size one from the UVVert value and copies the to be a local value for particle with index "particleIndex". Returns true if successful. - - - - - Copies to be a shared value for particles with indices in "particleIndices". Returns true if successful. - - - - - Creates a of size one from the UVVert value and copies the to be a shared value for particles with indices in "particleIndices". Returns true if successful. - - - - - Copies to be a global value for all particles. Returns true if successful. - - - - - Creates a of size one from the UVVert value and copies the to be a global values for all particles. Returns true if successful. - - - - - Copies the value from fromParticle to toParticle. - - - - - Copies the value from fromParticle to toParticles. - - - - - Copies the value from fromParticle to all particles. - - - - - Gets a property for a particle by index. - - - - - Verifies that the channel is global. - - - - - If the channel is global, returns the global value. If channel is not global, returns value of the first particle. - - - - - Sets a property for the particle with the specified index. - - - - - Sets a property for all particles at once, thus making the channel global. - - - - - get a primary particle system for the particle group - - - - - get a primary action list for the particle group - - - - - get activity status of the group; the group can be put into "idle" mode if returns zero then the group is in the "idle" mode - - - - - updates activity status of the group taking into consideration schematics of the primary particle system and primary action list if the group is "fertile" but the primary particle system does not have direct association with the primary action list then the group is put into "idle" mode returns activity status to be set - - - - - updates set of actions in the particle group the set is composed from global actions from the primary particle system and local actions from the associated primary actionList - - - - - get material from the list of actions the last action that has a material is the one - - - - - get wire color from the list of actions the last action that has a PFViewport interface is the one - - - - - get a particle container for the particle group - - - - - get validity interval for the particle group - - - - - set initial state for the particle group with time - - - - - returns fertility time of the particle group: the first time moment when the particle group can generate particles from scratch if the group is not active then it is not "fertile" - - - - - advance particles in the group to the given time - - - - - the following method allows to apply the actions Proceed method as a pre procedure before any modification to the particle container has been made. It is not recommended to change the particle container in this method. It is mostly to inquiring particle properties. - - - - - the following method allows to apply the actions Proceed method as a post procedure when the amount of particles in all particle groups has been established and there won't be any particle transfers from one particle group to another - - - - - returns a ptr at particleContainer to be transferred to another Event the particle group looses this ptr completely if the group doesn't have surplus containers then it returns false - - - - - appends the given container to the container of the group but first the given container is advanced in time to be in sync with the container of the group - - - - - returns true if content of the particle group is synchronized in time if group is in "sync" then it doesn't have surplus containers if false then the method returns the closest sync time for the particle group it could be a time of the closest cache moment. The closest time is always smaller (earlier) then the request time. - - - - - set particles in the group to the given time it should not involve any history dependent operations if the method is called it implies that the group is able to make an instant jump to the given time thus there is a cache for that time - - - - - inform the group what would be a final time for the series of update calls - - - - - Informs the particle group about the handle of the particle group node the handle is later used to uniquely identify particle container for cache purposes. - - - - - clear particle content in the particle group then enum should be in sync with IPFCache - - - - - clear caches in the particle group - - - - - in normal circumstances when a particle group receives a change notification message from the encapsulated operator/test the particle group should invalidate itself. However if the particle system is in the stage of proceeding then it is not possible to invalidate particle group right away. The particle group can know the status of the particle system by using global IsPFProceeding method (IPViewManager.h). Then if the system has the proceed status then the particle group should delay the invalidation. - - - - - check if the group has a delayed invalidation - - - - - Particle Group stores pointers at interfaces for efficiency. Those pointers are maintained automatically. In some circumstances (during Replace) it is necessary to flush those interfaces because they may become invalid. - - - - - identifies whether the update associated with the call Update(TimeValue t) was finished. If the update was not finished then the method Update(..) has to be called again (with the same TimeValue t) until it is finished - - - - - defines whether is it allowed to interrupt an update for a particle group. If the update interruption is not allowed then UpdateIsFinished should return true - - - - - Resample() This forces the modifier to resample itself. This will force the system to resample the patch - - - - - int GetNumberOfPoints(INode *node) This returns the number of points that are deformed - - - - - int GetPointUVW(INode *node, int index) This returns the closest UVW point on the patch to this point *node this is the node that owns the modifier so we can get the right local data int index this is the index of the point you want to lookup - - - - - int GetPointUVW(INode *node, int index) This returns the local space point of the deforming point before deformation *node this is the node that owns the modifier so we can get the right local data int index this is the index of the point you want to lookup - - - - - int GetPointPatchSpace(INode *node, int index) This returns the point in the space of the patch of the deforming point before deformation *node this is the node that owns the modifier so we can get the right local data int index this is the index of the point you want to lookup - - - - - int int GetPointPatchIndex(INode *node, int index) This returns closest patch to this point *node this is the node that owns the modifier so we can get the right local data int index this is the index of the point you want to lookup - - - - - Description: - This class provides an interface to the command modes and button press operations of the Editable object. To obtain a pointer to this class use the method Animatable::GetInterface() passing I_PATCHOPS. - - For example: - - )anim->GetInterface(I_PATCHOPS)); - - ipo->StartCommandMode(PcmAttach); - - - - - Begins the specified interactive command mode. - Parameters: - patchCommandMode mode - - PcmAttach - - PcmExtrude - - PcmBevel - - PcmCreate - - PcmWeldTarget - - PcmFlipNormal - - PcmBind - - - - - Performs the same operation as a button press inside the Editable UI. - Parameters: - patchButtonOp opcode - - The button operation to execute. One of the following values: - - PopBind - - PopUnbind - - PopHide - - PopUnhideAll - - PopWeld - - PopDelete - - PopSubdivide - - PopAddTri - - PopAddQuad - - PopDetach - - - - - This method allows you to get the edit patch parameters from the command panel. Currently not in use. - Parameters: - patchUIParam uiCode - - This enum is currently empty. - - int &ret - - The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit patch parameters from the command panel. Currently not in use. - Parameters: - patchUIParam uiCode - - This enum is currently empty. - - int val - - The value to set. - Default Implementation: - { } - - - - - This method allows you to get the edit patch parameters from the command panel. Currently not in use. - Parameters: - patchUIParam uiCode - - This enum is currently empty. - - float &ret - - The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit patch parameters from the command panel. Currently not in use. - Parameters: - patchUIParam uiCode - - This enum is currently empty. - - float val - - The value to set. - Default Implementation: - { } - - - - - Description: - This class provides an interface to the Select Modifer. To obtain a pointer to this class use the method Animatable::GetInterface() passing I_PATCHSELECT. - - For example: - - )anim->GetInterface(I_PATCHSELECT)); - - GetSelLevel(); - - - - - Returns a value indicating the current selection level of the modifier. One of the following values: - - PO_VERTEX - - PO_EDGE - - PO_PATCH - - PO_OBJECT - - - - - This method must be called when the selection level of the modifier is changed. Developers can use the methods of this class to get and set the actual selection data. When a developers does set any of these selection sets this method must be called when done. - - - - - Description: - When a developer gets the from the of the Select , they may cast it to this class and use these methods. They may be used to get/set the vertex/edge/patch sub-object selection state of the modifier as well as the named selection sets. - - To obtain a pointer to this class use the method Animatable::GetInterface() passing I_PATCHSELECTDATA. - - For example: - - )anim->GetInterface(I_PATCHSELECTDATA)); - - ; - - - - - Returns a that reflects the current vertex selection. There is one bit for each vertex. Bits that are 1 indicate the vertex is selected. - - - - - Returns a that reflects the current edge selection. There is one bit for each edge. Bits that are 1 indicate the edge is selected. - - - - - Returns a that reflects the current patch selection. There is one bit for each patch. Bits that are 1 indicate the patch is selected. - - - - - Sets the vertex selection of the modifier. - Parameters: - &set - - There is one bit for each vertex. Bits that are 1 indicate the vertex should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Sets the edge selection of the modifier. - Parameters: - &set - - There is one bit for each edge. Bits that are 1 indicate the edge should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Sets the patch selection of the modifier. - Parameters: - &set - - There is one bit for each patch. Bits that are 1 indicate the patch should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Returns a reference to a class used for manipulating the lists of vertex level named selection sets associated with this modifier. - - - - - Returns a reference to a class used for manipulating the lists of edge level named selection sets associated with this modifier. - - - - - Returns a reference to a class used for manipulating the lists of patch level named selection sets associated with this modifier. - - - - - Provides access to application path configuration functionality. - - - Note that the terms "map paths" and "External Files" (as seen in the UI) are used interchangeably below. This class provides access to all exposed path configuration functionality, including loading and saving of path configuration files. Should be used in lieu of for path-related operations. - To access the single instance, call the static function IPathConfigMgr::GetPathConfigMgr(). - - - - - Loads a path configuration file. - - - Loads a path configuration file and returns true if paths are loaded successfully. - file passed to function is a path configuration file - Paths found in file are loaded into application persistently. - true if any paths are loaded - - The fully-qualified path of the file to be loaded. - - - - Merges a path configuration file. - - - Merges a path configuration file and returns true if paths are merged successfully. A merge differs from a load in that map, xref and plugin directories are appended to the list instead of the list being overwritten. File IO paths are simply overwritten, as is the case with load. - file passed to function is a path configuration file - true if any paths are loaded - - The fully-qualified path of the file to be loaded. - - - - Saves out the current path configuration to the specified file. - - - Specified path is valid and writable. - The current user path configuration is saved to the specified file. - true if file is successfully saved out - - The fully-qualified path of the file to which paths are saved. - - - - Returns the default directory for the specified ID. - - - the default directory - - APP_XXX_DIR directory ID. For the complete list see . - - - - Sets the default directory. - - - true if the directory is set and valid - - The index of the directory to set. For the complete list see . - The new default directory. - - - - Returns the number of plugin path entries in PLUGIN.INI. - - - the number of plugin path entries. - - - - - Returns the description string for the given entry number. - - - the ith description string - - entry number - - - - Returns the directory string for the given entry number. - - - the ith directory string - - entry number - - - - Returns the number of assetType directories in path. - - - number of dirs in path - - specifies which type of count you are looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Returns the ith assetType directory in path. - - - the ith assetType directory in path - - index of path to get - specifies the directory category from which to get the directory. examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Adds an assetType path to the list. - - - true if added successfully - - directory to add - specifies the directory category to which the new directory should be added. examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Adds an assetType path to the list. - - - - directory to add - specifies the directory category to which the new directory should be added. examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - Should the .ini file containing the paths be updated with the defined search paths for the assetType after the add? - - - - Deletes an assetType path. - - - Deletes a assetType path from the path list. - true if Deletes successfully - - Directory to delete. - Specifies the asset type associated with this path? examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - Should the .ini file containing the paths be updated with the defined search paths for the assetType after the delete? - - - - Adds a session path. - - - Adds a session path to the path list. Session paths are not persistent, meaning they are lost when the application shuts down. - true if added successfully - - Directory to add. - Specifies which category of search directories should be used. examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - Should the .ini file containing the paths be updated with the defined search paths for the assetType after the add? - - - - Returns the number of assetType session directories in path. - - - number of session dirs in path - - specifies which type of count looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Returns the assetType session directory in path. - - - the ith assetType session directory in path - - index of path to get - specifies which type of asset directory you are looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Deletes a session path. - - - Deletes a session path in the path list. Session paths are not persistent, meaning they are lost when the application shuts down. - true if Deletes successfully - - Index for the directory to delete. - specifies which type of asset directory you are looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - Should the .ini file containing the paths be updated with the defined search paths for the assetType after the delete? - - - - Gets the combined total of session and permanent paths. - - - These methods provide access to the combined list of permanent and temporary (session) dirs, therefore the current total set of directories for a particular asset type. - the combined total of session and permanent paths - - specifies which type of count looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Gets the ith assetType directory. - - - Gets ith directory. Session paths are enumerated before permanent paths. - the ith directory - - index to return - specifies which type asset directory you are looking for examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Forces an update on the application. - - - Forces the application to update itself with the currently set path. - - specifies which type asset type directories to update examples of assetType include kBitmapAsset, kXRefAsset, kVideoPost, etc - - - - Returns the name of the .ini file used by 3ds Max. - - - The name of the .ini file Returns empty MSTR if locType == LOC_REGISTRY. - - - - - Returns the Preferences - > Files [Convert networked file paths to UNC] property. - - - If this method returns true, then paths will automatically be converted to their UNC representation if the path originates from a mapped drive. - If paths are automatically resolved to their UNC equivalents - - - - - Returns the Preferences - > Files [Convert local file paths to Relative] property If this method returns true, then paths selected as assets will automatically be converted to their relative equivalents, made relative to the current Project Folder setting. - - - true if asset paths should be made relative - - - - - Will Normalize this absolute path according to the current application settings. - - - Normalizes the passed-in path according to current application settings. The passed in path must be absolute to be normalized. Relative paths are ignored. Currently, the path will be normalized according to the two settings in the application that determine whether a path should automatically be converted to to a path relative to the current application Project Folder, and, if not, whether the absolute path should be converted to its UNC equivalent. - - The path to normalize - - - - This function appends a slash character to the end of the path passed unless one already exists. - - - - The path name to append. If NULL, no operation. - - - - This function removes the slash character from the end of the path passed if present. - - - - The path name to append. If NULL, no operation. - - - - This function appends a slash character to the end of the path passed unless one already exists. - - - - The path name to append. - - - - This function removes the slash character from the end of the path passed if present. - - - - The path name to append. If NULL, no operation. - - - - Checks whether the application is configured to use User Profile directories. - - - true if the application is configured to use User Profile directories false if the application's system paths and configuration files are stored in the legacy location (i.e. under the install root) - - - - - Checks whether the application is configured to use roaming profiles. Assuming that the application is configured to use User Profiles (see IsUsingProfileDirectories()) , determines whether paths are set to store information in the roaming profile location (i.e. /Documents and Data/<username>/Application Data...) or whether they are stored in the per-user Local Settings for the machine. (i.e. /Documents and Data/<username>/Local Settings/Application Data...) - - - true if the application is configured to use roaming profiles (moot if IsUsingProfileDirectory() returns true - - - - - Creates a hierarchy of directories. - - - This method will ensure that a hierarchy of directories exists. For example, if Path object representing "C:/A/B/C/D" is passed to this method, then this method will create A, B, C, and D, if they do not exist. - - true if the directories are created successfully or if the path already exists, false if an error occured while creating the directory, or if the parameter does not conform to stated restrictions. - - A Path object representing the directory hierarchy to create, if needed. This path must be absolute, and it's length cannot exceed 249 characters. - - - - Checks if a file or directory exists in the location pointed to by the absolute path parameter, potentially considering the missing file cache. - - - Checks for the existence of a file or directory pointed to by the absolute Path parameter. - true if the path is absolute and points to a file or directory that currently exists - - An absolute path to check for existence. Note that the disk is accessed to check for its existence, so checking paths (especially on network drives) may incur a performance cost. - If true, testing does not consider whether the file's path may be in the missing path cache. - - - - Searches for the given path and records the path in the NameEnum according to its ability to resolve the path and if missing only is set in the flags. Calls SearchForExternalFiles on the specified path, and if the path resolves to an existing file, and FILE_ENUM_MISSING_ONLY is not set, records the asset in the . If the path is not resolved and the flags are set with FILE_ENUM_MISSING_ONLY, it records the original path in the callback. - - - This is intended to be the default asset registration policy for calls to EnumAuxFiles on input-only assets when not using . - - The asset path as listed in the asset tracking system. - The in which to register this asset. - If FILE_ENUM_MISSING_ONLY is set, only paths that cannot be resolved to existing files will be recorded. If the FILE_ENUM_MISSING_ONLY is not set, only found files will be recorded. - - - - Converts the given path to absolute and records the path in the AssetEnum according to its ability to resolve the path and if missing only is set in the flags. - - - Calls Path.ConvertToAbsolute on the specified path, and if the path resolves to an existing file, and FILE_ENUM_MISSING_ONLY is not set, records the asset in the . If the path is not resolved and the flags are set with FILE_ENUM_MISSING_ONLY, it records the original path in the callback. - This is intended to be the default asset registration policy for calls to EnumAuxFiles for write assets when not using . - - The asset as listed in the asset tracking system. - The in which to register this asset. - If FILE_ENUM_MISSING_ONLY is set, only paths that cannot be resolved to existing files will be recorded. If the FILE_ENUM_MISSING_ONLY is not set, only found files will be recorded. - - - - Returns the current Project Folder folder. - - - Gets the current Project Folder setting in 3ds Max. This is the setting to which newly created relative paths are set relative to. Though this setting is also accessible by calling it is highly recommended that this method be used to access this value. - The current Project Folder setting folder. - - - - - Sets the current Project Folder folder. - - - Sets the current Project Folder setting in 3ds Max. This is the setting to which newly created relative paths are set relative to. Though this setting can also be set by calling it is highly recommended that this method be used to change this value, as other steps to adjust the environment may be taken internally. - Returns true if the folder is valid and absolute, or false otherwise - - The folder to which the Project Folder should be set. This value must be an absolute path. If the folder path does not exist, 3ds will attempt to create it. - - - - Sets a Project Folder which will be used for this application session only. - - - Sets a session-only path as the current Project Folder. This value does not persist if the application is shut down. The previous Project Folder setting will not be overwritten and will be the default setting upon future boot-ups. Calls to GetCurrentProjectFolder() will resolve to this session Project Folder, and relative paths will resolve themselves relative to this new value. The only difference is that this value is not persistent across sessions. - Returns true if the folder is valid and absolute, or false otherwise - - The folder to which the Project Folder should be set. This value must be an absolute path. - - - - Initiates the steps to choose and setup a default 3ds Max project. This call will initiate the workflow for allowing a user to choose and create a default project. In effect, this method will launch the "CreateDefaultProject" macroscript. The user will be prompted to browse to a new directory. - - - true if the steps succeeded and the user did not cancel the action Will return false immediately if the app is in Quiet Mode. - - - - - Initiates the steps to set up a default 3ds Max project without prompting the user. This call will initiate the workflow for setting up a default project. In effect, this method will launch the "CreateDefaultProject" macroscript. It will use the passed in parameter as the new Project Folder. - - - true if the steps succeeded and the path is absolute - - The directory that will be the new root of the project. This path must be absolute. - - - - Initiates the steps to set an existing 3ds Max project folder as the active project folder. This call will initiate the workflow for allowing a user to choose an existing 3ds Max project folder as the active project folder. In effect, this method will launch the "SetProjectFolder" macroscript. The user will be prompted to browse to an existing directory. - - - true if the steps succeeded and the user did not cancel the action Will return false immediately if the app is in Quiet Mode. - - - - - Initiates the steps to set an existing 3ds Max project folder as the active project folder without prompting the user. This call will set an existing 3ds Max project folder as the active project folder. In effect, this method will launch the "SetProjectFolder" macroscript. It will use the passed in parameter as the new Project Folder to set active. - - - true if the steps succeeded and the path is absolute - - The directory that will be set as the active project folder. This path must be absolute. - - - - Will check for the existence of a project in a folder. - - - Given a folder path, will check if a project exists in that folder. A project exists if a .mxp file exists in that path. - true if a project exists at the location specified by the passed -in parameter - - An absolute path to check for the existence of a project. - - - - Will return the fully-qualified path of the project file, given the root folder of an existing project. - - - Given a project root of a project which exists, will return the .mxp file for that project. Normally the .mxp filename is the same name as the project root folder, but if that file does not exist, then the first file that matches the "*.mxp" pattern will be returned. - The fully-qualified path of the project file. A project file is searched for, but if not found, then a file name is generated. - - The path of the root of a project to check. - - - - Returns the file path of the current project file, if it exists. - - - Gets the project file path of the current project, if it exists. - The fully-qualified path of the current project file. A project file is searched for, but if not found, then a file name is generated. - - - - - Converts an absolute path into a path that is relative to the current Project Folder. - - - Converts an absolute path into a path that is relative to the current Project Folder. If the path cannot be made relative (if it is rooted on a different drive, for instance), then it is left untouched. A path parameter which already relative is also left untouched. - - A mutable absolute Path which will be converted to a relative path, if possible. - - - - Gets a count of the number of Project directories. - - - This method will return a count of the directories listed in the Configure User Paths... -> File IO dialog. - the number of Project directories - - - - - Returns a project directory according to an index, not an ID This method will return a Project directory by index, rather than by ID. This is to allow an SDK user to iterate over the list of Project directories. The directories are sorted by Description and are ordered alphanumerically. - - - The directory associated by the index value, not by ID. if the input index is invalid, then NULL is returned - - The index value of the directory to return, which must be between 0 and -1. - - - - Adds an ID to a persistent internal filter table. - - - Adds a File IO ID to an internal filter table that is referenced when creating a Project setup. Folders added to this list (by their ID) are NOT created when creating a Project workspace. - - An ID for a folder to not include in the Project workspace creating process. - - - - Removes all IDs from a persistent internal filter table. - - - Removes all File IO IDs from an internal filter table that is referenced when creating a Project setup. Folders added to this list (by their ID) are NOT created when creating a Project workspace. - - - - - Removes an ID from a persistent internal filter table. Removes a File IO ID from an internal filter table that is referenced when creating a Project setup. Folders added to this list (by their ID) are NOT created when creating a Project workspace. - - - - An ID for a folder to not include in the Project workspace creating process. - - - - Returns a of the IDs in the persistent internal filter table. - - - Gets the IDs from the persistent internal filter table. - - containing the IDs from the persistent internal filter table. - - - - Description: - This class represents the interface to the Path Position Controller. You can obtain a pointer to the path position controller interface using; GetIPathConstInterface(cd). This macro will return - - (IPathPosition*)(CD)->GetFPInterface(PATH_CONSTRAINT_INTERFACE). - - PATHPOS_PATH_REF may be used to access the position constraint controller's references and PATHPOS_PBLOCK_REF to reference the parameter block. - - All methods of this class are Implemented by the System. - - - - - This method is available in release 4.0 and later only. - - Returns the number of nodes in the path list. - - - - - This method is available in release 4.0 and later only. - - Gets one of the path nodes that the path controller follows, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the path list to be obtained. - - - - - This method is available in release 4.0 and later only. - - Gets the weight of one of the path nodes that the path controller follows, specified by targetNumber, and time t. If the targetNumber is not relevant then 0.0f is returned. - Parameters: - int targetNumber - - The node number in the path list whose weight is to be obtained. - - - - - This method is available in release 4.0 and later only. - - Sets the weight of one of the path nodes that the path controller follows, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the path list whose weight is to be set. - - float weight - - The weight to assign. - TRUE if there is more than one path in the list and you are trying to set weight, FALSE otherwise. - - - - - This method is available in release 4.0 and later only. - - Appends the current path list by one and appends the current weight list by one. - Parameters: - *target - - The node that is to be appended to the current path list. - - float weight=50.0 - - The weight to be assigned to the newly appended path. - - - - - This method is available in release 4.0 and later only. - - This method allows you to delete a specified target. - Parameters: - int selection - - The node number in the orientation target list to delete. - TRUE if successful, otherwise FALSE. - - - - - This method returns the state of the follow flag. TRUE if on; FALSE if off. - - - - - Returns the bank amount setting. See the remarks in SetBankAmount() above. - - - - - Returns the on/off state of the bank parameter. TRUE if on; FALSE if off. - - - - - Returns the smoothness setting. See remarks in SetTracking() above. - - - - - Returns the state of the 'Allow Upside Down' parameter. - TRUE for on; FALSE for off. - - - - - Returns the state of the 'Constant Velocity' parameter. - TRUE for on; FALSE for off. - - - - - Returns the state of the 'Flip' parameter. - TRUE for on; FALSE for off. - - - - - Returns the axis setting. - One of the following values: - - 0: X axis. - - 1: Y axis. - - 2: Z axis. - - - - - Returns the state of the loop flag. - TRUE for on; FALSE for off. - - - - - Returns the state of the relative/absolute flag. - TRUE if relative is on; FALSE is off (i.e. absolute). - - - - - for accessing functionality that exists in the Perez All Weather Model. - - - The Perez All-Weather model is used to calculate the luminance of the sky based on various sets of parameters, which may all be measured or derived from each other: - - - - - Calculates the Perez coefficients based on measured illumiance values. - - - - The day of the year, index from 1. - The atmospheric water content (maybe calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The measured diffuse horizontal illuminance. - The measured direct normal illuminance. - The Perez coefficients are returned through this. - - - - Calculates the Perez coefficients based on measured irradiance values. - - - - The day of the year, index from 1. - The angle between the sun and the zenith (0,0,1), in radians. - The measured diffuse horizontal irradiance. - The measured direct normal irradiance. - The Perez coefficients are returned through this. - - - - Calculates the Perez coefficients based on measured sky brightness and clearness values. - - - - The measured sky brightness (may be calculated through ). - The measured sky clearness (may be calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The Perez coefficients are returned through this. - - - - Derives the sky brightness from measured irradiance values. - - - The calculated brightness value. - - The day of the year, index from 1. - The angle between the sun and the zenith (0,0,1), in radians. - The measured diffuse horizontal irradiance. - The measured direct normal irradiance. - - - - Derives the sky clearness from measured irradiance values. - - - The calculated clearness value. - - The angle between the sun and the zenith (0,0,1), in radians. - The measured diffuse horizontal irradiance. - The measured direct normal irradiance. - - - - Derives the diffuse horizontal irradiance value from sky brightness. - - - The calculated diffuse horizontal irradiance value. - - The day of the year, index from 1. - The measured sky brightness. - The angle between the sun and the zenith (0,0,1), in radians. - - - - Derives the direct normal irradiance value from sky clearness. - - - The calculated diffuse horizontal irradiance value. - - The diffuse horizontal irradiance, which may be calculated with . - The angle between the sun and the zenith (0,0,1), in radians. - The measured sky clearness. - - - - Converts a radiance value to an illuminance. - - - The illuminance value, calculated from the inputs. - - The measured diffuse horizontal radiance. - The measured sky brightness (may be calculated through ). - The measured sky clearness (may be calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The atmospheric water content (maybe calculated through ). - - - - Converts a radiance value to an illuminance. - - - The illuminance value, calculated from the inputs. - - The measured direct normal radiance. - The measured sky brightness (may be calculated through ). - The measured sky clearness (may be calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The atmospheric water content (maybe calculated through ). - - - - Converts an illuminance value to an irradiance. - - - The irradiance value, calculated from the inputs. - - The measured diffuse horizontal illuminance. - The measured sky brightness (may be calculated through ). - The measured sky clearness (may be calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The atmospheric water content (maybe calculated through ). - - - - Converts an illuminance value to an irradiance. - - - The irradiance value, calculated from the inputs. - - The measured direct normal illuminance. - The measured sky brightness (may be calculated through ). - The measured sky clearness (may be calculated through ). - The angle between the sun and the zenith (0,0,1), in radians. - The atmospheric water content (maybe calculated through ). - - - - Converts a dew point temperature to an atmospheric water content. - - - The atmospheric water content, calculated from the input value. - - Indicates whether the value stored in surfaceDewPointTemp is valid and usable. If false, then the value stored in surfaceDewPointTemp is ignored, and a default value is returned instead. - The dew point temperature. - - - - Description: - This class describes a 2D point using int x and y coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, normalize and compute the dot product of two IPoint2s. All methods are implemented by the system. - Data Members: - int x,y; - - - - - Allows access to x, y using the subscript operator. - An index of 0 will return x, 1 will return y. - - - - - Unary -. Negates both x and y. - - - - - Unary +. Returns the Ipoint2 unaltered. - - - - - Returns the length squared of the - - - - - Returns the length of the - - - - - Returns the component with the maximum abs value. 0=x, 1=y. - - - - - Returns the component with the minimum abs value. 0=x, 1=y. - - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Member-wise, in-place multiplication of this vector: (x*x, y*y) - - - - - Member-wise, in-place division of this vector: - - - - - Multiplies this by an integer value. - - - - - Divides this by an integer value. - - - - - Adds floating point value to this . - - - - - Subtracts floating point value from this . - - - - - Subtracts from this . - - - - - Adds to this . - - - - - Member-wise multiplication of two vectors: (x*x, y*y) - - - - - Member-wise division of two vectors: - - - - - Returns the dot product of two 's. - - - - - Equality operator. Compares two 's. - - - - - Description: - This class describes a 3D point using integer x, y and z coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, and element by element multiply and divide two points. All methods are implemented by the system. - - Data Members: - int x,y,z; - - - - - Allows access to x, y and z using the [ ] operator. - An index of 0 will return x, 1 will return y, 2 will return z. - - - - - Unary - operator. Negates x, y and z. - - - - - Unary +. Returns the point unaltered. - - - - - Returns the length squared of the - - - - - Returns the length of the - - - - - Returns the component with the maximum abs value. 0=x, 1=y, 2=z. - - - - - Returns the component with the minimum abs value. 0=x, 1=y, 2=z. - - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Member-wise, in-place multiplication of this vector. - - - - - Member-wise, in-place division of this vector. - - - - - Multiplies this by an integer value. - - - - - Divides this by an integer value. - - - - - Adds int point value to this . - - - - - Subtracts int point value from this . - - - - - Subtracts a from a . - - - - - Adds a to a . - - - - - Member-wise multiplication of two vectors: (x*x, y*y, z*z) - - - - - Member-wise division of two vectors: (x/x, y/y, z/z) - - - - - Returns the dot product of two IPoint3s. - - - - - The cross product of two 's (vectors). - - - - - The cross product of two 's (vectors). - - - - - Test for equality between two 's. - true if the 's are equal; otherwise false. - - - - - - - Description: - This class represents the interface to the PointCache . You can obtain a pointer to the PointCache interface using; GetIPointCacheInterface(cd). This macro will return - - *)(cd)->GetFPInterace(POINTCACHE_INTERFACE). Sample code supporting this class can be found in /MAXSDK/SAMPLES/MODIFIERS/POINTCACHE. - - All methods of this class are Implemented by the System. - - - - - This method will press the Record button in the rollup interface. - - - - - This method will press the Cache button in the rollup interface. - - - - - This method will press the Enable Modifiers Below button in the rollup interface. - - - - - This method will press the Disable Modifiers Below button in the rollup interface. - - - - - Description: - This class represents the interface to the PointCache World Space . You can obtain a pointer to the PointCache World Space interface using; GetIPointCacheWSMInterface(cd). This macro will return *)(cd)->GetFPInterace(POINTCACHEWSM_INTERFACE). Sample code supporting this class can be found in /MAXSDK/SAMPLES/MODIFIERS/POINTCACHE. - - All methods of this class are Implemented by the System. - - - - - This method will press the Record button in the rollup interface. - - - - - This method will press the Cache button in the rollup interface. - - - - - This method will press the Enable Modifiers Below button in the rollup interface. - - - - - This method will press the Disable Modifiers Below button in the rollup interface. - - - - - Description: - This class represents the interface to the Position Constraint. You can obtain a pointer to the position constraint interface using; GetIPosConstInterface(cd). This macro will return - - (IPosConstPosition*)(CD)->GetFPInterface(POS_CONSTRAINT_INTERFACE). - - POSPOS_PBLOCK_REF may be used to access the position constraint controller's references: - - All methods of this class are Implemented by the System. - - - - - Returns the number of target nodes in the position target list. - - - - - Gets one of the position nodes that the position constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the position target list to be obtained. - - - - - Gets the weight of one of the position nodes that the position constraint controller targets, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the position target list to set. - Returns the position target weight if the targetNumber is relevant, 0.0f otherwise. - - - - - Sets the weight of one of the position nodes that the position constraint controller follows, specified by targetNumber. - Parameters: - int targetNumber - - The node number in the position target list whose weight is to be set. - - float weight - - The weight to set. - TRUE if there is more than one position target in the list and you are trying to set weight, FALSE otherwise. - - - - - Appends the current position target list by one and appends. - Parameters: - *target - - The node that is to be appended to the current position target list. - - float weight=50.0 - - This is the weight that is to be assigned to the newly appended position target. The default weight is 50.0. - TRUE if the target was appended, otherwise FALSE. - - - - - - - This method allows you to delete a specified target. - Parameters: - int selection - - The node number in the position target list to delete. - TRUE if successful, otherwise FALSE. - - - - - Description - provides an interface to the Projection Intersector which provides ray-tracing tools intended for use by the plug-ins. - - - - - - - The root is normally the object on which the projection modifier is applied. - - The cage is optional, it may be NULL or empty; if supplied, the cage must have the same topology as the root. - - The object to world transform matrix. - - - - - - The root is normally the object on which the projection modifier is applied. - - The cage is optional, it may be NULL or empty; if supplied, the cage must have the same topology as the root. - - The object to world transform matrix. - - - - true if initialized, false when freed - - - - - - - A leaf is normally one of the objects targeted by the projection modifier. - - The object to world transform matrix. - - - - - - A leaf is normally one of the objects targeted by the projection modifier. - - The object to world transform matrix. - - - - true if initialized, false when freed - - - - - releases memory allocated by the Init functions - - - - - Given a point in root object space, and a normal for the point (optional - may be zero), find the closest face, and barycentric coordinates of the point as projected onto the face - Root functions: Require the root be initialized first - - - - - Find an intersection on a leaf, given a ray - Require a leaf be initialized first - - - - - Find an intersection on a leaf, given a point on the root mesh - Require that BOTH the root and a leaf are initialized - - - - - Description: - provides an interface to the Projection . This interface gives access to the geometry selections, cage settings, validity checks, and projection types. - - - - - of Nodes in geometry selection. - - - int number of objects. - - - - - Get Node by Index. - - - - - zero based index into number of objects - - - - Get by Index. - - - - - zero based index into number of objects - - - - Get Selection Level by Index. - - - enum PM_SL_OBJECT, PM_SL_FACE, or PM_SL_ELEM - - - zero based index into number of objects - - - - Delete by Index. - - - - - zero based index into number of objects - - - - of Geometry Selection. - - - int number of geometry selections. - - - - - Get Geometry Selection by Index. - - - - - zero based index into number of geometry selections - - - - Get Geometry Selection Selection Level by Index. - - - enum PM_SL_OBJECT, PM_SL_FACE, or PM_SL_ELEM - - zero based index into number of geometry selections - - - - Get number of nodes in Geometry Selection by Index. - - - int number of nodes - - zero based index into number of geometry selections - - - - Get Node in Geometry Selection by Index. - - - - zero based index into number of geometry selections - zero based index into number of nodes in geometry selections - - - - Get Geometry Selection Map Proportions by Index. Used to offset the proportion this geometry selection will occupy in the generated bake element. - - - - Zero-based index into number of geometry selections. - The proportion adjustment. - - - - Delete node from Geometry Selection by Index. - - - - zero based index into number of geometry selections - - - - Delete Geometry Selection by Index. - - - - zero based index into number of geometry selections - - - - Delete node from Geometry Selection by Index. - - - - zero based index into number of geometry selections - zero based index into number of nodes in geometry selections - - - - Retrieve the for the specified node. Access to ModData for selection set and cage information. - - - - that contains Projection - - - - Is this a valid node for geometry selections. - - - bool true if this is a valid geometry selection object - - INode* - - - - Add Level Node. - - - bool true if node was successfully added - - INode* - - - - Delete all geometry selections. - - - - - Get the visibility of the geometry selection nodes. If their visibility state varies, the majority state will be returned. - - - bool true if the nodes are visible - - - - - Refresh the projection type list. - - - - - Triggers an auto wrap cage. This will destroy the current cage and generate a new one based on the current geometry selections. - - - - - Resets the cage. This will destroy the current cage and return all verts back to their original/zero-offset location. - - - - - Pushes the cage. This will work on the selected verts. If no verts are selected, the entire cage will be affected. - - - - float pushes the cage by specified amount. - - - - Get list of material IDs by Index. - - - int number of material IDs - - INode* that contains the projection modifier - zero based index into number of objects - - array of material IDs - - - - Get list of material IDs by Index. - - - int number of material IDs - - - INode* that contains the projection modifier. - - Zero-based index into number of objects. - - array of material IDs. - - - - Get Selected surface area by Geometry Selection Index. - - - float surface areas of faces - - INode* that contains the projection modifier - zero based index into number of geometry selections - - - - Check for duplicate IDs within Geometry Selections Duplicate material IDs can create unwanted results with certain Project Mapping settings in RTT. - - - int of faces with duplicates - - INode* that contains the projection modifier - - bitarray of face duplicates - - - - Check for duplicate face selections within Geometry Selections Duplicate face selections can create unwanted results with certain Project Mapping settings in RTT. - - - int of faces with duplicates - - INode* that contains the projection modifier - - bitarray of face duplicates - - - - Select by ID. - - - - ID - - - - Select by Smoothing Group. - - - - Smoothing Group - - - - Get the number of Projection Types Projection Types are classes that load into the Projection . These plugins can use the geometry selection and cage information to perform projections of any type they wish. Examples would be projecting UVWs, vertex location, material IDs, etc. - - - int of Projection Types created by user - - - - - Get Projection Type by Index. - - - ReferenceTarget* pointer of created Projection Type - - zero based index into number of Projection Types - - - - Remove Projection Type by Index. - - - - zero based index into number of Projection Types - - - - Invoke Project command for Projection Type by Index This will invoke the project command for the specified projection type. - - - - zero based index into number of Projection Types - - - - Invoke Project command for all Projection Types. - - - - - Get the number of Registered Projection Types Registered Projection Types are classes that load into the Projection . Instances of these Registered Projection Types are called Projection Types. - - - int of Registered Projection Types in the system. - - - - - Create an instance of a Registered Projection Type by Index. - - - - zero based index into number of Registered Projection Types - - - - Get the Class ID of a specified Registered Projection Type. - - - - zero based index into number of Registered Projection Types - - containing the two Class ID values - - - - Enable Show Alignment feature. - - - - - Disable/Clear Show Alignment feature. - - - - - Description: - provides an interface to the Projection Mod Data. - - - - - Get for the Base . The base object refers to the object that contains the Projection . - - - reference to - - - - - Get for the Cage. - - - reference to - - - - - Get the object selection by Index. - - - bool true if valid bitarray was returned - - zero based index into number of objects - - bitarray of face selection - - - - Get the material IDs by Index. - - - int number of material IDs found - - zero based index into number of objects - - of material IDs in selection - - - - Get the object selection by Geometry Selection. - - - bool true if valid bitarray was returned - - zero based index into number of geometry selections. - - bitarray of face selection - - - - Get the material IDs by Geometry Selection. - - - int number of material IDs found - - zero based index into number of geometry selections - - of material IDs in selection - - - - Get the surface area of selection by Geometry Selection. - - - float surface area of face selection - - zero based index into number of geometry selections. - - - - Check for duplicate IDs Duplicate material IDs can create unwanted results with certain Project Mapping settings in RTT. - - - int of faces with duplicates - - - bitarray of face duplicates - - - - Check for duplicate face selection Duplicate face selections can create unwanted results with certain Project Mapping settings in RTT. - - - int of faces with duplicates - - - bitarray of face duplicates - - - - Description - provides an interface to the Projection Type Plugins. Projection Types are classes that load into the Projection . These classes can use the geometry selection and cage information to perform projections of any type they wish. Examples would be projecting UVWs, vertex location, material IDs, etc. - - These classes must specify a class category of: ProjectionModType - - - - - Sets pointer. Give the Projection Mod Type a pointer back to the Projection . - - - - - Pointer to projection modifier. - - - - Determine if the Projection Mod Type can project the geometry selection. Allows the projection modifier type to tell the projection modifiers if its projection algorithm supports the current geometry selection. If it doesn't, the projection modifier will disable the Project button for this type. - - - bool return true if the projection is supported - - Tab< INode*> an array of nodes that contain the projection modifier - int index into geometry selection. -1 indicates all geometry selections. - int index into the geometry selection's nodes. -1 indicates all nodes within the geometry selection. - - - - Specifies which geometry selections and/or nodes should be projected. This method triggers the projection mod types projection algorithm for the specified geometry selections. - - - - Tab< INode*> an array of node that contain the projection modifier - int index into geometry selection. -1 indicates all geometry selections. - int index into the geometry selection's nodes. -1 indicates all nodes within the geometry selection. - - - - Tell the plugin to generate an initial name. - - - - int An index value to help create a unique name. Unique names are not required. - - - - Get the plugin's display name. - - - MCHAR* name - - - - - Allows the projection modifier to enable or disable a projection mod type plugin Class should assume they are enabled unless notified otherwise. - - - - bool true if enable - - - - Specifies if the projection mod type is currently in an editing mode. - - - bool return true if in editing mode. - - - - - Forces a projection mod type plugin to end editing. - - - - - Allows the projection modifier to enable or disable the ability to edit within a projection mod type plugin Class should assume they are enabled for editing unless notified otherwise. - - - - bool true if enable - - - - ModifyObject Method Pass Through Calls to ModifyObject in the Projection are passed through this method to the projection mod types. The corresponding is an additional parameter. - - - - - - - NotifyInputChanged Method Pass Through Calls to NotifyInputChanged in the Projection are passed through this method to the projection mod types. The corresponding is an addition parameter. - - - - - - - GetWorldBoundBox Method Pass Through Calls to GetWorldBoundBox in the Projection are passed through this method to the projection mod types. - - - - - - - Display Method Pass Through Calls to Display in the Projection are passed through this method to the projection mod types. - - - - - - - HitTest Method Pass Through Calls to HitTest in the Projection are passed through this method to the projection mod types. - - - - - - - SelectSubComponent Method Pass Through Calls to SelectSubComponent in the Projection are passed through this method to the projection mod types. - - - - - - - Move Method Pass Through Calls to Move in the Projection are passed through this method to the projection mod types. - - - - - - - GetSubObjectCenters Method Pass Through. - - - Calls to GetSubObjectCenters in the Projection are passed through this method to the projection mod types. - - - - - GetSubObjectTMs Method Pass Through Calls to GetSubObjectTMs in the Projection are passed through this method to the projection mod types. - - - - - - - ClearSelection Method Pass Through Calls to ClearSelection in the Projection are passed through this method to the projection mod types. - - - - - - - SelectAll Method Pass Through Calls to SelectAll in the Projection are passed through this method to the projection mod types. - - - - - - - InvertSelection Method Pass Through Calls to InvertSelection in the Projection are passed through this method to the projection mod types. - - - - - - - Description: - This interface provides access to some shade context information for the working model. It is used when performing a projection mapped Render To Texture, to support shading operations on the reference models which additionally require information about the working model. - - This interface is provided by the renderer to Texture Bake elements, when performing a Render To Texture (RTT) in projection mode. In this mode, pixels are shaded as follows. First, the renderer locates a point on the working model. A ray is cast to locate a corresponding point on one of the reference models. shading proceeds on the reference model instead of the working model. The material is responsible for invoking each texture bake element and render element, as part of its shading operation. However, the texture bake elements might need information about the working model, and the shade context only contains information for the reference model. The renderer solves this problem by attaching an interface to the that it passes to the material. - - When a bake projection is done, all the information in the shade context is overriden to represent the intersection point on the projected object. If a bake render element still needs access to shade context information from the original object (the working model), then this interface may be used. - - This interface provides a render instance of the working model and information about the working model point being shaded. It should be queried from the shade context through ShadeContext::GetInterface(). A NULL pointer will be returned if no projection was done. - Examples: - For an example of usage, please refer to the Normal Map and Height Map texture bake elements, in the SDK samples maxsdk\samples\render\renderelements\stdBakeElem.cpp. - - - - - Returns the render instance of the working model. - - - - - Returns the face number of that hit face. - - - - - Returns the original interpolated normal. - - - - - Returns the barycentric coordinates of the hit point. - - - - - Returns whether the backface was hit. - - - - - Returns the point that was hit, in camera space. - - - - - Get the view direction, in camera space (equivalent to SContext::V()) - - - - - Get the original view direction, in camera space (equivalent to SContext::OrigView()) - - - - - Get the material number of the hit face. - - - - - Get the bump basis vectors of the hit face (equivalent to SContext::BumpBasisVectors()) - - - - - Get the map basis vectors (aks bump basis vectors) interpolated at the current position. - - - - - Property container. - - - This class provides an extension mechanism that IGame can use - an Entity is free to use them. The developer can extend the properties that are "known" to IGame can be extended this way the property can be retrieved directly by the developer. As it is "known" to the developer the property type is also known and can be accessed directly - - - - - User Defined Property Access. - - - Using the unique ID in the IGameProp.xml file, the user defined property can be queried directly - A pointer to if found, NULL otherwise - - User Property ID used in the IGameProp.xml file - - - - The number of Properties for the Entity. - - - The number of properties found. The default is 0 - - - - - Direct Property Access. - - - The property can be accessed directly from the index provided by GetNumberOfProperties(). It will return NULL for "hidden" paramameters names (defined as empty string in paramblocks) - A pointer to the . The default is NULL - - The index of the property to return - - - - Property Access. - - - Using the name, the property can be queried directly - A pointer to if found. The default is NULL - - Property name as defined in or User Property name - - - - Enumerate the Properties. - - - All properties can be enumerated by using this method. A user defined callback is used to provide access to the properties. - - The callback object to use. - - - - Any which wants to support being published should implement this interface. - - - When users xref objects with published custom attribute, users can visit and edit those values and saved with the XRef main scene and later if the value of source scene was changed, the main scene will also be updated accordingly(merge the value from source scene and the value saved in the main scene) - - - - - Return the name of the published custom attribute. - - - the name of the published custom attribute - - - - - Return the custom attribute this interface publishes. - - - the the interface publishes - - - - - Return how many published parameters there are in this custom attribute. - - - the count of published parameters. - - - - - Retrieve the name of the i-th published parameter. - - - - the name of the i-th published parameter. - - - index of the published parameter whose name we want to get. - - - - Retrieve the controller of the i-th published parameter. - - - - the controller of the i-th published parameter. - - - index of the published parameter whose controller we want to get. - - - - the controller of the i-th published parameter. - - - - if the operation is succeeded or not - - - index of the published parameter whose controller we want to set. - - the controller to be set to the i-th parameter. - - - - Get the controller type of the i-th published parameter. - - - - the controller type of the i-th parameter, return 0 if not applicable. - - - index of the published parameter whose controller type we want to get. - - - - Returns true if the operation has been proceeded successfully. The method is called when the ActionList is established the first time, when there is a first particle that enters the ActionList and there is a need to proceed particles. /param pCont: particle container with particle data /param pSystem: the particle system that generates the particle stream; the same operator may get calls from different particle systems; if the result varies according to the particle system that generates particles, then this parameter is useful. /param pNode: of the particle system that generates the particles. /param actions: Tab<Object*> of Actions in the current ActionList. The stack will be used to proceed particles. The stack is mutable: an Action may change the stack (to remove or add some Actions) to fine-tune the order of execution or add some extra actions. The next parameter should sync with the mutation. /param actionNodes: Tab<INode*> of action nodes. - - - - - See Init(). - - - - - See Init(). - - - - - "Function publishing" alternative for ChannelsUsed method. Reserved for future use. - - - - - Casting the FPValue->ptr parameter to * as in PFExport void ChannelsUsed(...); an Action may have a time interval when the Action is active. Outside this interval the Action does nothing, therefore there is no need to proceed particles outside the activity interval. - - - - - Birth Action is a special type of actions since it can create particles from scratch. All other type of actions proceed existing particles. Only Action that can create absolutely new particles (if number of particles in the container is zero) should override this method returning true. - - - - - There is a special case of non-executable actions. They are present in the action schematics but don't affect the particle behavior. Example: Comments operator. - - - - - An action may have 3d icon representation in viewport. The 3d icon can be used as a reference for some of the action parameters. - - - - - If an operator/test has a 3D icon the icon can be automatically color matched to the color of the display operator in the same event. For the automatic color match the operator/test should return 1 in this method. If returns 0 then the action gets the default color for operator/test. If returns -1 then the action doesn't need any color coordination from Particle Flow. - - - - - An Action may carry some chaos/unpredictibility in its processing. This method supports chaos randomness. - - - - - For chaos/unpredictibility action, gets rand value. - - - - - For chaos/unpredictibility action, sets and returns new rand value. - - - - - If the Action may potentically change particle material, then return true. - - - - - Returns a material for particles. - - - - - Return true if material was set successfully. - - - - - An Action may have parameters controlled by script channels. How the script wiring is set up is controlled by a separate rollup with script-wiring pblock. The rollup is visible if "Use Script Wiring" option in the right-click menu is set to ON. The option is visible only for actions that support script wiring. - - - - - Supports script wiring. See SupportScriptWiring(). - - - - - An Action may or may not be dependent on the particle system emitter. When the emitter is invalidated, a particle group has to decide if it needs to invalidate itself. To make the decision, the group checks all the actions if any of them are dependent on the emitter change. There are two categories of dependency: the transformation matrix of the emitter (TM), and object parameters of the emitter (props). This method checks the TM category. - - - - - Checks the props category for dependency. See IsEmitterTMDependent(). - - - - - Returns action state (see IPFActionState.h for details). You have to delete the by DeleteIObject method when the state is no longer needed. - - - - - Sets the state of the action to the given state. - - - - - The method can be used to signal the a container update for a particle group has to be interrupted on this action. Only after all particle groups in the system are updated (with possible interruptions as well), the container update can be continued. This is done for operators that are instanced across a PFlow system to ensure the real instant snapshot of the whole system to guarantee the proper interaction between particles at the same instant moment. - - - - - defines whether is it allowed to interrupt an update for an action. If the update interruption is not allowed then InterruptUpdate cannot return true - - - - - inform the action what would be a final time for the series of update calls - - - - - Activate/deactivate all the actions in the list. - - - - - Activate/deactivate all the actions in the list. 1: active; 0: non-active for operators and "always false" for tests; -1: "always true" for tests. - - - - - Activate/deactivate all the actions in the list. - - - - - Returns x-coord of the right side of the action list. - - - - - Action list may be shown in a "collapsed" state in ParticleView. - - - - - Action list may be shown in a "collapsed" state in ParticleView. - - - - - Action list may be shown in a "collapsed" state in ParticleView. - - - - - Indicates if there are PFSystems or ActionLists that direct particle flow in this action list. If returns false then the action list won't produce particles. - - - - - ActionList has its own methods for selecting. Selected ActionList has a white boundary in the ParticleView. If the corresponding particle system has Event-Based Selection ON, the the corresponding particles are shown as selected. - - - - - ActionList has some restrictions on whether it is able to add a "fertile" action. ActionList may have only single "fertile" action in the list of actions. Also, ActionList may have a "fertile" action only if no test uses this actionList as a next event. - - - - - The method is used to initiate material update in the associated particle group. - - - - - If the ActionList has an associated material (either via material inheritance or from any actions at the action list, then return true. - - - - - Defines whether this action list depends on the upstream action lists to generate its material. If the action list has an operator with a material, and it does not inherit material then it returns false. - - - - - Generates material as defined by inheritance. - - - - - Returns a material for particles. - - - - - Return true if material was set successfully. - - - - - Returns material priority number. The priority is used when defining material inheritance, for example material inheritance can be defined by inheriting material with highest (largest) priority. - - - - - Returns stream depth index - shortest distance to pf source up stream. - - - - - Returns of up-stream action list nodes (for read and write) - - - - - Returns of up-stream action list nodes that are relevant for material inheritance re-generation (for read and write) - - - - - The method is used to implemented Visitor pattern in the actionList graph. - - - - - The method is used to implemented Visitor pattern in the actionList graph. - - - - - The method is used to sort action lists to resolve material dependency for inheritance. - - - - - Returns whether the event material was updated. - - - - - Returns number of actionLists/events with materials updated. - - - - - Returns number of actionLists/events with materials updated. The functions updates materials in all events in the downstream of the current event; The function does not update material in the current event; use UpdateMaterial function instead for this purpose. - - - - - Returns number of ActionLists in the current scene. - - - - - Returns i-th action lists in the scene. - - - - action list index - - - - Checks if the given aciton list node is present in the scene. - - - - action list node - - - - check if the scene has an action list with the given node handle - - - - - Register notification with the action list pool. The given function is called each time the set of all action lists is changing Returns nonzero if the event was registered; otherwise zero. - - - - The callback function called when the event occurs. - A pointer to a parameter which will be passed to the callback function. - - - - Unregister notification with the action list pool. This function is called to break the connection between the event and the callback. After this function executes the callback is no longer invoked when the event occurs. Returns nonzero if the event was unregistered; otherwise zero. - - - - The callback function called when the event occurs. - A pointer to a parameter which will be passed to the callback function. - - - - The method returns the unique ID for the action state class. The ID is used for constructing the action state when loading since the action state class is not inherited from class . - - - - - Returns node handle of the action with the action state. - - - - - Saving content of the action state to file. - - - - - Loading content of the action state from file. - - - - - test the particles are coming from. Returns true if has been set successfully The can be rejected if it is not a real test (doesn't have interface). - - - - - actionList for particles to come to. Returns true if has been set successfully. The can be rejected if it is not a real actionList (doesn't have interface). - - - - - For internal use. - - - - - For internal use. - - - - - For internal use. - - - - - Proceed a single particle with the given index to the given time. If pCont is NULL then the method works with previously given container. It will expedite the call since the method won't acquire particle channels from the container but uses the previously acquired channels. When working with individual particles from the same container, a good practice is to make the call for the first particle with the container specified, and then for all other particles with the container set to NULL. - - - true if the operation has been proceeded successfully. - - the particleContainer - the time for particles to come to; each particle may have its own current valid time; the parameter sets the time for all particles to synchronize to - the index of the particle to proceed - - - - Proceed all particles in the container to the given time - - - - - the particleContainer - the time for particles to come to; each particle may have its own current valid time; the parameter sets the time for all particles to synchronize to - - - - Proceed all particles in the container to the given times (may be different for each particle). - - - - the particleContainer - time value for a particle to come to; particles may have different time values to come to - - - - Proceed selected particles only to the given time. - - - - the particleContainer - the time for particles to come to; each particle may have its own current valid time; the parameter sets the time for all particles to synchronize to - bitArray to define which particles to proceed - - - - Proceed selected particles only to the given times (maybe different for each particle) - - - - the particleContainer - time value for a particle to come to; particles may have different time values to come to - bitArray to define which particles to proceed - - - - "function-publishing" hook-up for the methods above - - - - particleContainer - time for particles to come to. All particles may have the same time value to come to, in that case the method with timeTick and timeFraction have to used. Sum of timeTick and timeFraction define the exact time value (without TimeValue granularity). If particles have different time values to come to than use the second method with Tabs of timeTicks and timeFractions - if only part of particles need to be time-advanced then isSelected is true, and "selected" have to be defined - - - - "function-publishing" hook-up for the methods above - - - - particleContainer - time for particles to come to. All particles may have the same time value to come to, in that case the method with timeTick and timeFraction have to used. Sum of timeTick and timeFraction define the exact time value (without TimeValue granularity). If particles have different time values to come to than use the second method with Tabs of timeTicks and timeFractions - if only part of particles need to be time-advanced then isSelected is true, and "selected" have to be defined - - - - An integrator may rely on another integrator to calculation some particle proceedings. For example, a Collision test has interface to proceed particles according to collision approximations. At the same time a Collision test doesn't proceed angular velocity of a particle. For that the test relies on encapsulated standard integrator. - - - - - Check if the current integrator has the given integrator encapsulated inside the encapsulated integrator can be more than one level down. - - - - - Returns true if the operation has been proceeded successfully. Methods' signatures are presented in two forms: one is compact, and the other one is for function-publishing where is presented as a pair (int,float). - - - - particleContainer - the time for particle to start from the simulation. Each particle may have its own current valid time greater than timeStart. In this case the operator should consider the current particle time and timeEnd parameter. Some operators (like Birth) may not consider current particle time since it works with timeStart and timeEnd parameters only. - the time for particles to come to; each particle may have its own current valid time; the parameter sets the time for all particles to synchronize to. If current particle time is greater than timeEnd it means that the particle doesn't require processing at all; the particle has been already updated beyond the interval ]timeStart, timeEnd] of the current operator. Sometimes the operator may not be able to proceed all the particles to the given timeEnd. In this case the operator proceeds the particles as far as possible and set the parameter to the time achieved. All the following operators will be given the new timeEnd value as a time value for particles to come to, and the particle system will run another round of operator stack modification in the attempt to proceed all the particles to the initially set time. - the particle system that generates the particle stream; the same operator may get calls from different particle systems; if the result varies according to the particle system that generates particles, then this parameter is useful. - of the particle system that generates the particles. - of the operator (if any; can be NULL) - an operator to proceed particles according to "inertia" rules. The operator updates time, speed, position, spin, orientation channels on the basis of time, acceleration, speed, angular acceleration and spin channels. Each particle system has a default inertia operator. When an operator want to update current time for particles, it uses the "inertia" operator. An Action in the ActionList stack my "switch" the suggested "inertia" operator by its own if the Action support the "inertial" operator interface. The particle system recognizes such an Action as a holder of "inertia" interface, and use it for "inertia" purposes later on. If the parameter is NULL then the particle system doesn't allow the operator to advance particles in the time channel. - - - - "function publishing" alternative for the method above - - - - - Three methods apply the Proceed method as a pre-procedure before the regular proceed for all operators starts. It is not recommended to modify particle container. The call is mostly used to give an operator opportunity to snapshot the state of particle container before any operator modifies it. The Proceed method is called in between PretProceedBegin and PreProceedEnd methods if HasPreProceed method returns "true". Those methods are not supported in MaxScript intentionally. - - - - - See virtual bool HasPreProceed(}. - - - - - See virtual bool HasPreProceed(}. - - - - - Three methods apply the Proceed method as a post procedure when the amount of particles in all particle groups has been established and there won't be any particle transfers from one particle group to another. The Proceed method is called again in between PostProceedBegin and PostProceedEnd methods if HasPostProceed method returns "true". Since the post proceed methods are applied after everything has established, it is applied to a "time" moment, not [timeStart, timeEnt] interval. The Proceed method is called with the same value for timeStart and timeEnd. Those methods are not supported in MaxScript intentionally. - - - - - See virtual bool HasPostProceed(}. - - - - - See virtual bool HasPostProceed(}. - - - - - The following methods are redirected from the particle object level to a particular ActionList. The first parameter is a particle container of the ActionList. Returns 0 if the action doesn't render in all frames for any reason, for example a non-animated parameter prevents render. - - - - - If an object creates different meshes depending on the particular instance (view-dependent) it should return 1. - - - - particle container to render particles from - primary particle system shell - - - - GetRenderMesh should be implemented by all renderable GeomObjects. needDelete to TRUE if the render should delete the mesh, FALSE otherwise. Primitives that already have a mesh cached can just return a pointer to it (and set needDelete = FALSE). - - - - particle container to render particles from - current frame to render particles at. It's supposed that the container has been already updated to satisfy this moment - primary particle system shell - of the particle group - as of the method - boolean as of the method - - - - Objects may now supply multiple render meshes. If this function returns a positive number, then GetMultipleRenderMesh and GetMultipleRenderMeshTM will be called for each mesh, instead of calling GetRenderMesh. - - - - particle container to render particles from - current frame to render particles at. It's supposed that the container has been already updated to satisfy this moment - primary particle system shell - - - - For multiple render meshes, this method must be implemented. needDelete to TRUE if the render should delete the mesh, FALSE otherwise. meshNumber specifies which of the multiplie meshes is being asked for. - - - - particle container to render particles from - current frame to render particles at. It's supposed that the container has been already updated to satisfy this moment - primary particle system shell - of the particle group - as of the method - boolean as of the method - specifies which of the multiplie meshes is being asked for - - - - For multiple render meshes, this method must be implemented. meshTM should be returned with the transform defining the offset of the particular mesh in object space. meshTMValid should contain the validity interval of meshTM. - - - - particle container to render particles from - current frame to render particles at. It's supposed that the container has been already updated to satisfy this moment - primary particle system shell - of the particle group - as of the method - specifies which of the multiplie meshes is being asked for - - - - - - If this returns NULL, then GetRenderMesh will be called. - - - - particle container to render particles from - current frame to render particles at. It's supposed that the container has been already updated to satisfy this moment - primary particle system shell - of the particle group - as of the method - boolean as of the method - - - - This method allows objects to specify the class that is the best class to convert to when the user collapses the stack. - - - The of the preferred object type. - - particle container - primary particle system shell - - - - Returns TRUE if this object can do displacement mapping; otherwise FALSE. - - - - particle container - primary particle system shell - - - - Returns multiplier coefficient to generate particles. 1.0f means that an operator produces particles at 100% rate. 0.5f means that an operator produces only half of particles that it supposed to be generating, i.e. if a Birth operator is set to produce 1000 particles total, then under multiplier = 0.5f the operator produces only 500 particles. - - - - - Returns number of particles allowed to be generated at current time. Particle system has an upper limit of a total number of particles in the system. At each moment of time particle system is able to calculate the current number of particle in the system and how many particles are allowed to be generated to not exceed the limit threshold. Birth and Spawn Operators use this method to find out how many particles they are allowed to generate. - - - - - PF System has an icon that can be used as an emitter for particles. For Operators to use the icon as an emitter the following five methods should be supported. If PF System doesn't support emitter icon then it returns "false" in the first method. The default implementation of the following five methods is if PF System doesn't support icon emission. - - - - - Returns spacial dimensions of the emitter icon. It may have less or more than three as emitter type requires. For example, sphere emitter type has only one dimension. - - - - - Returns emitter geometry in form of mesh. - - - - - If the emitter mesh is geometry-animated, return "true" in the following method. - - - - - PF System has two states: render and viewport. At any given moment PF System is exclusively in one state or the other. PF System may have different parameters during render and viewport (i.e. Multiplier value, or emitter geometry etc.) therefore it's important to know what state the PF System is in. It's also possible to alterate the state of PF System. PF System alterates its state automatically when the rendering starts and when the rendering ends. - - - - - Works with SetRenderState. - - - - - PF System has an integration step parameter that defines granularity in proceeding particles in time. An PF System may have different integration steps for viewports and for render. - - - - - PF system has different modes for update. Forward mode: particles aren't updated right away. At playback time the particle history is not recalculated. Only new events that will happen with the particles have new settings Complete mode: the whole particle animation is recalculated. - - - - - PF system may select sub-components. There are two types of sub-components: particles and action lists. Returns amount of selected particles. - - - - - Returns born ID of the i-th selected particle. - - - - - Verifies if a particle with the given born ID is selected or not. - - - - - Returns amount of selected action lists. - - - - - Returns node of the i-th selected action list. - - - - - Verifies if an action list is selected or not. - - - - - Returns true if the particle system is in the process of runnint Every Step or Final Step scripts. - - - - - For internal use. - - - - - Works with IsCopyClone. - - - - - returns number of PFSystems in the current scene - - - - - Returns i-th PFSystem in the scene. - - - - PFSystem index - - - - Checks if the given PFSystem node is present in the scene. - - - - PFSystem node - - - - Check if the scene has a PFSystem with the given node handle. - - - - - Register notification with the PFSystem pool. The given function is called each time the set of all PFSystems is changing. Returns nonzero if the event was registered; otherwise zero. - - - - The callback function called when the event occurs. - A pointer that is passed to the callback function when the notification is made. - - - - Unregister notification with the PFSystem pool. This function is called to break the connection between the event and the callback. After this function executes the callback is no longer invoked when the event occurs. Returns nonzero if the event was unregistered; otherwise zero. - - - - The callback function called when the event occurs. - A pointer that is passed to the callback function when the notification is made. - - - - Returns true if the test has been proceeded successfully. Verifies the test condition and may change particle channels; particle (that satisfy the condition) may be advanced to the time of the condition satisfaction according to the inertia operator "integrator". If ptr to the integrator is set to NULL then particles are not advanced in time. - - - - the particle container. - the time for a particle to start the simulation. Each particle may have its own current valid time greater than timeStart. In this case the test should consider the current particle time and timeEnd parameter. - the time for particles to come to; each particle may have its own current valid time; the parameter sets the time for all particles to synchronize to. Sometimes the test may not be able to proceed all the particles to the given timeEnd. In this case the operator proceeds the particles as far as possible and set the parameter to the time achieved. All the following actions will be given the new timeEnd value as a time value for particles to come to, and the particle system will run another round of action stack modification in the attempt to proceed all the particles to the initially set time. - the particle system that generates the particle stream; the same operator may get calls from different particle systems; if the result varies according to the particle system that generates particles, then this parameter is useful - of the particle system that generates the particles. - of the test - an operator to proceed particles according to "inertia" rules. The operator updates time, speed, position, spin, orientation channels on the basis of time, acceleration, speed, angular acceleration and spin channels. Each particle system has a default inertia operator. When an action want to update current time for particles, it uses the "inertia" operator. An Action in the ActionList stack my "switch" the suggested "inertia" operator by its own if the Action support the "inertial" operator interface. The particle system recognizes such an Action as a holder of "inertia" interface, and use it for "inertia" purposes later on. If the parameter is NULL then the particle system doesn't allow the test to advance particles in the time channel - a bit array to indicate which particles satisfy the test condition - for particles that satisfy the condition, the list of time moments when a particle satisfies the condifion. The tab has the same number of entry as particles in the container. Only for particles that satisfy the condition the entry is set. - - - - FnPub alternative to virtual bool Proceed() above. FnPub doesn't allow having more than 7 parameters; therefore the method consists of two parts. The methods should be called successively: Step1 and then Step2. - - - - - FnPub alternative to virtual bool Proceed() above. FnPub doesn't allow having more than 7 parameters; therefore the method consists of two parts. The methods should be called successively: Step1 and then Step2. - - - - - Gets of the next ActionList. If particle satisfies the test then it is directed to this ActionList. Since a test may have several instances with different next events, it is necessary to define the the method returns activity status of the link to the next ActionList. - - - - - Modifies the next ActionList for the test. Returns true if the next actionList has been set successfully. The nextAL node can be rejected if it is not real actionList. - - - - - FnPub alternative for the method above; used by maxscript to set the next action list. - - - - - Modifies activity status for the link to the next ActionList. Returns true if the modification has been done successfully. - - - - - Deletes the wire going to the nextActionList for the test. Returns true if the wire was deleted successfully. The test node can be rejected if it is not a real test action. - - - - - for internal use only - - - - - for internal use only - - - - - for internal use only - - - - - for internal use only - - - - - The following methods are redirected from the particle object level to a particular ActionList. The first parameter is a particle container of the ActionList. - - - - particle container to draw particles from - current frame to draw particles at. It's supposed that the container has been already updated to satisfy this moment - particle system that makes the call - of the particle system. - of particle group. Particle system may have several particle groups according to number of ActionLists - viewport as of the (...) method - flags as of the (...) method - - - - See virtual int Display() - - - - - See virtual int Display() - - - - - See virtual int Display() - - - - - See virtual int Display() - - - - - See virtual int Display() - - - - - This interface is used for extending with an additional method UpdateDisplay(). This provides a default implementation of the virtual function MaxSDK::Graphics::IObjectDisplay::UpdateDisplay(). - - - - - virtual int PrepareDisplay(IObject* pCont, TimeValue time, Object* pSystem, INode* psNode, INode* pgNode, ViewExp *vpt, int flags); This provides a default implementation of the virtual function MaxSDK::Graphics::IObjectDisplay::UpdateDisplay(). - - context used for prepare render items. - - - - Generate render items for current particle node. - - context for generated render items - The display context, which contains all the requirements for the plugin to generate render items. - Contains all information required for adding per node relevant render items. - - The target render item container to which this plugin object will be added. - particle container to draw particles from - particle system that makes the call - of the particle system. - - - - Implement if you want your operator/test to be shown with a custom icon in ParticleView. - - - - - Defines whether the custom icons in Particle have alpha channels. It is not possible for any specific PFlow action/operator/test to have some icons with alpha, and some without. If the method returns true, then the PFlow action/operator/test has to implement all PViewIcon related methods below and return a 32-bit HBITMAP with alpha channel. - - - - - Implement if you want your operator/test to be shown with a custom icon in ParticleView. For operator/test when in active state. - - - - - Implement if you want your operator/test to be shown with a custom icon in ParticleView. For operator when in disabled state. - - - - - Implement if you want your operator/test to be shown with a custom icon in ParticleView. For test when in "always true" state. - - - - - Implement if you want your operator/test to be shown with a custom icon in ParticleView. For test when in "always false" state. - - - - - An operator may have a color swatch UI (color circle on the right side) if it can be used to display particles in viewport. The method is used for the case when the color swatch is variable: visibility of the swatch depends on the parameters of the operator. The typical case is 'mP Shape' operator where the particle collision shape is used for debugging purposes only. The operators Display, Display , Display Data don't implement this method since they always show their color swatch. - - - - - Used to track instanced actions. An action may have several instances, which PView shows in italic font. - - - - - Used to track instanced actions. An action may have several instances, which PView shows in italic font. - - - - - A PView item can have comments. Comments are also shown and edited via right-click above the PView item. - - - - - See HasComments(). - - - - - See HasComments(). - - - - - See HasComments(). - - - - - For dynamic names support; if the action has a dynamic name then it supplies the name suffix. - - - - - A PView item may have its own creation routine. If so, then the item is given an opportunity to create itself when the item is created in Pview. sourceNodes is a list of anchor nodes for PViews, showNodes is a list of all additional nodes that are added to PView to show. - - - - - Opens ParticleView for a given PFEngine. If there are several ParticleViews with the given PFEngine, a dialog pops up to make a choice. - - - - PFEngine to open particle view for - - - - If nothing was delete from PView then additionsOnly is set to true. - - - - - If procedures between Pre.. and Post.. involve additions of new items only then set "additionsOnly" to "true". The rollup panel won't be updated. - - - - - If procedures between Pre.. and Post.. involve additions of new items only then set "additionsOnly" to "true". The rollup panel won't be updated. - - - - - Not supported for maxscript. - - - - - Return true when in between PreUpdate and PostUpdate. - - - - - Updates particle amount shown in PViews. - - - - - Shows that an action starts the proceed. - - - - - Shows that an action ends the proceed. - - - - - Check if any ParticleView is a foreground window. - - - - - Used for CUI shortcuts. - - - - - Used for CUI shortcuts. - - - - - Returns X coordinate of half-plane of space free from any PF item. The method is usually used to calculate (x,y) location of newly created PF systems. - - - - - The method is used to prevent automatic removal of non-used materials from the scene. The method is used by Shape Instance operator. The operator creates combined materials on-the-fly to be assigned to particles. When the reference object for the operator is changed, the material is changed. The old material could be deleted because it doesn't have any more references in the scene. This may create a problem for undo/redo operations. To prevent that this method creates a reference dependency between PViewManager and the . Since PViewManager is not saved with the scene, the materials won't be saved either. - - - - - Description: - This abstract class represents an interface for quad menu settings. The methods contained in this class allow you to access and control all quad menu related settings and configuration parameters. - - - - - This method returns the index of the first quad which will be displayed. - The quad index, one of the following; QUAD_ONE, QUAD_TWO, QUAD_THREE, or QUAD_FOUR. - - - - - This method returns the status of the uniform width flag for the quad menu. TRUE if the quad menu has been set to use uniform width, otherwise FALSE. - - - - - This method returns the status of the uniform width flag for the quad menu. TRUE if the quad menu has been set to use uniform width, otherwise FALSE. This version of GetUseUniformQuadWidth() is provided for the function publishing system. - - - - - This method returns TRUE if the cursor moves when the quad menu is repositioned because of clipping the edge of the screen, otherwise FALSE. - - - - - This method returns TRUE if the cursor moves when the quad menu is repositioned because of clipping the edge of the screen, otherwise FALSE. This version of GetMoveCursorOnReposition() is provided for the function publishing system. - - - - - This method returns TRUE if the cursor is moved the opposite distance that it was automatically moved when the quad menu is repositioned because of clipping the edge of the screen, otherwise FALSE. - - - - - This method returns TRUE if the cursor is moved the opposite distance that it was automatically moved when the quad menu is repositioned because of clipping the edge of the screen, otherwise FALSE. This version of GetReturnCursorAfterReposition() is provided for the function publishing system. - - - - - This method allows you to set the initial location of the cursor in the center quad box. - Parameters: - float x, float y - - The location of the cursor, as a ratio of the box size, between 0.0 and 1.0. - - - - - This method returns the initial x location of the cursor in the center quad box, as a ratio of the box size, between 0.0 and 1.0. - - - - - This method returns the initial y location of the cursor in the center quad box, as a ratio of the box size, between 0.0 and 1.0. - - - - - This method returns the color array for a specific quad. - Parameters: - int quadNum - - The quad to obtain the color array for, (numbered 1 through 4). - - - - - This method allows you to set the title bar background color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the title bar background color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the title bar background color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the title bar text color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the title bar text color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the title bar text color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the item background color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the item background color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the item background color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the item text color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the item text color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the item text color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the last executed item text color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the last executed item text color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the last executed item text color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the highlighted item background color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the highlighted item background color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the highlighted item background color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the highlighted item text color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the highlighted item text color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the highlighted item text color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the border color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the border color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the border color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the disabled shadow color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the disabled shadow color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the disabled shadow color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method allows you to set the disabled highlight color for a specific quad. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - & color - - The color to set. - - - - - This method returns the disabled highlight color of a specific quad. This method returns the color as a . - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - This method returns the disabled highlight color of a specific quad. This method returns the color as a COLORREF. - Parameters: - int quadNum - - The quad (numbered 1 through 4). - - - - - Description: - This class is only available in release 5 or later. - - This class provides additional functionality for class . To use this functionality with a class, derive the class from both and , and implement RadiosityEffect::GetInterface() to return a pointer to this interface on request. - - Given an instance of , you may retrieve the extension interface as follows: - - IRadiosityEffectExtension* r = static_cast<IRadiosityEffectExtension*>(radiosityInstance->GetInterface(IRADIOSITYEFFECT_EXTENSION_INTERFACE)); - - If the result is NULL, the does not support this interface. - - All methods of this class are virtual. - - - - - - - Returns whether the specified default light should be used by the scanline renderer. - - - The scanline renderer normally creates default lights when there are no lights in the scene. A radiosity plug-in could override this if it uses objects other than lights as light sources (e.g. self-emitting surfaces) - Returns whether or not the scanline renderer should use the light for the current rendering. - - - A default light created by the scanline renderer when it begins rendering. - - Indicates whether the solution will be re-calculated (ie, there is a glowing object that will create the solution). - - - - Returns whether the the radiosity plugin is interested in any. - - - of the channels in the part id. plug-in. It allows the to tell the system which messages will not invalidate the lighting solution. - - If the decides that all messages of a given PartID are irrelevant to the lighting solution, it can return false when that PartID flag is present in the input parameter (and no other, more relevant, PartID flags are present). Otherwise it should return true, indicating it needs those messages. - - If the return value is false, the system will add the PartID flag PART_EXCLUDE_RADIOSITY to all appropriate reference messages; this flag generically indicates an event which should not invalidate a radiosity solution. The will still receive the message but can ignore it. Other modules which need to discriminate messages pertinent radiosity, can also check this flag. - - As an example of when this is important, an edit mesh modifier may send change messages which are meant to flush internal caches but not relevant to radiosity. As the message propagates, some PartID flags are added in order to force modifiers to re-evaluate downstream in the stack. This may confuse the radiosity engine into invalidating its lighting solution. But the edit mesh ensures the original message bears the PART_EXCLUDE_RADIOSITY flag, and as subsequent messages inherit the flag, the can correctly ignore the message. - Whether or not to filter the given messages, by setting their PART_EXCLUDE_RADIOSITY PartID flag. - - - One or more PartID flags defining the category of messages to be filtered. - - - - Description: - This class is only available in release 5 or later. - - This class defines the interface for accessing the Advanced Lighting Preferences from the 'Advanced Lighting' tab in the preferences dialog. It also provides access to the use/compute advanced lighting controls found in the Rendering dialog. This is a function-published static interface; you can use GetCOREInterface() to obtain an instance of the class, as follows: - - IRadiosityPreferences* r = static_cast<IRadiosityPreferences*>(GetCOREInterface(IRADIOSITYPREFERENCES_INTERFACE)); - - This interface is also accessible via MAXScript as "<b>RadiosityPreferences</b>". - - All methods of this class are implemented by the system. - - - - - - - Returns the state of the checkbox "Automatically Process RefineIterations Stored in Geometric Objects", in the preferences dialog Advanced Lighting tab - - - - - Returns the state of the checkbox "Display Reflectance \&Transmittance Information", in the preferences dialog Advanced Lighting tab - - - - - - - Returns the state of the checkbox "Display Radiosity inViewports", in the preferences dialog Advanced Lighting tab - - - - - - - Returns the state of the checkbox "Display Reset Warning", in the preferences dialog Advanced Lighting tab - - - - - - - Returns the state of the checkbox "Save Scene Information inMAX File", in the preferences dialog Advanced Lighting tab - - - - - - - The functions below provide access to current radiosity settings. These properties are saved on a per file basis, so they are not written into the .ini file. the render dialog - - - - - - - Returns the state of the "Compute Advanced Lighting whenRequired" checkbox in the render dialog - - - - - - - Description: - This interface groups reference hierarchy related methods. - - The global method GetRefHierarchyInterface()IRefHierarchy* will return a pointer to the reference hierarchy interface class. - - - - - This method can be used to find out if an object is instanced (instanced pipeline). It Checks if the Derived is instanced. If it is, the pipeline part below and including that derived object is instanced.If the argument is NULL, returns FALSE - Parameters: - ReferenceTarget* refTarget - - A pointer to a reference target to check for instantiation. - TRUE if the reference target is instanced, otherwise FALSE. - - - - - Container that handles references to ReferenceTargets. - - - This is the interface for a container that references a variable number of objects. - 3ds Max's implementation of this interface persists itself and its operations support being undone/redone. Plugins that need to store a variable number of references to other plugin objects should create an instance of this container type and make a reference to it. - The code below shows how to create an instance of 3ds Max's implementation of this interface: - Or, you can create an instance via the static IRefTargContainer::CreateInstance() method. - When this container points to a and that is deleted, the corresponding reference slot is nulled out, but not deleted. Therefore the number of items reported by NumRefs() and GetNumItems()) will not shrink. For example: If ten ReferenceTargets are added to the container, and then each is deleted, the container will still report ten references. The only way to shrink the count of the real number of references used is to call RemoveItem(). - A REFMSG_CONTAINER_ELEMENT_NULLED notification is sent to the immediate dependents of the instance when a stored in the container is deleted. A REFMSG_CONTAINER_ELEMENT_ADDED notification is sent to the immediate dependents of the instance when an item slot is added. A REFMSG_CONTAINER_ELEMENT_REMOVED notification is sent to the immediate dependents of the instance when an item slot is removed. A REFMSG_CONTAINER_ELEMENT_SET notification is sent to the immediate dependents of the instance when an item slot is set. When processing notifications, the GetChangedRefTarget() method can be used to identify which item triggered the notification, and GetChangedRefTargetIndex() which item index. - - - - - Returns the number of items in the container. - - - The number of items in the container. - - - - - Returns the i-th item, NULL if i is out of range. - - - The i-th item, or NULL if index is out of range. - - The index of the item to return. Must be in range [0, -1] - - - - Adds an item at the end of the container. - - - The index of the newly added item. - - The item to be added - - - - Sets the value of the i-th container item. Can be used to append more than one item to the container at a time. For example: It is possible to call this method on an empty container, passing in an integer value of, say 10. After doing this, the container will return 11 from the GetNumItems() and NumRefs() method. - - - - - The index of the item to set. Must be >= 0. If i is greater than or equal to the current number of items, the container will be resized, with NULL items added as necessary. - - The item to set as the i-th item. - - - - Inserts specified item at i-th place into the container. - - - Index where the item has been inserted. - - - The index where the item should be inserted. Must be in range [0, ], otherwise i is truncated to fit in this range. When i is , the item is appended to the end of the container. - - The item to be inserted. - - - - Removes the i-th item from the container. - - - De-references the i-th item and removes it from the container, thus effectively changing the number of items the container reports to have via GetNumItems(). - When removing more than one item from the container, iterate from high index to low index. - - - The index of the item to be removed. Must be in range [0, -1]. - - - - Finds the first occurrence of a given reference target in the container. - - - - - Returns whether the references are held as weak references. - - - - - - - When a NotifyRefChanged is received from an IRefContainer, this method can be called to retrieve the index of the item that generated the notification. - - - The value returned by this method is valid only while processing notifications from the - - - - - When a NotifyRefChanged is received from an IRefContainer, this method can be called to retrieve the item that generated the notification. - - - The value returned by this method is valid only while processing notifications from the - - - - - The interface for an owner of a class. - - - The owner of a instance must implement this interface. Messages from the instance are passed to the owner through this interface. - - - - - Calls to the instance's NotifyRefChanged method are passed to its owner through this method. - - - The owner is responsible for ensuring that an infinite recursion of message passing does not occur. Typically the owner would set a flag while propogating a message, and not propogate a new message if that flag is set. - Since the owner doesn't hold a reference to the 's watched object, the watched object may not be saved or loaded when the owner is saved or loaded. The owner must handle this case. Typically, the owner would also derive from , which will result in the watched object being saved and loaded. For an example, see the NodeTransformMonitor class in maxsdk\samples\controllers\nodetransformmonitor.cpp. - The arguments to this method, other than fromMonitoredTarget, correspond to the arguments of ReferenceMaker::NotifyRefChanged. - Typically REF_SUCCEED indicating the message was processed. - - - This is the interval of time over which the message is active. - - This is the handle of the reference target the message was sent by. - - This contains information specific to the message passed in. - - The message which needs to be handled. - - true if message originated from 's monitored target. - - If called through , the value of 'propagate' passed to it. Used if calling NotifyDependents() from within NotifyRefChanged(). - - The instance making this call. May be needed if multiple instances reference the monitored target. - - - - Calls to the instance's DoEnumDependents method are passed to its owner through this method. - - - The owner is responsible for ensuring that an infinite recursion does not occur. Typically the owner would set a flag while enumerating dependents, and not start a new enumeration if that flag is set. - 1 to stop the enumeration and 0 to continue. - - - the . - - - - The interface for working with RefTargMonitor class. - - - The RefTargMonitor class (defined in ctrl.dlc) is used to monitor a RefTarg for its - REFMSG_TARGET_DELETED messages. The RefTargMonitor class creates a instance pointing at a RefTarg, and allows only the REFMSG_TARGET_DELETED message to propagate to the RefTargMonitor's dependents. To prevent circular message loops, the messages are not propagated if that message type is already being propagated. - - - - - Retrieves the RefTarg being watched. - - - The RefTarg being watched. - - - - - Retrieves whether to force persistence of the target on partial load/save. - - - True if force persistence in on. - - - - - An interface for ReferenceTargets that wrap ReferenceTargets, where the wrapping provides UI/storage on top of the wrapped . - - - - - Returns the wrapped . - - - The wrapped . - - - If true, the implementation should check to see if the wrapped derives from , and if so recurse into that object. - - - - This class represents the interface for the Render Effects Manager. It enables the aggregation of several Effects where a single Effect* may be passed, most notably RendParams::effect. A pointer to this class may be obtained through a dynamic cast from an Effect*, most notably RendParams::effect. - - - - - Returns number of Render Effects in manager's list. - - - - - Returns pointer to a specific Render in manager's list. - The indexed Render , NULL if invalid index - - - The index of the Render in the manager's list. - - - - Replaces a Render in the manager's list. - - - The index of the Render in the manager's list. - - The Render to place in the manager's list. - - - - Adds a Render to the manager's list. - - - The Render to place in the manager's list. - - - - Returns TRUE if any Render in the manager's list is active. - - - - - Removes a Render in the manager's list - - - The index of the Render in the manager's list. - - - - Called by system to prepare the manager for rendering. Used internally. - - - - - Temporarily disables Render Effects. This only disables functionality implemented via Effect::Apply(). Called by system when rendering multipass effects. - - - - - Re-enable Render Effects disabled via Disable(). - - - - - Description: - This is the interface that must be supported by all render elements whether they support the 3ds Max renderer or some other renderer. The UI in the render dialog uses this interface exclusively to control the element. - - The methods are almost all state-setting methods, with ones that are settable by the UI provided by both sets and gets. A sample plugin of a Render Element can be found in the SDK samples; /MAXSDK/SAMPLES/RENDER/RENDERELEMENTS. - - - - - This method enables or disables the Render Element. - Parameters: - BOOL enabled - - to TRUE in order to enable the Render Element. FALSE to disable it. - - - - - This method returns TRUE if the Render Element is enabled, otherwise FALSE. - - - - - Each active render element has the option of either using the current AA filter or simple blending within the pixel. This method will set the internal filter enable to the value of parameter filterEnabled. - Parameters: - BOOL filterEnabled - - to TRUE in order to enable. FALSE to disable it. - - - - - This method returns the current state of whether the AA filter is enabled. - Parameters: - This method returns TRUE if filters for the Render Element are enabled, otherwise FALSE. - - - - - This method returns whether this element type should be blended during multipass effects. - - When multipass camera effects such as depth of field are used in a rendering, each of the separate elements may be blended into a final bitmap like the composite color, or they may be "frozen" after the first pass. Blending is not appropriate for some elements, like z-depth. This is typically a query only, it is unlikely that this will need to be turned on & off. - TRUE if blending during multipass effects, otherwise FALSE. - - - - - This method returns TRUE if atmospheric effects for the Render Element are enabled, otherwise FALSE. - - - - - This method returns TRUE if shadows for the Render Element are enabled, otherwise FALSE. - - - - - This method returns a string representing the Render Element's name as it appears in the render dialog. - - - - - This method allows you to set the bitmapinfo/bitmap to use for the Render Element. - - Each render element has an output bitmap. We use the pb2 style bitmap as it contains the pathname as well as the bitmap & bitmapInfo structures needed by windows. The bitmap is created by the render element manager, then held by the element until it's not needed. These are the calls that set & get the elements bitmap. - Parameters: - PBBitmap* &pPBBitmap - - The pointer to the reference. - - - - - This method allows you to get the bitmapinfo/bitmap that is used for the Render Element. - Parameters: - PBBitmap* &pPBBitmap - - The pointer to the reference which was retrieved. - - - - - Description: - This class represents the interface for the Render Element Manager. A sample plugin of a Render Element can be found in the SDK samples; /MAXSDK/SAMPLES/RENDER/RENDERELEMENTS. - - - - - This method gets called by the system to add a Render Element when it is merged from another file. - Parameters: - *pRenderElement - - A pointer to the Render Element to add. - TRUE if the merging was successful, FALSE if it was not. - - - - - This method gets called by the system to add a Render Element when it is merged from another file and ensures that the Reference Target is a Render Element. - Parameters: - *pRenderElement - - A pointer to the Render Element to add. - TRUE if the merging was successful, FALSE if it was not. - - - - - This method adds an instance to the manager's list. - Parameters: - *pRenderElement - - A pointer to the Render Element to add. - TRUE if the addition was successful, FALSE if it was not. - - - - - This method adds an instance to the manager's list and ensures that the Reference Target is a Render Element. - Parameters: - *pRenderElement - - A pointer to the Render Element to add. - TRUE if the addition was successful, FALSE if it was not. - - - - - This method removes an instance from the manager's list and ensures that the Reference Target is a Render Element. - Parameters: - *pRenderElement - - A pointer to the Render Element to remove. - TRUE if the addition was successful, FALSE if it was not. - - - - - This method will remove all the instances from the manager's list. - - - - - This method returns the number of Render Elements contained in the manager's list. - - - - - This method returns a pointer to a specific Render Element in manager's list. - Parameters: - int index - - The index of the Render Element in the manager's list. - A pointer to the specific Render Element or NULL if the index is invalid. - - - - - This method checks if the Render Elements List is active during a render and will return TRUE if it is or FALSE if it is not. - - - - - This method checks whether the Render Elements are displayed in their own (VFB) viewer window and will return TRUE if they are or FALSE if they are not. - - - - - This method is used to know if the renderer has the given requirement. - - - - true if the renderer has the given requirement, false otherwise. - - - The requirement to be looked for in the renderer. - - - - Maintains a Dx version of the current mesh in the cache. It will render either the 3ds Max mesh or a screen aligned quad. - - - - - Defines what the mesh represents. - - - - specify whether it is a mesh or a full screen quad - - - - Used to update the Quad version of the mesh. - - - TRUE if successful - - A Pointer to the main DX interface - The width of the render target - The height of the render target - The width of the texture being used - The height of the texture being used - - - - Setting the node parameter to non NULL, will make sure the Normals are transformed correctly. - - - TRUE if successful - - A Pointer to the main DX interface - The mesh whose data is to be extracted - The material index for the faces to be rendered. This provides support for multi subobject materials - Used to determine if negative scale is being used on the object. - - - - Store relevant mapping data. - - - Allows the app to provide up to 8 mapping channels, this is used to extract the texcoord data from the mesh - - A tab of active mapping channels - - - - Renders the current object. - - - TRUE if successful - - A Pointer to the main DX interface - - - - force an invalidation of the internal data structures - - - - - Get the current Vertex format for the mesh. - - - This retrieves the current active vertex format for the mesh. The return value will be false if DirectX9 is running or true and an itemCount >0 if DirectX 10 is running. - TRUE if successful. In Dx9 and 3ds Max 9 this will be false. - - A pointer to vertex descriptor - this will be different for Dx9 and Dx10 - The number of items in the vertex descriptor - - - - This class maintains a list of the meshes and RenderMeshes used per instance. It acts as a factory class. - - - This is useful for Materials where a single material could be applied to multiple nodes, so a cache is needed so the material can pull the correct mesh data - - - - - the type of the mesh cache to maintain;. - - - - the type of object to hold. This can be either a mesh or a quad. - - - - Fill up the cache with data from 3ds Max. - - - This method needs to be called when the node has actually changed. In 3ds Max 8 and before you could call this method at any time and the method would attempt to cache and maintain the data. However this would not work correctly with a type object. Now the method expects to only update itself when the object changes. This is easily achieved by only calling this method when IStdDualVSCallback::InitValid() is called. To simply get the cache position for the node you can call this method with a NULL mnMesh pointer. - The position in the cache of the mesh/node combo - - The to store in the cache. If this is NULL the system will return the cache entry only - The node to store in the cache - The time to use in any evaluations - If the mesh is different to that in the cache, this specifies the case. - - - - Fill up the cache with data from 3ds Max. - - - This method needs to be called when the node has actually changed. In 3ds Max 8 and before you could call this method at any time and the method would attempt to cache and maintain the data. However this would not work correctly with a type object. Now the method expects to only update itself when the object changes. This is easily achieved by only calling this method when IStdDualVSCallback::InitValid() is called. To simply get the cache position for the node you can call this method with a NULL mesh pointer. - The position in the cache of the mesh/node combo - - The mesh to store in the cache. If this is NULL the system will return the cache entry only - The node to store in the cache - The time to use in any evaluations - If the mesh is different to that in the cache, this specifies the case. - - - - Get the number of cached mesh. - - - The number of cached mesh - - - - - Get the active render mesh. - - - The based on the index provided - - The index of the mesh to retrieve - - - - The for the current cache - - Get the node for the current cached object - - - - The for the current cache - - Get the mesh for the current cached object - - - - Used to release any data stored by the cache. - - - - - Used to delete the cache for a specific node. - - - - - An interface to manage the renderer messages (error, warning, progress, etc.). - - - Clients log messages to this manager, and the manager will automatically dispatch the messages - to the message window, or to Max log system (if Max is running in quiet mode or network rendering is taking place). - - A pointer to this interface may be retrieved using GetRenderMessageManager(). - - - - - Open the message window. - - - True if the window is opened successfully, false otherwise. - - - - - Clear all the displayed messages on the message window. - - - - - Destroy the message window. - - - - - Make the message window invisible. - - - - - Log a message to the manager. - - - This function is thread-safe. Message manager caches incoming messages to a queue and returns immediately. Then from main thread it regularly flushes the pending messages to either the message window, or Max log system, depending on if Max is running in "window" mode. - The difference between msgType and systemLogType is particularly important when reporting errors. A msgType of kType_Error will cause the message to be shown red in the render message window, while a systemLogType of SYSLOG_ERROR will cause a network render to abort (if the system is set to abort on errors). Both types should not necessarily be set identically! For example, an error in scene translation (say, a material not supported by the renderer) could be reported as an error to the user, but would most likely by a warning to the system as one would not expect network rendering to fail. This will be used if the manager attempts to send the message to Max main log system. 0 to let the manager automatically assign a proper value. - True if the message is successfully logged, false otherwise. - - Source of the message; determines which tab, in the render message dialog, the message is reports in. - Type of the message for purposes of . Affects how the message is reported to the render message window. - Type of the message for purposes of . See systemErrorLogMessageTypes in . - - - - Flush pending messages from a certain source. - - - This function must be called from main thread. If the manager is working in non-window mode, and the source is kSource_Production, the pending messages will be sent to 3ds Max main log system. If the manager is working in window mode, the pending messages will be flushed to the message window. This function will also get called automatically from a system timer, to ensure that pending messages are always flushed regularly. - - Source of the message. - - - - Clear displayed messages from a certain source. - - - - Source of the messages that client wants to clear. - - - - Open the log file for message logging if possible. Typically this is called from a renderer's Open() implementation. - - - True if the log file is successfully created. - - - - - Flush buffer to the log file for specific message source. - - - - - Close log file for specific message source. Typically this is called from a renderer's Close() implementation. - - - - - Register a client defined callback to get notification whenever a preference option is changed via UI operation, API call, and MAXScript. - - - - The callback function client wants to register. - A pointer to client data. This pointer will be used as the only parameter of the callback function. - - - - Unregister preference change callbacks. - - - - The callback function client wants to unregister. - A pointer to client data. Make sure it matches the one passed along with . - - - - Get the "Open Message Window on Error" option. - - - True if the window will be opened whenever there's a fatal/error message sent in, false otherwise. - Note that if Max is running in quiet mode, the message window will never show up. - - - - - Get the "Show/Log Information Messages" option. - - - True if the manager handles information messages. - - - - - Get the "Show/Log Progress Messages" option. - - - True if the manager handles progress messages, false otherwise. - - - - - Get the "Log Debug Messages (To File)" option. - - - True if the manager attempts to log debug messages to the log file, false otherwise. - - - - - Get the message log file name template. - - - Different postfixes will be appended to this template for Production/MEditor/ActiveShade renderers. For instance, if the template name is "MaxRendererMessages.log", then messages log file name for Production renderer will be "MaxRendererMessages_Production.log". - The log file name template. - - - - - Get the actual message log file name for a specific message source. - - - The actual log file name which is related to the message source. - - Source of the messages that the log file is related to. - - - - Get the "Write Messages to File" option. - - - True if the manager logs messages to files, false otherwise. - - - - - Get the "Append to File" option. - - - True if the manager appends messages to log files (rather than creating new ones). - - - - - Get the "Open Message Window on Warning" option. - - - - True if the window will be opened whenever there's a warning message sent in, false otherwise. - - Note that if Max is running in quiet mode, the message window will never show up. - - - - - Get the "Auto Scroll" option. - - - True if the message window is set to automatically scroll to the latest message, false otherwise. - - - - - Description: - The Render Preset Manager allows for loading and saving of render presets through the SDK. The manager can be obtained as follows: - - GetCOREInterface()->GetRenderPresetsManager(); - - - - - Save selected categories of render presets to the file. - - - This function has the same effect as selecting "Save Preset..." in "Rendering->Render Setup->Preset" drop-down list in Max - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to save the presets of - - - - Save selected categories of render presets to the file. - - - When calling this function, the user will be presented with a dialog to select which presets to save for the specified render category. - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to save the presets of - The file to save the user-selected presets to. - - - - Save selected categories of render presets to the file. - - - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to save the presets of - The file to save the user-selected presets to. - A specifying the presets categories to be saved. - - - - Load selected categories of render presets from the file. - - - Calling this function has the same effect as selecting "Load Preset..." in "Rendering->Render Setup->Preset" drop-down list in Max - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to load the presets for - - - - Load selected categories of render presets from the file. - - - Calling this function will display a dialog prompting the user to select which presets in fileName to load. - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to load the presets for - A path to file to load the render presets from - - - - Load selected categories of render presets from the file. - - - Calling this function will pop a dialog prompting the user to select which presets in fileName to load. - RENDER_PRESETS_SUCCESS on success, or one of the RP_ERROR values if an error occurs - - Which renderer to load the presets for - A path to file to load the render presets from - The preset categories to for the specified renderer - One of the NodeRefAction enum values - - - - Check to see if file is compatable with current renderer. - - - For Example: If the user saves a preset for the Default Scanline , but does NOT choose the category called "Default Scanline Renderer", then the preset is considered incompatible with any other renderer. This is because the renderer itself will not be saved within the preset, so loading the preset will not change which renderer is active; but the render-specific parameters in the preset are not compatible with other renderers. - TRUE if the renderer currently assigned to rendSpecifier can load the presets in fileName - - The category to check compatability for - The saved render preset file - - - - Retrieve a render presets name based on its ID. - - - the name of the specified render preset - - The file containing the preset we are looking for the name to - The ID of the category saved in fileName to retrieve the name of - - - - retrieve a render presets ID based on its name - - - the ID of the specified render preset - - The file containing the preset we are looking for the ID for - The name of the category saved in fileName to retrieve the ID of - - - - retrieve a render presets name based on its ID for the current renderers - - - the name of the specified render preset - - Which current renderer to query for the preset category name. - The ID of the render preset to retrieve the name of - - - - retrieve a render presets ID based on its name for the current renderers - - - the ID of the specified render preset if found, else -1 - - Which current renderer to query for the preset category ID. - The name of the category to retrieve the ID of - - - - return a list of all preset category ID's saved in a given preset file. - - - - The file to query for saved preset categories - - - - return a list of all preset category names saved in a given preset file. - - - - The file to query for saved preset categories - - - - return a list of all preset category ID's that are meaningful to the specified renderer. - - - An array specifying the preset categories ID's that are applicable to the current renderer - - Which current renderer to query for meaningful categories - - - - return a list of all preset category names that are meaningful to the specified renderer. - - - An array specifying the preset categories ID's that are applicable to the current renderer - - Which current renderer to query for meaningful categories - - - - Retrieve the current RenderPresetContext. - - - This is provided so that renderers can tailor their save and load methods to accomodate the saving and loading of any combination of render preset categories. - - This method will return NULL unless a render preset is currently being loaded or saved. An example usage would be to call this inside a Load() method or post-load callback, and if not NULL, check for compatibility by looking at the version number and categories of the preset context. - the current RenderPresetContext if present, else NULL. - - - - - Represents access to render region editing for the viewport and VFB. - - - - - Query whether the system is currently editing a region. - - - - - Query whether the current render mode supports region render editing. - - - - - Pushes the region command mode on to the command stack to start region editing. This action will switch to a region editable mode if the current render mode does not support regions. - - - - - Pops the command mode off of the command stack to leave region editing. - - - - - Helper that calls Begin/EndRegion to toggle between enabled and disabled. - - - - - Handler called when region editing has started. - - - - - Handler called when region editing has ended. - - - - - Handler called when the region or related conditions have changed. This will notify region clients to update their display. This may also end editing if it is no longer valid (e.g. region render mode is no longer selected). - - - - - Get the render region (crop or blowup, depending on the current mode) in 0-1.0 space. - - - - - Get the render region for a specific mode (crop or blowup) for a specific viewport. - - - - The viewport id. - RENDER_CROP or RENDER_BLOWUP. - - - - the render region for a specific mode (crop or blowup) for a specific viewport. - - - - The viewport id. - RENDER_CROP or RENDER_BLOWUP. - The render region. - - - - Mark the current region values for undo if the is holding. - - - - - Whether the region manager is the current VFB crop handler. - - - - - This is the interface given to a renderer, or atmospheric effect when it needs to display its parameters. For a renderer, the Render Scene dialog may be extended using this class. All methods of this class are implemented by the system. - - - - - - Returns the current position of the frame slider. - - - - - Register a callback object that will get called every time the current animation time is changed. - Parameters: - *tc - - The callback object to register. - - - - - Un-registers a callback object registered using RegisterTimeChangeCallback(). - Parameters: - *tc - - The callback object to un-register. - - - - - Brings up the material browse dialog allowing the user to select a material. - Parameters: - HWND hParent - - The parent window handle. - - DWORD flags - - See Material Browser Flags . - - BOOL &newMat - - to TRUE if the material is new OR cloned; otherwise FALSE. - - BOOL &cancel - - to TRUE if the user cancels the dialog; otherwise FALSE. - The material returned will be NULL if the user selects 'None' - - - - - This method adds rollup pages to the dialog and returns the window handle of the page. - Parameters: - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the message sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar. - - LPARAM param=0 - - Any specific data to pass along may be stored here. This may be later retrieved using the GetWindowLong() call from the Windows API. - - DWORD flags=0 - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Allthough it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The window handle of the rollup page. - - - - - Removes a rollup page and destroys it. - Parameters: - HWND hRollup - - The handle of the rollup window. This is the handle returned from AddRollupPage(). - - - - - This allows hand cursor scrolling when the user clicks the mouse in an unused area of the dialog. When the user mouses down in dead area of the dialog, the plug-in should pass mouse messages to this function which will pass them on to the rollup. - - Note: In 3ds Max 2.0 and later only use of this method is no longer required - the functionality happens automatically. - Parameters: - HWND hDlg - - The window handle of the dialog. - - UINT message - - The message sent to the dialog proc. - - WPARAM wParam - - Passed in to the dialog proc. Pass along to this method. - - LPARAM lParam - - Passed in to the dialog proc. Pass along to this method. - - - - - This will set the command mode to a standard pick mode. The callback implements hit testing and a method that is called when the user actually picks an item. - Parameters: - *proc - - The callback object. See Class . - - - - - If a plug-in is finished editing its parameters it should not leave the user in a pick mode. This method will flush out any pick modes in the command stack. - - - - - When a plugin has a , clicking on the button associated with that map should cause this routine to be called. - Parameters: - *mb - - The ( or ) to put to the materials editor. - - - - - This method is used internally. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Extension class that adds functionality to class for 3ds Max 2017 Service Pack 2. - A pointer to this extension interface may be retrieved through a dynamic_cast from a . - Note: this class will eventually disappear, having its functionality folded into . - - - - - Description: - The Reshade Fragment interface is the materials/shaders/textures interface to reshading fragments. This interface is only concerned with saving and retrieving values in the fragments variable sized cache. Values are always saved in multiples of 32 bit words, and they can be a variety of types, colors, float's, int's, etc. Unit vectors are compressed to a single 32 bit word. and data types save multiple floats. - - channels will be compressed to a 32 bit rgba color and saved in the cache. - - Color32 channels are only used internally. This is the 'raw' form of what's stored, other forms may be accessed from this class. - - and integer channels are stored uncompressed, they are stored directly in the 32 bits. - - The & channels are shells that store multiple float channels so these values will be uncompressed. These should be used with great caution, as this memory is stored per fragment, in a scene with 100,000 fragments of a given material, a point3 channel will add 1.2 megabytes to the storage for the reshading buffer. - - - - - This method returns the number of textures for the fragment. - - - - - This method returns the index of the first channel. - - - - - This method returns the number of textures. - - - - - This method allows you to add a new color channel to the end of the cache. The color will be compressed to 32bits. - Parameters: - RGBA tex - - The color channel value you wish to add. - - - - - - - This method allows you to add a float channel in the fragment cache. - Parameters: - float f - - The channel value to add. - - - - - This method allows you to add an integer channel in the fragment cache. - Parameters: - int i - - The integer value to add. - - - - - This method allows you to add a unit vector channel in the fragment cache, compressed to 32-bits. - Parameters: - v - - The unit vector to add. - - - - - This method allows you to add a channel in the fragment cache, uncompressed. - Parameters: - p - - The to add. - - - - - This method allows you to add a channel in the fragment cache, uncompressed. - Parameters: - p - - The to add. - - - - - This method sets the existing color channel number nChan to the new value. - Parameters: - int nChan - - The color channel number. - - RGBA text - - The new color value. - - - - - This method allows you to set a float channel in the fragment cache to a new value. - Parameters: - int nChan - - The float channel number. - - float f - - The new value to set. - - - - - This method allows you to set an int channel in the fragment cache to a new value. - Parameters: - int nChan - - The int channel number. - - int i - - The new value to set. - - - - - This method allows you to set a unit vector channel in the fragment cache to a new value. - Parameters: - int nChan - - The unit vector channel number. - - v - - The new value to set. - - - - - This method allows you to set a channel in the fragment cache to a new value. - Parameters: - int nChan - - The channel number. - - p - - The new value to set. - - - - - This method allows you to set a channel in the fragment cache to a new value. - Parameters: - int nChan - - The channel number. - - p - - The new value to set. - - - - - This method will return an existing color channel, expanded to float RGBA. - Parameters: - int nChan - - The color channel you wish to return. - - - - - This method will return an existing float channel. - Parameters: - int nChan - - The float channel you wish to return. - - - - - This method will return an existing int channel. - Parameters: - int nChan - - The int channel you wish to return. - - - - - This method will return an existing unit vector channel. - Parameters: - int nChan - - The unit vector channel you wish to return. - - - - - This method will return an existing channel. - Parameters: - int nChan - - The channel you wish to return. - - - - - This method will return an existing channel. - Parameters: - int nChan - - The channel you wish to return. - - - - - Description: - This interface class is the interface that must be supported by materials and shaders to support interactive rendering in 3ds Max. If this interface is not returned when requested through GetInterface() on the mtl or shader, then it is determined they do not support reshading. Any material that does not support reshading is evaluated only at preshading time. - - In 3ds Max, interactive rendering is implemented as fragment based caching scheme. It's very much like a giant multi-layer g-buffer with enough information stored with each fragment to re-run the material shading process without re-rendering, all stored in a compressed form. - - The rendering process in divided into 2 parts: preshading and reshading. Preshading builds the scene and renders fragments to the compressed g-buffer, called the rsBuffer. To do this, it saves a minimal amount of information with each fragment, then gives each material and texture the opportunity to pre-shade itself. - - Basically, the reshader populates a minimal , with the fragment center position in camera space (where shading is done), the shading normal, the sub-pixel mask, the coverage, pointers to the original material and , light lists, screen bounding box of object, the renderID, and screen integer x and y. - - Any other values from the shade context that a material, shader, texture(future), atmosphere(future) or light(future) needs to save, it does so at pre-shade time, and retrieves the data at reshading time. So, for example, the multi-materials save which material is visible, anisotropic shaders save the Anisotropic reference vector. - - - - - This method is called by the interactive reshader after being notified that the material has changed. The return value indicates if the material is still valid, or needs to be preshaded or reshaded. The value should pertain only to the latest change to the material. If a material doesn't support reshading, it doesn't need to override this function - any change will cause the nodes to which it's attached to be re- preShaded. - One of the following values; - - RR_None - - No actions needs to be taken. - - RR_NeedPreshade - - A pre-shade is needed. - - RR_NeedReshade - - A re-shade is needed. - Default Implementation: - { return RR_NeedPreshade; } - - - - - This method will pre-shade the object and cache any needed values in the fragment. - - This method is called on the materials/shaders/textures as the reshading buffer is being built at the same point in the rendering process where the materials shade function would normally be called. Note that at this time the shade context is completely valid, as in a normal rendering. Any values the material wishes to cache can be attached to the reshading fragment passed in, and retrieved later at postShade time. - Parameters: - & sc - - A reference to the shade context. - - IReshadeFragment* pFrag - - A pointer to the fragment. - Default Implementation: - { } - - - - - This method will retrieve cached values and compute shade & transparency for the fragment. - - This method is called for the material of each fragment as the reshading buffer is being traversed. Materials retrieve whatever they may have stored to complete the minimal shade context and compute a shade for the fragment. PostShade() calls to shaders contain an additional parameter, the , filled with the textured/blended but unshaded values for each texture. The shade context passed into PostShade() is the minimal shade context outlined above. - Parameters: - & sc - - A reference to the shade context. - - IReshadeFragment* pFrag - - A pointer to the fragment. - - int& nextTexIndex - - A reference to the next texture index. - - IllumParams* ip = NULL - - A pointer to the containing textured/blended but unshaded values for each texture. - Default Implementation: - { } - - - - - class : public - Description: - This class represents the abstract interface for a rollup window callback object to assist developers in handling custom drag and drop of rollouts. - - - - - - Any plugin (or core component), that wants to implement a custom behavior when a rollup page is drag and dropped onto another rollout, it can do so, by registering a and overwriting this method and GetEditObjClassID(). After rearranging rollup pages the HandleDrop code should call: GetIRollupSettings()->GetCatReg()->; in order to save the rollout order. - Parameters: - *src - - A pointer to the source rollup panel. - - *targ - - A pointer to the target rollup panel. - - bool before - - TRUE to insert before the panel it was dropped on; FALSE to insert after. - TRUE to indicate to the system, that it took over the drop handling, otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - This method has to be implemented in order to support drag and drop for rollups, no matter if custom drop handling is used, or not. The order of rollup panels is stored in the RollupOrder.cfg file in the UI directory. The order is stored under a SuperClassID and ClassID (and an optional context, if available). The RollupCallback has to specify what the SuperClassID and ClassID is. E.g. for the Modify Panel it is the ClassID for the currently edited object. For the DisplayPanel it is only one ClassID, that has no real class assigned to it, since the rollouts are independent from the object being edited (DISPLAY_PANEL_ROLLUPCFG_CLASSID). - TRUE if drag and drop is supported, otherwise FALSE. - The default implementation returns FALSE and does not touch sid and cid. - - The SuperClassID of the object. - The class ID of the object. - - - - This method can be implemented in order to support different contexts for drag and drop for rollups, no matter if custom drop handling is used, or not. It also requires the GetEditObjClassID function to be implemented and returning TRUE as well. - The order of rollup panels is stored in the RollupOrder.cfg file in the UI directory. The order is stored under a SuperClassID and ClassID and this context string, if present. The RollupCallback has to specify what the Context is, if present. - TRUE, if the context should be used, otherwise FALSE. - The default implementation returns FALSE and does not touch the context string. - - A reference to a string that shall receive the current context of the object being edited. This contexts is used to store and retrieve the rollup oder and state. - - - - This method is called when the user selected the "open all" function and it currently used internally. The method will return TRUE if successful and FALSE otherwise. - Default Implementation: - {return FALSE;} - - - - - This method is called when the user selected the "close all" function and it currently used internally. The method will return TRUE if successful and FALSE otherwise. - Default Implementation: - { return FALSE;} - - - - - This method is called as the RollupWindow is being destroyed. - Default Implementation: - {} - - - - - class : public - Description: - This class represents the interface for a rollup panel and describes the properties of that panel (which is one rollup). You can obtain a pointer to the class for any given specified window by calling IRollupWindow::IRollupPanel *GetPanel(HWND hWnd); - - - - - This method returns a handle to the rollup panel instance. - - - - - This method returns the resource ID of the rollup panel. - - - - - Equality test operator. - - - - - This method returns the rollup panel category identifier. - - - - - This method returns a handle to the rollup window. - - - - - This method returns a handle to the actual panel in the rollup window. - - - - - This method returns a handle to the window from which you can get the title through the GWLP_USERDATA. - - - - - This function gets the main panel window handle. - Returns the panel window handle - - - - - This function gets the height of the panel. - Returns the panel height. - - - - - class : public - Description: - This class represents a right click menu item for rollups. - - - - - This method returns the text of the menu item. - - - - - This method is the callback that will be triggered when the user selects the menu item. - - - - - This method allows you to control the checkmark for the menu item, in case it needs be shown or hidden (by returning TRUE to show or FALSE to hide). - - - - - This method should return TRUE if you wish a separator item before the menu item. - - - - - This class represents the interface class for rollup settings. You can obtain a pointer to this interface using. This macro will return . - - - - - This method initializes the Rollup settings. - - - - - This method returns a pointer to the category registry. - - - - - Description: - This control is used to access existing rollup pages or if you are creating a dialog box which will not be used in the command panel. This control may be used to add a container area for rollup pages to be added to the dialog, and provides a scroll bar just like the command panel itself. - - Note that this is a special case. Normally, adding rollup pages to the command panel is done using the simple AddRollupPage() method of the class. This control is only used when you want to have a scrolling region for rollup pages in a dialog box. - - To initialize the pointer to the control call: - - *GetIRollup(HWND hCtrl); - - To release the control call: - - ReleaseIRollup(IRollupWindow *irw); - - The value to use in the Class field of the Custom Properties dialog is: RollupWindow - - - - - This causes all the rollup windows to be visible. - - - - - This causes all the rollup windows to become invisible. - - - - - This will make the rollup window whose index is passed visible. - Parameters: - int index - - The index of the rollup to show. - - - - - This will make the rollup window whose index is passed invisible. - Parameters: - int index - - The index of the rollup to hide. - - - - - Returns the handle of the rollup page whose index is passed. - Parameters: - int index - - The index of the rollup whose handle is to be returned. - - - - - Returns an index to the rollup page given its handle. - Parameters: - HWND hWnd - - The handle of the rollup. - - - - - This method sets the title text displayed in the rollup page whose index is passed. - Parameters: - int index - - Specifies the rollup whose title is to be set. - - MCHAR *title - - The title string. - - - - - Gets the title text displayed in the rollup page whose index is passed. - - - The title of the specified rollup. - - Specifies the rollup whose title is to be returned. - - - - This method is used to add a rollup page. - Parameters: - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the message sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar. - - LPARAM param=0 - - Any specific data to pass along may be stored here. - - DWORD flags=0 - - Append rollup page flags: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - The index of the new page is returned. - - - - - This method is used to replace the rollup page whose index is passed. - Parameters: - int index - - Specifies the rollup whose to be replaced. - - HINSTANCE hInst - - The DLL instance handle of the plug-in. - - MCHAR *dlgTemplate - - The dialog template for the rollup page. - - DLGPROC dlgProc - - The dialog proc to handle the message sent to the rollup page. - - MCHAR *title - - The title displayed in the title bar. - - LPARAM param=0 - - Any specific data to pass along may be stored here. - - DWORD flags=0 - - Append rollup page flags: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - The index of the replacement page is returned. - - - - - This method deletes the rollup pages starting at the index passed. The count parameter controls how many pages are deleted. - Parameters: - int index - - The starting index. - - int count - - The number of pages. - - - - - This method is used to change the height of a rollup page. - Parameters: - int index - - The index of the rollup to change. - - int height - - The new height of the dialog in pixels. - - - - - Get the height of a rollup dialog. - - - The height of the dialog inside the rollup page - - The index of the rollup to change. - - - - This method saves the state of the rollup (the position of the scroll bars, which pages are open, etc...). - Parameters: - RollupState *hState - - Pointer to storage for the rollup state. Note: typedef void RollupState; - - - - - This methods restores a saved state. - Parameters: - RollupState *hState - - Pointer to storage for the rollup state. Note: typedef void RollupState; - - - - - Passing WM_LBUTTONDOWN, WM_MOUSEMOVE, and WM_LBUTTONUP to this function allows hand cursor scrolling with unused areas in the dialog. - Parameters: - HWND hDlg - - The handle of the dialog. - - UINT message - - The message to pass along: WM_LBUTTONDOWN, WM_MOUSEMOVE, or WM_LBUTTONUP. - - WPARAM wParam - - LPARAM lParam - - These are passed as part of the message sent in. Pass them along to this method. - - - - - This method returns the number of panels used in the rollup. - - - - - This method return TRUE if the rollup page whose index is passed is open and FALSE if it is closed. - - - - - This causes the page whose index is passed to either open or close. If isOpen is passed a value of TRUE, the page is opened. - Parameters: - int index - - The page to open or close. - - BOOL isOpen - - If TRUE, the page is opened, if FALSE it is closed. - - BOOL ignoreFlags = TRUE - - The method would close the panel if the DONTAUTOCLOSE flag is not set on the rollup. This flag indicates if it should be closed anyway, even if the flag is set. - - - - - This method returns the scroll position of the window. - - - - - This methods moves a RollupPanel to another RollupWindow. It either inserts it at the top, or appends it at the end (depending on the top parameter) - Parameters: - *from - - A pointer to the rollup window you are moving from. - - HWND hPanel - - The handle to the destination panel. - - BOOL top - - TRUE to insert at the top; FALSE to append at the end. - - - - - Returns the height of the specified RollupPanel. - Parameters: - int index - - The zero based index of the rollup panel. - - - - - - - Returns the height of a RollupWindow, that it is longer than the visible area - - - - - This method is used internally - - - - - Returns a pointer to the rollup panel for the specified window handle. An describes the properties of a single rollup. - Parameters: - HWND hWnd - - The window handle to get the rollup for. - - - - - This method allows you to register a rollup callback function to handle any custom handling for dragging and dropping rollouts. - Parameters: - *callb - - A pointer to the callback function you wish to register. - - - - - This method allows you to unregister a rollup callback function. - Parameters: - *callb - - A pointer to the callback function you wish to unregister. - - - - - This method allows you to register a rollup right-click menu item which will be added to the list of items. For rollups that support Drag and Drop this is used to register a ResetCategories RightClickMenu. Reset Categories will get rid of all the changes that have been made through drag and drop and restore the default. - Parameters: - *item - - A pointer to the right-click menu item you wish to register. - - - - - This method allows you to unregister a rollup right-click menu item. - Parameters: - *item - - A pointer to the right-click menu item you wish to unregister. - - - - - This method will reset the category information on all the panels in the rollup window. The plugin will have to be reloaded (EndEditParams, BeginEditparams) in order to show this in the UI. - Parameters: - bool update = true - - TRUE to update the layout, otherwise FALSE. Leave this on TRUE. - - - - - Returns TRUE if the rollup window is borderless, FALSE otherwise. - - - A borderless rollup window has no outer line, making it appear inset. By default, rollup windows have a border (are not borderless). - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Description: - The interface is the interface to root nodes in the scene. There is a root node at the top of the scene, and each scene xref has a root node at the top of its tree. Each root node holds its immediate xref scene children root nodes. All methods of this class are implemented by the system. - - - - - Returns the root node of the tree for the specified XRef. This method, when called on a root node, will access the various XRef scenes. Note that these can be nested so calling this on the root node of the scene will return the root node of one of the scene XRefs. Calling it on the root node of the scene XRef will get the root node of a nested XRef and so on. Note that this is not the parent of the XRef (see GetXRefParent() below). - - The zero based index of the XRef. - - - - Returns the parent node. This is the node in the scene (if any) which the scene XRef is linked to through the special bind function in the scene XRef dialog. - - - - - Returns the number of scene xrefs. - - - - - Returns the state of flags for the specified XRef. - See XRef Flag Bits. - - The zero based index of the XRef whose flags are returned. - - - - Returns the owning node. This is the root node that holds this root node as a nested XRef. The owning node of the top scene root node is null. - - - - - Returns the xref index of this xref in the owning node. - - - - - A simple public manager for . - - - A simple public manager that creates and maintains IRTShaderNodes used by materials and other nodes in max. All creation and deletion of the objects is performed by the manager. The developer simply requests a new and releases it when finished. Internally the manager is responsible for maintaining the validity of the nodes, and performing Lost Devices routines on all nodes. It implements and manages all calls to the interfaces. - - - - - Register a new . THe developer can keep hold of this pointer until they release it. The pointer is used to look up the data in various methods internally and also the FindShaderNode. - A pointer to a new object. - - The associated for the render node - - - - When the animatable (e.g. a material) is being deleted the should be removed from the active list - - The node to remove. - - - - Given an the associated can be retrieved. An example is the background image display. - A can be displayed in the viewport background, so max checks to see if the currently assigned has a shader node registered. If it does it will use this to render the background, instead of the default software processing - The corresponding shader node, or NULL if nothing is found - - The to query - - - - An extension to the interface. - - - - - For the given access the compiled effect code from the system. THis will be the actual code generated by the tree compiler, and passed to the DirectX frame work. - A buffer containing the effect (shader) code. The pointer should not be stored as the shader node responsible for maintaining the buffer could be destroyed. - - The animatable whose shader code is requested - - - - A Hardware shader node for use with compiled shader trees. - - - is an interface to a node that has its visual representation handled by an internal shade tree generated by a compiler technology such as AMD's Ashli or Mental Images Mental Mill technology. The interface wraps many of the draw calls, shader and state management, including cache creation for these complex shaders. It would typically be used with in a , but for 3ds max 2008, it was extended to support background nodes. Internally the system implements the interfaces. A developer can create a unique node by using methods of , in particular AddShaderNode. This interface does not remove the need to implement interfaces, but simply allows passing control of certain methods to the interfaces. Currently only the Standard and the Architectural participate in these shade trees. - NB - This system is only valid for DirectX Viewports - it will not be active on openGL or Heidi. - - - - - Assign the current active mesh and node data to the shading sub system. This would be implemented in IDX9VertexShader::Initialize(..) - TRUE if the data was successfully allocated. FALSE would indicate an internal failure. - - The node to render - The mesh to render - - - - Assign the current active and node data to the shading sub system. This would be implemented in IDX9VertexShader::Initialize(..) - TRUE if the data was successfully allocated. FALSE would indicate an internal failure. - - The node to render - The mesh to render - - - - Request the rendering of the assigned shade tree. The calling code has no control over what is rendered it simple initiates the draw call. This would typically be called in response to the IDX9VertexShader::DrawMeshStrips(). The return code can be passed directly back to DrawMeshStrips. FALSE would indicate that the object(s) was not drawn. - TRUE if the objects are rendered, false if an error was raised. Returning false to DrawMeshStrips would allow the GFX layer to continue to render the objects - returning TRUE would indicated that no further processing is required. - - - - - The underlying system requires access to key viewport interfaces. This method allows the shader node to assign the current window interface. It is passed as a LPVOID so as to assist working with DirectX9 and DirectX10 interfaces. The underlying system knows which sub system is running, but can't access the viewport directly. To assign a DirectX9 window simply cast an obtained from IDX9VertexShader::ConfirmDevice. For DirectX10 ID3D10GraphicsWindow would be used instead. - - A pointer to the current active hardware viewport - - - - for setting parameters in a compiled effect file. - - - A would implement this new interface to allow setting of parameters to the underlying graphics subsystem. When a shade tree is created a Microsoft file is generated that contains all the parameters exposed during compiling of the tree. At runtime the subsystem needs to set values to these parameters. At this level it knows nothing about the underlying material structure, and simply has a bunch parameter names and data types. To aid this, at render time the hardware renderer will query the host for the interface, and will call BindParameter to have the data assigned to the effect frame work. The "value" passed to the method is the correct size for the underlying data type, so the BindParameter method must understand the data request. In general this would either be a float, or a D3DXVECTOR (or D3DCOLORVALUE) type for colors. This value is assigned directly to the effect framework. An example of setting a value can be seen below - taken from the Architectural and Design - This checks the name of the parameter, accesses the correct data item from the paramblock, and sets the value correctly. - - - - - Assign the correct value based on the name parsed from the effect file. This method will be called for every parameter parsed from the effect file that the renderer doesn't understand - - The name of the parameter as parsed from the effect file - The pointer to a data structure that will receive the value to set - - - - Assign the correct value based on the name parsed from the effect file. This method will be called for every parameter parsed from the effect file that the renderer doesn't understand - - Current time value - The name of the parameter as parsed from the effect file - The pointer to a data structure that will receive the value to set - - - - Called once before the parameter list is parsed. Allows for one time setup of data. This could be used to make sure all parameters are valid before being queried - - - - - Description: - This class provides methods to save data to disk. - - Note: It is not valid to write two CStrs in the same chunk of a 3ds Max file, since ILoad::ReadCStringChunk() sets the size for the string to the ChunkSize. However it is possible to write other data, such as two ints, into the same chunk. - - Note about member alignment: Please make sure that when you save data from your plugin you save individual data members using a chunk ID instead of saving the image of a class. Saving (and loading) a class image puts you at risk of running into member alignment problems and as such could potentially corrupt saved files. File IO would be put further at risk when you keep Intel's IA-64 architecture in mind which depends on member alignment. What you should not do is outlined in the following example when loading a class image; iload->Read(&myclass, sizeof(MyClass), &ab); - - Once you change the class in such a way that it affects the data size you run the risk of having to support different versions, file IO incompatibility, and member alignment issues. - - The following global function is not part of this class but is available for use: - - - - - This method is not normally used because the reference hierarchy is saved automatically. In certain cases however this method is quite useful. This method is used in saving a pointer to some object (or a table of pointers). This is a pointer to one of the objects that the scene saves with the reference hierarchy, but it is not a pointer that itself is a reference. - The id that may be saved to disk. - - The pointer to save. - - - - This method is used to begin a chunk. The ID passed need only be unique within the plug-ins data itself. - - The id for the chunk. - - - - This method is used to end a chunk, and back-patch the length. - - - - - This method is used internally for checking balanced BeginChunk/EndChunk. - - - - - This method writes a block of bytes to the output stream. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. Note that the plug-in should not put up a message box if a write error occurs. It should simply return the error status. This prevents a overabundance of messages from appearing. - - The buffer to write. - The number of bytes to write. - The number of bytes actually written. - - - - This method is used to write wide character strings. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - The string to write. The string must be ACP encoded. - - - - This method is used to write wide character strings. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - The string to write. - - - - This method is used to write single byte character strings. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - The string to write. The string must be ACP encoded. - - - - This method is used to write single byte character strings. - IO_OK - The write was acceptable - no errors. - - IO_ERROR - This is returned if an error occurred. - - The string to write. - - - - Determines if we are saving a standard 3ds Max file (.MAX) or a material library (.MAT). - One of the following values: - - IOTYPE_MAX - - IOTYPE_MATLIB - - - - - This method returns a value to indicate the current version of the file being saved. It returns 0 for the current version, MAX_RELEASE_R12 for 3ds Max 2010, etc. Call this method to determine the format in which to save the data. - - - - - This method is available in release 3.0 and later only. - - This method returns a load reference ID for the given Reference 's object in the stream. - Default Implementation: - { return 0xffff; } - - Points to the reference maker. - - - - Returns the name of the scene file being saved. - - - - - This method is used by Asset Manager to save to the scene file the asset meta data. - A return value of IO_ERROR indicates an error occurred, otherwise IO_OK. - - The id for the asset. - Whether to store the asset's resolved filename. - - - - This method is used to tell when to store an asset as a guid rather than as the asset filename. - A return value of true indicates to store eassets as guids, otherwise as the asset filename. - - - - - This method is used to Disable/Enable chunk warnings. In 3ds Max 2026, if a instance is saved to the scene file in its own chunk, a warning dialog is displayed. instances should always be saved in their own chunk. This method is provided to temporarily disable the warning dialog to support where current code is updated to save the in its own chunk, but Save To Previous requires that previous behavior also be used. - - True to disable chunk warnings, false to re-enable chunk warnings. - - - - This class provides an interface into the standard 3ds Max scanline renderer. This renderer has a of . All methods of this class are implemented by the system. - - - - - - Returns TRUE if anti-aliasing is on; FALSE if off. - - - - - Returns TRUE if Filter Maps is on; FALSE if off. - - - - - Returns TRUE if the rendering of shadow is on; FALSE if off. - - - - - Returns TRUE if the Mapping setting is on; FALSE if off. - - - - - Returns TRUE if Force Wire is on; FALSE if off. - - - - - Returns TRUE if auto reflect is on; FALSE if off. - - - - - Returns TRUE if object motion blur is on; FALSE if off. - - - - - Returns TRUE if velocity motion blur is on; FALSE if off. - - - - - Sets the Auto Reflect/Refract Maps Rendering Iterations setting to the value passed. - Parameters: - int n - - The value to set in the range of 1 to 10. - - - - - Sets the ''Wire Thickness' setting to the value passed. - Parameters: - float t - - The value to set in the range of 0.0 to 10000.0. - - - - - Sets the Motion Blur Duration setting to the value passed. - Parameters: - int n - - The value to set in the range of 1 to 16. - - - - - Sets the Motion Blur Samples setting to the value passed. - Parameters: - int n - - The value to set in the range of 1 to 16. - - - - - Returns the maximum ray depth. - - - - - Returns a pointer to the anti-aliasing filter in use. See Class . - - - - - Returns the anti-aliasing filter size. - - - - - Returns TRUE if anti-aliasing is on; FALSE if off. - - - - - Description: - Methods of this class may be used to enumerate the scene and to flag certain nodes in the scene. Nodes chosen by the plug-in may be flagged using the EnumTree() method. Selected nodes may be flagged using FlagFGSelected(). Animated nodes may be flagged using FlagFGAnimated() and dependent nodes may be flagged using FlagFGDependent(). - - - - - Implemented by the System. - - This may be called to enumerate every in the scene. The callback may flag any of these nodes (using INode::FlagForeground()). - Nonzero if the process was aborted by the callback (TREE_ABORT); otherwise 0. - - This callback object is called once for each in the scene. - true to include scene xRef nodes, false otherwise. - false to include scene root node, true otherwise. - - - - Implemented by the System. - - Flags all selected nodes in the scene. - - The time to flag the nodes. - - - - Implemented by the System. - - Flags all animated nodes in the scene. - - The time to flag the nodes. - - - - Implemented by the System. - - Flags nodes that are dependent on the given object. - - The time to flag the nodes. - The object whose dependent nodes should be flagged. - - - - An interface to set priority to 's. Used in conjunction with class . Callbacks with higher priority will be called earlier than callbacks with lower priority. Larger number represents higher priority. 's that do not implement this interface (such as most internal callbacks) will have priority 0. - - - - - Get the priority of this scene callback. - Return the priority of this scene callback. - - - - - Casts to an if possible If this object is an , this method downcasts and returns a pointer. Otherwise this returns NULL. - - - pointer if the object is an ; otherwise NULL. - - - - - Registers a scene event callback, including NodeEventCallback objects. - - - The callback key ID (zero on failure) - - The callback object. This may be any scene event callback type, including NodeEventCallback. - In polling mode, messages are sent only when is called. Otherwise, messages are sent immediately after the given delay and mouseUp conditions are met. Polling mode cannot be used if a delay or mouseUp is specified. - If delay is zero, messages are triggered immediately when an event is completed. If delay is nonzero, messages are delayed until the specified time passes with no events (an uninterrupted period with no event noise). - If mouseUp is true, messages are delayed until the mouse is up. - - - - Unregister a callback object. - - - - The callback key ID - - - - Returns a callback object, given its key ID. - - - The callback object - - The callback key ID - - - - Returns a callback key ID, given a registered callback object. - - - The callback key ID (zero on failure) - - The callback object. - - - - Triggers messages about all events gathered for a callback, immediately This may be used with callbacks in any mode, but is particularly necessary to trigger messages for callbacks in polling mode. - - - - The callback key ID - - - - Clears out all gathered messages for a callback The currently gathered events will not be included in the next batch of messages for the callback. - - - - The callback key ID - - - - This class is the public interface to the scene state feature. - - - - - Get the number of scene states stored in the scene. - - - The number of scene states stored in the scene. - - - - - Get the name of the scene state at this index. - - - The name of the scene state, or NULL in case of an error. - - - The index of the scene state - - - - Find the index of the scene state with this name. - - - The index of the scene state, or -1 in case of an error. - - - The name of the scene state. - - - - Capture, or save, a scene state. All scene state parts will be saved. - - - true if successful, otherwise false. - - - The name of the scene state - - - - Capture, or save, a scene state with a specific set of parts. - - - true if successful, otherwise false. - - - The name of the scene state - - A representing the scene state parts to save. - - - - Restore a scene state. All scene state parts included in the scene state will be restored. - - - true if successful, otherwise false. - - - The name of the scene state to restore - - - - Restore a scene state. - - - true if successful, otherwise false. - - - The name of the scene state to restore - - A representing the scene state parts to restore. - - - - Delete the scene state with this name. - - - true if successful, otherwise false. - - - The name of the scene state to delete - - - - Rename a scene state. - - - true if successful, otherwise false. - - - The name of the scene state to rename - - The new name of the scene state - - - - Get the parts that are stored in a specific scene state. - - - A bitarray representing the parts that the scene state contains. - - - The name of the scene state - - - - Open the Scene State manager dialog. - - - - - Enumerate external files used by objects stored in the scene states. - - - - - The callback where external files are logged. - - Standard EnumAuxFiles flags. - - - - Description: - It provides a list of ray / triangle intersection structures (struct ). Methods are available for initializing the list, adding to the list, and selectively removing items from the list. - - All methods of this class are implemented by the system. - - Note the following global functions may be used to create and free instances of this class. - - - - - Returns TRUE if the list is empty; otherwise FALSE. - - - - - Adds the specified to the list with the most distant layers first. - Parameters: - *is - - Points to the structure to add to the list. - - - - - Removes the structures from the list whose t values are less than or equal to the specified value a. - Parameters: - float a - - The ray parameter used for comparison. - - - - - Deletes any items from the list and sets first to NULL. - - - - - This is a helper class. If we want to set just one attribute of the IK Key Property, we can derive a new class from it as follows: - - - - - This class is an API extension for the class. - - - It is used specifically for querying motion information of shade context. - - - - - This method returns the velocity information for shade context. - - - - This method returns a containing the velocity information for shade context. - - - - - Access shadow data from 3ds Max lights. - - - This is the main access to the lights. The user would request the light data from the LightManager based on the D3DHANDLE - - - - - Update current shadow data - - - - - Reset this shadow data - - - - - Rectangular Shape Render Parameters API This interface gives access to the new Renderable SPline parameters for Rectangular Shapes The interface can be retrieved like this: IShapeRectRenderParams* rparams = (IShapeRectRenderParams*)obj->GetProperty(SHAPE_RECT_RENDERPARAMS_PROPID); Note that this interface contains VPT and non VPT parameters. The non VPT parameters are used for the renderer and the viewport in case GetViewportOrRenderer() returns true, or if GetViewportOrRenderer() returns false and GetUseViewPort() returns false. Otherwise the non vpt settings only control the mesh for the renderer, not the viewport. - - - - - Gets the Rectangular setting of the shape - Rectangular setting of the shape - - - Time to get the value for - - - - Sets the Rectangular setting of the shape - - - Time to set the value for - - if true, shape is rectangular, if false radial - - - - Gets the Width of the rectangular section of the shape - Width of the rectangular section of the shape - - - Time to get the value for - - - - Sets the Width of the rectangular section of the shape - - - Time to set the value for - - Width (must be positive) - - - - Gets the Length of the rectangular section of the shape - Length of the rectangular section of the shape - - - Time to get the value for - - - - Sets the Length of the rectangular section of the shape - - - Time to set the value for - - Length (must be positive) - - - - Gets the Angle of the rectangular section of the shape - Angle of the rectangular section of the shape - - - Time to get the value for - - - - Sets the Angle of the rectangular section of the shape - - - Time to set the value for - - Angle for rectangular shape - - - - Gets the AspectLock parameter of the rectangular section of the shape - AspectLock parameter of the rectangular section of the shape - - - Time to get the value for - - - - Sets the AspectLock parameter of the rectangular section of the shape - - - Time to set the value for - - TRUE if aspect is locked, FALSE otherwise - - - - Gets the Rectangular setting of the shape for the viewport - Rectangular setting of the shape for the viewport - - - Time to get the value for - - - - Sets the Rectangular parameter of the rectangular section of the shape for the viewport - - - Time to set the value for - - if true, shape is rectangular, if false radial - - - - Gets the Width of the rectangular section of the shape for the viewport - Width of the rectangular section of the shape for the viewport - - - Time to get the value for - - - - Sets the Width of the rectangular section of the shape for the viewport - - - Time to set the value for - - Width (must be positive) - - - - Gets the Length of the rectangular section of the shape for the viewport - Length of the rectangular section of the shape for the viewport - - - Time to get the value for - - - - Sets the Length of the rectangular section of the shape for the viewport - - - Time to set the value for - - Length (must be positive) - - - - Gets the Angle of the rectangular section of the shape for the viewport - Angle of the rectangular section of the shape for the viewport - - - Time to get the value for - - - - Sets the Angle of the rectangular section of the shape for the viewport - - - Time to set the value for - - Angle for rectangular shape - - - - Gets the AspectLock parameter of the rectangular section of the shape for the viewport - AspectLock parameter of the rectangular section of the shape for the viewport - - - Time to get the value for - - - - Sets the AspectLock parameter of the rectangular section of the shape for the viewport - - - Time to set the value for - - TRUE if aspect is locked, FALSE otherwise - - - - Gets the AutoSmooth parameter of the shape - AutoSmooth parameter of the shape - - - Time to get the value for - - - - Sets the AutoSmooth parameter of the shape for the viewport - - - Time to set the value for - - TRUE if resulting mesh should be autosmoothed, FALSE otherwise - - - - Gets the AutoSmooth Threshold of the shape - AutoSmooth Threshold of the shape - - - Time to get the value for - - - - Sets the AutoSmooth Threshold of the shape - - - Time to set the value for - - threashold angle in radians - - - - The function-published interface for a simple per-face data channel. - - - Provides read/write access to a simple per-face data channel's description and data values. An instance of this mixin function-published interface can be obtained through the SimpleFaceDataManager or from the implementing object using GetInterface() and this interface's defined ID, SimpleFaceDataChannel_InterfaceID. Functions provided by this interface can also be called through function-publish dispatching and through Maxscript. - - - - - Get the name of the channel. (C++, Maxscript) - - - Gets the name of the channel. - A pointer to the string buffer containing the channel's name. - - - - - Get the channel ID of this channel. (C++) - - - Gets the identifying channel ID of this channel. The channel's ID cannot be changed after it has been created. - The that identifies this channel. - - - - - Get the channel ID of this channel. (Maxscript) - - - The maxscript exposed wrapper for ChannelID(). The only difference is that the channel ID is returned as a 2 element array of DWORDS. - - - - - Get the number of faces in this channel. - - - Gets the number of per-face data items in this channel. The number of items in the channel will always match the number of faces on the object. - The number of faces in this channel. 0 if an error occurred. - - - - - Get the data type of the channel. - - - Gets the data type of per-face data items in this channel. The channel's type cannot be changed after it has been created. - The ParamType or ParamType2 enum value that corresponds to the channel's data type. - - - - - Get a face's per-face data value. - - - Gets the value of the specified face's per-face data. - An that wraps the face's per-face data. An wrapping NULL is returned if the per-face data item could not be found. - - - The target face's 0-based index. - - - - a face's per-face data value. - - - Sets the value of the specified face's per-face data. - TRUE if the specified face value is set, FALSE otherwise. - - - The target face's 0-based index. - - The new of the face's per-face data. Must be non-null, loaded, and the type must match the channel type. - - - - Get the entire list of per-face data values for the channel. - - - Get a copy of the entire array of per-face data values for this channel. - An that wraps an array of per-face data items. An wrapping NULL is returned if the per-face data item could not be found. - - - - - the value of each face in the channel. - - - Sets the value of each face in the channel to a new value specified in an array. - TRUE if the specified face values were set, FALSE otherwise. - - - A that wraps an array of per-face data items that specify the channel's new per-face data values. Must be non-null, loaded, and the type must match the channel type. The array and the channel must have an equal number of data elements. - - - - Get the per-face value of a selection of faces. - - - Gets the common per-face value of a selection of faces specified by a . - An that wraps the selection's per-face value. An wrapping NULL is returned if the selected faces don't have a matching value or no selection was specified. - - - A that indicates the face selection. Must be non-null. This selection array must have fewer or an equal number of elements as the data channel. - - - - the per-face value of a selection of faces. - - - Sets the per-face value of the specified selection of faces to a new specified value. - TRUE if the per-face data values were set, FALSE otherwise. - - - A that indicates the face selection. Must be non-null. This selection array must have fewer or an equal number of elements as the data channel. - The new of the faces' per-face data. Must be non-null, loaded, and the type must match the channel type. - - - - The function-published interface for managing SimpleFaceData channels on an object. - - - This manager allows simple per-face data channels to be added, removed and retrieved from the specified editable mesh or poly object. This static function-published interface is registered as a core interface. Obtain a pointer to this interface with GetInterface() using its defined ID, SimpleFaceDataManger_InterfaceID. Functions provided by this interface can also be called through function-publish dispatching and through Maxscript. - - - - - Add a simple per-face data channel to a geometry object (C++). - - - A new per-face data channel of the specified type with an identifying ID and name is added to specified object's base object. Per-face data channels are geometry pipeline clients - adding a channel to an object adds the channel throughout the entire modifier stack. - A pointer to the new channel instance if one was added. NULL if no channel was added. - - - The target geometry object. Must be non-null. Only editable mesh and editable poly objects are currently supported. - - A ParamType or ParamType2 enum value that specifies the data type for all faces within the data channel. The current list of supported types is: - - The identifying of the new channel. Specify NULL to have a unique ID generated and assigned to the new channel. If an ID is specified, no channel is added if a channel with the specified ID already exists. - - The name of the new channel. Specify NULL to use a default channel name. - - - - Add a simple per-face data channel to the specified geometry object (Maxscript). - - - The maxscript exposed wrapper for AddChannel(). The only difference is that this channel ID is specified as a 2 element array of DWORDS. - - - - - Remove a simple per-face data channel from a geometry object (C++). - - - Remove the per-face data channel on the specified object's base object that matches the specified channel ID. The channel is removed throughout the entire modifier stack. - - - The target geometry object. Must be non-null. - - The identifying of the channel to remove. - - - - Remove a simple per-face data channel from a geometry object (Maxscript). - - - The maxscript exposed wrapper for RemoveChannel(). The only difference is that the channel ID is specified as a 2 element array of DWORDS. - - - - - Get a simple per-face data channel from a geometry object (C++). - - - Obtain a pointer to the per-face data channel on the specified object that matches the specified channel ID. - A pointer to the desired channel instance. NULL if a channel with the specified ID was not found. - - - The target geometry object. Must be non-null. - - The identifying of the channel to retrieve. - - - - Get a simple per-face data channel from a geometry object (Maxscript). - - - The maxscript exposed wrapper for GetChannel(). The only difference is that this channel ID is specified as a 2 element array of DWORDS. - - - - - Get all simple per-face data channels from a geometry object (C++, Maxscript). - - - Obtain an array of pointers to all simple per-face data channels on the specified object. - An array of pointers to simple per-face data channels. An empty array if no channels were found. - - - The target geometry object. Must be non-null. - - - - Description: - The class is an interface to SimpleManipulators with built-in ParamBlock2 support and a variety of additionally useful methods. - - - - - - Implemented by the system. - - Removes all of the current gizmos in the manipulator. This is normally called at the top of UpdateShapes() to clear out any previous gizmos before creating new ones. - - - - - Implemented by the system. - - This method adds a new gizmo to the manipulator. The shape is defined in the local coordinates of the node that owns the manipulator. - Parameters: - PolyShape* pPolyShape - - A pointer to the poly shape to add. - - DWORD flags = 0 - - The flags can have one or more of the following values: - - kGizmoDontDisplay - - Instruct the gizmo not to display. It will still hit-test. - - kGizmoDontHitTest - - Instruct the gizmo not to do any hit testing. It will still display. - - kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - kGizmoUseRelativeScreenSpace - - The coordinates are in normalized screen space. the X and Y values are in the range 0.0 to 1.0, and interpreted as percentages of screen space. - - kGizmoUseScreenSpace - - The coordinates are in screen space. - - kGizmoApplyUIScaling - - If the coordinates are in screen space, the coordinates are 100% dpi scaled values and will be internally converted to current dpi scaling. - - & unselColor = GetUIColor(COLOR_SEL_GIZMOS) - - The color of the gizmo when unselected. - - & selColor = - - The color of the gizmo when selected. - - - - - Implemented by the system. - - This method adds a new to the manipulator. The shape is defined in the local coordinates of the node that owns the manipulator. - Parameters: - GizmoShape* pGizmoShape - - A pointer to the gizmo shape to add. - - DWORD flags = 0 - - The flags can have one or more of the following values: - - kGizmoDontDisplay - - Instruct the gizmo not to display. It will still hit-test. - - kGizmoDontHitTest - - Instruct the gizmo not to do any hit testing. It will still display. - - kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - kGizmoUseRelativeScreenSpace - - The coordinates are in normalized screen space. the X and Y values are in the range 0.0 to 1.0, and interpreted as percentages of screen space. - - kGizmoUseScreenSpace - - The coordinates are in screen space. - - kGizmoApplyUIScaling - - If the coordinates are in screen space, the coordinates are 100% dpi scaled values and will be internally converted to current dpi scaling. - - & unselColor = GetUIColor(COLOR_SEL_GIZMOS) - - The color of the gizmo when unselected. - - & selColor = - - The color of the gizmo when selected. - - - - - Implemented by the system. - - This method adds a new mesh to the manipulator. The mesh is defined in the local coordinates of the node that owns the manipulator. - Parameters: - Mesh* pMesh - - A pointer to the mesh to add. - - DWORD flags = 0 - - The flags can have one or more of the following values: - - kGizmoDontDisplay - - Instruct the gizmo not to display. It will still hit-test. - - kGizmoDontHitTest - - Instruct the gizmo not to do any hit testing. It will still display. - - kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - kGizmoScaleToViewport - - Instruct the gizmo to scale itself to have a constant size in the viewport. In this case the system will use the ManipulatorGizmo::mGizmoSize to determine how big the manipulator should be. It interprets mGizmoSize as pixels in this case. - - & unselColor = GetUIColor(COLOR_SEL_GIZMOS) - - The color of the gizmo when unselected. - - & selColor = - - The color of the gizmo when selected. - - - - - Implemented by the system. - - This method adds a new marker to the manipulator. - Parameters: - MarkerType markerType - - The marker type to add. - - & position - - The position of the marker. - - DWORD flags = 0 - - The flags can have one or more of the following values: - - kGizmoDontDisplay - - Instruct the gizmo not to display. It will still hit-test. - - kGizmoDontHitTest - - Instruct the gizmo not to do any hit testing. It will still display. - - kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - kGizmoUseRelativeScreenSpace - - The coordinates are in normalized screen space. the X and Y values are in the range 0.0 to 1.0, and interpreted as percentages of screen space. - - kGizmoUseScreenSpace - - The coordinates are in screen space. - - kGizmoApplyUIScaling - - If the coordinates are in screen space, the coordinates are 100% dpi scaled values and will be internally converted to current dpi scaling. - - & unselColor = GetUIColor(COLOR_SEL_GIZMOS) - - The color of the gizmo when unselected. - - & selColor = - - The color of the gizmo when selected. - - - - - Implemented by the system. - - This method adds a new text entry to the manipulator. - Parameters: - MCHAR* pText - - The string containing the text to add. - - & position - - The position of the text. - - DWORD flags = 0 - - The flags can have one or more of the following values: - - kGizmoDontDisplay - - Instruct the gizmo not to display. It will still hit-test. - - kGizmoDontHitTest - - Instruct the gizmo not to do any hit testing. It will still display. - - kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - kGizmoUseRelativeScreenSpace - - The coordinates are in normalized screen space. the X and Y values are in the range 0.0 to 1.0, and interpreted as percentages of screen space. - - kGizmoUseScreenSpace - - The coordinates are in screen space. - - kGizmoApplyUIScaling - - If the coordinates are in screen space, the coordinates are 100% dpi scaled values and will be internally converted to current dpi scaling. - - & unselColor = GetUIColor(COLOR_SEL_GIZMOS) - - The color of the gizmo when unselected. - - & selColor = - - The color of the gizmo when selected. - - - - - This method returns the current status of the mouse. - One of the following values: - - kMouseIdle - - The mouse is idle, manipulator not active and the mouse is not over it. - - kMouseDragging - - The mouse is currently dragging the manipulator. - - kMouseOverManip - - The mouse is over the manipulator, but it is not being dragged. - - - - - This method gets the view ray going through the given screen coordinate. The result is in local coordinates of the owning . - Parameters: - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The screen coordinate. - - & viewRay - - The returned local view ray. - - - - - This method gets called whenever the manipulator needs to update its gizmos. This is implemented by the manipulator to create the gizmos based on the current state of the node being manipulated. - Parameters: - TimeValue t - - The time value at which the shapes should be updated. - - MSTR& toolTip - - The tooltip string. - - - - - This method gets called when the mouse moves within the manipulator context. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The screen coordinates of the mouse. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - - - - - Description: - This class represents the interface for the Skin modifier. - - - - - This method retrieves the intial matrix of the bone when it was applied to skin. - Parameters: - *pNode - - The of the bone you want to get the TM from. - - &InitTM - - This returns either the initial node TM or object TM of the bone when it was applied to skin. - - bool bObjOffset = false - - When TRUE the InitTM returns the object TM else the node TM. - SKIN_OK if the pNode was in the system else it returns SKIN_INVALID_NODE_PTR. - - - - - This method gets the initial matrix of the skinned object when it was applied to skin. - Parameters: - *pNode - - The of the bone you want to get the TM from. - - &InitTM - - This returns either the initial skinned node tm or object tm of the bone when it was applied to skin. - - bool bObjOffset = false - - When TRUE the InitTM returns the object TM else the node TM. - SKIN_OK if the pNode was in the system else it returns SKIN_INVALID_NODE_PTR. - - - - - This method returns the actual number of non NULL bones in the system. - - - - - This method returns the of a particular bone. - Parameters: - int idx - - The index of the bone that you want to get the from. Note there are 2 tables that contain bone date. One has NULL entries and the other has all the invalid NULL bones removed. The index here points to the table that has the NULL entries removed. - - - - - This method returns the flags of a particular bone. - Parameters: - int idx - - The index of the bone that you want to get the from. Note there are 2 tables that contain bone data. One has NULL entries and the other has all the invalid NULL bones removed. The index here points to the table that has the NULL entries removed. - One of the following; - - BONE_LOCK_FLAG - - Not used. - - BONE_ABSOLUTE_FLAG - - The bone is in absolute mode (i.e. all the vertices weight must add up to 1.0f). - - BONE_SPLINE_FLAG - - This bone is a spline. - - BONE_SPLINECLOSED_FLAG - - This bone is a closed spline. - - BONE_DRAW_ENVELOPE_FLAG - - Always draw this bones envelope. - - BONE_BONE_FLAG - - This bone is one of 3ds Max' bone objects.. - - BONE_DEAD_FLAG - - This bone is no longer used. - - - - - This method returns the interface pointer to the local skin data for the node. - Parameters: - *pNode - - The node that you want to retrieve the skin interface to. - - - - - This method returns the name of the bone pointed to by index. - Parameters: - int index - - The index of the bone that you want to get the name of. Note there are 2 tables that contain bone data. One has NULL entries and the other has all the invalid NULL bones removed. The index here points to the table that has the NULL entries in them. - - - - - This method returns the current selected bone. - - - - - This method forces the gizmo list box to update. - - - - - This method retrieves the start and end points of the envelope in bone space. - Parameters: - int id - - The index of the bone that you want to get the from. Note there are 2 tables that contain bone data. One has NULL entries and the other has all the invalid NULL bones removed. The index here points to the table that has the NULL entries - - &l1 - - The start point of the envelope in bone space. - - &l2 - - The end point of the envelope in bone space. - - - - - This method returns the bone TM of the specified bone. - Parameters: - int id - - The index of the bone. - - - - - This method returns the of a particular bone. - Parameters: - int idx - - The index of the bone that you want to get the from. Note there are 2 tables that contain bone data. One has NULL entries and the other has all the invalid NULL bones removed. The index here points to the table that has the NULL entries - - - - - This method returns the actual number of NULL bones in the system including NULL entries. - - - - - This returns the reference frame of the skin modifier. - - - - - Returns whether the skin modifier is in DQ blending mode - - - - - - - class - - - Description: - This interface provide access to the stretch matrix for bones. This update is provide from a result of previous work on bones where stretch data was extracted from the base matrix. - - Methods are available for both setting and getting. Also an additional method has been added that provides the ability to select vertices in the modifier. - - - - - This will set the initial stretch tm for a bone in skin. The stretch matrix is the bone stretch matrix applied to bone objects. You can get a node stretch tm by calling INode::GetStretchTM() - - NOTE SetBoneTm will clear the stretchTM and set it to identity so make sure you call this after SetBoneTm - true if the function succeeds - - - the node of the bone to set - - the stretch matrix - - - - This will return the initial stretch tm for a bone in skin - The stretch matrix off boneNode - - - The node of the bone to get the stretch TM off. - - - - This will let you get the current vertex selection set for skin - - - the node of the skinned object - - The vertex selection set - - - - This will let you set the current vertex selection set for skin - - - the node of the skinned object - - The vertex selection set - - - - Description: - This class represents the interface that allows you to get at the local modifier data for skin. The data is stored in the form of vertex weight arrays. Each vertex has an array of boneID's and weights which affect that particular vertex. - - - - - This method returns the number of points that skin affects. - - - - - This method returns the number of bones that control this vertex. - Parameters: - int vertexIdx - - The index into the vertex array. - - - - - This method returns the index of the bone that affecting the vertex - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method returns the weight that is affecting the vertex - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method currently returns 0 since the only the first curve is used in for spline animation. - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method returns the segment that of the spline that is affecting the vertex. - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method returns how far away the point was initially from the curve. - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method returns closest initial tangent to the vertex. - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - This method returns closest initial point on the curve to the vertex. - Parameters: - int vertexIdx - - The index into the vertex array. - - int boneIdx - - The index into the affected bone array for that vertex. - - - - - Sets the DQ blend weight of an individual vert, this is the amount that the DQ solver will contribute to the deformation - Parameters: - int index is the index of the vertex you want to set the weight to - - int v is the weight that DQ will use for this vertex should between 0-1 - - - - - - - Gets the DQ blend weight of an individual vert, this is the amount that the DQ solver will contribute to the deformation - Parameters: - int index is the index of the vertex you want to get the weight to - - - - - - - - - class - - - Description: - The interface that allows to import data: bones, initial skin and bone transforms, and vertex weighting into skin. - - - - - - - Adds a bone to the skin system - - - Parameters: - *node - - The bone to be added to skin. - - BOOL update - - The flag for UI update - - - TRUE if the operation succeeded. - - - - - - - When skin is applied to a node, that nodes initial ObjectTM is stored off, so the initial position of the skin object can be recomputed. The function allows to set that TM. Stores TM and the inverse TM of the matrix passed to it. - - - Parameters: - *skinNode - - The node that Skin is applied to - - objectTm - - The object matrix to assign as the new Skin object TM. - - nodeTm - - The node matrix to assign as the new Skin node TM - - - TRUE if the operation succeeded. - - - - - - - When a bone is added to skin it stores off the initial object and node TM of that bone. The function sets the initial matrix of a particular bone. - - - Parameters: - *boneNode - - The pointer to the bone that is having its initial matrix change - - objectTm - - The object matrix to assign as the new Skin object TM. - - nodeTm - - The node matrix to assign as the new Skin node TM - - - TRUE if the operation succeeded. - - - - - - - Adds weight to a specific vertex. Replaces the current vertex weight data supplied. The weights should sum to 1.0f. Both boneNodelist and weights must be the same size . - - - Parameters: - *skinNode - - The node that has skin applied to it, used to obtain the local mod data for that node and skin since the same modifier can be applied to multiple nodes through instancing. - - int vertexID - - The index of the vertex to apply weights to. - - <INode*> &boneNodeList - - The list of bones that will control the vertex, these must already be added to the skin modifier. - - <float> &weights - - The weight of each bone. - - - TRUE if the operation succeeded. - - - - - Description: - class for setting and getting a special, - - non-animated, transformation pose, SkinPose. - - - - - - - Method to obtain the position part of the transformation pose. - - - - - The position of the pose expressed as 3-vector (). - - - - - - - Method to obtain the rotation part of the transformation pose. - - - - - The rotation of the pose expressed as an , which can be quaternion or Euler angle type. - - - - - - - Method to obtain the scale part of the transformation pose. - - - - - The scale of the pose expressed as possibly unequal values along the principal axes of a coordinate system whose orientation is defined by a quaternion. - - - - - - - Method to set the pose rotation to a given Euler angle. - - - Parameters: - - - The rotation of the pose expressed as an Euler angle vector. - - - - - - - Method to determine if the pose position is enabled. - - - bool - - If true, the pose position is enabled. - - If false, the pose position is disabled. - - - - - - - Method to determine if the pose rotation is enabled. - - - bool - - If true, the pose rotation is enabled. - - If false, the pose rotation is disabled. - - - - - - - Method to determine if the pose scale is enabled. - - - bool - - If true, the pose scale is enabled. - - If false, the pose scale is disabled. - - - - - - - Member function yielding a whether the node is in the Skin Pose mode. In this mode, the node will assume the skin pose, subject to "enabled" flags of the three (position, rotation, and scale) parts, as its transformation, rather than from the normal channel, the transform controller. - - - bool - - If true, the node transformation is in the skin pose mode. - - If false, it is in the normal mode. - - - - - - - Sets the state of the pose position transform. - - - Parameters: - bool - - If true, the pose position transform is enabled. - - If false, the pose position transform is disabled. - - - - - - - Sets the state of the pose rotation transform. - - - Parameters: - bool - - If true, the pose rotation transform is enabled. - - If false, the pose rotation transform is disabled. - - - - - - - Sets the state of the pose scale transform. - - - Parameters: - bool - - If true, the pose scale transform is enabled. - - If false, the pose scale transform is disabled. - - - - - - - Sets the state of all three non-animated skin pose transforms, subject to the "enabled" flags, to the animated normal pose at a particular time. - - - Parameters: - TimeValue - - Time at which the animated normal pose is used as the target to set the skin pose transforms. - - - - - - - Sets the state of all three animated normal pose transforms, subject to the "enabled" flags, at a particular time, to the non-animated skin pose transforms. - - - Parameters: - TimeValue - - Time at which to set the normal pose transforms. - - - - - - - This is a utility method used to set value to the node transform. According to whether it is in the skin pose mode and the three "enabled" flags, it will set value to the TM controller or the skin pose transforms. - - - Parameters: - TimeValue - - Time at which to set the pose transform. - - & - - Controller values for the transform. - - - - - - - Method to obtaion the Euler angles of the pose rotation. - - - - - The Euler angles about x, y, and z. - - - - - - - Method to obtain the scale factors of the pose transformation. - - - - - The scale factors along the x, y, and z axes. - - - - - - - Method to obtain the scale factor orientation of the pose transformation. - - - - - The axis and angle of the scale factor orientation. - - - - - - - Method to determine if the pose position component is enabled and the node is in the skin pose mode. - - - bool - - If true, the position of the node transform will come from the skin pose. - - If false, the position of the node transform comes from the normal TM controller. - - - - - - - Method to determine if the pose rotation component is enabled and the node is in the skin pose mode. - - - bool - - If true, the rotation of the node transform will come from the skin pose. - - If false, the rotation of the node transform comes from the normal TM controller. - - - - - - - Method to determine if the pose scale component is enabled and the node is in the skin pose mode. - - - bool - - If true, the scale of the node transform will come from the skin pose. - - If false, the scale of the node transform comes from the normal TM controller. - - - - - - - Method to determine if one or more pose components; position, rotation, or scale are enabled. - - - bool - - If true, one or more components are enabled. - - If false, none of the components are enabled. - - - - - - - Method to indicate that a post transform component has changed from the default and needs to be saved. - - - bool - - If true, a pose component has changed. - - If false, no pose component has changed. - - - - - - - Method to write pose data to a file. - - - Parameters: - ISave* - - Pointer for use in calling write methods. - - - IOResult - - If IO_OK, the method succeeded. - - If IO_ERROR, the method was unsuccessful. - - - - - - - Method to read pose data from a file. - - - Parameters: - ILoad* - - Pointer for use in calling read methods. - - - IOResult - - If IO_OK, the method succeeded. - - If IO_ERROR, the method was unsuccessful. - - - - - - - Method to copy data members from an existing instance to the current one. - - - Parameters: - & - - Reference to instance of this class to copy from. - - - - - - - Determines whether this is a const object of a particular subclass derived from . It is used for the internal implementation purpose. - - - Parameters: - void* - - Pointer to the subclass identifier to test. - - - void* - - Const pointer to subclass. - - - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - is used by the radiosity system and LightTracer to evaluate skylight. It also is used to determine whether the intensity of the light object should be measured as a 3ds Max multiplier (for example Texture Sky) or as a physical quantity (for example the IES Sky). - - If a light object's class claims to be a sky, it should derive from and implement IsIntensityInMAXUnits to return true if its intensity is in 3ds Max units, or false if its intensity is in lux. It also needs to implement CreateSkyEval which is used to create an object that can be used to evaluate the skylight at different directions. - - Deriving from an interface (such as ) also require the child class to override GetInterface() to return the interface pointer. Here is a code example: - - - - - - - - - This method is used to create the object that samples the sky for the radiosity and global lighting plugins. - - - Parameters: - TimeValue t - - T is the current time - - *node - - node is the node for the light object we are asking to create the - - & tm - - tm is a matrix that transforms (0,0,1) to the Zenith direction (that is straight up) for the sky in the scene - - - - - - - none - - - - - Description: - Important Note: The slider control ensures that it only displays, and the user is only allowed to input, values within the specified ranges. However the slider is just a front end to a controller which actually controls the value. The user can thus circumvent the slider constraints by editing the controller directly (via function curves in track view, key info, etc.). Therefore, when a plug-in gets a value from a controller (or a parameter block, which may use a controller) it is its responsibility to clamp the value to a valid range. - - - The custom slider control is functionality similar to the custom spinner control. It supports the following features: - - - - - - - Returns the floating point value of the control. - - - - - Returns the integer value of the control. - - - - - Sets the number of segments (tick marks) used by the control. - Parameters: - int num - - The number to set. - - - - - This method sets the value of the control to the specific floating point number passed. You may pass FALSE as the notify parameter so the control wont send a message when you set the value. - Parameters: - float v - - The new value for the control. - - int notify - - If TRUE a message is sent indicating the control has changed; if FALSE no message is sent. - - - - - This method sets the value of the control to the specific integer number passed. You may pass FALSE as the notify parameter so the control wont send a message when you set the value. - Parameters: - int v - - The new value for the control. - - int notify - - If TRUE a message is sent indicating the control has changed; if FALSE no message is sent. - - - - - This method establishes the allowable limits for integer values entered. - Parameters: - int min - - The minimum allowable value. - - int max - - The maximum allowable value. - - int limitCurValue = TRUE - - You may pass FALSE to the this parameter so the control will not send a spinner changed message when the limits are set. - - - - - This method establishes the allowable limits for floating point values entered. - Parameters: - float min - - The minimum allowable value. - - float max - - The maximum allowable value. - - int limitCurValue = TRUE - - You may pass FALSE to the this parameter so the control will not send a spinner changed message when the limits are set. - - - - - When an edit control is used in conjunction with the slider control, this method is used to link the two, so values entered using the slider are displayed in the edit control. This method is also used to set the type of value which may be entered. - Parameters: - HWND hEdit - - The handle of the edit control to link. - - EditSpinnerType type - - The type of value that may be entered. One of the following values: - - EDITTYPE_INT - - Any integer value. - - EDITTYPE_FLOAT - - Any floating point value. - - EDITTYPE_UNIVERSE - - This is a value in world space units. It respects the system's unit settings (for example feet and inches). - - EDITTYPE_POS_INT - - Any integer >= 0 - - EDITTYPE_POS_FLOAT - - Any floating point value >= 0.0 - - EDITTYPE_POS_UNIVERSE - - This is a positive value in world space units. It respects the system's unit settings (for example feet and inches) . - - EDITTYPE_TIME - - This is a time value. It respects the system time settings (SMPTE for example). - - - - - This method is used to show commonality. When several different values are being reflected by the slider, the value is indeterminate. When TRUE, the value field of the slider appears empty. - Parameters: - BOOL i=TRUE - - Pass TRUE to this method to set the value to indeterminate. - - - - - This method returns TRUE if the current state of the slider is indeterminate; otherwise FALSE. See SetIndeterminate() above. - - - - - A user may right click on a slider to reset it to its 'reset' value (after it has been changed). This method specifies the value used when the reset occurs. - Parameters: - float v - - The reset value. - - - - - A user may right click on a slider to reset it to its 'reset' value (after it has been changed). This method specifies the value used when the reset occurs. - Parameters: - int v - - The reset value. - - - - - Sets the display of the 'brackets' surrounding the slider control. This is used to indicate if a key exists for the parameter controlled by the slider at the current time. These brackets turned on and off automatically if you are using a parameter map and parameter block to handle the control. If not you'll need to use this method. For a slider, the 'brackets' appear as a colored dot in the position marker. - Parameters: - BOOL onOff - - TRUE for on; FALSE for off. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - This class is only used to communicate some information between the 3ds Max Standard and the Shaders for the 3ds Max Standard . The information that the Shaders require that wasn't supplied previous is the . This would be used by 3rd parties who want to write shaders for the 3ds Max standard material. This is only required if the shader performs operations that are not valid for arbitrary light values. For example: Using the default values, the Physical Sun has light multiplier values that are around 60. - - Several standard 3ds Max shaders, like the Aniso and ONB shaders, composite specular highlights over the diffuse light, and the calculation looks something like: - - color = diffuse * (1 - specular) + specular; - - This works fine as long as specular is between 0 and 1. If specular goes above 1, you get all kinds of unusual artifacts. This calculation is done this way to prevent color clipping because of bright specular highlights. With lighting values at 60, the specular is frequently greater than 1.With an exposure control, the exposure control manages the color clipping and we can simply add the diffuse and specular components. - - This interface gives the shader a chance to investigate the render parameters and decide how the lighting is to be combined. - - This is usually done by using multiple inheritances and deriving the Implementation from and . - - The needs to override GetInterface(Interface_ID id) and return the address of the ISpecularCompositShader interface and GetRequirements also needs to be overriden to return MTLREQ_PREPRO as one of the shader requirements. - - Then the shader needs to implement ChooseSpecularMethod. The typical implementation is: - - void CombineComponentsCompShader::ChooseSpecularMethod(TimeValue t, RenderGlobalContext* rgc) - - { - - useComposite = true; - - if (rgc == NULL) { - - ToneOperatorInterface* tint = static_cast<ToneOperatorInterface*>( - - GetCOREInterface(TONE_OPERATOR_INTERFACE)); - - if (tint != NULL) { - - ToneOperator* top = tint->GetToneOperator(); - - if (top != NULL && top->Active(t)) - - useComposite = false; - - } - - } else { - - ToneOperator* top = rgc->pToneOp; - - if (top != NULL && top->Active(t)) - - useComposite = false; - - } - - } - - - - - - - To be implemented Shaders. Provides a selection mechanism for the specular methods provided by various tone operators either provided by the System or by the implementing . - - - Parameters: - TimeValue t - - Present scene time value. - - *rgc - - Pointer to a that encapsulates the shared data between a Standard and the implementing . - - - - - Description: - The spinner control is used (usually in conjunction with the custom edit control) to provide input of values limited to a fixed type. For example, the control may be limited to the input of only positive integers. The input options are integer, float, universe (world space coordinates), positive integer, positive float, positive universal, and time. This control allows the user to increment or decrement a value by clicking on the up or down arrows. The user may also click and drag on the arrows to interactively adjust the value. The Ctrl key may be held to accelerate the value changing speed, while the Alt key may be held to decrease the value changing speed. - - The standard size used by 3ds Max for the spinner control is 7 wide by 10 high. If you use a larger size, the spinner control arrows will be position in the upper left corner of the control. - - Important Note: The spinner control ensures that it only displays, and the user is only allowed to input, values within the specified ranges. However the spinner is just a front end to a controller which actually controls the value. The user can thus circumvent the spinner constraints by editing the controller directly (via function curves in track view, key info, etc.). Therefore, when a plug-in gets a value from a controller (or a parameter block, which may use a controller) it is its responsibility to clamp the value to a valid range. - - - To initialize the pointer to the control call: - - *GetISpinner(HWND hCtrl); - - To release the control call: - - ReleaseISpinner(ISpinnerControl *isc); - - The value to use in the Class field of the Custom Properties dialog is: - - The following messages may be sent by the spinner control: - - This message is sent when the value of a spinner changes. - - CC_SPINNER_CHANGE - - lParam contains a pointer to the spinner control. You can cast this pointer to a type and then call methods of the control. - - LOWORD(wParam) contains the ID of the spinner. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) is TRUE if the user is dragging the spinner interactively. - - This message is sent when the user presses down on the spinner buttons. - - CC_SPINNER_BUTTONDOWN - - lParam contains a pointer to the spinner control. You can cast this pointer to a type and then call methods of the control. - - LOWORD(wParam) contains the ID of the spinner. This is the named established in the ID field of the Custom Properties dialog. - - This message is sent when the user releases a spinner button. - - CC_SPINNER_BUTTONUP - - lParam contains a pointer to the spinner control. You can cast this pointer to a type and then call methods of the control. - - LOWORD(wParam) contains the ID of the spinner. This is the named established in the ID field of the Custom Properties dialog. - - HIWORD(wParam) is FALSE if the user canceled and TRUE otherwise. - - For example, if the user is interactively dragging the spinner, then does a right click to cancel, the following messages are sent: - - 1 A CC_SPINNER_BUTTONDOWN message indicating the user has pressed the spinner button. - - 2. A series of CC_SPINNER_CHANGE where HIWORD(wParam) = TRUE. This indicates that the spinner is being dragged interactively. - - 3. A CC_SPINNER_CHANGE where HIWORD(wParam) = FALSE. - - 4. A CC_SPINNER_BUTTONUP message where HIWORD(wParam) = FALSE. This indicates the user has cancelled. - - - - - Returns the floating point value of the control. - - - - - This method returns the integer value of the control. - - - - - This method sets the scale for the spinner based on the current value of the spinner. This allows the spinner to cover a larger range of values with less mouse motion. If you wish to use auto scale, pass TRUE to this method. - - If you wish to use auto scale pass TRUE to this method; otherwise FALSE. - - - - This method sets the value which is added to or subtracted from the current control value as the arrow buttons are pressed, or the user interactively drags the spinner. - - The value is added to or subtracted from the current control value. - - - - This method sets the value of the control to the specific floating point number passed. You may pass FALSE as the notify parameter so the control wont send a message when you set the value. - - The new value for the control. - If TRUE a message is sent indicating the control has changed. Note that sometimes the method is used to update the display of parameters in the user interface. For example, if the user changes the current time and the parameters are animated, the user interface controls must be updated to reflect the value at the new time. The programmer calls to update the value displayed in the control. This is an example of when to pass FALSE as the notify parameter. If you were to pass TRUE, a message would be sent as if the user had actually enter a new value at this time. These are of course very different conditions. - - - - This method sets the value to the specific integer passed. You may pass FALSE as the notify parameter so the control won't send a message when you set the value. - - The new value for the control. - If TRUE a message is sent indicating the control has changed. - - - - This method establishes the allowable limits for integer values entered. - - The minimum allowable value. - The maximum allowable value. - You may pass FALSE to the this parameter so the control will not send a spinner changed message when the limits are set. - - - - This method establishes the allowable limits for floating point values entered. - - The minimum allowable value. - The maximum allowable value. - You may pass FALSE to the this parameter so the control will not send a spinner changed message when the limits are set. - - - - When an edit control is used in conjunction with the spinner control, this method is used to link the two, so values entered using the spinner are displayed in the edit control. This method is also used to set the type of value which may be entered. - - The handle of the edit control to link. - The type of value that may be entered. One of the following values: Any integer value. Any floating point value. This is a value in world space units. It respects the system's unit settings (for example feet and inches). Any integer >= 0 \ Any floating point value >= 0.0 This is a positive value in world space units. It respects the system's unit settings (for example feet and inches). This is a time value. It respects the system time settings (SMPTE for example). - - - - This method is used to show commonality. When several different values are being reflected by the spinner, the value is indeterminate. When TRUE, the value field of the spinner appears empty. - - Pass TRUE to this method to set the value to indeterminate. - - - - This method returns TRUE if the current state of the spinner is indeterminate. See SetIndeterminate() above. - - - - - A 3ds Max user may right click on the spinner buttons to reset them to their 'reset' value (after they have been changed). This method specifies the value used when the reset occurs. - - The reset value. - - - - A 3ds Max user may right click on the spinner buttons to reset them to their 'reset' value (after they have been changed). This method specifies the value used when the reset occurs. - - The reset value. - - - - Sets the display of the brackets surrounding the spinner control to on. This is used to indicate if a key exists for the parameter controlled by the spinner at the current time. These brackets turned on and off automatically if you are using a parameter map and parameter block to handle the control. If not you'll need to use this method. - Sample Code: - This example shows how you do this if you only use a parameter block. - - The following functions are not part of class but are available for use with spinner controls. - - TRUE for on; FALSE for off. - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - This class is only available in release 5 or later. - This class refers to the new modifier which, when assigned to a spline (or a NURBS) curve, generates a certain number of helper objects attached to the knots of the curve. - - Spline IK (works for NURBS Point curve and NURBS CV Curve too): This is a modifier and can be used independently of the SplineIK. When applied to a spline, this modifier creates one point helper for each knot of the spline. The user can then animate the spline by simply animating (position and rotation) the point helpers. Thus to animate the spline, the user wouldn't need to get into the sub-object level. - - There are three options Link Types, presented as a set of 3 radio buttons: - - Link All in Hierarchy (default): - - Makes a helper a child to its immediately previous helper. So, Helper#2 is child to Helper#1, Helper#3 is child to Helper#2, and so on. Helper#1 is still child to the world. Translation and rotation of a helper then "solidly" moves/rotates part of the spline subsequent to the selected helper. The part of the spline previous to the helper is unaffected. - - Link All to Root - - Makes all helpers children to Helper#1, i.e., knot#1. Helper#1 can be position constrained or linked to another object, like it is possible above. Additionally individual helpers can be moved and rotated without any other helper being affect. - - No Linking - - All helpers are independent - not linked to any other helper - so that they can be moved and rotated without any other helper being affect. - - "Create Helpers" button: - - Helpers are not automatically added to the spline on the assignment of the modifier. To do that the user need to press the "Create Helpers" button. - - Helper Display: - - These are the all the options: If the user adds ("insert") a knot to the spline, a new helper object is automatically created at that knotpoint. - - Furthermore, please refer to the implementation project which is in /maxsdk/samples/modifiers/splineikcontrol. - - The following helper methods have been added to istdplug.h for general access: - - - - - Obtain the number of helpers created - - - - - - - Gets the total number of knots for spline. - - - - - - - Makes all helpers children to Helper#1, i.e., knot#1. Helper#1 can be position constrained or linked to another object, like it is possible above. Additionally individual helpers can be moved and rotated without any other helper being affected. - - - - - - - Makes a helper a child to its immediately previous helper. So, Helper#2 is child to Helper#1, Helper#3 is child to Helper#2, and so on. Helper#1 is still child to the world. Translation and rotation of a helper then "solidly" moves/rotates part of the spline subsequent to the selected helper. The part of the spline previous to the helper is unaffected. - - - - - - - All helpers are independent - not linked to any other helper so that they can be moved and rotated without any other helper being affected. - - - - - - - Helpers are not automatically added to the spline on the assignment of the modifier. To do that the user need to press the "<b>Create Helpers</b>" button. - - - - - Get's the helper nodes that define the spline. param [out] helperNodes. The node of the spline helpers. - - - - - Description: - This class provides an interface to the command modes and button press operations of the Editable Spline object. To obtain a pointer to this class use the method Animatable::GetInterface() passing I_SPLINEOPS. - - For example: - - )anim->GetInterface(I_SPLINEOPS)); - - iso->StartCommandMode(ScmAttach); - - - - - Begins the specified interactive command mode. - Parameters: - splineCommandMode mode - - The mode to begin. One of the following values: - - ScmCreateLine - - ScmAttach - - ScmInsert - - ScmConnect - - ScmRefine - - ScmFillet - - ScmChamfer - - ScmBind - - ScmRefineConnect - - ScmOutline - - ScmTrim - - ScmExtend - - ScmBreak - - ScmUnion - - ScmCrossInsert - - - - - Performs the same operation as a button press inside the Editable Spline UI. - Parameters: - splineButtonOp opcode - - The button operation to execute. One of the following values: - - SopHide - - SopUnhideAll - - SopDelete - - SopDetach - - SopDivide - - SopBreak - - SopCycle - - SopUnbind - - SopWeld - - SopMakeFirst - - SopAttachMultiple - - SopExplode - - SopReverse - - SopClose - - SopUnion - - SopSubstract - - SopIntersect - - SopMirrorHoriz - - SopMirrorVert - - SopMirrorBoth - - SopSelectByID - - SopFuse - - - - - This method allows you to get the edit spline parameters from the command panel. Currently not in use. - Parameters: - splineUIParam uiCode - - This enum is currently empty. - - int &ret - - The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit spline parameters from the command panel. Currently not in use. - Parameters: - splineUIParam uiCode - - This enum is currently empty. - - int val - - The value to set. - Default Implementation: - { } - - - - - This method allows you to get the edit spline parameters from the command panel. Currently not in use. - Parameters: - splineUIParam uiCode - - This enum is currently empty. - - float &ret - - The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit spline parameters from the command panel. Currently not in use. - Parameters: - splineUIParam uiCode - - This enum is currently empty. - - float val - - The value to set. - Default Implementation: - { } - - - - - Description: - This class provides an interface to the Spline Select Modifer. To obtain a pointer to this class use the method Animatable::GetInterface() passing I_SPLINESELECT. - - For example: - - )anim->GetInterface(I_SPLINESELECT)); - - GetSelLevel(); - - - - - Returns a value indicating the current selection level of the modifier. One of the following values: - - SS_VERTEX - - SS_SEGMENT - - SS_SPLINE - - SS_OBJECT - - - - - This method must be called when the selection level of the modifier is changed. Developers can use the methods of to get and set the actual selection data. When a developers does set any of these selection sets this method must be called when done. - - - - - Description: - When a developer gets the from the of the Spline Select , they may cast it to this class and use these methods. They may be used to get/set the vertex/segment/spline selection state of the modifier as well as the named selection sets. - - To obtain a pointer to this class use the method Animatable::GetInterface() passing I_SPLINESELECTDATA. - - For example: - - )anim->GetInterface(I_SPLINESELECTDATA)); - - ; - - - - - Returns a that reflects the current vertex selection. There is one bit for each vertex. Bits that are 1 indicate the vertex is selected. - - - - - Returns a that reflects the current segment selection. There is one bit for each segment. Bits that are 1 indicate the segment is selected. - - - - - Returns a that reflects the current spline selection. There is one bit for each spline. Bits that are 1 indicate the spline is selected. - - - - - Sets the vertex selection of the modifier. - Parameters: - &set - - There is one bit for each vertex. Bits that are 1 indicate the vertex should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Sets the segment selection of the modifier. - Parameters: - &set - - There is one bit for each vertex. Bits that are 1 indicate the segment should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Sets the spline selection of the modifier. - Parameters: - &set - - There is one bit for each spline. Bits that are 1 indicate the spline should be selected. - - *imod - - Points to the instance (generally this is a modifier). - - TimeValue t - - The current time at which the call is made. - - - - - Returns a reference to a class used for manipulating the lists of vertex level named selection sets associated with this modifier. - - - - - Returns a reference to a class used for manipulating the lists of segment level named selection sets associated with this modifier. - - - - - Returns a reference to a class used for manipulating the lists of spline level named selection sets associated with this modifier. - - - - - Description: - The methods of this class provide access to the sub-textures of a . These properties include the number of sub-maps, the slot type, on / off state, etc. - - The class sub-classes from this class. If a developer is creating a plug-in derived from (for instance a or Texture) then implementations of these methods are required. Developers may call these methods on an existing sub-class. - - - - - Returns the number of sub-textures managed by this material or texture. - Default Implementation: - { return 0; } - - - - - Returns a pointer to the 'i-th' sub-texmap managed by the material or texture. - - Note: For the 3ds Max Standard material, the sub-texmap indexes used with this method are listed in Texture Map Indices. - Parameters: - int i - - Specifies the texmap to return. - Default Implementation: - { return NULL; } - - - - - In the Coordinates rollup in the user interface for a texture map are two options. These options are Texture or Environment. The slot type is one of these two options, texture coordinates or environment coordinates. There are a variety of texture coordinate types. There are the type assigned to the object and the environment type (Spherical, Cylindrical, Shrink-wrap, Screen). This method is used to determine the type required by the particular sub-texture. This is either texture coordinates (MAPSLOT_TEXTURE) or environment coordinates (MAPSLOT_ENVIRON). - Parameters: - int i - - The index of the sub-texture whose slot type to return. - See Map Slot Types. - Default Implementation: - { return MAPSLOT_TEXTURE; } - - - - - Stores the 'i-th' sub-texmap managed by the material or texture. - - Note: For the 3ds Max Standard material, the sub-texmap indexes used with this method are listed in Texture Map Indices. - Parameters: - int i - - The index of the storage for the texmap. - - *m - - The texmap to store. - Default Implementation: - {} - - - - - Returns nonzero if the specified sub-texmap is on; otherwise zero. Some materials may have user interface controls to toggle the sub-maps on and off. The Standard material has such controls for example. - Parameters: - int i - - The index of the sub-texmap to check. - Default Implementation: - { return 1; } - - - - - This method returns the slot name of the 'i-th' sub-texmap. This name appears in the materials editor dialog. For instance, if you are in a material and then you go down into a map, this is the name that appears just below the 'Get ' icon. For example, in the Standard material when you choose one of the maps, the map name appears to let you know which slot you are working on. For the Standard material, this may be "Ambient", "Diffuse", "Specular", etc. - Parameters: - int i - - Specifies the slot whose name is returned. bool localized - - If true, then the slot name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the slot name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the slot name in English. - Default Implementation: - The default implementation returns an empty ("") string. - - - - - Returns the name to appear in Track of the 'i-th' sub-texmap. - Parameters: - int i - - Specifies the sub-texmap whose track view name is returned. bool localized - - If true, then the sub-texmap TV name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the sub-texmap TV name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the sub-texmap TV name in English. - - - - - This method is called by the ParamMap2 AUTO_UI system if the material/texmap is letting the system build an AutoMParamDlg for it. This method is called on a material/texmap coming into an existing set of ParamDlgs, once for each secondary and it should set the appropriate 'thing' into the given dlg (the 'thing' being, for example, a Texout* or UVGen*). Return FALSE if dlg is unrecognized. - - Note: See the discussion above in CreateParamDlg() for additional details on this method. - Parameters: - ParamDlg* dlg - - Points to the to check. See Class . - TRUE if the dlg passed is recognized; FALSE if unrecognized. - Default Implementation: - { return FALSE; } - Sample Code: - - - - - Implemented by the System. - - This method is used to handle the drag-and-drop of texmaps. A developer implements the logic to handle the drag and drop. Once they have the information about what slot was dropped on what other slot, this method may be called to handle the copying. This is used by the 3ds Max Standard material. - Parameters: - HWND hwnd - - The rollup page window handle. - - int ifrom - - The source texmap. - - int ito - - The destination texmap. - - - - - Implemented by the System. - - The implementation of this method is provided by . It returns its this pointer. - - - - - Description: - This class is used if you wish to support the direct assignment of sub materials to selected faces. For a reference implementation of this class, please refer to the code in /MAXSDK/SAMPLES/MESH/EDITABLEMESH/TRIOBJED.CPP. - - - - - This method returns a material ID that is currently not used by the object. If the current face selection share one single MtlDI that is not used by any other faces, you should use it. - - - - - This method indicates if you are active in the modifier panel and have an active face selection. Return TRUE if so, otherwise FALSE. - - - - - This method sets the selected faces to the specified material ID.. - Parameters: - MtlID id - - The material id to set for the selected faces. - - BOOL bResetUnsel = FALSE - - If TRUE, then you should set the remaining unselected face material IDs to 0. - - - - - This method returns the material ID of the selected face(s). If multiple faces are selected they should all have the same MtlID - otherwise you should return -1. If faces other than the selected share the same material ID, then return -1. - - - - - This method returns the material ID of the selected face(s). If multiple faces are selected they should all have the same MtlID, otherwise return -1. - - - - - This method returns the highest MtlID on the object. - - - - - - - - - Returns a filter for the i-th sub-texmap (indices are identical to those used with class ). - - - The filter at index i - - - The index of the filter to return - - - - Returns a filter for the i-th sub-material. - - - The (indices are identical to those used with class ). Note that this is only useful for plugins. plugins should return NULL. - The filter at index i - - - The index of the filter to return - - - - Developers have to return a class derived from this class with implementations for all the methods when implementing sub-objects for objects and modifiers (see BaseObject::GetSubObjType()). - - - - - - Returns a pointer to the icon for this sub-object type. This icon appears in the stack view beside the name. - - - - - Returns the name of this sub-object type that appears in the stack view. - - - - - gives access to sub-transform controller. - - - This interface is used to detect when a transform controller is just modifying the transform of a sub-transform-controller. The target of the sub-controller must be returned as the target of the parent controller. Setting the value of the parent controller should modify the value and set the value of the sub-controller to the modified value. - - - - - Return whether this controller allows the sub-controller to be assigned. - - - - - Assign the sub-controller. - - - - Sub-controller to assign; must be a controller. - - - - Returns the sub-controller. - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - is used by the radiosity system to determine whether the intensity of the light object should be measured as a 3ds Max multiplier (for example directional light) or as a physical quantity (for example the IES Sun). - - If a light object's class claims to be a sun, it should derive from and implement IsIntensityInMAXUnits to return true if its intensity is in 3ds Max units, or false if its intensity is in lux. - - - - - - - return true if its intensity is in 3ds Max units, or false if its intensity is in lux. - - - - - Description: - This class provides access to the surface position controller's parameters. - - The following values may be used to access the surface controller's references. - - SURFCONT_U_REF - - SURFCONT_V_REF - - SURFCONT_SURFOBJ_REF - - All methods of this class are implemented by the system. - - - - - Sets the node that this controller uses as the surface object. - Parameters: - *node - - Points to the node to set. - - - - - Returns the alignment setting. - One of the following values: - - 0: No Alignment. - - 1: Align to U. - - 2: Align to V. - - - - - Returns the flip setting. TRUE if on; FALSE if off. - - - - - for interactions between 'systems', in particular biped, and the max xref core. This interface allows for xrefs to notify systems when key operations occur so they may act accordingly. The interface ID is I_SYSTEM_XREF defined in AnimatableInterfaceIDs.h. - - - - - The system is created as an object xref. - - - - - The system is no longer an object xref. Most likely because it has been merged into the scene. - - - - - The system is updated. Passed in this the head node of the system that's being xref'd in. - - - the first node returned from - - - - Description: - This interface is used to manage a tabbed dialog. You can add pages and either display a modal or modeless dialog. You can add a rollout page, that can contain MAX rollouts - - - - - Return the dialogID for this dialog. - - - - - Add a page to the dialog. - - - The created page - - - the tab text. - - instance for the dialog template. If instance is NULL, the tmplt is a pointer to the dialog template in memory. - - The resource for the dialog template. - - The message handler for the page. - - The ID of the page to add the rollout to - - The plugin to set as the tab pages plugin - is ID used for context sensitive help. - - The order that the tab will appear in the tabs. Two pages with the same order are ordered by the order they are added. - - An image for the tab in the image list set by SetImageList. - - - - Add a rollout page to the dialog. - - - - - the tab text. - - the message handler for the page. - - The ID of the page to add the rollout to - - The plugin to set as the tab pages plugin - - The ID of the control window - - The width of the rollout to create - - The margins give additional space between the rollout control and the client. - - ID used for context sensitive help. - - the order that the tab will appear in the tabs. Two pages with the same order are ordered by the order they are added. - - an image for the tab in the image list set by SetImageList. - - - - Add and remove registered tabs to the dialog. - - - - - Get the filter for this dialog. - - - This dialogs filter - - - - - Get the dialog proc. - - - The current dialog proc - - - - - the dialog proc. - - - The previous dialog proc - - - - - Display and process modal dialog. - - - - - Display and process modeless dialog. - - - - - Switch to the given page. - - - - - Invalidate all pages in the dialog. - - - - - the image list for the tab control. - - - - - Get the index of the current page. - - - - - the margins for the tab in the dialog. - - - This is only applicable if the tabCtrl is not part of the dialog template. If SetTabbedRect is called with a nonempty rectangle, it is used, otherwise the margins are used. - - - The left margin - - the top margin - - the right margin - - the bottom margin - - - - the margins for the tab in the dialog. - - - This is only applicable if the tabCtrl is not part of the dialog template. If SetTabbedRect is called with a nonempty rectangle, it is used, otherwise the margins are used. - - - - - Get the number of pages. - - - - - return the page at index - - - - - return the page with the passed class ID - - - - - Get the window for the tabbed dialog. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - Used for modeless dialogs. - - - note that if the user hits the X in the upper right corner, a cancel message will be sent. - - - - - Used for modeless dialogs. - - - note that if the user hits the X in the upper right corner, a cancel message will be sent. - - - - - Used for both modal and modeless dialogs. - - - - - Used for both modal and modeless dialogs. - - - - - Get the window for the tab control. - - - - - Description: - This interface is used to filter plugin tabs in a tabbed dialog. - - - - - Test if the passed tab is acceptable to the dialog being filtered. - - - true if the tabs added by the tab are acceptable for this dialog. - - The Dialog tab to test - - - - Launch the dialog for this filter, open the dialog at a specific page. - - - - The ID of the dialog page to open - - - - The following functions return various information that is likely to be interesting when deciding whether or not to add a tab. - - - If this dialog is the UI for a , return it here. - - - - - Otherwise, if this dialog is the UI for an , return it here. - - - - - Otherwise, If this dialog has some known class ID and super class ID. - - - - - Otherwise, you will need to define a special interface. - - - - - Description - This interface is used to create tabbed dialogs and to register tabs with dialogs that are created by the system or other plugins - - - - - Create a tabbed dialog. - - - The created - - - the parent window of the dialog - - the instance where the dialog template is stored - - the name of the dialog template resource. If instance is NULL, then dlg is a pointer to the dialog template in memory. - - the object that is used to handle messages for the dialog. - - true if the tab control should be multiline and is only applicable when tabID is -1. - - is used to bring up context sensitive help when the F1 key is pressed. - - the ID of a tab control in the dialog template that is to be used. If tabID is -1, then a tab control is created. - - the id of the dialog this tab is to be used with. - - - - Register a tab for a dialog. - - - true on success, false otherwise - - - the id of the dialog this tab is to be used with. - - is the address of an object that is used to add the tab when the dialog is created. must remain valid while it is registered. - - - - UnRegister a tab for a dialog. - - - - - the id of the dialog this tab is to be used with. - - is the address of an object that is used to add the tab when the dialog is created. must remain valid while it is registered. - - - - the current plugin tab filter for a dialog. - - - This filter is used to determine which tabs will be present when the dialog is created. - - - the id of the dialog this filter is to be used with. - - The filter to run over the tabs in the dialog - - - - Get the current plugin tab filter for a dialog. - - - This filter is used to determine which tabs will be present when the dialog is created. - The current filter on the dialog - - - the id of the dialog to return the filter off. - - - - Get the for the dialog id. - - - Returns NULL if dialog not present. Assumes that only one dialog is present for a dialog id at a time. Note: NOTIFY_TABBED_DIALOG_CREATED and NOTIFY_TABBED_DIALOG_DELETED sent when a tabbed dialog is created or deleted. - The of the passed dialog if present, else NULL - - - the id of the dialog to return the of - - - - Notify the object that the dialog is activated in a tabbed dialog. - - - - - Notify the object that the dialog is deactivated in a tabbed dialog. - - - - - Add your tab(s) to the dialog. - - - This will only be called if both this object and the dialog agree that the tab should be added. - - - the address of the dialog. - - The tab to add - - - - Return true if the tabs added by the tab are acceptable for this dialog. - - - The acceptable action to take for this tab - - - the tab being filtered. - - - - Add your tab(s) to the dialog. - - - This will only be called if both this object and the dialog agree that the tab should be added. - - - a pointer to the dialog. - - - - Test to accept this tab in this dialog. - - - Return true if the tab should be added. Return false if the tab should not be added or should be removed if it was added previously. - - - the dialog filter. - - - - The following functions return various information that is likely to be interesting when deciding whether or not to use this tab. - - - If this tab is the UI for a , return it here. - - - - - Otherwise, if this tab is the UI for an , return it here. - - - - - Otherwise, If this tab has some known class ID and super class ID. - - - - - Otherwise, you will need to define a special interface. - - - - - Description - This interface is implemented by the code that wants to use the tab dialog. The implementer can choose whether to respond to the methods or to messages - - - - - Get the dialog we are handling messages for. - - - the current dialog - - - - - Initialize the dialog. - - - - - Invalidate the dialog. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - The dialog is being closed. - - - This is called after all of the pages have been committed. - - - - - The dialog is being canceled. - - - - - Resize the dialog. - - - This method is only called if the size needs to be increased. If the dialog was resize, the dialog manager will resize the tab control and the content. The dialog proc may change the delta values to correspond the the amount the dialog was resized. - true if the dialog was resized. - - - The required change in size. - - - - The general message proc. - - - This proc is like a dialog proc, not a window proc - TRUE if the message was handled, else FALSE to allow further processing - - - See the - - the meaning and usage of these parameters depends on the message. - - - - Get extension interfaces, if there are any. - - - - - Description - This interface is used to manage a page in a tabbed dialog. - - - - - Get the window for this page. - - - - - Get the for this page. - - - - - Get the help ID for the page. - - - - - Get the tab dialog containing this page. - - - - - Get the tab dialog page proc. - - - The current proc - - - - - the tab dialog page proc. - - - The previous tab dialog page proc - - - The proc tab dialog page proc to use - - - - Get the Plugin that added this page. - - - - - Convert pages to indices. - - - - - Refresh your UI. - - - - - Get the interface for the rollout. - - - This interface should not be released, because it is release by this object when the rollout is destroyed. - NULL is returned if the page is not a rollout. - - - - - Description: - This interface is used to filter plugin tabs in a tabbed dialog. - - - - - Get the dialog page we are handling messages for. - - - The current dialog page - - - - - Initialize the dialog. - - - - - Invalidate the dialog. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - Used for modal dialogs with IDOK and IDCANCEL. - - - - - The dialog is being closed. This is called after all of the pages have been committed. - - - - - The dialog is being canceled. - - - - - Switch from this page. - - - - - Switch to this page. - - - - - The general message proc. - - - This proc is like a dialog proc, not a window proc - TRUE if the message was handled, else FALSE to allow further processing - - - See the - - the meaning and usage of these parameters depends on the message. - - - - This class is a callback for computing bump basis vectors on a given set of triangle/quad faces. The callback could be used as an input parameter of the method ComputeMikkTangents to compute the tangent and binormal(bitangent). The Plug-ins need to implement GetNumberOfFaces, GetNumberVerticesOfFace, GetVertex, GetNormal and GetTexture methods to input all required data to be computed, and SetTangent method to output the computation results. Usage: The following code demostrates how to compute the MikkT tangents for a given triangle face. - - - - - Get the number of faces to be computed. - The the number of faces to be computed. - - - - - Get the number of vertices for the given index of face. - The number of vertices for the given index of face. - - The index of the face. - - - - Get the vertex coordinates for the given index of face and index of vertex. - - The vertex coordinates for the given index of face and index of vertex. - The index of the face. - The index of the vertex based on the face. - - - - Get the normal coordinates for the given index of face and index of vertex. - - The normal coordinates for the given index of face and index of vertex. - The index of the face. - The index of the vertex based on the face. - - - - Get the texture coordinates for the given index of face and index of vertex. - - The texture coordinates for the given index of face and index of vertex. - The index of the face. - The index of the vertex based on the face. - - - - the tangent and binormal(bitangent) coordinates for the given index of face and index of vertex. - - The tangent coordinates for the given index of face and index of vertex. - The binormal(bitangent) coordinates for the given index of face and index of vertex. - The handedness of tangent basis, either 1.0f or -1.0f. the handedness can be used to determine the direction of the binormal(bitangent), callers can use normal, tangent and handedness to re-calculate the binormal(bitangent) in pixel level, binormal(bitangent) = handedness * CrossProd(normal, tangent); - The index of the face. - The index of the vertex based on the face. - - - - Description: - The TargetedIO system is useful for renderers that wish to implement custom Render Preset categories. The Mental categories "Processing" and "Illumination" are an example. TargetedIO is NOT important to developers who wish only to load and save render presets, and are not implementing their own renderer. - - Abstractly, represents a subset of the current scene, a "targeted" set of parameters, to be saved as a preset. Render Preset files are stored in the same format as .max files, but contain only the target parts of the scene, namely the renderer's parameters. - - In practice, an instance is passed to the renderer when presets are saved and loaded. The renderer filters what is saved and loaded by interacting with this IO object. - - - - - This is used when a preset is saved. - - - It is possible for the user to choose some categories for the preset without selecting the renderer itself. In this case the renderer is NOT part of the preset and its Load() method is not called when the preset is loaded. Other categories defined by the renderer might still be saved in the preset. For this reason, it is important that each category be separate a with its own Load() and Save(). - - - a category ID number as determined by the renderer. - - the object which embodies this category of parameters. - - - - This is used when a preset is loaded. - - - The renderer can then copy this loaded set of parameters into its own active set. As described above, the renderer might not have its Load() method called when the preset is loaded, so so the renderer must take responsibility to call GetSaveTarget() and manually copy its parameters out of this object. - the that was loaded under that category. - - - A category ID number as determined by the renderer. - - - - This is used internally and should not be called by developers. - - - - - This is used internally and should not be called by developers. - - - - - Allows the renderer to preserve a object before a preset is loaded. - - - these utility methods can be used by renderers to hang on to reference targets between the RenderPresetsPreLoad and RenderPresetsPostLoad calls. This is needed when the user has chosen to save the renderer in the preset, but NOT all of its parameters. In this case the renderer's Load() will be called which may result in loading parameters that the user did not want as part of the preset. If the renderer sees that a certain category is not being loaded, it can Store() that object before the load and Retrieve() it afterwards, restoring its active set of parameters to their correct value. - - - A category ID number as determined by the renderer. - - the object which embodies this category of parameters. - - - - returns a referenceTarget that was previously saved with Store(). - - - these utility methods can be used by renderers to hang on to reference targets between the RenderPresetsPreLoad and RenderPresetsPostLoad calls. - the object which embodies this category of parameters. - - - A category ID number as determined by the renderer. - - - - Description: - This is the text shape object interface. This class gives access to the standard 3ds Max text object. It allows the text objects font, string, and style bits to be retrieved and set. All methods of this class are implemented by the system. - - To get a pointer to an interface given a pointer to a object, use the following macro (defined in AnimatableInterfaceIDs.h ). Using this macro, given any , it is easy to ask for the text object interface. - - GetTextObjectInterface(anim)#define - - ((ITextObject*)anim->GetInterface(I_TEXTOBJECT)) - - A plug-in developer may use this macro as follows: - - ; - - This return value will either be NULL or a pointer to a valid text object interface. You may then use this pointer to call methods of this class to retrieve and modify the object data. For example: - - ito->SetUnderline(TRUE); - - Note: Some aspects of the text are controlled by its parameter block. Developers can access the parameter block by calling ito->GetParamBlock(). The following are the indices into the parameter block used to access the size, kerning and leading parameters: - - TEXT_SIZE - - TEXT_KERNING - - TEXT_LEADING - - - - - This method may be called to change the text string. Note that you can't change the string if the current font is not installed. - Parameters: - MSTR string - - The new text string. - TRUE if the string is changed; otherwise FALSE. - - - - - This method may be called to change the text font. - Parameters: - MSTR name - - The name of the font. - - DWORD flags - - One or more of the following values: - - TEXTOBJ_ITALIC - - TEXTOBJ_UNDERLINE - TRUE if the font was successfully changed; otherwise FALSE. - - - - - Returns the name of the text font. - - - - - Returns the text string. - - - - - Returns TRUE if the text is italicized; otherwise FALSE. - - - - - Returns TRUE if the text is underlined; otherwise FALSE. - - - - - This class represents the interface for the time slider. - - - The interface ID is defined as TIMESLIDER_INTERFACE. - - All methods of this class are Implemented by the System. - - - - - This method allows you to set the visibility flags of the time slider. - Parameters: - BOOL bVisible - - TRUE to set the time slider visible, otherwise FALSE. - - BOOL bPersistent = TRUE - - If this parameter is set to TRUE the value will be written to the ini file so the visibility switch will be persistent between sessions. this parameter to FALSE if you wish to reset the visibility switch the next time 3ds Max starts. - - - - - This method returns TRUE if the time slider is visible, otherwise FALSE. - - - - - Description: - The track bar offers a quick way to manipulate keyframes for selected objects. Keys are displayed on the track bar just like they are in Track . Developers are able to manipulate the track bar using this class. There is a method of class which returns a pointer to an instance of this class: - - ITrackBar* GetTrackBar(). - - All methods of this class are Implemented by the System. - - - - - Sets the visibility of the track bar to on or off. - Parameters: - BOOL bVisible - - TRUE to make visible; FALSE to hide. - - - - - Returns TRUE if the track bar is visible; otherwise FALSE. - - - - - Returns the filter value which determines which keys are shown in the track bar. See the list specified in the method above for details. - - - - - This method returns the time of the next key given a start time and a flag which indicates if the search should proceed forward or backwards. This is similar to the behavior of Animatable::GetNextKeyTime(). - Parameters: - TimeValue tStart - - Specifies the time to start looking for the next key. - - BOOL bForward - - TRUE to return the time of the next key; FALSE for the previous key. - The time of the next (or previous) key. - - - - - Redraws the Track Bar if required an optionally forces a redraw (even if not known to be required). - Parameters: - bool bForce = false - - Pass true to force a redraw; false to only redraw if 3ds Max deems it required. - - - - - Returns true if frame numbers are visible in the Track Bar; false if not. - - - - - Returns true if the audio track is displayed; false if it is not. - - - - - Returns true if the selection range bar is visible; false if it is not. - - - - - Returns true if snap to frames is on; false if it is off. - - - - - This method returns the transparency of keyframes displayed in the trackbar. - The transparency value between 0 and 255. - - - - - This method returns the transparency of selected keyframes displayed in the trackbar. - The transparency value between 0 and 255. - - - - - This method returns the transparency of the cursor displayed in the trackbar. - The transparency value between 0 and 255. - - - - - Register a new filter with the filter manager. This is usually done at startup, but does not have to be. callbackFilter or callbackAddition can be NULL The name is a UI displayable name. The ID is a unique ID so filters are not duplicated. If active is true the filter will be used to filter TrackBar key display. If stopTraversal is false. This filter will not filter out subAnims of the object is supports. - - - - - Remove a registered filter from the filter manager. - - - - - Remove a registered filter from the filter manager. - - - - - Returns the number of filters registered with the filter manager. - - - - - Get a registered filter's ID. - - - - - Get a registered filter's . - - - - - If the filter is active its Filter() method will be called once for each animatable visited by the TrackBar's traverser. - - - - - Activate or deactivate the filter. If active it will be used to filter the key display. - - - - - MAXScript support through function publishing. - - - - - Description: - This class represents the interface to the track views array. An pointer can be obtained by calling: GetCOREInterface(ITRACKVIEWS). - - - - - Description: - This class provides an interface to Track Nodes. A Track Node is simpy a class that has zero or more sub-track view nodes and zero or more sub-controllers. This is mainly used to provide a place for Global Variable tracks (labeled "Global Tracks" in Track ) and Video Post tracks (labelled "Video Post" in Track ). - - The TrackViewNode sub-nodes and sub-controllers are identified by a unique ID in the form of a variable. This does not necessarily have to be the of an existing plug-in, however plug-ins may wish to use their for any items they add to be sure they are unique. - - The class provides access to the root track view node: - - *GetTrackViewRootNode()=0; - - From the root track view node, new nodes may be added. There are two defined sub nodes identified by the following #defined Class_IDs: These can be retreived by calling GetNode() on the track view root node and passing in one of the above IDs. - - All methods of this class are implemented by the system. - - Note: Developers can also create their own track view node using the following global function: - - - - - - - This method is used to add a track view node. Note: Modifying the track view node list both from a context in which the undo system is On (holding) and Off (not holding) is unsafe. Since 3ds Max can turn on or off the undo system as needed, adding or removing track view nodes should be considered safe only when the undo system is Off. - Parameters: - ITrackViewNode* node - - Points to the Track Node to add. - - MCHAR* name - - The name for the node that appears in Track . - - cid - - The which identifies the plug-in that added the node. - - int pos = TVNODE_APPEND - - The position in the list of nodes where this one is added. If this defaults to TVNODE_APPEND the node is added at the end of the list. - If the name specified is localized, the name and its corresponding English (non-localized) name should be registered to ensure proper MAXScript access. - - - - - This method is used to add a track view controller. Note: Modifying the track view node list both from a context in which the undo system is On (holding) and Off (not holding) is unsafe. Since 3ds Max can turn on or off the undo system as needed, adding or removing track view nodes should be considered safe only when the undo system is Off. - Parameters: - Control* c - - Points to the controller to add. - - MCHAR* name - - The name that will appear in Track . - - cid - - The of the plug-in that adds the controller. - - int pos = TVNODE_APPEND - - The position in the list where the controller is added. If this defaults to TVNODE_APPEND the controller is added at the end of the list. - If the name specified is localized, the name and its corresponding English (non-localized) name should be registered to ensure proper MAXScript access. - - - - - A Track Node maintains a table that contains the sub-nodes and sub-controllers. This method returns the index into the table of the node or controller whose is passed. If the could not be found then -1 is returned. - Parameters: - cid - - The to find. - - - - - A Track Node maintains a table that contains the sub-nodes and sub-controllers. This method removes the 'i-th' sub-node or sub-controller of the table. Note: Modifying the track view node list both from a context in which the undo system is On (holding) and Off (not holding) is unsafe. Since 3ds Max can turn on or off the undo system as needed, adding or removing track view nodes should be considered safe only when the undo system is Off. - Parameters: - int i - - The zero based index into the table of the item to remove. - - - - - A Track Node maintains a table that contains the sub-nodes and sub-controllers. This method removes the sub-node or sub-controller whose is passed from the table. Note: Modifying the track view node list both from a context in which the undo system is On (holding) and Off (not holding) is unsafe. Since 3ds Max can turn on or off the undo system as needed, adding or removing track view nodes should be considered safe only when the undo system is Off. - Parameters: - cid - - The used when the node or controller was added. - - - - - This method returns a pointer to the 'I-th' sub-controller. - Parameters: - int i - - The zero based index of the sub-controller. - - - - - This method returns a pointer to the sub-controller whose is passed. - Parameters: - cid - - The used when the controller was added. - - - - - This method returns a pointer to the 'i-th' sub-node. - Parameters: - int i - - The zero based index of the sub-node. - - - - - This method returns a pointer to the sub-node whose is passed. - Parameters: - cid - - The used when the controller was added. - - - - - This method returns the total number of sub-nodes and/or sub-controllers in the table. - - - - - This method is used to rearrange the elements in the table so item i1 is where i2 was and i2 is where i1 was. Note: Modifying the track view node list both from a context in which the undo system is On (holding) and Off (not holding) is unsafe. Since 3ds Max can turn on or off the undo system as needed, adding or removing track view nodes should be considered safe only when the undo system is Off. - Parameters: - int i1 - - The zero based index into the table of one of the items to swap. - - int i2 - - The zero based index into the table of the other item to swap. - - - - - Returns the name of the 'i-th' sub-node or sub-controller. - Parameters: - int i - - The zero based index into the table of the item whose name to return. - - - - - Sets the name of the 'i-th' sub-node or sub-controller to the name passed. - Parameters: - int i - - The zero based index into the table of the item whose name to set. - - MCHAR *name - - The new name for the sub-node or sub-controller. - - - - - Registers the track view notify callback object so it recieves reference messages. - Parameters: - *notify - - Points to the callback object to register. - - - - - Un-Registers the track view notify callback object. - Parameters: - *notify - - Points to the callback object to register. - - - - - This method is available in release 4.0 and later only. - - This may be used to prevent child nodes from showing up in Track . - Parameters: - BOOL chide - - Pass TRUE to have children hidden; FALSE to have them visible. - - - - - - - Description: - This is the callback object used by IScene::EnumTree(). To use it, derive a class from this class, and implement the callback method. - - - - - This method may flag the node passed based on some property of the node. - One of the following values may be returned to control how enumeration continues: - - TREE_CONTINUE - Continue enumerating. - - TREE_IGNORECHILDREN - Don't enumerate the children of this node, but continue enumerating. - - TREE_ABORT - Stop enumerating. - - The node. The class has a method that may be used to flag this node to go into the foreground. - - - - Description: - While this is the main TreeView class used for trackview operations, most of the operations for TreeView's are inherited through the class. - - - - - - - This method will position the TreeView window at the specified position using the specified size. - Parameters: - int x, int y - - The x and y position of the TreeView window, in screen pixels. - - int w, int h - - The width and height of the TreeView window, in screen pixels. - - - - - This method shows the TreeView window. - - - - - This method hides the TreeView window. - - - - - This method allows you to enquire if the TreeView window is currently visible. - TRUE if the TreeView window is visible, otherwise FALSE. - - - - - This method allows you to enquire whether the TreeView is being displayed in a viewport. - TRUE if the TreeView is displayed in a viewport, otherwise FALSE. - - - - - This method allows you to set the TreeView root which represents the initial tree branch. - Parameters: - *root - - A pointer to a reference target to use as the root in the TreeView. - - *client - - A pointer to the reference target which is the root's client. - - int subNum - - The sub-animatable number of the root you wish to set. - - - - - This method will instruct the TreeView to show the labels only. - Parameters: - BOOL only - - The only parameter specifies if the label only flag should be set (TRUE) or not (FALSE). - - - - - This method controls the state of the TreeView's multi-select capability and allows you to enable or disable the selection of multiple selections. - Parameters: - BOOL on - - this parameter to TRUE to enable multi-select. FALSE to disable multi-select. - - - - - This method allows you to set set a TreeView selection filter which controls the amount of information displayed in the TreeView. - Parameters: - *f - - A pointer to a trackview filter which defines the displayable sub-set. - - - - - This method allows you to activate or inactivate the treeview. - Parameters: - BOOL active - - TRUE to activate, FALSE to deactivate. - - - - - This method returns whether the TreeView is active (TRUE) or inactive (FALSE). - - - - - This method returns the handle to the TreeView window. - - - - - This method - - This method returns the parent index of a specific TrackView entry. If no parent is found, -1 will be returned. - Parameters: - int index - - The index of the TrackView entry for which to return the parent index. - - - - - This method will flush the TreeView and resets its size to 0. - - - - - This method will recalculate the sub-tree and signal the list has changed. - - - - - This method will set the material browser flag. - - - - - This method returns the TrackView ID. - - - - - Description: - This class contains the operations you can do on any open trackview. - - - - - This method returns the number of tracks in the TreeView. - - - - - This method returns the number of currently selected tracks in the TreeView. - - - - - This method retrieves a track by its specified index. - Parameters: - int i - - The index of the track you wish you retrieve. - - AnimatablePtr &anim - - A reference to the object of the track that was specified. - - AnimatablePtr &client - - A reference to the client object of the track that was specified. This is the 'parent' or 'owner' of the specified item. - - int &subNum - - The index of the sub-anim of the track that was specified. - - - - - This method returns a pointer to the reference target associated with a TrackView entry. - Parameters: - int index - - The index of the TrackView entry for which to retrieve the reference target. - - - - - This method returns a pointer to the client of the specified track. This is the 'parent' or 'owner' of the specified item. - Parameters: - int index - - The index of the TrackView entry for which to retrieve the client. - - - - - This method returns TRUE if a controller can be assigned and FALSE if no controller can be assigned. - - - - - This method will invoke the assign controller dialog. - Parameters: - BOOL clearMot - - As of 2024.2, clearMot parameter is no longer used. - - - - - This method allows you to set the show controller type flag, on or off. - Parameters: - BOOL show - - the parameter to TRUE if the controller type should be shown. FALSE if the controller type should not be shown. - - - - - This method returns the name of the TreeView name. - - - - - This method will close the TreeView window. - - - - - This method allows you to set set a TreeView selection filter by adding to the selection mask. - Parameters: - DWORD mask - - The filter selection mask. See the List of TrackView Filter Mask Types for details. - - int which - - The filter you wish to set, 0 for filter 1, and 1 for filter 2. - - BOOL redraw - - Signal that a redraw should be issued. - - - - - This method allows you to set set a TreeView selection filter by subtracting from the selection mask. - Parameters: - DWORD mask - - The filter selection mask. See the List of TrackView Filter Mask Types for details. - - int which - - The filter you wish to clear, 0 for filter 1, and 1 for filter 2. - - BOOL redraw - - Signal that a redraw should be issued. - - - - - This method allows you to test if a filter has been set. - Parameters: - DWORD mask - - The filter selection mask. See the List of TrackView Filter Mask Types for details. - - int which - - The filter you wish to test, 0 for filter 1, and 1 for filter 2. - - - - - This method allows you to zoom/focus on a specified entry. - Parameters: - Animatable* owner - - A pointer to the you wish to zoom/focus on. - - int subnum - - The sub-anim you wish to zoom/focus on. - - - - - This method will zoom/focus on the selected entry. - - - - - This method will expand the tracks in the TreeView. - - - - - This method returns the index of the specified . - Parameters: - *anim - - A pointer to the you wish to get the index of. - - - - - This method allows you to select a specific track by providing its index. - Parameters: - int index - - The index of the track you wish to select. - - BOOL clearSelection - - this parameter to TRUE to signal the TreeView to clear the current selection, otherwise FALSE. - - - - - This method allows you to select the track in trackview corresponding to the Animatable* passed as the argument. - Parameters: - Animatable* anim - - A pointer to the you wish to select. - - BOOL clearSelection - - this parameter to TRUE to signal the TreeView to clear the current selection, otherwise FALSE. - - - - - This method allows you to assign a controller to the selected entry. The function checks to make sure a controller can be assigned to the selected tracks, and that the controller passed in is of the appropriate SuperClass_ID. Returns FALSE if the tracks don't all have the same SuperClassID, or if the controller argument is of the wrong type. - Parameters: - Animatable* ctrl - - A pointer to the controller you wish to assign. - TRUE if the assignment was successful, otherwise FALSE. - - - - - This method returns the current edit mode. - The edit mode, which is one of the following; - - MODE_EDITKEYS - - Edit keys mode. - - MODE_EDITTIME - - Edit time mode. - - MODE_EDITRANGES - - Edit ranges mode. - - MODE_POSRANGES - - Edit pos ranges model - - MODE_EDITFCURVE - - Edit function curves mode. - - - - - This method returns TRUE if this trackview is the last trackview used by the user, otherwise FALSE. - - - - - This method allows you to set this trackview to be the current trackview. - - - - - function-mapping version of SelectTrackByIndex, throwing an exception on an invalid index - - - - - Get whether the Isolate Curve state is active. - - - Return TRUE if the Isolate Curve state is active, FALSE otherwise. - - - - - Remove redundant keys of selected tracks (or just the selected keys if keys are selected for a track) - - - - if removing a key results in a change of value less than the tolerance, the key is removed. - - - - Deletes all the selected keys and creates two new keys for each deleted key, one on the previous frame, the other one on the next frame. - - - - - Moves the key selection backwards. - - - - - Moves the key selection forward. - - - - - Shrinks key selection. - - - - - Grows Key Selection. - - - - - Eases the selected key value to the previous key. - - - - - Eases the selected key value to the next key. - - - - - Mirrors the tangents of the selected key to the adjacent ones. - - - - - Nudges key selection (moves the selected keys on the next frame). - - - - When true, nudges the key selection to the previous frame. - - - - Scales tangents length and angle down. - - - - When true, scales only the inner tangent handles of the selection. - - - - Scales tangents length and angle up. - - - - When true, scales only the inner tangent handles of the selection. - - - - Copies the first key value to the last frame of the current animation range. - - - - When true, copies the first key value of the current animation to the last one. - - - - Works with Scales Values tool.Moves the scale origin to the first selected key. - - - - - Spaces the key selection evenly in time between the first and last keys. - - - - When true, spaces evenly in value. - - - - Eases key values and tangents between the first and last keys of the selection. - - - - When true, aligns the keys between the first and last keys of the selection - - - - Flattens the selected keys to the first selected key value. - - - - When true, flattens the selected keys to the value of the last selected one. - - - - Flattens the selected keys to the average value of the selected keys. - - - - When true, welds the selected keys. - - - - Turn the unlocked icon on and off before a trackview item. \ This function is used to turn on or off the display of the unlocked icon before a trackview item. \ param visible If true the unlocked or locked icon is displayed before the track name, if false the icons are not shown. - - - - - Tells you wether or not the unlocked icon is on or off. - - - If true then an unlocked or locked item will be displayed before a trackview item, if false then none will. - - - - - Description: - This class stores a Tension Continuity and Bias (TCB) floating point key. - Data Members: - float val; - - The value of the key. - - - - - Description: - This is the base class for Tension Continuity and Bias keys. - Data Members: - float tens; - - The tension setting. Values are in the range -1.0 to 1.0, where 0.0 is the default. - - float cont; - - The continuity setting. Values are in the range -1.0 to 1.0, where 0.0 is the default. - - float bias; - - The bias setting. Values are in the range -1.0 to 1.0, where 0.0 is the default. - - float easeIn; - - The ease in value. Values are in the range 0.0 to 50.0, where25.0 is the default. - - float easeOut; - - The ease out value. Values are in the range 0.0 to 50.0, where 25.0 is the default. - - - - - Description: - This class stores a Tension Continuity and Bias (TCB) key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class stores a Tension Continuity and Bias (TCB) rotation key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class stores a Tension Continuity and Bias (TCB) Scale key. - Data Members: - val; - - The value of the key. - - - - - Description: - This class is an interface that is given to track view utilities that allows them to access the track view they were launched from. All methods of this class are implemented by the system. - - - - - Returns the total number of visible (open) tracks in Track . This determines valid values to use for 'i' in the methods below. - - - - - Returns a pointer to the Animatalbe for the 'i-th' track. - Parameters: - int i - - Specifies the track. - - - - - Returns a pointer to the client of the 'i-th' track. This is the 'parent' or 'owner' of the 'i-th' item. - Parameters: - int i - - Specifies the track. - - - - - Returns the sub-anim number of the 'i-th' track. - Parameters: - int i - - Specifies the track. - - - - - Returns the name of the 'i-th' track. - Parameters: - int i - - The index of the track whose name is returned. - - - - - Returns TRUE if the 'i-th' track is selected; otherwise FALSE. - Parameters: - int i - - The index of the track to test. - - - - - Sets the selected state of the 'i-th' track to the state passed. - Parameters: - int i - - The index of the track whose selected state is set. - - BOOL sel - - Specifies the selected state. TRUE for selected; FALSE for not selected. - - - - - Returns the windows handle of the main Track window. - - - - - Returns a value to indicate the current mode Track is operating in. This is one of five modes. - One of the following values: - - TVMODE_EDITKEYS - - TVMODE_EDITTIME - - TVMODE_EDITRANGES - - TVMODE_POSRANGES - - TVMODE_EDITFCURVE - - - - - Returns the current interval of selected time. - - - - - Returns TRUE if 'Modify Subtree' mode is active; otherwise FALSE. - - - - - Returns a pointer to the Track Root. - - - - - This must be called when a track view utility is closing so that it can be unregistered from notifications - Parameters: - *util - - Points to the utility that is closing. This is usually called by passing the this pointer as in: TVUtilClosing(this); - - - - - Description: - This class represents the interface to the UVW Unwrap . You can obtain a pointer to the UVW Unwrap interface using; GetIUnwrapInterface(cd). This macro will return - - *)(cd)->GetFPInterace(UNWRAP_INTERFACE). Sample code supporting this class can be found in /MAXSDK/SAMPLES/MODIFIERS/UVWUNWRAP - - All methods of this class are Implemented by the System. - - - - - This method will press the Planar Map button in the rollup interface. - - - - - This method will press the Save button in the rollup interface. - - - - - This method will press the Load button in the rollup interface. - - - - - This method will press the Reset button in the rollup interface. - - - - - This method will press the Edit button in the rollup interface. - - - - - This method will set the Map Channel field value in the rollup. - Parameters: - int channel - - The Map Channel you want to set to. - - - - - This method will return the Map Channel field in the rollup. - - - - - This method will set the mapping type. - Parameters: - int proj - - The mapping type; 1 for X aligned, 2 for Y aligned, 3 for Z aligned, 4 for normal aligned. - - - - - This method will return the mapping type; 1 for X aligned, 2 for Y aligned, 3 for Z aligned, 4 for normal aligned. - - - - - This method will set the Vertex Channel radio button in the rollup interface. - Parameters: - BOOL vc - - TRUE to enable; FALSE to disable. - - - - - - - This method returns the current state of the Vertex Channel radio button in the rollup interface. - - - - - This method will press the Move button in the edit floater. - - - - - This method will press the Move Horizontal button in the edit floater. - - - - - This method will press the Move Vertical button in the edit floater. - - - - - This method will press the Rotate button in the edit floater. - - - - - This method will press the Scale button in the edit floater. - - - - - This method will press the Scale Horizontal button in the edit floater. - - - - - This method will press the Scale Vertical button in the edit floater. - - - - - This method will press the Mirror Horizontal button in the edit floater. - - - - - This method will press the Mirror Vertical button in the edit floater. - - - - - This method will press the Expand Selection button in the edit floater. - - - - - This method will press the Contract Selection button in the edit floater. - - - - - This method will set the Falloff type. - Parameters: - int falloff - - The falloff type; 1 for linear, 2 for sinual, 3 for fast, and 4 for slow. - - - - - This method will return the falloff type; 1 for linear, 2 for sinual, 3 for fast, and 4 for slow. - - - - - This method will set the space you want the falloff to be computed in. - Parameters: - int space - - The falloff space; 1 for XY, the local space of the object, 2 for UV, the UVW space of the object. - - - - - This method will return the falloff space; 1 for XY, the local space of the object, 2 for UV, the UVW space of the object. - - - - - This method will set the falloff distance in the edit floater. - Parameters: - float dist - - The falloff distance. - - - - - This method will return the falloff distance. - - - - - This method will press the Break Selected button in the edit floater. - - - - - This method will press the Target Weld button in the edit floater. - - - - - This method will press the Weld Selected button in the edit floater. - - - - - This method will press the Update Map button in the edit floater. - - - - - This method sets the state of the Display Map button in the edit floater - Parameters: - BOOL update - - TRUE to toggle the Display Map button on; FALSE to toggle it off. - - - - - This method returns the state of the Display Map button in the edit floater. TRUE if it's on; FALSE if it's off. - - - - - This method sets the space that you want to view the texture vertices in. - Parameters: - int space - - The texture space; 1 for UV, 2 for VW, 3 for UW. - - - - - This method returns the space that the texture vertices are viewed in; 1 for UV, 2 for VW, 3 for UW. - - - - - This method will press the Options button in the edit floater. - - - - - This method will toggle the Lock Selected Vertices button in the edit floater. - - - - - This method will press the Hide button in the edit floater. - - - - - This method will press the Unhide button in the edit floater. - - - - - This method will press the Freeze button in the edit floater. - - - - - This method will press the Unfreeze button in the edit floater. - - - - - This method will press the Filter Selected Faces button in the edit floater. - - - - - This method will press the Pan button in the edit floater. - - - - - This method will press the Zoom button in the edit floater. - - - - - This method will press the Zoom Region button in the edit floater. - - - - - This method will press the Fit button in the edit floater. - - - - - This method will press the Fit Selected button in the edit floater. - - - - - This method will press the Snap button in the edit floater. - - - - - This method returns the index into the map drop down list of the current map in the view of the edit floater. - - - - - This method sets the currently displayed map to the specified map index. - Parameters: - int map - - The index of the map in the drop down list to display. - - - - - This method returns the number of maps in the map drop down list. - - - - - This method returns the color of the lines used to connect the texture vertices edges as a pointer. - - - - - This method sets the line color of the texture vertices. - Parameters: - color - - The color as a . - - - - - This method returns the texture vertices selection color as . - - - - - This method sets the color of selected texture vertices. - Parameters: - color - - The color as a . - - - - - This method sets the width of the bitmap used to render to for display. - Parameters: - int dist - - The width in pixels. - - - - - This method returns the width of the bitmap used to render 2d/3d textures to and if the Use Resolution bitmaps is not set the width used to render bitmap. - - - - - This method sets the width of the bitmap used to render to for display. - Parameters: - int dist - - The height in pixels. - - - - - This method returns the height of the bitmap used to render 2d/3d textures to and if the Use Resolution bitmaps is not set the height used to render bitmap. - - - - - This method sets the threshold values for welds. - Parameters: - float dist - - The welding threshold/ - - - - - This method returns the weld threshold. - - - - - This method sets the state of the Use Resolution value. If it is false the bitmaps are rendered using the RenderWidth/Height values. - Parameters: - BOOL useBitmapRes - - TRUE to toggle on; FALSE to toggle off. - - - - - This method returns the state of the Use Resolution, if false the bitmaps are rendered using the RenderWidth/Height values. - - - - - This method returns the state of the Constant Update value which when set true forces the veiwport to be updated on every move, otherwise it is just updated on mouse up. - - - - - This method Sets the state of the Constant Update value which when set true forces the viewport to be updated on every move, otherwise it is just updated on mouse up. - Parameters: - BOOL constantUpdates - - TRUE to toggle on; FALSE to toggle off. - - - - - This method returns whether the selected texture vertices are also displayed in the view port. - - - - - This method sets whether the selected texture vertices are also displayed in the view port. - Parameters: - BOOL show - - TRUE to toggle on; FALSE to toggle off. - - - - - This method returns whether the mid pixels snap is used, if it is false the snap is set to the bottom right corner of the pixel, else it snaps to the center of the pixel. - - - - - This method sets whether the mid pixels snap is used, if it is false the snap is set to the bottom right corner of the pixel, else it snaps to the center of the pixel. - Parameters: - BOOL midPixel - - TRUE to toggle on; FALSE to toggle off. - - - - - This method returns the current material id index filter. - - - - - This method sets the material drop list to the index supplied. - Parameters: - int matid - - The material ID index to set. - - - - - This method returns the number of material ids in the material id filter drop down. - - - - - This method returns the current selected texture vertices in the edit floater as a bit array. - - - - - This method selects texture vertices in the edit floater dialog. - Parameters: - *sel - - The selection set as a bit array. - - - - - This method returns whether a texture vertex is selected. - Parameters: - int index - - The index of the vertex to check. - - - - - This method moves the selected texture vertices by the offset. - Parameters: - offset - - The offset by which you want to move the vertices. - - - - - This method rotates the selected vertices around their center point. - Parameters: - float angle - - The angle in radians that you want to rotate the selection by. - - - - - This method rotates the selected vertices around a specified point. - Parameters: - float angle - - The angle in radians that you want to rotate the selection by. - - axis - - The axis that you want to rotate the selected vertices by. This is in the space of the window. - - - - - This method scales the selected points around their center. - Parameters: - float scale - - The amount that you want to scale by - - int dir - - The direction; 1 for uniform scaling, 2 for X, and 3 for Y. - - - - - This method scales the selected points around a specified point. - Parameters: - float scale - - The amount that you want to scale by - - int dir - - The direction; 1 for uniform scaling, 2 for X, and 3 for Y. - - axis - - The axis that you want to scale the selected vertices by. This is in the space of the window. - - - - - This method returns the position of the vertex. - Parameters: - TimeValue t - - The time at which you want to get the vertex. - - int index - - The index of the vertex. - - - - - This method returns the number of texture vertices - - - - - This method sets the selected vertices x values in absolute coordinates. - Parameters: - float p - - The absolute position along the x axis - - - - - This method sets the selected vertices y values in absolute coordinates. - Parameters: - float p - - The absolute position along the y axis - - - - - This method sets the selected vertices z values in absolute coordinates. - Parameters: - float p - - The absolute position along the s axis - - - - - This method returns the selected polygons in the view port as a bit array. - - - - - This method selects the polygons in the view ports. - Parameters: - *sel - - The polygons you wish to select. - - - - - This method returns whether a polygon is selected or not. - Parameters: - int index - - The index of the polygon to check. - - - - - This method returns the number of polygons in the object. - - - - - This method detaches any vertex that is not completely surrounded by selected vertices. This is similar to a polygon selection detach except it uses the vertex selection to determine what is detached. - - - - - This method will press the Flip Horizontal button in the edit floater. - - - - - This method will press the Flip Vertical button in the edit floater. - - - - - This method returns whether the edit window aspect ratio is locked or not, if the aspect ratio is not locked the image will try stretch to fit the aspect ratio of the window. - TRUE if locked; FALSE if unlocked. - - - - - This method sets the Lock Aspect Ratio value - Parameters: - BOOL a - - TRUE to lock; FALSE to unlock. - - - - - This method returns the scaling factor when the user applies a planar map. The smaller the value the more planar map is scaled down. - - - - - This method sets the scaling factor when the user applies a planar map. The smaller the value the more planar map is scaled down - Parameters: - float sc - - The scaling factor for planar map. - - - - - This method takes the current polygon selection and uses it to select the texture vertices that are associated with it. - - - - - This method sets a flag to determines how Unwrap will behave when a topology change occurs. If update is TRUE the mapping gets reset, otherwise unwrap skips mapping the object if it has a different topology. It is sometimes useful to turn this off if you have MeshSmooth or other topology changing modifiers below Unwrap that have different topologies when rendering. - Parameters: - BOOL update - - This determines whether the mapping is reset on topology change. TRUE to update, otherwise FALSE. - - - - - This method zooms the selected or all the viewports to zoom to the current planar map gizmo. - Parameters: - BOOL all - - This determines whether the active or all the viewports get zoomed. TRUE to zoom all viewports, FALSE to view the active viewport. - - - - - This method sets the position of a UVW vertex at a specific time. - Parameters: - TimeValue t - - The time at what you want to set the position. - - int index - - The index of the vertex. - - pos - - The position of the vertex in UVW space. - - - - - This method marks a vertex that it is dead, and no longer in use. Vertices are not actually deleted they are just marked and recycled when needed. That means when a vertex is added vertices marked as dead will be the first ones checked. If there are no dead vertices, the vertex is appended to the end of the list. Using this function carefully since marking a vertex as dead that is actually in use will cause strange results. - Parameters: - int vertex - - The index of the vertex to mark as dead. - - - - - This method retrieves the numbers of vertices that a face contains. A face can contain 3 to N number of points depending on what type of topology Unwrap is working on. For Tri Meshes this is always 3, for patches this can be 3 or 4, and for polygons this can be 3 or greater. Unwrap abstracts all three object types into one generic format. - Parameters: - int index - - The index of the face to inspect. - - - - - This method retrieves the index of a vertex, from a face. A face contains 0 to N number of vertices. So to retrieve a particular vertex index, you give it the face index and the I-th vertex that you want to inspect. So if you wanted to look at the 3 vertex on face 1 you would call GetVertexIndexFromFace(1,3). - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th vertex of that you want to retrieve. This value should range from 1 to the number of vertices that the face contains. - - - - - This method retrieves the index of a handle, from a face. A face contains 0 to N number of handles. So to retrieve a particular handle index, you give it the face index and the I-th handle that you want to inspect. So if you wanted to look at the 3 handle on face 1 you would call GetHandleIndexFromFace(1,3). This only applies for patch meshes. - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th handle of that you want to retrieve. This value should range from 1 to the number of vertices*2 that the face contains. - - - - - This method retrieves the index of a interior handle, from a face. A face contains 0 to N number of interior handles. So to retrieve a particular interior handle index, you give it the face index and the I-th interior handle that you want to inspect. So if you wanted to look at the 3 interior handle on face 1 you would call GetInteriorIndexFromFace(1,3). This only applies for patch meshes. - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th interior handle of that you want to retrieve. This value should range from 1 to the number of vertices that the face contains. - - - - - This method retrieves the index of a geometric vertex, from a face. This the vertex that is attached to the mesh and not the texture faces. A face contains 0 to N number of vertices. So to retrieve a particular vertex index, you give it the face index and the I-th vertex that you want to inspect. So if you wanted to look at the 3 vertex on face 1 you would call GetVertexGeomIndexFromFace(1,3). - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th vertex of that you want to retrieve. This value should range from 1 to the number of vertices that the face contains. - - - - - This method retrieves the index of a geometric handle from a patch. This the handle that is attached to the patch and not the texture faces. A face contains 0 to N number of handle. So to retrieve a particular handle index, you give it the face index and the I-th handle that you want to inspect. So if you wanted to look at the 3 handle on face 1 you would call GetHandleGeomIndexFromFace(1,3). - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th handle of that you want to retrieve. This value should range from 1 to the number of vertices*2 that the face contains. - - - - - This method retrieves the index of a geometric interior handle from a patch. This the interior handle that is attached to the patch and not the texture faces. A face contains 0 to N number of interior handle. So to retrieve a particular interior handle index, you give it the face index and the I-th interior handle that you want to inspect. So if you wanted to look at the 3 interior handle on face 1 you would call GetInteriorGeomIndexFromFace(1,3). - Parameters: - int index - - The index of the face to inspect. - - int vertexIndex - - The I-th interior handle of that you want to retrieve. This value should range from 1 to the number of vertices that the face contains. - - - - - This method allows you to manipulate the position of vertex attached to a face. Basically it detaches the vertex if multiple faces share that vertex and then moves it to the position specified. So if you want to move the 3rd vertex of face 1 to .5,.5,.0 you would do setFaceVertex [.5 .5 .0] 1 3. If you don't want the vertex broken use SetVertexSPosition. - Parameters: - pos - - The position that you want to move a vertex to. - - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to change - - BOOL sel - - Whether or not to select the vertex after it is recreated - - - - - This method is identical to SetFaceVertex except works on patch handles. - Parameters: - pos - - The position that you want to move a vertex to. - - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to change - - BOOL sel - - Whether or not to select the vertex after it is recreated - - - - - This method is identical to SetFaceVertex except works on patch interior handles. - Parameters: - pos - - The position that you want to move a vertex to. - - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to change - - BOOL sel - - Whether or not to select the vertex after it is recreated - - - - - This method allows you to set the index of the ith vertex of a face. - Parameters: - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to manipulate. - - int vIndex - - The index into the vertex list that you want to set to - - - - - This method is identical to setFaceVertexIndex but works on handles for patches. - Parameters: - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to manipulate. - - int vIndex - - The index into the vertex list that you want to set to - - - - - This method is identical to setFaceVertexIndex but works on interior handles for patches. - Parameters: - int fIndex - - The index of the face that you wish to work on. - - int ithV - - The ith vertex of the face that you want to manipulate. - - int vIndex - - The index into the vertex list that you want to set to - - - - - - - This method forces the viewport and dialog to update. - - - - - This method looks at the current face selection in the stack, and copies it to the unwrap face selection. The reason this is useful is that if some one creates a new selection modifier Unwrap can use it. An example would be if you applied to Unwrap to a whole editable mesh , then you went back into the editable mesh, selected some faces by smoothing group, then turned off the face subobject selection. If you went back to Unwrap you could get this selection by calling getFaceSelectionFromStack. - - - - - Description: - This class is only available in release 5 or later. - - The new class allows for Normal, Flatten, and Unfold mapping. You can bring them up through a dialog or through a script command. All these tools basically work the same. They are either applied to the current selected faces or the whole object if no faces are selected. - - As this class has been fully developed with the new Function-Published System (FPS), all of its methods have a one-to-one correspondence with MaxScript commands. For the sake of brevity, references to MaxScript commands mean that there is an attendant C++ method in iunwrap.h that is prepended by lowercase fn. Examples of this are as follows ( MaxScript and its attendant C++ method): - - copy fpCopy(); - - normalMapNoParams fnNormalMapNoParams(). - - There are three distinct modes of unmapping: - - Normal Mapping - - Normal Mapping is mapping based solely are the normals provided. This is identically to box mapping except you customize what normals you want to project on. There are three methods to apply a "normalMap" which applies a normal map based on the parameters passed in (see the methods below) , "normalMapNoParams" which applies a normal map using the default setting, and "normalMapDialog" which brings up a dialog that lets you set the setting. Right now there are 6 types of default mapping Back/Front, Left/Right, Top/Bottom, Box Mapping No Top, Box Mapping, and Diamond mapping. Just apply the mapping to a teapot to see the differences they are pretty obvious once you see the effect. Parameters in the Normal Mapping dialog are: - - - - Hitting the Save As Default will take the current setting and set them as defaults for the next time you bring up the dialog and when you use the script command "<b>normalMapNoParams</b>". - - Flatten Mapping - - Flatten Mapping is similar to normal mapping, except it uses an angle threshold to define the clusters and the clusters will always be contiguous faces. This type of mapping will generate mapping that does not overlap so it is useful for baking textures and lighting. Just like normal mapping this comes in 3 flavors "flattenMap" which applies a normal map based on the parameters passed in (see the methods below) , "flattenMapNoParams" which applies a map using the default setting, and "flattenMapDialog" which brings up a dialog that lets you set the setting. The parameters for the Flatten Map Dialog are: - - Angle Threshold - when building contiguous faces this the angle used to determine whether a face is part of that cluster. The larger this angle the larger the cluster will be, but you will get more distortion since the texture faces area will start deviating from there geometric face area. - - Unfold Mapping - - Unfold Mapping where as the Normal and Flatten Mapping basically use a lot of planar mapping to get their results, this is an actual unfolding algorithm. It guarantees that all texture faces will have the exact same proportions as their geometric equivalents, but you may get faces that overlap. This type of mapping is only good on meshes that are very regular things like cylinders etc. This has the same type of function calls as the above "unfoldMap" which applies an unfold map based on the parameters passed in (see the methods below) , "unfoldMapNoParams" which applies a map using the default setting, and "unfoldMapDialog" which brings up a dialog that lets you set the setting. The parameters for the Unfold Map Dialog are: - - Copy/Paste allows you to copy a texture face/faces from one part or mesh to another or to a new mesh. These functions are extremely topology dependant so if you copy faces onto faces that have a different topology or face order you will get unpredictable results. There is a "copy" script which takes the current selected faces and puts them in the copy buffer. There is the "Paste" and "PasteInstance" commands which do the pasting to current selected faces. "Paste" take one parameter called rotate which determines if every time you paste to the same face whether the tvs are reoriented. For instance if you paste a quad onto a another quad there are actually 4 possible ways you can paste it onto it. If rotate is on, every time you paste it will go onto the next variation. "Paste Instance" forces the faces that are being pastes to use the vertices that the copy buffer use (NOTE you cannot paste instance across objects). This similar to doing a regular paste and then selecting all the overlapping vertices and doing a weld. There is no rotate option with this method. As noted above Pasting faces that have a different topology or face order will result in unpredictable results. - - Stitching allows you find all the texture vertices that are assigned to the same geometric vertex and bring them all to the same spot and weld them together. This allows you take faces that geometrically contiguous, but not texture face contiguous and line them up. There is a stitchVerts command which takes parameters, stitchVertsNoParams which uses the current defaults, and a stitchVertsDialog which brings up a dialog to apply a stitch and set defaults. The Stitch Tool params are: - - - - Note stitching will respect the soft selection. - - - MaxScript Commands / Methods: - Note: the following are MaxScript commands, however, referring to the above qualifier, their C++ method name is the same as in MaxScript but prepended with fn. - - The format for input/output parameters is as follows: - - <output type> <name of function> <input type params 1...n> - - copy - this takes the selected faces and places them in the copy buffer - - paste - - rotate TYPE_BOOL if this on, every time you paste to the same selection it will try a different variation - - This paste the current copy buffer onto the current face selection. - - pasteInstance this forces the faces that are being pastes to use the vertices that the copy buffer use (NOTE you cannot paste instance across objects). This similar to doing a regular paste and then selecting all the overlapping vertices and doing a weld. There is no rotate option with this method. - - SetDebugLevel - - level TYPE_INT level of debug info 0 means no debug info, the higher the value the more spam you will see in your script window - - Debugging tool so I can control the amount of debug info that goes to the listener and script window. - - TYPE_BOOL getTileMap - returns whether the background is tiled. - - setTileMap - - tile TYPE_BOOL - whether or not to tile the background - - This allows you set the tile state of the background - - TYPE_INT getTileMapLimit - returns the max number of tiles to use in a direction - - setTileMapLimit - - limit TYPE_INT - the number of tile to limit in a direction - - This allows you to set the tile limit - - TYPE_FLOAT getTileMapBrightness returns the brightness of the tiles. - - setTileMapBrightness brightness - - TYPE_FLOAT - the brightness of the tiled maps - - This allows you to set the brightness of the tiled maps - - New Maxscript funtions - - TYPE_BOOL getShowMap returns the state of the show map button - - TYPE_VOID setShowMap - - showMap TYPE_BOOL the state you want to set the show map button - - Lets you set the state of the show map button - - TYPE_BOOL getLimitSoftSel returns whether the soft selection limit is on/off - - SetLimitSoftSel - - limit TYPE_BOOL state the to set the soft selection limit - - Allows you to set the soft selection limit state - - TYPE_INT getLimitSoftSelRange returns the edge limit for the for the soft selection - - setLimitSoftSelRange - - range TYPE_INT this is how far out in edges that soft selection will expand to - - This lets you set the edge limit range for soft selection - - TYPE_FLOAT getVertexWeight - - index TYPE_INT the index of the vertex you want to inspect - - returns the soft selection weight of a particular vertex - - setVertexWeight - - index TYPE_INT the index of the vertex you want to change - - weight TYPE_FLOAT the soft selection weight you want to set the vertex to - - This lets you set the soft selection weight of a particular vertex. Note once you set the weight of a vertex, it is tagged as being modified and will not change value unless you unmodifiy or call setVertexWeight on it again. - - TYPE_BOOL isWeightModified - - index TYPE_INT the index of the vertex you want to inspect - - This returns whether a vertex is modified or not. - - modifyWeight - - index TYPE_INT the index of the vertex you want to change - - modify TYPE_BOOL the modified state of the vertex - - This lets you set the modified state of vertex. If a vertex is modified it ignores regular UI soft selection and the vertex soft selection weight is locked to it current state and can only be changed by the setVertexWeight method. - - TYPE_BOOL getGeomSelectElementMode returns whether you are in element mode for face - - selection in the viewport. - - setGeomSelectElementMode - - mode TYPE_BOOL - the state that you want to put viewport selection in - - Lets you set the viewport element mode. - - TYPE_BOOL getGeomPlanarThresholdMode return the whether you are in planar select mode. - - setGeomPlanarThresholdMode - - mode TYPE_BOOL the state that you want to put planar selection mode - - Lets set the planar selection mode. - - TYPE_FLOAT getGeomPlanarThreshold return the planar selection angle threshold - - setGeomPlanarThreshold - - angle TYPE_FLOAT the angle threshold - - Lets you set the angle threshold for the planar selection mode. - - TYPE_INT getWindowX returns the current X position of the Unwrap Edit window - - TYPE_INT getWindowY returns the current Y position of the Unwrap Edit window - - TYPE_INT getWindowW returns the current width of the Unwrap Edit window - - TYPE_INT getWindowH returns the current height of the Unwrap Edit window - - TYPE_BOOL getIgnoreBackFaceCull returns the state of the Ignore Back mode - - setIgnoreBackFaceCull - - ignoreBackFaceCull TYPE_BOOL state of the Ignore Back Faces mode - - Lets you set the Ignore Back mode - - TYPE_BOOL getOldSelMethod returns whether the system is in the old selection mode. Where drag selection always uses back faces and single pick mode ignore back faces. - - SetOldSelMethod - - oldSelMethod TYPE_BOOL the state of the old selection method - - This lets you set the system back to the old selection method. Where drag selection always uses back faces and single pick mode ignore back faces. - - This will override the Ignore Back Faces mode. - - SelectByMatID - - matID TYPE_INT the matID of the face that you want to select - - This lets you select faces by material ids. - - selectBySG - - sg TYPE_INT the smoothing group that you want to select - - This lets you select faces by smoothing group - - TYPE_VOID expandGeomFaceSelection - expands your current viewport face selection - - TYPE_VOID contractGeomFaceSelection- contracts your current viewport face selection - - TYPE_BOOL getAlwaysEdit - This returns whether the always edit mode is on. This mode will always bring up the edit dialog when the Unwrap rollup window is displayed. - - TYPE_VOID setAlwaysEdit - - always TYPE_BOOL the state that you want to set the always edit mode to. - - This lets you set the always edit mode. This mode will always bring up the edit dialog when the Unwrap rollup window is displayed. - - TYPE_BOOL getShowVertexConnections this returns whether vertex connection indices are displayed. Vertex Connections are TV vertices that share the same geometric vertices - - TYPE_VOID setShowVertexConnections - - show TYPE_BOOL whether to display the vertex connection data. - - This lets you toggle the vertex connection data. - - TYPE_BOOL getFilterSelected this returns the state of the Filter Selected Faces button - - TYPE_VOID setFilterSelected - - filter TYPE_BOOL the filter state - - This lets you set the Filter Selected Faces button - - TYPE_BOOL getSnap this returns the snap state. - - TYPE_VOID setSnap - - snap TYPE_BOOL the snap state - - This lets you set the snap state. - - TYPE_BOOL getLock this returns the lock selection state - - TYPE_VOID setLock - - lock TYPE_BOOL state of the lock selection. - - This lets you set the state of the lock selection - - TYPE_VOID pack - - method TYPE_INT - 0 is a linear packing algorithm fast but not that efficient, 1 is a recursive algorithm slower but more efficient. - - spacing TYPE_FLOAT - the gap between cluster in percentage of the edge distance of the square - - normalize TYPE_BOOL - whether the clusters will be fit to 0 to 1 space. - - rotate TYPE_BOOL - whether a cluster will be rotated so it takes up less space. - - fillholes TYPE_BOOL - whether smaller clusters will be put in the holes of the larger cluster. - - This lets you pack the texture vertex elements so that they fit within a square space. - - TYPE_VOID packNoParams - this packs the clusters using the default parameters. - - TYPE_VOID packDialog - this brings up a dialog that lets the user set the parameters and then packs the clusters. - - TYPE_INT getTVSubObjectMode sets the current texture subobject mode 1 vertices, 2 edges, 3 faces. - - TYPE_VOID setTVSubObjectMode - - mode TYPE_INT - the subobject mode 1 vertices, 2 edges, 3 faces. - - Lets you set the tv subobject mode. - - TYPE_BITARRAY getSelectedFaces returns the selected face list - - TYPE_VOID selectFaces - - Selection TYPE_BITARRAY selection that you want to make the face selection - - This lets you set the face selection - - TYPE_BOOL IsFaceSelected - - Index TYPE_INT the index of the face you want to check - - This lets you check to see if a face is selected. - - TYPE_INT getFillMode - returns the fill mode type for face selections. The fill modes are as follows. - - FILL_MODE_OFF 1 - - FILL_MODE_SOLID 2 - - FILL_MODE_BDIAGONAL 3 - - FILL_MODE_CROSS 4 - - FILL_MODE_DIAGCROSS 5 - - FILL_MODE_FDIAGONAL 6 - - FILL_MODE_HORIZONAL 7 - - FILL_MODE_VERTICAL 8 - - TYPE_VOID setFillMode - - mode TYPE_INT - the fill mode that you want to set - - This lets you set the fill mode for selected faces. - - MoveSelected, RotateSelected, RotateSelectedCenter, ScaleSelectedCenter, and ScaleSelected are identical to there vertex counter parts but are applied to the current selection. - - TYPE_VOID MoveSelected - - Offset TYPE_POINT3 - - TYPE_VOID RotateSelectedCenter - - Angle TYPE_FLOAT - - TYPE_VOID RotateSelected - - Angle TYPE_FLOAT - - Axis TYPE_POINT3 - - TYPE_VOID ScaleSelectedCenter - - Scale TYPE_FLOAT - - Dir TYPE_INT - - TYPE_VOID ScaleSelected - - Scale TYPE_FLOAT - - Dir TYPE_INT - - Axis TYPE_POINT3 - - TYPE_BITARRAY getSelectedEdges returns the selected edge list - - TYPE_VOID selectEdges - - Selection TYPE_BITARRAY selection that you want to make the edge selection - - This lets you set the edge selection - - TYPE_BOOL IsEdgeSelected - - Index TYPE_INT the index of the edge you want to check - - This lets you check to see if a face is selected. - - TYPE_BOOL getDisplayOpenEdges returns whethe open edges will display - - TYPE_VOID setDisplayOpenEdges - - displayOpenEdges TYPE_BOOL the state of the open edge display - - This lets you set the open edge display - - TYPE_POINT3 getOpenEdgeColor returns the color used for the open edges - - TYPE_VOID setOpenEdgeColor - - color TYPE_POINT3 the color to be used for open edges - - This lets you set the open edge color - - TYPE_BOOL getUVEdgeMode returns whether you are in the UV Selection mode. This mode will try to automatically select all the U or V edges when you select an edge. Since this is based on edges, the regular tri mesh may produce incorrect results since the hidden edges are not taken into account. - - TYPE_VOID setUVEdgeMode - - uvEdgeMode TYPE_BOOL the state of the you want to set the UV mode - - This lets you set the UV mode - - TYPE_VOID uvEdgeSelect - this is a command that will take your current edge selection and try to expand out along the U and V directions. Works best when you only have one edge selected. - - TYPE_BOOL getOpenEdgeMode returns whether you are in the Open Selection mode. This mode will try to automatically select all the opens edges when you select an open edge. - - TYPE_VOID setOpenEdgeMode - - uvOpenMode TYPE_BOOL the state of the you want to set the Open mode - - This lets you set the Open mode - - TYPE_VOID openEdgeSelect - this is a command that will take your current selection and try to expand all the open edges in it. - - TYPE_VOID vertToEdgeSelect - this command takes your vertex selection and converts it to the edge selection. - - TYPE_VOID vertToFaceSelect - this command takes your vertex selection and converts it to the face selection. - - TYPE_VOID edgeToVertSelect - this command takes your edge selection and converts it to the vertex selection. - - TYPE_VOID edgeToFaceSelect - this command takes your edge selection and converts it to the face selection. - - TYPE_VOID faceToVertSelect - this command takes your face selection and converts it to the vertex selection. - - TYPE_VOID faceToEdgeSelect - this command takes your face selection and converts it to the edge selection. - - TYPE_BOOL getDisplayHiddenEdges return whether hidden edges of a tri mesh are displayed. - - TYPE_VOID setDisplayHiddenEdges - - displayHiddenEdges TYPE_BOOL - the state that you want to the hidden display to be. - - This lets you turn on/off whether tri mesh hidden edges are displayed. - - TYPE_POINT3 getHandleColor - returns the color that will be used to display patch handles. - - TYPE_VOID setHandleColor - - color TYPE_POINT3 - the color that you want to set patch handles to - - This lets you set the color that will be used to display patch handles. - - TYPE_BOOL getFreeFormMode this toggle the free form mode on and off. This mode is similar to the Photoshops free form mode. You select any where inside the bounding rectangle to move the selection. You select the corners to scale the selection, and you you select the edge centers to rotate the selection. You can also move the center cross which is your rotation pivot point. - - TYPE_VOID setFreeFormMode - - freeFormMode TYPE_BOOL the state of the free form mode. - - Lets you turn on/off the free from mode. - - TYPE_POINT3 getFreeFormColor returns the color of the free form gizmo. - - TYPE_VOID setFreeFormColor - - color TYPE_POINT3 the color that you want the gizmo to be - - This lets you set the color of the Free Form Gizmo - - TYPE_VOID ScaleSelectedXY - - ScaleX TYPE_FLOAT the x scale factor - - ScaleY TYPE_FLOAT the y scale factor - - Axis TYPE_POINT3 the axis to scale around - - This lets you nu scale the current selection around an axis - - TYPE_VOID SnapPivot - - Pos TYPE_INT - the pivot position where - - 1 is the center - - 2 is the lower left of the selection - - 3 is the lower center of the selection - - 4 is the lower right of the selection - - 5 is the right center of the selection - - 6 is the upper right of the selection - - 7 is the upper center of the selection - - 8 is the upper left of the selection - - 9 is the left center of the selection - - This lets you quickly snap the free form gizmo pivot the bounding rectangle. - - TYPE_POINT3 getPivotOffset - returns the pivot offset of the free form gizmo. This is an offset from the center of the selection. - - TYPE_VOID setPivotOffset - - offset TYPE_POINT3 the offset of the free form gizmo pivot - - This lets you set the offset of the free form gizmo pivot. - - TYPE_POINT3 fnGetSelCenter this returns the selection center so you can compute the pivot offset from a world uv position. - - TYPE_BOOL getPolygonMode - - This returns whether the polygon mode for sub object face mode is on. Polygon Mode will just select across triangles across hidden edges of a triangle. - - TYPE_VOID setPolygonMode - - mode TYPE_BOOL the state you want to set the Polygon Mode - - This lets you set the state the of the Polygon Mode - - TYPE_VOID PolygonSelect - - This is command that will take your current selection and expand it to include all polygons. - - TYPE_VOID sketch - - IndexList TYPE_INT_TAB the indices of the points you want to move. - - PositionList TYPE_POINT3_TAB the list of a points you want to align your vertices to. - - This lets you align texture vertices to a series of points - - TYPE_VOID sketchNoParams - - This puts you in sketch mode using the default parameters. - - TYPE_VOID sketchDialog - - This brings up the sketch options dialog. - - TYPE_VOID sketchReverse - - This will reverse the order of the select vertices that are being used for sketch when you use the Use Current Selection option. - - TYPE_INT getHitSize - - This returns the hit size whne you do a single click in pixels. - - TYPE_VOID SetHitSize - - size TYPE_INT the size you want to set the hit size to - - This lets you set the hit size of a single click. - - TYPE_BOOL getResetPivotOnSelection - - This will return whether the Transform Gizmo will reset when the selection is changed. - - TYPE_VOID SetResetPivotOnSelection - - reset TYPE_BOOL the state you want to set the reset pivot on selection - - This lets you set the Reset the Pivot On Selection. - - TYPE_BOOL getAllowSelectionInsideGizmo - - This returns whether a user can select sub objects inside the gizmo or not. If this is FALSE the user is in move mode when inside the gizmo unless they are over the pivot. If this is TRUE the user is in move mode when they are inside and over a selected sub object otherwise they are in select mode. - - AllowSelectionInsideGizmo - - select TYPE_BOOL - the state you want to set the Allow Selection Inside Gizmo to be - - This lets you set the Allow Selection Inside Gizmo flag - - TYPE_VOID SaveCurrentSettingsAsDefault - - This takes the current state of Unwrap UVW and save it to the plugin cfg directory into a file called unwrapUVW.ini. The next time the user creates an Unwrap UVW modifier this ini file will be used to set the defaults. - - TYPE_VOID LoadDefault - - This will load the unwrapUVW.ini defaults into the current Unwrap UVW modifier. - - TYPE_BOOL getShowShared - - This returns whether shared sub objects are displayed. Shared sub objects are texture vertices or edges that share the same geometric vertex or edge. - - TYPE_VOID setShowShared - - select TYPE_BOOL whether to display shared sub objects or not. - - This lets you toggle the Show Shared flag. - - TYPE_POINT3 getSharedColor - - This returns the color that will be used to show shared sub objects. - - TYPE_VOID setSharedColor - - color TYPE_POINT3 the color to be used for shared sub objects - - This lets you set the color to be used for shared sub objects. - - TYPE_BOOL getSyncSelectionMode - - Returns whether the viewport and the dialog selections are synced - - TYPE_VOID setSyncSelectionMode - - sync TYPE_BOOL - - Lets you set whether the viewport and the dialog selections are synced - - TYPE_VOID syncTVSelection - - This is a commmand the synces the dialog to the viewport - - TYPE_VOID syncGeomSelection - - This is a commmand the synces the viewport to the dialog - - TYPE_POINT3 getBackgroundColor - - returns the color of the background in the dialog - - TYPE_VOID setBackgroundColor - - color TYPE_POINT3 - - Lets you set the color of the background in the dialog - - TYPE_VOID updateMenuBar - - Forces the menu bar to update - - TYPE_BOOL getBrightnessAffectsCenterTile - - This returns whether the brightness value affects the center tile - - TYPE_VOID setBrightnessAffectsCenterTile - - bright TYPE_BOOL - - This lets you set whether the brightness value affects the center tile - - TYPE_BOOL getBlendTileToBackground - - This returns whether the tiled images are blended to the background color or black - - TYPE_VOID setBlendTileToBackground - - blend TYPE_BOOL, - - This lets you set whether the tiled images are blended to the background color or black - - TYPE_BOOL getPaintSelectMode - - This returns whether you are in paint select mode - - TYPE_VOID setPaintSelectMode - - paint TYPE_BOOL, - - This lets you set whether you are in paint select mode - - TYPE_INT getPaintSelectSize - - Returns the size of the paint select brush this is clamped between 1 and - - - - - This class is only available in Max 6.0 and higher - Description: - UVW Unwrap has an auto background option which ties the current background to the current Filter ID. When the Filter ID is changed, it will automatically change the background to a map that uses that material ID. The GetAutoBackground and SetAutoBackground function published methods enable and disable this feature. - - The remainder of the new methods are related to the Relax UV feature of UVW Unwrap. The relax UV dialog can be invoked with the Relax2Dialog method. Or, the parameters within the dialog can be set and applied directly with the Relax2 method. Get/SetRelaxBoundary corresponds to the "Keep Boundary Points Fixed" parameter. Get/SetRelaxSaddle corresponds to the "Save Outer Corners" parameter. - - - - - Returns whether we are in thin and thick viewport open edge display. - true if we are in thick edge display mode - - - - - let you toggle between thin and thick viewport open edge display. - - - if true, display thick edges - - - - Select the inverted faces - - - - - The getter for the Relative toggle for the typeins - the state of the relateive toggle for the typeins - - - - - The setter for the Relative toggle for the typeins - - - If true, disable the relative toggle for the typeins - - - - A stitch function which includes the option to match the scale of the clusters - - - - - Gives the user access to add maps to the map drop down through script - - - - - A flatten which separates and flattens an object based on its matID. - - - - - returns the area of a selection of faces - - - - - The getter for the Respect Aspect ratio option. This option determines how things get rotated on non-square bitmaps - - - - - The setter for the Respect Aspect ratio option. This options determines how things get rotated on non-square bitmaps - - - - - Forces the flatten algorithm to act like the Max5 version. - - - if true, the flatten algorithm will act like the Max5 version - - - - Basically it's a backwards-compatabile fix for the fact that the 'IsReplaceable' control flag isn't used by PB2's. Secondly the class provides. - - - is a new interface which if present lets the internal system know that the controller can't be replaced. - - Description: - This interface is mainly used by the wire controller UI. - - For example, a controller that implements this interface can't be replaced by a wire controller, it can only participate in one way wires where this controller is the driver. In addition when the controller is replaced and collapsed the returned by the GetReplacementClone function will be used to replace the wire. - - The interface is retrieved by calling GetInterface(I_UNREPLACEABLECTL). - Examples: - The expose transform controller (see maxsdk\samples\objects\helpers\exposetransform) implements this interface. - - - - - Description: - This class provides a single method to allow the developer to close their utility plug-in in the command panel. - - - - - Implemented by the System. - - A developer may call this method to close the current utility in the command panel. If a plug-in developer chooses to use a Close button in one of their rollup pages this method should be called when the user has selected the Close button. This method simply tells the system that the plug-in should be closed. A developer does not need to use this method. It is just available if a developer wants to have a specific termination point to their utility plug-in. - - - - - - - class : public - - - Description: - The interface to the utility panel manager. This class defines an interface for opening and closing utility plugins, and provides maxscript access to the same. - - An instance of this interface can be retrieved as - - static_cast<IUtilityPanel*>(GetCOREInterface(IUTIL_FO_INTERFACE)); - - - - - - - Opens the Utility plugin in UI - - - Parameters: - ClassDesc* - - The Utility class name to open - - - Return Type: - TRUE if succeeded - - - - - - - Closes the Utility plugin in UI - - - - - A simple class that a developer must implement if they want to use Scene traversal - - - - - A simple test to define whether the node is accepted or rejected. - Whether the node is valid or not. - - The node to test - The active view - - - - This allows a sort of the nodes accepted. This needs to be quick as it is called during the render process. \ param & nodeList - the list to sort. - - - - - The interface provides a way to set the vertex colors held in a VertexPaint modifier. - - - The interface can be obtained as follows: - The class ID for the new VertexPaint in R6 and up is PAINTLAYERMOD_CLASS_ID, different from the legacy modifier. The legacy modifier does not support - - - - - the colors by providing one color per vert. - - - If the vertex paint modifier is applied on a poly object, you should provide colors based on the tri-mesh version of the object, as this is the object-type operated on by the modifier. - 0 if the colors could not be applied, else 1 - - The node to apply the vertex painting to - A table of colors, this should supply one for each vertex - - - - colors by providing three colors per triangle. - - - If the vertex paint modifier is applied on a poly object, you should provide colors based on the tri-mesh version of the object, as this is the object-type operated on by the modifier. - 0 if the colors could not be applied, else 1 - - The node to apply the vertex painting to - A table of face colors, each with 3 colors for each vertex. - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - The Get/SetOptions() methods control the parameters used for the lighting calculation, as shown in the UI of the utility. - - - - - Description: - The abstract interface for a vertex shader. - - - - - This method loads VertexShader instructions, create any additional per vertex data on a per node basis. VertexShader instructions should be loaded once and shared among all the nodes using this VertexShader. Additional per vertex data should be (re)created only when the associated node data changes. In addition, if there is sufficient memory, VertexBuffers can be created and updated only when node data changes in order to improve rendering performance. - Parameters: - *mesh - - A pointer to the mesh to initialize. - - *node - - A pointer to the node to initialize. - - - - - This method loads VertexShader instructions, create any additional per vertex data on a per node basis. VertexShader instructions should be loaded once and shared among all the nodes using this VertexShader. Additional per vertex data should be (re)created only when the associated node data changes. In addition, if there is sufficient memory, VertexBuffers can be created and updated only when node data changes in order to improve rendering performance. - Parameters: - *mnmesh - - A pointer to the to initialize. - - *node - - A pointer to the node to initialize. - - - - - Use this class to easily retrieve the vertex velocity data from an object. The data maybe stored in the map channels which makes it volatile and if the vertex count does not equal the velocity count it will return a nullptr. Use - to access the interface. - - - - - If velocity data has been registered for the object this interface was acquired from, this method returns a pointer to the array of the velocity in units per frame otherwise it return null pointer. - - - - returns the number of velocity verts which should equal the number of geometry vertices. note since the velocities maybe in a map channel or some editable channel someone could edit these and change the number of vertices - - - - Description: - This control allows the creation of vertical toolbars containing buttons (push, check, and fly-offs), status fields, separators (spacers), and other Windows or user defined controls. The standard size for 3ds Max toolbar button icons is 16x15 or 16x16 pixels. - - All methods of this class are implemented by the system. - - To initialize the pointer to the control call: - ; To release the control call: - ReleaseIVertToolbar(IVertToolbar *ict); The value to use in the Class field of the Custom Properties dialog is: VertToolbar - - - - - This method establishes the image list used to display images in the toolbar. - Parameters: - HIMAGELIST hImage - - The image list. An image list is a collection of same-sized images, each of which can be referred to by an index. Image lists are used to efficiently manage large sets of icons or bitmaps in Windows. All images in an image list are contained in a single, wide bitmap in screen device format. An image list may also include a monochrome bitmap that contains masks used to draw images transparently (icon style). The Windows API provides image list functions, which enable you to draw images, create and destroy image lists, add and remove images, replace images, and merge images. - - - - - The developer calls this method once for each item in the toolbar. The items appear in the toolbar from left to right in the order that they were added using this method. (Note that this method adds tools to the custom toolbar and not the 3ds Max toolbar). - Parameters: - & entry - - Describes the of item to add to the toolbar. - - int pos=-1 - - Controls where the added tool is inserted. The default of -1 indicates the control will be added at the right end of the toolbar. - - - - - This method is used to delete tools from the toolbar. - Parameters: - int start - - Specifies which tool is the first to be deleted. - - int num=-1 - - Specifies the number of tools to delete. If this parameter is -1 (the default) it deletes 'start' through count-1 tools. - - - - - Passing TRUE to this method draws a border beneath the toolbar. - Parameters: - BOOL on - - TRUE to draw the border; FALSE for no border. - - - - - Passing TRUE to this method draws a border above the toolbar. - Parameters: - BOOL on - - TRUE to draw the border; FALSE for no border. - - - - - This method is used to return a pointer to one of the toolbar's buttons. Using this pointer you can call methods on the button. If you use this method, you must release the control after you are finished with it. - Parameters: - int id - - Specifies the id of the toolbar button. - A pointer to one of the toolbar's buttons. - - - - - This method is used to return a pointer to one of the toolbars status controls. Using this pointer you can call methods on the status control. If you use this method, you must release the control after you are finished with it. - Parameters: - int id - - Specifies the id of the toolbar button. - A pointer to one of the toolbars status controls - - - - - Returns the handle to the toolbar item whose ID is passed. - Parameters: - int id - - Specifies the id of the toolbar button. - - - - - Class representing the DestructorPolicy for AutoPtr instances wrapping pointers. - - - Sample Code: - - - - - Viewport button abstraction. - - - The new viewport menu system is implemented using this interface. It provides control over the text to display and location to be drawn in. ViewportButtonText implements this interface to draw text based button in the viewport. - - - - - Access to the enabled flag - TRUE if enabled - - - - - the Enabled flag. If set to false, the button will not be drawn - - true to enable, false to disable the button. - is the view panel index where the button is. If it is a negative value, we will use the active viewport to refresh the buttons - is the viewport index in the view panel where the button is. If it is a negative value, we will use the active viewport to refresh the buttons - - - - Access to the button text to be displayed in the viewport - A string containing the current label to be displayed. - - - - - Get the current location for the button - The location of the button - - - - - Get the current color for the button - The current color - - - - - Defines whether the button is only shown in the current active viewport - TRUE if only drawn in the active viewport - - - - - A callback to allow the button to perform an action, such as pop up a menu, or run a function - TRUE if an action was performed. - - The Window handle where the action we performed - A pointer to the - The point where the action occured - this allows the button to perform a hittest. - The type of action - - - - An update callback that can be used to update internal data structures. The uses this to determine the Label to be used and location based on the current viewport being drawn. - TRUE if an update was implemented. - - The Window handle issueing the update request - A pointer to current - - - - Callback to display the button. The uses this to draw text into the viewport using API. All drawing should go through this API - no GDI. - - The current time - THe viewport to draw into - - - - - Get the viewport rect for the button - - The current time - The active viewport - The result of the viewport rect is stored here. - - - - A manager to control the usage of the viewport buttons. - - - A Manager that the developer uses to register viewport buttons. It also contains helper function to provide global hittesting and per button hittesting. The developer can use these from within the OnAction callback. The manager is not responsible for deleting the manager. The developer should Unregister and then delete the button - To use simply use static_cast<IViewportButtonManager*>(GetCOREInterface(IVIEWPORTBUTTONMANAGER_INTERFACE )) - - - - - Register a new button. - - - Register a new button with the manager. The system will check against buttons already registered - - The new button to register - - - - Remove a previously registered button. - - - Remove a button already registered with the system. The manager will not delete the button, simply removes it from the table - - The button to remove - - - - A query to check if a button is registered. - - - Check to see if the button is registered. Developers can use this to check to see if a button is registered before trying to register it - - The button to test against - - - - The total number of buttons. - - - The number of button registered with the manager - The total button count - - - - - Access an indivdual button. - - - Access to a specfiic button by index. - The actual button, or NULL if index is invalid - - The index of the button to acess - - - - globally enable/disable the viewport buttons - - - A global method for enabling the viewport button. If the buttons are disabled, nothing will be displayed or processed. - - TRUE if the buttons are to be enabled - - - - Globally acces whether the viewport buttons are enabled. - - - A global method for querying viewport buttons enabled status. If the buttons are disabled, nothing will be displayed or processed. - TRUE if enabled - - - - - Sends the OnAction command. - - - Send the OnAction command to all registered viewports - TRUE if an action was performed. - - The Window handle where the action we performed - A pointer to the - The point where the action occured - this allow the button to perform a hittest. - The type of action - - - - Send the OnUpdate command. - - - Sends the OnUpate command to all registered viewports - TRUE if an update was implemented. - - The Window handle issueing the update request - A pointer to current - - - - Provides a single hittest of the text. - - - Utility function to perform hittesting on the supplied string and the location provided The derived can use this for localised hit testing, for example in the OnAction method - TRUE if the mouse point intersects the string rectangle - - The window handle - pointer from the active viewport - The start location of the supplied string - The mouse position - The label to hittest against - - - - Global hittesting on all registered buttons. - - - Utility function to allow hittesting on all buttons registered. It will simply return TRUE on the first successful hit test on the button label - TRUE if the mouse point intersects any button's label - - The window handle - The for the active viewport - The mouse position - - - - Render the buttons. - - - Global function to draw each button registered in the system. - - The current active viewport - If none NULL, the complete viewport Rect is stored here. - - - - Utility function for forcing a refresh of the button display. - - - - - An class to access the Viewport Manager. - - - This allows access to the various components of the Viewport Manager. THis includes finding out how many effects are registered with the system - - - - - Get the number of effects registered with the system - The total number of effects - - - - - Get the current active effect. This effect will implement the classes - A referenceTarget implementing the effect - - - - - Access the UI name for the effect - A MCHAR containing the name - - An index of the effect whose name is required - - - - the actual viewport effect to be used. - A pointer to the effect - - An index of the effect to set. - - - - Turns on the effect based on the material and state supplied. THis sets the internal flag on the material that tells the system that a DX shader is present - - THe material to activate - A boolean value that defines the state of the flag - - - - A new interface for 3dsmax 7. - - - This extends the current interface, and provides support for the new UI options on the Viewport Manager - - - - - Save the current effect based on the Standard as an effect file. - - - The success of the operation - - The name of the file to save - - - - Is the DX Display of the Standard enabled - TRUE/FALSE - - - - - Access to set the state of the DX Display of the Standard flag - - The state of the flag - TRUE to set - - - - The name of the current effect as displayed in the UI - The name of the effect - - - - - A new interface for 3dsmax 10. - - - Extends This interface is implemented by 3ds Max, more specifically by the DirectX Manager and Mental custom attributes of materials. Client code can get this interface from a material with the following code: - - - - - GetActiveEffect and GetActiveEffectName returns information of currently selected effect, however, the effect may still not be "enabled". To get the enable/disable state of the effect, use this function. - The enable/disable state of the effect - - - - - Access to set the enable/disable state of the current selected effect. - if current effect is enabled successfully, return true, otherwise return false. - - The state of the flag - TRUE to set - - - - Is the DX Display of the is supported at this moment. - true means that we could turn directX rendering of the material on. otherwise return false. - - - - - Is saving Standard as .fx file is supported at this moment. - true means that we could save current material as a .fx file. otherwise return false. - - - - - Is current selected effect is supported. - true means that we could enable current effect. otherwise if current effect can not be enabled, return false. - - - - - owner material of this interface - - - - - Viewport manager to control general illumination, including shadow support in the viewport. - - - New to 3ds Max 2008, the gives access to the new viewport Shading feature. The viewports have been redesigned to support more realistic rendering including Shadows. The interface also provides access to various flags that control how lights are used in the viewport. This is used closely with the new INodeShadingProperites API, that manages the actual flags set by The developer can get access to the CORE interface by using - - - - - Define the viewports shading quality. - - - the viewport rendering quality to a value defined in EViewportDisplayQuality. Please make sure you call IsShadingLimitValid before this method to determine if the graphics hardware supports this shading level. - - The shading limits as defined by EViewportDisplayQuality - True to enable quiet mode. No dialogs will be produced to provide user feedback. This defaults to true. - - - - Retrieve the viewport quality. - - - Get the viewport rendering quality, as defined by EViewportDisplayQuality - The rendering quality - - - - - Get the current state of the Auto Display Selected light flag. - - - This will return the current state of the Auto Display of selected lights flag Any lights that are selected will automatically have their illumination flag set and take part in viewport rendering. If they have their shadow flag set as well, they will become shadow casters. - The state of the flag - - - - - Access the flag defining whether shadows are generated for default lights. - - - The state of the flag - - - - - A method that defines that the current selected lights will be part of viewport rendering. - - - When used, all lights that are currently selected will have their Illumination flag set, and will be part of the viewport rendering. All unselected lights will be deactivated. - - - - - Lock the current selected lights. - - - A locked light will be active in the viewport rendering, regardless of other flags set This could be something like a sun light, that always illuminates and casts shadows. Any selected light will have this flag set depending on the parameter value - - The value of the flag to set. - - - - A method to retrieve lights based on the usage in the scene. - - - This is a general method to retrieve a list of nodes based on EViewportLightFlags. This is a quick way off accessing all viewport shadow casting lights in the scene. - - A node tab to retrieve the node list based on type - The light type to store based on EViewportLightFlags - - - - Retrieve the Global shadow intensity. - - - This will return the current intensity value for the shadows. - The intensity value - - - - - Get the current Transparency in shadows flag. - - - See SetUseTransparencyInShadows - The current state of the flag - - - - - Get the current update shadow in active view only flag. - - - See SetUpdateShadowInActiveViewOnly - The current state of the flag - - - - - Determine whether the shading limit is compatible with the current graphics hardware. - - - This method is used to determine if the graphics hardware can support the shading level. This will query the GPU to find out what pixel shader support exists. For "Best", shader model 3 is required, "Good" needs a minimum of shader model 2. The developer should call this method before calling SetViewportShadingLimits as that method will not perform any additional tests. - True is the shading limit is supported - - The shading limit to test - - - - Get the light icon color based on the current viewport shading limits. - - - The light icon that gets drawn should reflect the current state of the viewport shading. When the light is shadow casting it will be displayed in a duller color. If the light is currently not illuminating again it will appear duller than the usual wireframe color. This method should be used for any lights that display a viewport icon and want to adhere to the new coloring scheme. The color returned can be used in the GraphicsWindow::setColor function. - The new altered color. If viewport shading is set to "None" - this will be the default wireframe color - - The light node to check for the current state of viewport shading flags - - - - Get whether the GI viewport system uses Transparency. - - - - - Get the shadow filter size of soft-edge shadow. - - - This will return the current filter size of soft-edge shadow. - The filter size value - - - - - Extends class . - - - - - The active viewport can be interpreted by the function is two ways. Firstly if bCurrentlyTraversed is false, the default, the actual active viewport is used. This would be the same as Interface::GetActiveViewport(). Secondly if bCurrentlyTraversed is true, then the viewport that is currently being traversed as part of the viewport rendering will be considered the active viewport. This could be used by a material that needs additional setup if hardware rendering is being performed. - TRUE if enabled - - Defines what the method will interpret as the active view. See notes for the function. - - - - Get the hardware enabled flag for the view supplied. - - - TRUE if enabled - - The view to query - - - - Many viewpanel related methods of CORE interface only work on the active tabbed view panel. For example, Interface::getNumViewports() only return the number of viewports of current view panel. This interface provides methods to get/modify settings of a tabbed view panel no matter it is currently active or not. - - - - - Gets number of the enabled and non-extended viewports. - the number of the enabled and non-extended viewports. - - - - - Gets the layout of this view panel. - the layout id - - - - - layout of this view panel. - - the layout configuration to use - force the config setting to be re-applied - - - - Gets index of the viewport with the specified window handle. User can use the viewport index to get the corresponding interface by calling IViewPanel::GetViewExpByIndex(int index). - the index of the viewport with the given window handle. If none of the viewport matches the given handle, -1 is returned. - - the window handle of a viewport in this viewpanel. - - - - active viewport according to the input param. - true if this operation succeeds, false otherwise. - - the index of the viewport to be activated - - - - Get the index of the active viewport. - the index of the active viewport. If there is no active viewport in this viewpanel, -1 is returned. - - - - - Get the window handle of the tabbed view panel - Return the window handle of the view panel. - - - - - Get the view panel name. - Return the view panel name. - - - - - Get the interface given the viewport index. - if input is valid, the specified interface will be returned. Otherwise, the interface of the first viewport(index = 0) will be returned. - - a valid viewport index - - - - Gets if this view panel is a floating view panel. - Return true if it is a floating view panel. - - - - - Gets if this view panel is currently visible . - Return true if this view panel is currently visible. - - - - - Is the view panel in presentation mode ? The presentation mode works only on floating view panels. It is a viewport mode where there are no border, no grid, no view cube, no gizmos... The view in presentation mode is always updated even if it is not the active view. - Return true if it is in presentation mode. - - - - - In 3ds Max 2013, 3ds Max introduces the tabbed view panels. Previously 3ds Max can have only one view panel(One view panel contains at most 4 viewports). Now 3ds Max users can create additional view panels other than the default view panel by using the tabbed view panel toolbar or MaxScript. Users can switch between those view panels. At one time, there can only be one view panel visible which we usually call it current view panel or active view panel. Each view panel can have one active viewport. Users can also destroy those additional view panels (NOTE: The default view panel can't be destroyed). Tabbed view panels will be saved & loaded during FileIO. When saving as previous, only the current active view panel will be saved. This interface is used to manage the multiple tabbed view panels. To acquire this interface, simply use the codes below. - In a future release of 3ds Max we will introduce the notion of visible and floating view panels. When this is done, more than one view panel at a time can be visible. There will always be the main view panel attached to 3ds Max main window but you will be able to set visible, floating view panels, which could be put on another monitor. To support these visible view panels, instead of using GetActiveViewPanel() and do things on its viewports, use the new methods IsViewPanelVisible and IsViewPanelFloating when iterating on all view panels. - - - - - Check if we can create any more tabbed view panels. - true if we can create more view panels, false otherwise. - - - - - Create a new tabbed view panel. - Return the index of the new tabbed view panel.If creation fails, -1 will be returned. - - the name of the new tabbed view panel. If NULL, a default name will be assigned to the new tabbed view panel automatically. - the initial layout of the new tabbed view panel. Use VP_LAYOUT_XXX macro in . - if true, the new tabbed view panel will be set as active view panel after creation. - - - - Create a new tabbed view panel. The panel is given a default name based on its layout. - Return the index of the new tabbed view panel. If creation fails, -1 will be returned. - - the initial layout of the new tabbed view panel. Use VP_LAYOUT_XXX macro in . - if true, the new tabbed view panel will be set as active view panel after creation. - - - - Destroy the specified tabbed view panel. - Return true if destruction succeeds, false otherwise. - - the index of the tabbed view panel to be destroyed. An valid index should be from 1(0 is the default view panel) to - 1. Also, the panel specified cannot be 'locked'. Locked panels cannot be destroyed. - - - - Get the interface of the active tabbed view panel. - Return the interface of the current active view panel or NULL if there is no active view panel. - - - - - a tabbed view panel as the current active view panel - Return true if operation succeeds, false otherwise. - - the index of the view panel to be activated. - - - - Get the index of the active view panel. - Return the index of the current active view panel or -1 if is there is no active view panel. - - - - - Get the index of the view panel. - Return the index of the view panel or -1 if pViewPanel is a nullptr or if pViewPanel is not in the view panel array. - - the view panel. - - - - Get the count of current existing view panels. - Return the count of current existing view panels. - - - - - Get the interface of the specified tabbed view panel. - Return the interface of the tabbed view panel specified by the input index. Return NULL - - the index of the tabbed view panel - - - - Get the name of the specified view panel. - Return the name of the specified view panel. If the input index is invalid, NULL will be returned. - - the index of the view panel whose name to be returned - - - - the name of the specified view panel. - Return true if the operation succeeds, false otherwise. - - the index of the view panel whose name to be set - the new name of the specified view panel - - - - A locked view panel is one that cannot be deleted by the user, such as the default view panel or a floating view panel - true if the index is valid and the panel is considered 'locked' by the manager - - of the panel to check - - - - This method gets if a view panel is currently visible by its index in the view panels array - Returns true if the view panel is visible, false if it is not or if viewpanelIndex is out of range - - the index in the view panel array - - - - This method gets if a view panel has the floating view panel property, whether or not it is currently visible - Returns true if the view panel is a floating view panel, false if it is not or if viewpanelIndex is out of range - - the index in the view panel array - - - - Get the number of floating view panels - Returns the number of floating view panels - - - - - Hides all the floating view panels - - - - - This method gets the view panel floating ID by its index in the array of view panels - Returns the ViewPanelFloatingID of this view panel. If it's not a floating view panel, it returns ViewPanelFloatingID::NotFloating - - the index in the view panel array - - - - This method gets the index of a view panel from its ViewPanelFloatingID - Returns the index of the view panel whose ViewPanelFloatingID is viewPanelFloatingID or -1 if not found. - - the ViewPanelFloatingID of the view panel to retrieve - - - - This method sets a floating view panel visible and active at the same time - - the ViewPanelFloatingID of the view panel - is true if we want the floating view panel to be visible and active or false if we want to hide it - - - - This method sums the viewports from all visible view panels by calling getNumViews() on each of the view panel - Return the number of viewports from all visible view panels - - - - - Gets the number of view panels currently visible - Returns the number of visible view panels. - - - - - Returns the index of the currently highlighted ViewPanel. This is the index of the tabs as iterated through via Ctrl-Tab - Index of the currently highlighted ViewPanel, or -1 if none are highlighted. - - - - - Cycle the highlight through available view panels. This is the equivalent of the ctrl-tab functionality - - - - - Cycle back through the highlight through available view panels. This is the equivalent of the shift-ctrl-tab functionality - - - - - Select the currently highlighted view panel - True if the active panel is changed. - - - - - SeeAlso: Class . - - - Description: - This class provides an interface into 3ds Max's default WAV sound object. Use the method GetSoundObject() to get a pointer to the current sound object and then use the macro GetWaveSoundInterface() on the result to see if it supports this interface. See the sample code below: - - // Retrieve the current sound object - - *sound = ip->GetSoundObject(); - - // Attempt to get a wave interface - - ; - - if (iWave) { - - iWave->SetSoundFileName(_M("LedZep.wav")) - - } - - All methods of this class are implemented by the system. - - - - - Returns the name of the current sound file asset. - - - - - Sets the sound file asset. This will cause the .WAV to be loaded into the track view. - Parameters: - MSTR name - - The name of the sound file asset to set. - FALSE if the file can't be opened or no wave track exists; otherwise TRUE. - - - - - Returns the start time offset for the wave. - - - - - Returns the end time for the wave. - - - - - The interface to the functionality for using the Working Pivot. - - - This class contains key functionality for using the working pivot. You get this interface by calling GetIWorkingPivot(). - - - - - This function returns whether or not we are using the working pivot transform space, thus whether or not the working pivot is the pivot for all of the objects in the scene. - Returns TRUE if we are using the working pivot transform space, FALSE otherwise. ! - - - - - This function gets whether or not we are in the mode where we can edit the working pivot. !\ return Return TRUE if we are in the mode where we can edit the working pivot, otherwise return FALSE. ! - - - - - This function puts us in a command mode where any click in the viewport will automatically move the working pivot to that position in screen space. - - If TRUE and not in the place pivot view command mode then we enter the place pivot view command mode, if FALSE and we are in the place pivot view command mode then we exit that mode. Note that we aren't in the edit working pivot mode when entering this mode we enter edit working pivot mode automatically and then if we exit in this case we also turn off edit working pivot mode. - If TRUE and we are entering this mode then when we place the pivot it also automatically aligns to the current view of the viewport when you click. Also note that in this case it also sets the Align To toggle in the 'Place Pivot To:' group in the Hierarchy panel. ! - - - - This function returns whether or not we are in the place pivot command mode - Returns TRUE if we are in the place pivot command mode, otherwise returns FALSE. Note that we will never be in the place pivot mode if not also in the edit working pivot mode. ! - - - - - This function puts us in a command mode where we will place the working pivot onto any surface in the scene, including grids. - - If TRUE and not in the place pivot on a surface command mode then we enter the place pivot on a surface command mode, if FALSE and we are in this command mode then we exit this mode. Note that we aren't in the edit working pivot mode when entering this mode then we enter edit working pivot mode automatically and then if we exit in this case we also turn off edit working pivot mode. - If TRUE and we are entering this mode then when we place the pivot by clicking it also automatically aligns to the current view of the viewport when you click. Also note that in this case it also sets the Align To toggle in the 'Place Pivot To:' group in the Hierarchy panel. ! - - - - This function returns whether or not we are in the place pivot on the auto grid command mode - Returns TRUE if we are in the place pivot on the auto grid command mode, otherwise returns FALSE. Note that we will never be in the place pivot on the auto grid mode if not also in the edit working pivot mode. ! - - - - - This function returns whether or not when we are in a place pivot mode if we are also aligning to the view. - Returns TRUE if we are in a place pivot mode and we are aligning to the view, otherwise if we aren't in a place pivot mode or we are but we aren't aligning to the view it returns FALSE. ! - - - - - This function returns whether or not when we are using the Pin Working Pivot option. - Returns TRUE if the Pin Working Pivot is turned on, returns FALSE otherwise. ! - - - - - This function gets the world space transofrm of the working pivot. When using the working pivot this will be the location about which pivoting will occur, and when editing the working pivot this is the location of where the pivot is when the mode is entered and exited. - Returns the world space location of the working pivot. ! - - - - - This function gets the axis display size of the working pivot when it's displayed when in use or being edited. - Returns the length of each working pivot axis in 3ds Max units. ! - - - - - This function gets the whether the caddy will be displayed while in Edit mode. ! - - - - - This function gets the whether the caddy will be displayed while in Place mode. ! - - - - - This function aligns the working pivot transform to the that of the active viewport. It does this by changing the rotation of the working pivot transform to match the rotation of the active viewport. Note that this function does nothing if we aren't in the edit or use working pivot modes. ! - - - - - This function allows you to reset the working pivot's transform so that it matches that of the current selection. After this function is called, the working pivots world space transformation will equal that of the current selection. Also note that this function does nothing if we aren't in the edit or use working pivot modes. - ! - - - - - This function allows you to reset the working pivot's transform so that it matches that of a selected node that's passed in as a parameter. - - The node whose world space transform the working pivot's transofrm will get set equal to. If the node is NULL, or if we aren't in the edit or use working pivot modes, then nothing will happen. Finally, the working pivot will match up with the node transform, not the object trnasform. ! - - - - Used internally. - - - - - The interface to the CS Workbench. - - - This class contains all of the functionality found in the UI of the workbench. Note that these functions also affect the drawing and viewing of CS curves in the normal trackview. Thus you can extend the normal curve editor, via quad menus, etc.. to basically work like the workbench. You get this interface by calling GetCOREInterface(WORKBENCH_INTERFACE) - - - - - Additional interface for the CS Workbench. - - - This class contains new functionality found in the UI of the workbench. You get this interface by calling GetCOREInterface(WORKBENCH2_INTERFACE) - - - - - Class representing xref atmospherics. - - - This interface groups functionality specific to xref atmospherics. In order to access functionality common to all xref scene entities, use the interface. An xref atmospheric acts as a wrapper around the xrefed atmospheric (also referred to as the "source atmospheric"). For example, requests for getting the atmospheric's gizmos (NumGizmos, GetGizmo) are passed to the source atmospheric, as are requests for interfaces. Client or plugin code working with atmospherics should not be required to write xref atmospheric specific code, unless the desired functionality is xref specific. - Note that xref atmospherics can only have gizmos that are xrefs (xref objects) themselves. Xref atmospherics will be automatically removed from the scene when all their gizmos have been removed. - Xref Atmospherics are never nested, even when their gizmos are, and they are always owned by non-nested (top-level) xref records. - - - - - Retrieves the source atmospheric, i.e., the actual atmospheric behind the XRef. - - - The source atmospheric, or NULL if the XRef is unresolved. - - - When set to true, the method will recursively resolve any nested XRef atmospherics, guaranteeing that the one being returned is NOT an XRef atmospheric. When set to false, the source is returned directly without attempting to resolve nesting. - - - - implemented by the XRef controller. - - - The XRef controller is a wrapper that allows the user to retrieve a pointer to the "source controller". - - - - - Retrieves the source controller, i.e., the actual controller behind the XRef. - - - The source controller, or NULL if the XRef is unresolved. - - - When set to true, the method will recursively resolve any nested XRef controllers, guaranteeing that the one being returned is NOT an XRef controller. When set to false, the source is returned directly without attempting to resolve nesting. - - - - Returns the function publishing descriptor for the XRef Controller. - - - This method is needed in order to avoid multiple inheritance problems. - The function publishing descriptor for the XRef Controller. - - - - - If the XRefCtrl is not nested, set its offset matrix back to identity, and if it is resolved, i.e., it has a Source controller, set this one's transformation matrix accordingly. - - - - - interface that represents an xrefed scene entity. - - - This interface exposes services common to all xref scene entities. 3rd party plugins do not need to derive from this interface. Support for xrefing different plugin categories is provided by the system (3ds Max). Each plugin category that supports xrefing is modeled as a class that implements this interface. - Xref items can be created and modified via the XRef Manager (), and live in xref records (). An xref item can live in one and only one xref record. - Sub-object animation of a scene entity is maintained when the scene entity is xrefed. Transform animation of a scene entity such as a node is brought into the main file, but is not updated when the xref record is updated. - In order to retrieve this interface from a scene entity, one must call either IXRefItem::GetInterface with a reference to a scene entity (, Atmospherics, etc.), - - - - - Retrieves the file asset that the source scene entity comes from. - - - - The file asset that the source scene entity comes from. - - - - - Retrieves the name of the source scene entity. - - - - Pointer to the name of the source scene entity or NULL if there's no source item name specified. - - - - - Retrieves the source scene entity xrefed by this xref item. - - - - Pointer to the source scene entity xrefed by this xref item. The source entity can be itself an xref item or a derived object if the supplied parameter is false. If the source scene entity is NULL, the xref item is unresolved. - - - If true, the method looks for the first non-xref source item. This could be a direct or indirect source item. - - - - Allows to verify whether the xref item is unresolved. - - - An xref item is unresolved if the source scene entity is invalid. This can happen for example if the source scene entity does not exist in the source file or the xref item has been pointed to a source file that does not exist. Unresolved xref items will not render, but have a default viewport representation. Unresolved xref items may get re-resolved on a subsequent reload of the xref item's record. - - true if this is an unresolved xref item - - - - - Retrieves the xref record this xref item belongs to. - - - The xref record this xref item belongs to. An xref item can belong to one and only one xref record at any one time. A return value of NULL, indicates that the xref item is not part of an xref record yet. - - - - - Retrieves the nodes associated with this xref item. - - - This method retrieves all the nodes that reference this xref item. If this xref item is an xref atmospheric, no nodes will be reported. If this xref item is nested, this method retrieves the nodes that reference it indirectly. Note that nodes that are not in the scene could also be returned by this method. - - - The tab of nodes that reference this xref item. The tab is not cleared by this method. The tab is guaranteed to not contain duplicated nodes. - - - - Retrieves the xref items under which this xref item is nested. - - - A nested xref item can have multiple parent items (when for example a nested xref item is cloned), and all of them have the same type as their child item. - - The number of parent xref items returned. - - - where the parent xref items of this item are returned. The parent xref items are added to the array without clearing it out first. - - - - Returns the list of every xref item for which GetParentItem() would return 'this'. - - - A child xref item is a xref item encountered when walking down any given path in the reference hierarchy of this xref item. An xref item may have several child xref items. - - The number of child xref items returned. - - - where the child xref items of this item are returned. The child xref items are added to the array without clearing it out first. - - - - Retrieves the root (top-level) xref items of this xref item. - - - This method retrieves all top-level parent xref items of this item. A top-level xref item is an item that does not have an ancestor. The top-level xref item of an item that doesn't have ancestors is itself. - - The number of top-level (root) xref items returned. - - - where the top-level (root) xref items of this item are returned. This array is guaranteed to contain at least this xref item. - - - - Checks whether this xref item is a nested one. - - - This method offers a more efficient way of finding out if this xref item is nested than calling GetParentItems. - - true if this xref item is a nested one. - - - - - Gets file name of xref. Implemented by the system. - - - - - Sets item name of xref. Implemented by the system. - - - - - Class representing xref materials. - - - This interface groups functionality specific to xref materials. In order to access functionality common to all xref scene entities, use the interface. An xref material acts as a wrapper around the xrefed material (also referred to as the "source material"). For example, all shading methods on the XRef are automatically forwarded to the source material, requests for interfaces are also forwarded to the source material. Client or plugin code working with materials should not be required to write xref material specific code, unless the desired functionality is xref specific. - - - - - Retrieves the source material, the actual material behind the XRef. - - - The source material, or NULL if the XRef is unresoled. - - - When set to true, the method will recursively resolve any nested XRef materials, guaranteeing that the material being returned is NOT an XRef material. When set to false, the source is returned directly without attempting to resolve nesting. - - - - Returns the function publishing descriptor for the XRef . - - - This method is need in order to avoid problems inherant to multiple inheritance. - The function publishing descriptor for the XRef . - - - - - Class extends interface with override material feature. - - - This interface adds access to the new override material of xref material. The override material replace source material when turns on. In nested case, the override material acts as the source material when enabled. Some new query methods are supplied to get override material status and current material in use. - - - - - Get/Set override material enableness flag. - - - - - Getting override/source material recursively, according to override enableness flag. - - - - The Xref material's active material. - - - - - Legacy interface for xref objects. - - - Note:In 3ds Max 8 this class was replaced with class IXrefObject8. It is still documented for backwards compatibility. - Description: - This class is an interface to the parameters of an XRef object. XRefs are derived from this class. - - If you have an object pointer you can check its super class ID and class ID to see if it is an XRef object. Then you can cast it to an instance of this class and call these methods. For example: However you may have an object that depends on an XRef object (for example a with an XRef object as one of it's operands) or you may have a pointer to the object that the XRef object references. In such cases the only way to know for sure is to look up and down the pipeline for XRef objects. - - - - - This method initializes a newly created XRef object. The caller provides the name of the file (fname), the name of the object in the file (oname), and a pointer to the object being XRefed (ob). - Parameters: - MSTR &fname - - The file name is set to this string. - - MSTR &oname - - The object name is set to this string. - - *ob - - Points to the object being XRefed. - - BOOL asProxy=FALSE - - If TRUE then the above information is considered to specify the proxy portion of the XRef. - - - - - Sets the Source or Proxy file depending on the value passed. - Parameters: - AssetUser &asset - - The asset to set. - - BOOL proxy=FALSE - - TRUE to set the Proxy file name; FALSE for the XRef file name. - - BOOL update=TRUE - - TRUE to update the scene; FALSE to not update immediately. - - - - - Sets the name or the Proxy name depending on the value passed. - Parameters: - MCHAR *name - - The name to set. - - BOOL proxy=FALSE - - TRUE to set the Proxy name; FALSE to set the name. - - - - - Sets the state of the Use Proxy choice and optionally redraws the viewports. - Parameters: - BOOL onOff - - TRUE for on; FALSE for off. - - BOOL redraw=TRUE - - TRUE to redraw the viewports; otherwise FALSE. - - - - - Sets the state of the Ignore Animation choice and optionally redraws the viewports. - Parameters: - BOOL onOff - - TRUE for on; FALSE for off. - - BOOL redraw=TRUE - - TRUE to redraw the viewports; otherwise FALSE. - - - - - Returns the File asset or the Proxy file asset depending on the value passed. - Parameters: - BOOL proxy=FALSE - - TRUE to return the Proxy file asset; FALSE for the XRef file asset. - - - - - Returns the name or the Proxy name depending on the value passed. - Parameters: - BOOL proxy=FALSE - - TRUE to return the Proxy name; FALSE to return the name. - - - - - Returns the XRef File. - - - - - Returns the XRef . - - - - - Returns TRUE if the Use Proxy option is on; otherwise FALSE. - - - - - Returns TRUE if the Render Proxy option is on; otherwise FALSE. - - - - - Returns TRUE if the Update option is on; otherwise FALSE. - - - - - Returns TRUE if the Ignore Animation option is on; otherwise FALSE. - - - - - This method brings up the browse object (Merge) dialog. - Parameters: - BOOL proxy - - TRUE to have Use Proxy mode active; FALSE to have it inactive. - - - - - This method brings up the browse file (Open File) dialog. - Parameters: - BOOL proxy - - TRUE to have Use Proxy mode active; FALSE to have it inactive. - - - - - Reloads this XRef. - - - - - Class representing Xref objects. - - - This interface groups functionality specific to xref objects. In order to access functionality common to all xref scene entities, use the interface. An xref object acts as a wrapper around the xrefed object (also referred to as the "source object"). For example, requests for evaluating the xref object (Eval) and finding its base object (FindBaseObject) are passed to the source object, as are requests for interfaces. Client or plugin code working with objects should not be required to write xref object specific code, unless the desired functionality is xref specific. - - - - - Retrieves the active source file. - - - The file currently used by the xref object could be the one where the source object comes from or the one where the proxy object comes from. Which file is currently used depends on the proxy settings of the xref object - - The file asset currently used by the xref object. - - - - - Retrieves the active source item name. - - - The object name currently used by the xref object could be the source or the proxy object name. Which object name currently used depends on the proxy settings of the xref object. - - Pointer to the name of the object currently xrefed or NULL if the name is not specified. - - - - - Retrieves the active xref record this xref object belongs to. - - - When the proxy object assigned to this xref object is active, this method returns the xref record that owns the xref proxy. Otherwise it returns the xref record that owns the original xref item. - The active xref record this xref object belongs to. A return value of NULL, indicates that the xref object is not part of an xref record yet. - - - - - Retrieves the actual source object behind the XRef. - - - The source object, or NULL if the xref is unresolved. - - - When set to true, the method will recursively resolve any nested xref objects, guaranteeing that the one being returned is NOT an xref object. When set to false, the source object is returned without attempting to resolve nesting. - - a pointer to a Tab<Modifier*> or NULL. If not NULL, the modifiers in the source object will be placed in the tab. - - - - Class for working with the proxy aspect of an xref scene entity. - - - Some types of xref scene entities allow to be replaced by a proxy (an alternate scene entity) that may reside in a different scene than the xrefed scene entity itself. The proxy scene entity can have a different type (superclass and class ids) than the xrefed scene entity. Proxies can be used to replace the actual xref scene entity in the viewport and/or rendering. Some xref scene entities provided by the system, such as xref objects, expose the interface. In order to retrieve this interface one must call IXRefProxy::GetInterface with a reference to a scene entity. - - - - - Gets file name of xref proxy. Implemented by the system. - - - - - Sets item name of xref proxy. Implemented by the system. - - - - - Retrieves the proxy file asset. - - - - The proxy file asset. - - - - - Retrieves the name of the proxy scene entity. - - - - Pointer to the name of the proxy scene entity or NULL if there's no proxy object set up. - - - - - Retrieves the xref record this xref proxy belongs to. - - - The xref record this xref proxy belongs to. An xref proxy can belong to only one xref record at any one time. A return value of NULL, indicates that the proxy is not part of an xref record yet. - - - - - Retrieves whether the proxy is being used for viewport display. - - - bool - True if the proxy is displayed in the viewport, otherwise false - - - - - Retrieves whether the proxy is being used for rendering purposes. - - - bool - True if the proxy is being rendered, otherwise false - - - - - Provides an interface to access Extension Channels. - - - - - - This method adds an extension object into the pipeline. - - The extension object you wish to add. - The priority to set. - The branch identifier to set. - - - - This method returns the number of extension objects. - - - - - This method returns the I-th extension object. - - The index of the extension object to return. - - - - This method allows you to remove the I-th extension object. - - The index of the extension object you wish to remove. - - - - This method allows you to set the priority for the I-th extension object. - - The index of the extension object for which to set the priority. - The priority to set. - - - - This method returns the priority for the I-th extension object. - - The index of the extension object. - - - - This method allows you to set the branch identifier for the I-th extension object. - - The index of the extension object. - The branch identifier to set. - - - - This method returns the branch identifier for the I-th extension object. - - The index of the extension object. - - - - This method has to be called whenever the CompoundObject updates a branch (calling Eval on it). *from is the object returned from Eval (os.obj); branchID is an int, that specifies that branch. The extension channel will get a callback to RemoveXTCObjectOnMergeBranches() and MergeXTCObject(). By default it returns true to RemoveXTCObjectOnMergeBranches(), which means, that the existing XTCObjects with that branchID will be deleted. The method MergeXTCObject() simply copies the XTCObjects from the incoming branch into the compound object. - - The object from which to merge additional channels - The branch identifier. - - - - This method has to be called on the CompoundObject, so it can delete the XTCObjects for the specific branch. The will have again the final decision if the gets really deleted or not in a callback to RemoveXTCObjectOnBranchDeleted(), which will return true, if the should be removed. - - The branch identifier. - TRUE to reorder the channels, otherwise FALSE. - - - - This method copies all extension objects from the "from" objects into the current object. In case deleteOld is false, the objects will be appended. In case it is true, the old XTCObjects will be deleted. - - The object to copy from. - TRUE to delete the old channel, FALSE to append the channels. - TRUE to create a shallow copy, FALSE to create a deep copy. - - - - This method allows you to delete all additional channels. - - - - - Description: - This class simply holds a few pointers used with joint parameter dialogs. - Data Members: - *ui; - - This points to storage where the window handle, the interface pointer, and the controller being edited can be retrieved. - - *jp; - - This points to a class used to work with the IK joint parameters dialog. - - - - - - Description: - This class handles the data storage and user interface for inverse kinematic joint parameters. The default 3ds Max controllers use this data structure to store their IK information. Plug-in controllers don't have to unless they want to. - - Note the following is a dialog proc for handling joint parameters that is exported for use by plug-ins. - - BOOL CALLBACK JointParamDlgProc(HWND hWnd,UINT message, - - WPARAM wParam,LPARAM lParam); - Data Members: - float *min, *max; - - Pointers to an array of floats corresponding to the number of degrees of freedom These are the From and To parameters. - - float *damping; - - Pointer to an array of floating point Damping parameters for each degree of freedom. - - float scale; - - This is a scale factor applied to the values in the spinner edit fields. This is to make them more sensible to the user. For example a percentage that is stored internally as 0.0 to 1.0 could be presented to the user as 0.0 to 100.0 by using a scale of 100. - - DWORD flags; - - One or more of the following values: - - JNT_XACTIVE - - JNT_YACTIVE - - JNT_ZACTIVE - - JNT_XLIMITED - - JNT_YLIMITED - - JNT_ZLIMITED - - JNT_XEASE - - JNT_YEASE - - JNT_ZEASE - - JNT_LIMITEXACT - - JNT_ROLLOPEN - - JNT_ROT - - JNT_POS - - int dofs; - - The number of degrees of freedom the plug-in has. - Operators: - - - - - Assignment operator. - - - - - Implemented by the System. - - Returns TRUE if the current state of the parameters are the defaults. - - - - - Implemented by the System. - - This method may be called to save the joint properties to the 3ds Max file. - Parameters: - *isave - - This pointer may be used to call methods to write data to disk. See Class . - One of the following values: - - IO_OK - The result was acceptable - no errors. - - IO_ERROR - This is returned if an error occured. - - - - - Implemented by the System. - - This method is called to load the joint properties from the 3ds Max file. - Parameters: - *iload - - This pointer may be used to call methods to load data from disk. See Class . - One of the following values: - - IO_OK - The result was acceptable - no errors. - - IO_ERROR - This is returned if an error occured. - - - - - Implemented by the System. - - This method applies constraints to the given delta based on parameters and the current value v. It uses the current min/max limits to constrain the result: v+delta so that v+delta < max and v+delta > min. It returns a new delta such that the previous will both be TRUE. If ease is turned on, then the values will be slowed down as they approach the limits. It also applies the damping if turned on. - Parameters: - int index - - This is the index of the parameter. For example on a position controller the index could be 0 (x), 1 (y), or 2 (z). - - float v - - The current value of the parameter. - - float delta - - The increment to apply. - A new delta value. Usually it will return delta, but if the value was constrained, then the value may be smaller or larger. - - - - - Implemented by the System. - - Returns TRUE if the specified joint is active; otherwise FALSE. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - TRUE if the joint is active; otherwise FALSE. - - - - - Implemented by the System. - - Returns TRUE if the joint is limited; otherwise FALSE. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - TRUE if the joint is limited; otherwise FALSE. - - - - - Implemented by the System. - - Returns TRUE if the joint has the Ease property set; otherwise FALSE. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - TRUE if the joint has the Ease property set; otherwise FALSE. - - - - - Implemented by the System. - - Returns the type of joint, sliding or rotation. This will either be JNT_POS for sliding joints of JNT_ROT for rotational joints. - - - - - Implemented by the System. - - Returns TRUE if the rollup page if open; otherwise FALSE. - - - - - Implemented by the System. - - Sets the specified joint to the specified active or inactive state. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - - BOOL s - - TRUE to set the joint active; otherwise FALSE. - - - - - Implemented by the System. - - Sets the specified joint to the specified limited or not limited state. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - - BOOL s - - TRUE to set the joint as limited; otherwise FALSE. - - - - - Implemented by the System. - - Sets the specified joint to the specified eased or not eased state. - Parameters: - int i - - One of the following values: - - 0 = X - - 1 = Y - - 2 = Z - - BOOL s - - TRUE to set the joint as eased; otherwise FALSE. - - - - - Implemented by the System. - - the rollup page as open or closed. - Parameters: - BOOL open - - TRUE to open the page; FALSE to close it. - - - - - This is called when the user is interactively manipulating one of the spinner controls or enters a value into a spinner's edit field. This method has a default implementation. - Parameters: - *ui - - This is simply a container class to hold some data while the controllers parameters are being edited. - - WORD id - - The spinner control id. - - *spin - - A pointer to the spinner control. - - BOOL interactive - - TRUE if the user is doing an interactive adjustment; otherwise FALSE. - - - - - - - Implemented by the System. - - This is used internally. - - - - - Implemented by the System. - - This is used internally. - - - - - Implemented by the System. - - This is used internally. - - - - - Implemented by the System. - - This is used internally. - - - - - Implemented by the System. - - This is used internally. - - - - - Implemented by the System. - - This is used internally. - - - - - Description: - This class is derived from class , which is the original data structure that holds joint parameter settings. This new derived class adds the preferredAngle parameter. Note that is not a virtual class and as such a flag definition of JNT_PARAMS2 is added in order to differentiate a instances from a instance. When the JNT_PARAMS2 flag is set, a pointer can be safely cast to a . - Data Members: - float *preferredAngle; - - The preferred angle parameter. - - - - - Description: - A callback object so the progress of key reduction can be checked and controlled. This class is used in conjunction with function ApplyKeyReduction(). - - - - - This method is called once before key reduction starts. It passes in the total number of keys that may potentially be reduced. - Parameters: - int total - - The total number of reduction candidate keys. - - - - - This is called every so often during key reduction. The number of keys process so far is passed in, so the percentage complete can be calculated as p/total * 100. This method should return a value to indicate if processing should proceed. - Parameters: - int p - - The number of keys processed so far. - Return one of the following values to indicate if processing should continue. - - KEYREDUCE_ABORT - - Stops processing and undoes any key reduction. - - KEYREDUCE_STOP - - Stops processing, but keeps any reduction done so far. - - KEYREDUCE_CONTINUE - - Keeps going. - - - - - This class is derived from in order to automatically track existing instances, and at shutdown write to Debug Output the creation count for leaked instances. The template class Obj should typically be set to the class deriving from this class. For example: class : private LeakedObjectInstances<ParamBlockDesc2> On shutdown, if leakage is present the output to Debug Output would be: 2022/08/26 14:28:00 [12616] : 55114ms : **Leaked class instances: 587, 588. - - - - - Describes lights used in the interactive renderer. All methods of this class are implemented by the system. - - - - - The type of the light. Has one of the following values: - - - - - The color of the light. - - - - - Attenuation type. GW_ATTEN_NONE by default. - - - - - Starting attenuation value. - - - - - Ending attenuation value. - - - - - multiplier factor. - - - - - Angle of cone for spot and cone lights in degrees. - - - - - Fall-off angle. - - - - - Indicates the shape of the light. It is either: - - - - - - The aspect ratio of the light. - - - - - If this value is non-zero it indicates the light supports overshoot. - - - - - When set to FALSE by a user the light does not illuminate the diffuse component of an object's material. This value is TRUE by default. - - - - - When set to FALSE by a user the light does not illuminate the specular component of an object's material. This value is TRUE by default. - - - - - Common Photometric light. - - - is the base class for all Photometric lights. You can safely cast an Animatble* to LightscapeLight* if IsSubClass(LIGHTSCAPE_LIGHT_CLASS) returns true. - - - - - Sets the light type. - - - The light type is changed or returned. When setting the light type to an invalid value, nothing is changed, and no error is returned. - - - The type name the light is to be changed to. May not be NULL. The valid strings are: - - - - Returns the light type. - - - The current light type, as a string - - - - - Returns the distribution of the light. - - - The distribution ID of the current distribution. - - - - - Returns the distance at which the light intensity is measured. - - - This distance is used then the light intensity type is LUX_AT. - The distance is returned. - - - - - Returns the intensity type of the light. - - - - - - - Sets the flux of the light. - - - The flux of a light is a measure of how much light the light produces. It is related to the intensity by a constant factor that depends on the distribution of the light. For example the flux of an isotropic light is always 4PI times the intensity (4PI is the area of a unit sphere). - The flux of the light is set, which changes the intensity. - - - The time at which the flux is set. - - The flux to be set in lumens. Must be greater than or equal to 0. - - - - Returns the flux of the light. - - - The flux is returned in lumens. - - - The time at which the flux is retrieved. - - The validity of the flux is intersected with the validity in this argument. - - - - Returns the flux of the light. - - - The flux is returned in lumens. - - - The time at which the flux is retrieved. - - - - Sets the color of the light filter. - - - Lightscape lights use separate values for the light color and filter color. You should imagine that the light color is the color of the light bulb, and the filter color is the color of the surrounding piece of glass or plastic. The effective color of the light is the product of the filter and light colors. The color can be set in either RGB or HSV format. - The filter color is changed or returned. - - - The time at which the filter color is set. - - The RGB color to be set - - - - Returns the color of the light filter. - - - The filter color is returned in either RGB format. - - - The time at which the filter color is retrieved. - - The validity of the filter color is intersected with the validity in this argument. - - - - Returns the color of the light filter. - - - The filter color is returned in either RGB format. - - - The time at which the filter color is retrieved. - - - - Sets the color of the light filter. - - - The filter color is changed or returned. - - - The time at which the filter color is set. - - The HSV color to be set - - - - Returns the color of the light filter. - - - The filter color is returned in either HSV format. - - - The time at which the filter color is retrieved. - - The validity of the filter color is intersected with the validity in this argument. - - - - Returns the color of the light filter. - - - The filter color is returned in either HSV format. - - - The time at which the filter color is retrieved. - - - - Returns the plug-in shadow generator. - - - There are two shadow generators that can be used by a light. The local shadow generator that is referenced by the light and the global shadow generator that is in the scene. The methods GetUseGlobal() and SetUseGlobal() access the parameter that determines which shadow generator is actually used. GetShadowGenerator() always returns the local shadow generator, while other methods return and set the shadow generator based on the value of the use global parameter. - The shadow generator is returned. - - - - - Returns the plug-in shadow generator name. - - - The local or global shadow generator name, depending on the value of the use global parameter. - - - - - Sets the plug-in shadow generator. - - - The shadow generator is set. - - - The class name of the shadow type to be set. - - - - Sets the controller for the Kelvin temperature. - - - The controller is set. - - - The new controller to use for kelvin temperature. NULL will remove any animation. - - - - Sets the controller for the filter color. - - - The controller is set. - - - The new controller to use for filter color. NULL will remove any animation. - - - - Returns the controller for the Kelvin temperature. - - - The controller is returned. - - - - - Returns the controller for the filter color. - - - The controller is returned. - - - - - Returns the Kelvin temperature of the light. - - - Kelvin temperature is a method for retrieving light color based on black body radiation from physics. - The current kelvin temperature. - - - The time at which the color is retrieved. - - The validity of the color is intersected with this argument. - - - - Returns the Kelvin temperature of the light. - - - Kelvin temperature is a method for retrieving light color based on black body radiation from physics. - The current kelvin temperature. - - - The time at which the color is retrieved. - - - - Sets the Kelvin temperature of the light. - - - Kelvin temperature is a method for specifying light color based on black body radiation from physics. - The kelvin temperature is changed. - - - The time at which the color is set. - - The kelvin temperature in degrees Kelvin. Should be greater than or equal to 0. - - - - Returns whether the kelvin temperature or light color is to be used. - - - The light color can be set using either an RGB value or a kelvin temperature. - TRUE if the kelvin temperature is used, or FALSE if the RBG value is used. - - - - - Returns the web distribution file for the light as an AssetUser. - - - The AssetUser is returned. - - - - - Returns the filename of the web distribution file for the light. - - - The full web filename is the full path to the web filename. If the file couldn't be found or the current distribution is not the web distribution, the filename stored in the light is returned. - The filename is returned. - - - - - Returns the rotation along the X axis of the web distribution in the light. - - - The rotation in degrees is returned. - - - - - Returns the rotation along the Y axis of the web distribution in the light. - - - The rotation in degrees is returned. - - - - - Returns the rotation along the Z axis of the web distribution in the light. - - - The rotation in degrees is returned. - - - - - Returns the dimmer value for the light. - - - An additional dimmer can be used to independently modify the light intensity. - the dimmer value is returned. - - - The time at which the dimmer value is retrieved. - - The validity of the dimmer is intersected with the validity in this argument. - - - - Returns the dimmer value for the light. - - - An additional dimmer can be used to independently modify the light intensity. - the dimmer value is returned. - - - The time at which the dimmer value is retrieved. - - - - Sets the dimmer value for the light. - - - An additional dimmer can be used to independently modify the light intensity. - The dimmer value is set. - - - The time at which the dimmer value is set. - - The value of the dimmer. 1.0 is full-on. 0.0 if full-off. - - - - Returns whether the dimmer is used. - - - The value of the flag is returned. - - - - - Returns whether the light's intensity shifts (affects) its color. - - - Note that this parameter is really activated only if GetUseMultiplier() is true. - The value of the flag is returned. - - - - - Sets whether the color of the light shifts when its intensity changes Note that this parameter is really activated only if GetUseMultiplier() is true. - - - The value of the flag is changed. - - - If true, the changes in the light's intensity will cause shifts in the light's color, otherwise the light's color will be unaffected by the intensity - - - - Returns the intensity including the dimmer multiplier if it is used. - - - This utility method returns the effective intensity of a light including the dimmer value if there is one. - The effective intensity in candelas. - - - The time at which to retrieve the intensity or flux. - - The validity of the effective intensity is intersected with this argument. This includes the validity of the dimmer. - - - - Returns the intensity including the dimmer multiplier if it is used. - - - This utility method returns the effective intensity of a light including the dimmer value if there is one. - The effective intensity in candelas. - - - The time at which to retrieve the intensity or flux. This includes the validity of the dimmer. - - - - Returns the flux including the dimmer multiplier if it is used. - - - This utility method returns the effective flux of a light including the dimmer value if there is one. - The effective flux in lumens. - - - The time at which to retrieve the intensity or flux. - - The validity of the effective flux is intersected with this argument. This includes the validity of the dimmer. - - - - Returns the flux including the dimmer multiplier if it is used. - - - This utility method returns the effective flux of a light including the dimmer value if there is one. - The effective flux in lumens. - - - The time at which to retrieve the intensity or flux. This includes the validity of the dimmer. - - - - Returns the radius of a disc, sphere, cylinder light. - - - This method allows to access the radius of a disc, sphere or cylinder light type. - The radius of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the radius is retrieved. - - The validity interval of the radius is intersected with this argument. - - - - Returns the radius of a disc, sphere, cylinder light. - - - This method allows to access the radius of a disc, sphere or cylinder light type. - The radius of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the radius is retrieved. - - - - Sets the radius of a disc, sphere, cylinder light. - - - This method allows to set the radius of a disc, sphere or cylinder light. If the light is not of one of the above mentioned types, the method is a no-op. - - - The time at which the radius is set. - - The new radius value - - - - Returns the length of a linear, area, cylinder light. - - - This method allows to access the length of a linear, area, or cylinder light. - The length of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the length is retrieved. - - The validity interval of the length is intersected with this argument. - - - - Returns the length of a linear, area, cylinder light. - - - This method allows to access the length of a linear, area, or cylinder light. - The length of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the length is retrieved. - - - - Sets the length of a linear, area, cylinder light. - - - This method allow to set the length of a linear, area, cylinder light. If the light is not of one of the above mentioned types, the method is a no-op. - - - The time at which the length is set. - - The new length value - - - - Returns the width of an area light. - - - This method allows to access the width of an area light. - The width of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the width is retrieved. - - The validity interval of the width is intersected with this argument. - - - - Returns the width of an area light. - - - This method allows to access the width of an area light. - The width of the light, or zero if the light is not of any of the above mentioned types. - - - The time at which the width is retrieved. - - - - Sets the width of an area light. - - - This method allows to set the width of an area light. If the light is not of one of the above mentioned types, the method is a no-op. - - - The time at which the width is set. - - The new width value - - - - Sets the coordinates of the light. - - - The use of this functions varies based on the current light type. If the light is a point light, the center is set to the center of the set of points. If the light is a linear light the light's line segment is set to the segment between the first two points. If fewer than two points are specified, no change is made. If the light is an area light, the light area is set to the triangle or quadrilateral defined by the 3 or 4 points, respectively. If fewer than 3 points is specified, no change is made. If more than 4 points is specified a quadrilateral is made from the first 4 points. - All points are in light coordinates. Quadrilaterals must be planar. - The shape is changed. - - - of points of the shape. - - The array of points in the shape. - - - - Returns the coordinates of the light. - - - The total number of vertices in the shape. This is independent of the number of point in the receiving buffer. - - - The buffer that will receive the vertices in the shape. If bufSize is 0 this can be NULL. - - The number of points in the buffer. Only the vertices that fit in the buffer will be stored. The return value will include the count of vertices that could not be stored. - - - - Returns the original flux for a light. - - - This is the original flux in the web distribution for a light. - The original flux in lumens is returned. - - - - - Returns the original intensity for a light. - - - This is the original intensity in the web distribution for a light. - The original intensity in candelas is returned. - - - - - Returns the color preset of the light. - - - preset is used when Kelvin temperature is not used. See LightscapeLight::GetUseKelvin(). - The current preset color. - - - - - Sets whether the Include/Exclude list should include or exclude objects. - - - The flag value is set. - - - The flag value to be set. TRUE indicates that the light should include objects in the Include/Exclude list. - - - - Returns the location of the center of the light. - - - This location is in the light's coordinates. - The light coordinate of the center of the light. - - - - - Extension to Photometric light This interface extends class with new functionality in 3ds Max 2016. - - - - - Bakes a web distribution into a spherical map. - - - Bakes the web (IES) distribution into a spherical map of floating-point intensities which are to be multiplied against the light's global intensity value. The resulting texture has the x coordinates covering the horizontal angles, from -PI to PI radians, and the y coordinates covering the vertical angles, from 0 to PI radians, 0 being +Z and PI being -Z. The rotation of the web distribution, returned by GetWebRotateX() and friends, is baked in the result. The resolution of the baked texture is determined internally and is based on the resolution of the original data from the web distribution (.ies) file. - false if and only the method is invalid on this light (i.e. if the light doesn't use a web distribution). If the light uses a web distribution but the file could not be loaded, this method returns true with an empty baked map (the resolution is zero). - - - An array of floating-point intensities which is allocated and filled by the method. The array represents a spherical texture map. The size of the array is: bakedWidth * bakedHeight. - - The width of the baked spherical texture map. - - The height of the baked spherical texture map. - - - - Description: - This class has a method Illuminate() used to determine the color and direction of the light striking the point sc.P() and a method to get the position of the light. It also has two public data members that determine if the diffuse and specular colors of objects are affected. - Data Members: - BOOL affectDiffuse; - - This data member is available in release 2.0 and later only. - - If TRUE the light affects the diffuse color; otherwise it does not. - - BOOL affectSpecular; - - This data member is available in release 2.0 and later only. - - If TRUE the light affects the specular color; otherwise it does not. - - BOOL ambientOnly; - - This data member is available in release 3.0 and later only. - - If TRUE the light affects the ambient color only; otherwise it does not. - - DWORD extra; - - This data member is available in release 3.0 and later only. - - This is not currently used and is available for use in the future. - - - - - This method is called to determine the color and direction of illumination from the light that is hitting the point (sc.P()). - Parameters: - & sc - - Describes the properties of the point to shade. The point itself is sc.P(). - - & normal - - The normal to the surface in camera space. - - & color - - The color that is returned. This is the brightness of light striking the point (sc.P()) - - &dir - - The direction that the light is coming from. - - float &dot_nl - - This provides a bit of optimization as most lights will have to calculate this quantity. This is the dot product between the light vector and the normal to the surface. - - float &diffuseCoef - - This parameter should be set by the Illuminate function. The default value is the same as dot_nl. It will be used by shading functions instead of dot_nl to compute the diffuse illumination of the surface. The built-in lights use the new "Contrast" parameter (which has a range of [0..100]) to compute the diffuseCoef from the dot_nl by the Contrast function: - Returns FALSE if the hitpoint is outside the effective range of the light or if the normal of the surface faces away from the light. This is a hint to the material that the light did not calculate its illumination because it is assumed it wasn't going to be used. If TRUE the point is being illuminated. - Default Implementation: - { return 0;} - - - - - Returns the position of the light. - Default Implementation: - ; } - - - - - This is the base class from which plug-in lights may be derived. - - - - - This method is called to update the passed and validity interval of the light. - REF_SUCCEED if the was updated; otherwise REF_FAIL. - - The time to evaluate the light state. - The validity interval of the light about the specified time. This interval should be updated to reflect the validity interval of the light. - A pointer to the structure which describes the properties of the light. This function updates the data in the structure to reflect the properties of the light at the specified time. See Structure . - - - - Use this override when validity interval is irrelevant - - - - - When the renderer goes to render the scene it asks all of the lights to create an ObjectLighDesc object. This is the method that is called to return this object. - An instance of ObjectLightDesc. See Class ObjectLightDesc. - - The node pointer of the light. - Forces the creation of a shadow buffer. - - - - Sets if the light is on or off. - - TRUE for on; FALSE for off. - - - - Returns TRUE if the light is on; otherwise FALSE. - - - - - Sets the hotspot to the specified angle at the specified time. - - The time to set the hotspot angle. - The angle to set in degrees. - - - - Retrieves the hotspot angle. - The hotspot angle (in degrees). - - The time to retrieve the angle. - The validity interval that this method will update to reflect the hotspot setting. - - - - Retrieves the hotspot angle. - The hotspot angle (in degrees). - - The time to retrieve the angle. - - - - Sets the falloff setting of the light. - - The time to set the falloff. - The falloff angle in degrees. - - - - Returns the falloff angle of the light in degrees. - The falloff angle of the light in degrees. - - The time to retrieve the falloff angle. - The validity interval that this method will update to reflect the falloff setting. - - - - Returns the falloff angle of the light in degrees. - The falloff angle of the light in degrees. - - The time to retrieve the falloff angle. - - - - Sets the specified attenuation range distance at the time passed. - - The time to set the attenuation distance. - Indicates which distance to set. One of the following values: - The start range radius. - The end range radius. - The distance to set. - - - - Returns the specified attenuation range distance at the time passed. - The specified attenuation range distance. - - The time to retrieve the attenuation distance. - Indicates which distance to retrieve. One of the following values: - The start range radius. - The end range radius. - The validity interval that this method will update to reflect the attenuation setting. - - - - Returns the specified attenuation range distance at the time passed. - The specified attenuation range distance. - - The time to retrieve the attenuation distance. - Indicates which distance to retrieve. One of the following values: - The start range radius. - The end range radius. - - - - Sets the light's target distance. - - The time to set the distance. - The distance to set. - - - - Retrieves the light's target distance. - The light's target distance. - - The time to retrieve the distance. - The validity interval that this method will update to reflect the target distance setting. - - - - Retrieves the light's target distance. - The light's target distance. - - The time to retrieve the distance. - - - - Sets the light's cone display flag. This controls if the cone is depicted graphically in the viewports. - - Indicates if the cone display should be on or off. If nonzero, the cone should be displayed; otherwise it should be turned off. - If notify is TRUE the plug-in should call to notify its dependents. - - - - Retrieves the light's cone display setting. This indicates if the cone is depicted graphically in the viewports. - TRUE to indicate the cone is displayed; FALSE to indicate it is turned off. - - - - - Returns the type of shadows used by the light. - One of the following values: LIGHTSHADOW_NONELIGHTSHADOW_MAPPEDLIGHTSHADOW_RAYTRACED - - - - - Sets the color of the light at the specified time. - - The time to set the color. - The color to set. - - - - Returns the color of the light at the specified time and updates the validity interval to reflect this parameters validity interval. - The color of the light at the specified time. - - The time to retrieve the value. - The validity interval to intersect with this parameters interval. - - - - Returns the color of the light at the specified time. - The color of the light at the specified time. - - The time to retrieve the value. - - - - Sets the intensity of the light to the value passed. - - The time to set the value. - The value to set. - - - - Retrieves the intensity of the light at the specified time and updates the validity interval passed to reflect the validity interval of this parameter. - The intensity of the light at the specified time - - The time to retrieve the value. - The validity interval to intersect with this parameters interval. - - - - Retrieves the intensity of the light at the specified time. - The intensity of the light at the specified time - - The time to retrieve the value. - - - - Sets the aspect ratio of the light at the specified time. - - The time to set the value. - The value to set. - - - - Retrieves the aspect ratio of the light at the specified time and updates the validity interval passed to reflect the validity interval of this parameter. - The aspect ratio of the light at the specified time - - The time to retrieve the value. - The validity interval to intersect with this parameters interval. - - - - Retrieves the aspect ratio of the light at the specified time. - The aspect ratio of the light at the specified time - - The time to retrieve the value. - - - - Sets the flag to indicate if the light is attenuated. - - Nonzero to indicate the light is attenuated; otherwise 0. - - - - Returns TRUE to indicate the light is attenuated; otherwise FALSE. - - - - - Sets the flag to indicate if the light attenuation ranges are displayed. - - Nonzero to indicate the light attenuation ranges are displayed; otherwise 0. - - - - Returns TRUE if the light attenuation ranges are displayed; otherwise FALSE. - - - - - Sets the light to enabled or disables (on or off). - - Nonzero to set the light to on; zero to turn the light off. - - - - Sets the map bias setting at the time passed. - - The time to set the value. - The map bias value to set. The 3ds lights use a range of 0.0 to 100.0. - - - - Returns the map bias setting at the time passed and updates the validity interval to reflect the validity interval of this parameter. - The map bias setting at the time passed. - - The time to retrieve the value. - The validity interval to update to reflect this parameters validity interval. - - - - Returns the map bias setting at the time passed. - The map bias setting at the time passed. - - The time to retrieve the value. - - - - Sets the map sample range setting to the value passed at the time passed. - - The time to set the value.\ - The value to set. The 3ds lights use a range of 0.0 to 20.0. - - - - Retrieves the lights map sample range setting at the specified time and updates the validity interval to reflect the validity interval of this parameter. - The lights map sample range setting. - - The time to retrieve the value. - The validity interval to update to reflect this parameters validity interval. - - - - Retrieves the lights map sample range setting at the specified time. - The lights map sample range setting. - - The time to retrieve the value. - - - - Sets the lights map size parameter to the value passed at the time passed. - - The time to set the value. - The value to set. - - - - Returns the lights map size parameter at the specified time and updates the validity interval passed to reflect the validity interval of this parameter. - The lights map size parameter. - - The time to retrieve the value. - The validity interval to update to reflect this parameters validity interval. - - - - Returns the lights map size parameter at the specified time. - The lights map size parameter. - - The time to retrieve the value. - - - - Sets the raytrace bias setting to the value passed at the specified time. - - The time to set the value. - The value to set. - - - - Returns the lights raytrace bias setting at the specified time and updates the validity interval passed to reflect the validity interval of this parameter. - The lights raytrace bias setting at the specified time. - - The time to retrieve the value. - The validity interval to update to reflect this parameters validity interval. - - - - Returns the lights raytrace bias setting at the specified time. - The lights raytrace bias setting at the specified time. - - The time to retrieve the value. - - - - Returns the Use Global Settings flag setting. - - - - - Returns the lights Cast Shadows flag. - Nonzero indicates the light casts shadows; otherwise 0. - - - - - Retrieves the type of shadows used by the light - mapped or raytraced. - One of the following values: -1: if the Shadow Generator is NULL. (R3 only). 0: if the light uses Shadow Maps. 1: if the light uses Raytraced Shadows. 0xffff: for any other Shadow Generators. (R3 only). - - - - - Returns the lights Absolute Map Bias setting. - Nonzero indicates Absolute Map Bias is on; zero indicates it is off. - - - - - Returns the lights Overshoot on / off setting. Nonzero indicates overshoot is on; otherwise 0. - - - - - Returns the lights Projector on / off setting. Nonzero indicates this light projects an image; otherwise 0. - - - - - Returns the list of names of items included or excluded by this light. See Class . - - - - - Returns TRUE if the light's name list is of items to be included by the light. Returns FALSE if the list is of items to exclude from the light. - - - - - Returns the map used by a projector light. - - - - - Updates the display of the light's target distance in the light's rollup page. - - The time to retrieve the distance. - The light node. - - - - This is a callback class that can be given to a to have a ray traced through the light volume. A plug-in derives a class from this one and passes it as a callback in the method TraverseVolume(). This allows a developer to integrate the illumination of a segment due to a light. t0 and t1 define the segment in terms of the given ray. This is what the 3ds Max spotlights do: First they break the segment up into three main pieces. The first piece is from the camera to where the ray intersects the lights cone volume. The callback Step() is called once over this segment (t0 and t1 will have this first piece). The illumination is constant over this entire segment from t0 to t1. It is a constant black since the light is not illuminating it at all. The next segment is inside the cone. This segment will be broken up into small pieces. First as it's stepping along it will be between the falloff and the hotspot. The illumination over this segment goes from black to brighter and brighter as it moves towards to hotspot. Across the entire hotspot region the illumination may be constant. Then as it steps from the hotspot to the falloff the illumination will go back down to black. Inside the hotspot region, if shadows are turned on, the light may be brighter or darker depending on if it's inside a shadow or on the edge of a shadow. The light handles all of this. It takes care of the shadows, attenuation, etc. Now consider how the 3ds Max atmospheric effects such as the volume lights use this information. For each light that they are bound to, they call the method TraverseVolume() on the light. The volume light atmospheric effect passes this callback to the TraverseVolume() method. The light then calls this Step() method of the callback for each partial segment of the ray. Given the illumination on the segment (illum) it computes the fog density over that piece. The density may be constant if noise is not turned on, or it may vary if noise is turned on. Using the fog density and the illumination it computes the light reflected off the atmosphere for the segment. - - - - - - This method is called for every step defined by t0 and t1. The illumination over this segment is passed in illum. - TRUE to continue; FALSE to halt the integration (stop the traversal). - - The start of the segment. This is a distance along the ray. The ray is made up of a point p and a unit length direction vector dir. The point defined by t0 is thus ray.p+t0*ray.dir. - The end of the segment. This is a distance along the ray. The ray is made up of a point p and a unit length direction vector dir. The point defined by t1 is thus ray.p+t1*ray.dir. - The light intensity over the entire segment. It can be assumed that the light intensity is constant for the segment. - This parameter may be used so that volume effects can use the distance attenuation value as an input variable to their effects. For instance, the volume light uses this to change the fog color based on the distance from the light. - - - - Description: - This class represents a linear shape object. This class is similar to a except this class uses a as its data while a uses a as its data. Therefore this is a shape made up of entirely linear segments. All methods of this class are implemented by the system. - Data Members: - shape; - - The that holds the linear shape. - - - - - Returns the shape data member. - - - - - This method does the job of setting all points in the to POLYPT_KNOT types, and removing the POLYPT_INTERPOLATED flag. This is because the knows nothing about its origin. - - - - - A line buffer, containing a single and color. Used by . - - - - - Class used to input retargeting info when creating a map file. - - - Contains info on how a particular mapped node will get retargeted. You specify a node that's being retargeted, and then parameters that specify how the node will get retargeted, ie the amount to scale the position and the coordinate space where the node will get scaled. This class is used in ILoadSaveAnimation::CreateMapFile and ILoadSaveAnimation::CreateMapFileNodeAnims - - - - - The name of the incoming node from the animation file that the current node is mapped to. Note that the map file that uses this information still needs to explicitly map the tracks from the incoming tracks to the current tracks. This information doesn't override that information, just confirms it. - - - - - Whether or not the scale attribute will be the absolute scale value or a relative scale value that is then multiplied by a scale that's calculated from the ratio of the length of specified current linked nodes versus the length of specified incoming linked nodes. - - - - - The scale attribute that's used to scale the retargeted position. If absolute is false then it's a relative value that's multiplied by the ratio of current versus incoming chain lengths. - - - - - The name of the base node whose coordinate space you will scale in. If the current base node is the same as the current node that's being being retargeted, then the node will be retargeted relative to it's first position. Note that if this value isn't set, then the world root node will be this node. - - - - - The name of the base node whose coordinate space you will scale the incoming node in. - Note that if this value isn't set, then the world root node will be this node. - - - - - The name of the base of the current chain node that will be used to calculate the scale for retargeting when the absolute value is false. The scale is then the difference in length from the current end chain to it's base versus the incoming end chain to it's base. Note that if this value isn't set, then the world root node will be this node. - - - - - The name of the end chain of the current chain node that the scale will be calculated from. The length is calculated by traversing the distances from the end chain to it's parents, down to the base chain node. Note that if this value isn't set, then the world root node will be this node. - - - - - The name of the base of the incoming chain node that the scale will be calculated from. - Note that if this value isn't set, then the world root node will be this node. - - - - - The name of the end of the incoming chain node that the scale will be calculated from. The length is calculated by traversing the distances from the end chain to it's parents, down to the base chain node. Note that if this value isn't set, then the world root node will be this node. - - - - - If TRUE the current FK node will retarget internally as a IK chain to a specified node. That way when retargeting FK chains we can correctly make sure that the end nodes(like feet) will stay planted on the ground relative to the center of mass. - - - - - The name of the node where the base of the internal IK chain will end. So if you were retargeting a foot node, you would usually specify this node to be the hip, so that when the foot retargets as the end of an IK chain, the ankle, and knee joints will get recalculated. Remember you only need to do this for FK nodes when you want them to be constrained relative to another node, usually the\ center of mass. Note that if this node isn't set, then this sort of retargeting won't occur, even if the FKRetargetingEnabled flag is TRUE. - - - - - This class allows a modifier to store application specific data. A reference to a pointer to an instance of this class is passed in to ModifyObject() as part of the . The value of the pointer starts out as NULL, but the modifier can set it to point at an actual instance of a derived class. When the mod app is deleted, if the pointer is not NULL, the will be deleted - the virtual destructor allows this to work. - - - - - - This method is called to allow a plug-in to copy its local data. It is called when the system is copying a . - The plug-in should return a pointer to a new instance of its . - - - - - - - - - - - - - Class for writing out log information to a file. - - - MAX maintains a log file that contains the text of error / warning / information / debug messages generated by the system and plug-ins. This class is used to work with the log and send messages to it. The log file is placed in the Network directory and is called Max.Log. To access this facility from anywhere in MAX use the pointer returned from the method Interface::Log(). All methods of this class are implemented by the system. - - - - - - Returns the conditions under which the log is deleted. - - - One of the following values: - - - - - Returns the conditions under which the log is cleared. - - - One of the following values: - - - - - Returns the size of the current log file in kilobytes (KB). - - - - - This method is used internally. - - - - - This method is used internally. - - - - - This method is used to find out what log types are enabled. See System Error Log Message Types. The type values are ORed together to create the value returned. - - - - - This method is used to log the error. - - - Defines the type of log entry defined in this header file. See . Note that since the System Error Log Message Types are specified as bit flag values, multiple types can be specified (although normally only a single type is specified). If multiple types are specified, the highest severity type that matches with the enabled log types is used. The types in level of severity are error, warn, info, debug. - - One of the following values: - - This title string is optional. If non NULL, it will be used to define the module. - - This parameter (and any other additional arguments that follow) make up the format specification. The format matches the standard C printf() function. - - - - Gets the Quiet Mode. - - - true if 'quiet' mode is enabled or false if it's disabled. - - - - - Gets the 'enabled' mode. - - - true if 'enabled' mode is enabled or false if it's disabled. - - - - - Retrieves the additional output log file name. - - - - the output file name set in SetSessionLogName() call or NULL if no file specified. - - - - - Retrieves the output log file name. - - - - the output log file name - - - - - Description: - A Macro Button is a button which can execute either a keyboard macro or macro script. This class contains the data and access methods for such a UI button. This data includes a macro type, command ID, macro script ID, label, tooltip, image name, and image ID. - - This object is used in the constructor. There are also methods of class to get and set the macro button data. - Data Members: - int macroType; - - The macro type. One of the following values: - - MB_TYPE_KBD - - A keyboard macro. - - MB_TYPE_SCRIPT - - A macro. - - ActionTableId tblID; - - The Shortcut Action Table ID. - - void *cb; - - The ShortcutCallback. This is currently not used. - - int cmdID; - - The command ID. There are method of class that provide access to the command IDs for various keyboard shortcut tables. See . - - int macroScriptID; - - The macroScriptID holds the id of the macroScript associated with this button. This id is the MacroID that is used by the methods in the and classes (at one time it was an indirect reference to this id and so was typed as an int). The id can have values from 0 to the number of macro scripts currently defined in the running 3ds Max or the special value UNDEFINED_MACRO. - - MCHAR *label; - - The label text for a text button. This is used if imageID is -1. - - MCHAR *tip; - - The tooltip text. - - MCHAR *imageName; - - This is the name for the button image. This is the 'base' name only. For example if the actual image name was Spline_16i.bmp then the name supplied here would be Spline. See the remarks in Class for details on the image naming scheme the CUI system uses. - - int imageID; - - The image ID. If this is set to -1 it indicates to use the label. If it is set to 0 or greater it indicates this is an image based button and this is the zero based index of the button that was added. This then is an ID into an image group as specified by imageName. Said another way, 3ds Max builds one large image list internally and uses the imageName to get an offset into the list and then uses this imageID as an additional offset from the start as indicated by the name (each imageName may contain multiple icons in the single BMP). - - ActionItem* actionItem; - - A pointer to the . - - DWORD flags; - - These flags contain the last state when redrawing - - - - - Assignment operator. - - - - - Returns the label text. - - - - - Returns the tooltip text. - - - - - Returns the command ID. - - - - - Returns the script ID. - - - - - Returns the image name. - - - - - Returns the image ID. - - - - - Returns the name of the multi-resolution icon assigned to the button. - - - - - This method returns the ActionTableID ID. - - - - - This method returns a pointer to the . - - - - - This method returns TRUE if the button is an Action button. FALSE if it is not. - - - - - Description: - This class provides access to Macro scripts. Macro scripts (or macros) are scripts that live in buttons and menus in the customizable UI. Methods of this class are availalble to access macros using IDs or category and name strings, methods to edit macro scripts, methods to execute macros, and methods for directory scanning and loading. - - The directory instance (access via the global function GetMacroScriptDir()) is used by the CUI to provide a list of available macros in the toolbar/menu editor. The API also provides a way for the CUI to open a macro editor to allow on-the-fly creation of macro scripts. - - The macro script manager keeps a directory of all known macros and provides an API for running and editing macros and for accessing and updating the directory. - - Macros are normally entered into the directory by the MAXScript compiler as a side-effect of compiling a macro definition. Anyone using MAXScript can at any time eval a macro definition and thereby add CUI macro scripts. - - Consequently, macros can be stored in any script file and be loaded just by executing the file. The macro definition syntax permits any number of macros per file. - - Most macros will be stored in files in a special CUI macro or config directory so that a user can take all his custom UI stuff with him by copying directories. (This directory supports recursive scanning of sub-dirs, so users can organize their macros). On-the-fly macro creation in the CUI editor or by text drag-and-drop onto the shelf or by evaling a definition in the listener will generate a file in this directory to provide permanent storage. - - Note: typedef short MacroID; - - Note: In order to use these methods you need to #include "IMACROSCRIPT.H" and link to "MAXSCRPT.LIB". - - - - - Returns a pointer to the for the macro script whose ID is passed. - Parameters: - MacroID mid - - The ID of the macro. - - - - - Returns a pointer to the corresponding to the given category and name strings passed (or NULL if not found). - Parameters: - MCHAR* category - - The category name. - - MCHAR* name - - The macro script name. - - - - - Returns TRUE if the macro ID is valid (or unused); otherwise FALSE. - Parameters: - MacroID mid - - The ID to check. - - - - - Returns the number of macro entries in this macro directory. - - - - - Returns a pointer to the macro entry whose index in the directory is passed. - Parameters: - int index - - The zero based index of the entry. This is a value between 0 and Count()-1. - - - - - Adds the macro whose parameters are passed and returns a pointer to the new macro entry. This form allows you to define a macro that is already in a file, by giving a source file name and seek offset into that file. This is typically used by the MAXScript compiler and .mcr file scanner to register macro definitions they come across. - Parameters: - MCHAR* category - - The category for the macro. - - MCHAR* name - - The name for the macro. - - MCHAR* tooltip - - The tooltip text. - - MCHAR* buttonText - - The button text. - - MCHAR* sourceFile - - The source file name. - - int sourceOffset - - The line number of the first line of the script in the source file. - - - - - Add or replaces a macro using given source text as the body of the macro. In this overload, name can be NULL in which case a unique name is generated. - - This form takes the body of the actual macro script as the sourceText argument and places it in a newly-created file in the UI directory and registers that file and a zero offset as the macro definition. All macroScripts need to be in files somewhere so that they are persistent if referenced in a CUI toolbar that the user saves. This form is used, for example, by the toolbar manager when you drag a piece of selected text onto a toolbar to cause a script button to be created. - Parameters: - MCHAR* category - - The category for the macro. - - MCHAR* name - - The name for the macro or NULL to generate a unique name. - - MCHAR* tooltip - - The tooltip text. - - MCHAR* buttonText - - The button text. - - MCHAR* sourceText - - The source text. MAXScript::ScriptSource scriptSource - - The source of the source text. - - - - - Sets the parameters for the macro entry whose ID is passed. - Parameters: - MacroID mid - - The macro ID. - - MCHAR* tooltip - - The tooltip text. - - MCHAR* btnText - - The button text. - - MCHAR* sourceFile - - The source file name. - - int sourceOffset - - The sorce offset. - TRUE if set; FALSE if the ID was not found. - - - - - This method modifies the string in place to be a valid macro name (no punctuations other than spaces). - Parameters: - MCHAR* s - - The name string. - - - - - This method modifies the string in place to be a valid category name (no punctuations other than spaces). - Parameters: - MCHAR* s - - The category string. - - - - - This methods brings up the editor for editing the specified macro script text. - Parameters: - MacroID mid - - The ID of the macro script to edit. - - - - - Executes the macro script whose ID is passed. - Parameters: - MacroID mid - - The ID of the macro to execute. - A pointer to the result of executing the macro. If a developer does't care about the result of executing a macroScript, which is usually the case, then the Value* returned from this method can just be ignored. If a developer does care, then the necessary information about working with Value*'s is in the MAXScript SDK documentation. - - - - - This method loads all the macro scripts found in the specified path and optionally its sub-directories. You can point this method at any directory and it will scan it for .mcr files and scan those for macroScript definitions. 3ds Max uses this during startup to scan the UI directory (recursively) for .mcr files. - Parameters: - MCHAR* path_name = NULL - - The path to check. If NULL the default path is used. - - BOOL recurse = TRUE - - If TRUE nested sub-directories are scanned and loaded as well. - - - - - Returns the default path for storing / searching macro script files. - - - - - This class provides access to a single macro entry. There are methods provided to access the macro ID, name, category, file name, tooltip, UI button text, and the UI button icon. MacroEntries are returned from methods of class . Macro scripts (or macros) are scripts that live in buttons and menus in the new customizable UI. The macro script manager keeps a directory of all known macros and provides an API for running and editing macros and for accessing and updating the directory. All macro scripts have a name and a category. The category is used to organize the macros into groupings and is given to the macro script at definition time. If you look at the macro scripts list in the UI Customize dialog, you see a Category dropdown with things like 'Cameras', 'DragandDrop', 'LightTools', etc., which is derived from the all categories present in the currently-defined macroscripts. Note that the normal way to define a macroScript is through MAXScript, the .mcr files in the UI/MacroScripts directory contain examples, and they all have category definitions. Note: In order to use these methods you need to link to "MAXSCRPT.LIB". - - - - - - Returns the ID for this macro script. - - - - - Returns the name for this macro script. - - - - - Returns the category for this macro script. - - - - - Returns the internal category for this macro script. The internal category is the non-localized category name. - - - - - Returns the file name of the script source text for this macro script. - - - - - Returns the byte offset for this macro script. - - - There can be any number of macroScripts in a single source file and the offset keeps track of the beginning of its definition in the file. - - - - - Returns the executable codetree for this macro script. - - - When the macroScript is defined, only its source file and source offset are registered. When the user first runs it, the MAXScript compiler is used to compile the definition into executable code, which is then cached and used for any later executions and is what this method returns. If this returns NULL, the macro hasn't been compiled or run yet. Another way to run the macro is via the MacroEntry::Execute() and this causes the code to be cached as a side effect also. Normally, developers only ever need to use the Execute() method, but if they are using the MAXScript SDK, they can grab the code using GetCode() and work with it directly. - - - - - Returns the tooltip text for the UI button. - - - - - Returns the UI button text (for label buttons). - - - - - Returns the file name of the icon file. - - - - - Returns the zero based index of the icon in the icon file. - - - - - Returns the name of the multi-resolution icon assigned to the UI button. - - - - - - - Returns the state of the specified flags. - - - The mask value ANDed with internal state for the above values - - The flags to get. One or more of the following values: - - - - Executes this macro entry. - - - A pointer to the result of executing the macro. If a developer doesn't care about the result of executing a macro script, which is usually the case, then the Value* returned from this method can just be ignored. If a developer does care, then the necessary information about working with Values is in the MAXScript SDK documentation. - - - - - Executes the specified handler in this macro entry. - - - A pointer to the result of executing the macro's handler. If a developer doesn't care about the result of executing a macro script, which is usually the case, then the Value* returned from this method can just be ignored. If a developer does care, then the necessary information about working with Value*'s is in the MAXScript SDK documentation. - - Either the name of the hander to run as a value, or the Value* returned by a call to . - An array of Value* that is passed to the handler function - The number of elements in arg_list - If true, the execution of the handler will be wrapped in an undo entry. The undo entry's name is the macroscript's name - - - - Executes the specified handler in this macro entry. - - - The failure or success status of the call. - - The name of the hander to run - An array of FPParams* that is passed to the handler function - [out] If the handler successfully executed, the result of executing the handler - If true, the execution of the handler will be wrapped in an undo entry. The undo entry's name is the macroscript's name - - - - Returns a Value* that can be passed to CallHandler() if the specified handler exists, NULL of the handler doesn't exist. - - - - - Returns whether the specified handler exists. - - - - - Compiles this macro entry. - - - True if the macro successfully compiled. - - The specified parser will be used to to perform the compile. If NULL, a temporary parser will be created and used. - - - - Flags the macro as used, and to be compiled by CompileUsed(). - - - - - Clears the code cache and deletes the icon. - - - - - Returns the icon for this macro script. - - - - - Provides various methods to emit pieces of script to the Macro Recorder. There are also methods to specify the nature of the scripts generated by the user operating 3ds Max. Additionally there are methods to enable or disable the recording of scripts. This class may be used by plug-ins but is also used internally as part of the 3ds Max Macro Recorder. Inside key areas of 3ds Max macro scripts are emitted corresponding to the operation being performed. For example when a call goes to a parameter block to set a value 3ds Max internally call this classes method ParamBlock2SetValue(...) to emit script to record the change. Thus, many operations a plug-in performs are recorded automatically. There are however operations a plug-in can perform which won't be recorded automatically. In these cases methods of this class may be used to emit script to record these operations. Several of the functions in this class use an ellipsis argument (...). This ellipsis is the var-args style of passing information to a method. This allows a developer to pass a variable number of values to the method. These are typically a set of tag values followed by some C++ types. The sample code shown with many of the methods shows how this is done. For a starting point for more general information on variable argument lists see va_arg in the Window help file. An instance of the can be retrieved using the function Interface::GetMacroRecorder(). - - - - - Used for implementing a custom creation manager. This method starts a special accumulation 'mode' in which certain other Macro Recorder calls are treated specially until the next EmitScript(). BeginCreate() effectively signals the start of a scene node creation and enters a mode in which calls to SetNodeTM(), SetProperty(), ParamBlockXSetValue() and SetSelProperty() all generate keyword parameters to the current constructor, rather than emitting stand-alone property assignment scripts. Outside the 'create' mode, a call to SetNodeTM() would generate something like: move $foo [10,0,0] - - but when in the mode would add a pos: argument to the constructor: - - sphere radius:20 pos:[10,0,0] - Parameters: - ClassDesc* cd Points to the class descriptor for the plug-in. - This tells you whether MAXScript successfully entered the BeginCreate mode. It will fail if MAXScript can't create the object described by the , so you might use it in some generic situations to decided whether to call the closing EmitScript(). - - - - - Provides a simple way to emit a property assignment script. An example of this type of script is s: $sphere01.radius = 50 - - Pointer to the object whose property is changing. - The string which is the name of the property. This is the fixed machine-parsable name. - One of the type tags from List of Macro Recorder Types - This ellipsis is the var-args style of passing information to a method. This allows a developer to pass a variable number of values to a method. These are typically a set of 'tags' followed by some C++ data types. - - - - Used to signal that an mr_reftarg argument in the currently accumulating script should be emitted as a copy. For example, when maps or materials are dragged onto sub-map/mtl buttons in the material editor, an instance/copy requester dialog is presented and depending on the choice, either a direct assignment or assignment of a copy is appropriate: The actual assignment script is set up using a macroRecorder->SetProperty() call with the dropped map/material supplied as an mr_reftarg argument. In situations where the copy/instance status is known, you can emit directly an mr_funcall argument for the copy, but there may be situations in which this choice is decided in some piece of remote code or control flow and so you can use this method to condition the emitted script to apply a 'copy ' call. - - The pointer to the object to be copied. - - - - Provides a simple way to emit a property assignment script for the current selection set. Sample Code: - - The name of the property to set. - One of the type tags from List of Macro Recorder Types. - This ellipsis is the var-args style of passing information to a method. This allows a developer to pass a variable number of values to a method. These are typically a set of 'tags' followed by some C++ types. - - - - Used to build a MAXScript function call. In the general case, such a call may have positional arguments followed by keyword arguments. Sample Code: This generates an addModifier() function call, such as * addModifier $foo (bend()) before:3 The call has 2 positional arguments and 1 keyword argument (hence the 2, 1). The first positional is given as mr_reftarg, this which refers to the current node, the second positional is given as mr_create, mod->ClassID(), mod->SuperClassID(), 0 which causes a 0-argument constructor to be emitted for the modifier, and finally the single keyword argument is given as _M("before"), mr_int, before which is the keyword name followed by the arg value. - - Pointer to the function to call. - The number of positional arguments in the var-args section. - The number of keyword arguments in the var-args section. - This ellipsis is the var-args style of passing information to a method. This allows a developer to pass a variable number of values to a method. These are typically a set of 'tags' followed by some C++ types. List of Macro Recorder Types for a list of potential tags and arguments. - - - - Emits a piece of macro script as a literal string. To understand when this is used consider the following example. Say you have a button in your user interface which does a certain thing but there is no way using the other macro recorder calls of constructing the piece of script that you need emitted. For instance the button may invoke a for loop. In such a case you can use this method to emit a macro script string which does a for loop. This is a string, just as you would type it into the Scripting . - - Pointer to the string to emit. - - - - Called to emit script to record the assignment to a MAXScript variable. - - The variable name. - One of the type tags from List of Macro Recorder Types - This ellipsis is the var-args style of passing information to a method. This allows a developer to pass a variable number of values to a method. These are typically a set of 'tags' followed by some C++ types. - - - - Cancels and clears the currently accumulating script. This would be used for example, if the operation that is being accumulated can be canceled by the user, such as right-clicking out of a transform or a geometry node create. There are calls to macroRecorder()-> in the MOUSE_ABORT processing in the default creation manager. - - - - - Signals the completion of an accumulating script, causing it to be frozen in the recorder pane and any new calls that might have been folded into the current script will cause a new one to be started. For example, when you drag the time slider, the sliderTime assignment script accumulates the changes, but when you let go of the mouse button, an EmitScript() is called, so that subsequent drags will start a separate script fragment. Same with interactive transforms and node creation. - - - - - Returns the property name of the 'i-th' sub-material of the specified material. - - The material whose 'i-th' sub-material property name is returned. - The zero based index of the sub-material. - - - - Returns the property name of the 'i-th' sub-texmap of the specified material. - - The material or texmap whose 'i-th' sub-texmap property name is returned. - The zero based index of the sub-texmap. - - - - Enables the Macro Recorder. This call is 'nestable', i.e. it uses a use counter internally so recursive or nested code can manage local enables and disable states. - - - - - Disables the Macro Recorder. This allows the developer to disable the automatic macro recording. - - - - - Returns true if the Macro Recorder is enabled (via Enable() ), false otherwise. - - - - - Super enable and option controls. In the Scripting Window Macro Recorder pull-down menu choice is an option to enable or disable the Macro Recorder. This method corresponds to that state. - true if enabled, false if disabled. - - - - - Returns TRUE if code is emitted when command panels are changed; FALSE if code is not emitted. - - - - - Returns true if the macro recorder will emit script for 3ds Max toolbar tool selections, false otherwise. - - - - - Returns true if the macro recorder will emit script for 3ds Max menu selections, false otherwise. - - - - - Returns true if specific node names are used in the generated code false, if the current selection is used. - - - - - Returns true if recording absolute sub-object numbers, false if using the selection set. - - - - - Tells if the code is generated using absolute transform assignments. - true if code is generated using absolute transform assignments, false if relative transforms operations are generated. - - - - - Derive from this class to pass a task to be executed on 3DS Max main thread. - - - - - This method will be called from the main thread. - - - - - Description: - This is the base class for the development of plug-ins. Shown are the methods that need to be implemented by the plug-in. Most of these methods are implemented by the class so most developers will not need to use these unless is not sufficient. - Data Members: - protected: - - INode* mpINode; - - The node being manipulated - - - - - This method can be used to tell the manipulator management system that this manipulator is always active. - Default Implementation: - { return false; } - - - - - This method returns the manipulator name string. The class uses this method for the tooltip in the viewport. - - - - - This method gets called when the mouse first passes over a manipulator object. The return value is used to determine whether a redraw is needed or not. Normally manipulators display in a different color when the mouse is over them, so this should return kFullRedrawNeeded. - Default Implementation: - {return kNoRedrawNeeded; } - The display state indicating whether no redraw, a full redraw, or a post redraw is needed. - - - The time to display the object. - - An interface that may be used to call methods associated with the viewports. - - The location of the tooltip. - - A pointer to the hitdata containing information on which manipulator was hit. - - - - This method gets called when the mouse leaves the manipulator object. The return value is used to determine whether a redraw is needed or not. Normally manipulators display in a different color when the mouse is over them, so this should return kFullRedrawNeeded. - Default Implementation: - {return kNoRedrawNeeded; } - The display state indicating whether no redraw, a full redraw, or a post redraw is needed. - - - The time to display the object. - - An interface that may be used to call methods associated with the viewports. - - The location of the tooltip. - - A pointer to the hitdata containing information on which manipulator was hit. - - - - This method gets called when the mouse is pressed down and moves within the manipulator context. It is the method that does the actual manipulator. It is up to the manipulator code to turn the mouse position into a new value for the parameter(s) being manipulated. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The location of the tooltip. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - Default Implementation: - { } - - - - - This method gets called when the mouse buttons is first pressed down within the manipulator context. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The location of the tooltip. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - Default Implementation: - { } - - - - - This method gets called when the mouse buttons is released within the manipulator context, and thus signals the end of the manipulation. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The location of the tooltip. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - Default Implementation: - { } - - - - - This method gets called when the right mouse button is first pressed down within the manipulator context. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The location of the tooltip. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - Default Implementation: - { } - - - - - This method gets called when the right mouse button is released within the manipulator context, and thus signals the end of the manipulation. - Parameters: - TimeValue t - - The time to display the object. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - & m - - The location of the tooltip. - - DWORD flags - - Not used, should be set to 0. - - ManipHitData* pHitData - - A pointer to the hitdata containing information on which manipulator was hit. - Default Implementation: - { } - - - - - This method returns a pointer to the that is currently being manipulated. - Default Implementation: - { return mpINode; } - - - - - Description: - This is the base class for the creation of manipulator gizmo objects and can hold a single , , Marker, or Text gizmo. - Data Members: - private: - - PolyShape* mpShape - - The polyshape gizmo. - - Mesh* mpMesh - - The mesh gizmo. - - mPosition - - The position for markers and text. - - MarkerType* mpMarkerType - - The marker type for marker gizmos. See the MarkerType enum - - MSTR* mpText - - The string used for text gizmos - - mUnselColor - - The color of the gizmo when unselected. - - mSelColor - - The color of the gizmo when selected. - - DWORD mFlags - - Display and hit testing flags. - - int mGizmoSize - - The size of the gizmo in pixels for kGizmoScaleToViewport gizmos - Data Members: - Display and hit-test flags. - - static const DWORD kGizmoDontDisplay - - Don't display this gizmo, it is still hit-tested. - - static const DWORD kGizmoDontHitTest - - Don't hit test this gizmo, it is still displayed. - - static const DWORD kGizmoActiveViewportOnly - - Only display the gizmo in the active viewport. - - static const DWORD kGizmoScaleToViewport - - Tells the gizmo to scale itself to have a constant size in the viewport. In this case, the system uses the mGizmoSize to determine how big the manipulator should be. It interprets mGizmoSize as pixels it this case. This flag only applies to mesh gizmo. - - static const DWORD kGizmoUseRelativeScreenSpace - - The coordinates are in normalized screen space. the X and Y values are in the range 0.0 to 1.0, and interpreted as percentages of screen space. Note: This is only supported for , Marker and Text gizmos. - - static const DWORD kGizmoUseScreenSpace - - The coordinates are in screen space. Note: This is only supported for , Marker and Text gizmos. - - static const DWORD kGizmoApplyUIScaling - - If the coordinates are in screen space, the coordinates are 100% dpi scaled values and will be internally converted to current dpi scaling. Note: This is only supported for , Marker and Text gizmos. - - - - - Used Internally. - - This method is called when a hit test on a manipulator is needed. - Parameters: - GraphicsWindow* pGW - - The graphics window where the hit test is done. - - HitRegion* pHR - - The hit region. See Class . - - ManipHitList* pHitList - - A pointer to the hit list. - - Matrix3* tm - - The transformation matrix. - - pScreenPoint - - The screen point to test. - - int gizmoIndex - - The index of the gizmo. - TRUE if the manipulator was hit, otherwise FALSE. - - - - - This method will render the manipulator gizmo. - Parameters: - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - - TimeValue t - - The time value to render at. - - INode* pNode - - A pointer to the node to render. - - int flags - - The manipulator flags. - - bool selected - - This flag sets the selected or unselected state. This will instruct the render process to use the proper color for the manipulator. - - bool isStandAlone - - This flag sets whether the manipulator is a stand alone manipulator (i.e. manipulators which manipulate themselves such as the slider manipulator). - - - - - Used Internally. - - This method returns the bounding box of the manipulator. - Parameters: - INode* pNode - - A pointer to the node to calculate the bounding box for. - - ViewExp* pVpt - - An interface that may be used to call methods associated with the viewports. - private: - - - - - Sets size of the gizmo in pixels for kGizmoScaleToViewport gizmos. - Parameters: - int gizmoSize - - The gizmo size in pixels. - - - - - - - This is a special storage class for hit records that keep track of which manipulator was hit. When this data is logged with the system, the memory is owned and freed by the System. - - - - - A pointer to the manipulator associated with the hit data. - - - - - The index of the selected manipulator. - - - - - This method allows you to copy the hit data. By default returns: - - - - - - - This class can be used to store a bit per map channel, including both negative and positive map channels, and it works with any size index. - - - - - Returns the highest index that this could have a non-default value for. All indices above this are guaranteed to have value "TextureDefault()". - - - - - Returns the lowest index that this could have a non-default value for. All indices below this are guaranteed to have value "ColorDefault()". - - - - - Sets the value of the given channel. - - - - - Clears the value of the given channel. - - - - - Gets the value of the given channel. (If this particular channel has not been set before, the default for the channel will be returned.) - - - - - Returns the default value for texture channels, channels 1 and above. - - - - - Returns the default value for color channels, channels 0 and below. - - - - - Inverts the value of all texture channels (1 and above). - - - - - Inverts the value of all color channels (0 and below). - - - - - Inverts all channel values. - - - - - Saves data to stream. - - - - - Loads data from stream. - - - - - Indexing operator. - - - - - Comparison operator. - - - - - Inequality operator. - - - - - Assignment operator. - - - - - Represents some kind of change to a mesh map. This "delta" can include changes in map vertices and/or faces. It is always a subordinate part of a . Most of the time, the programmer does not need to worry about this class directly, but can let the parent do most of the work. - - - - - Clears out all existing map changes. Zeroes all the vCreate, vSet, etc tables. - - - - - Sets the number of map vertices in the input map. NOTE that if n is less than the current vnum, the data relating to the extra vertices will be lost. (That is, if one of your map vertex sets is applied to map vertex 32, and you SetInVNum to 30, that vertex set will be lost, and will not be recovered if you later SetInVNum to 35.) It is NOT necessary to call this method before applying this to a smaller than expected Map. - Parameters: - DWORD n The number of vertices expected from the input mesh. - - - - - Sets the number of map faces in the input map. NOTE that if n is less than the current fnum, the data relating to the extra faces will be lost. (That is, if one of your face remaps is applied to face 32, and you SetInFNum to 30, that face remap will be lost, and will not be recovered if you later SetInFNum to 35.) It is NOT necessary to call this method before applying this to a smaller than expected Map. - Parameters: - DWORD n The number of faces expected from the input mesh. - - - - - Returns the number of map vertex sets that would be applied to a map with the specified number of map vertices. (If that number equals this 's vnum, this is simply vSet.Count().) - Parameters: - DWORD inVNum The number of vertices in the input map we're inquiring about. - - - - - Returns the number of vertices in the output map, assuming that the input map is of the expected (vnum) size. - - - - - Returns the number of vertices in the output map, assuming that the input map has the specified number of map vertices. - Parameters: - DWORD inVNum The number of map vertices expected in the input map. - - - - - Indicates whether the specified map vertex was created in this . - Parameters: - DWORD i The index in the output of the map vertex. - - - - - Obtains the index of the vSet entry that relates to this vertex. - Parameters: - DWORD i The map vertex index. - The index in the vSet array of the map vertex set corresponding to this vertex, or UNDEFINED if this map vertex has not been modified. - - - - - Obtains the index of the fRemap entry that relates to this face. - Parameters: - DWORD ff The map face index. - If there is such an entry, the index is returned, so fRemap[RemapID(ff)].fid == ff. If there is no remap record for this map face, the method returns UNDEFINED. - - - - - Tells whether the specified corner of the specified face has been remapped in this . - Parameters: - DWORD ff The map face index. DWORD vid The corner of the face - 0, 1, or 2. - If this corner has been remapped, it returns the vertex it's been remapped to. Otherwise, it returns UNDEFINED. - - - - - Returns the specified map face as it would appear in the output, taking into account any remaps. - Parameters: - *mf The input map face array. DWORD f The index of the face you want the output version of. - - - - - Creates new map vertices. - Parameters: - UVVert *v A pointer to an array of UVVerts representing the new map vertices. int num The size of the UVVert array. - The index (in the output map) of the first of these new map vertices. - - - - - Creates new map faces. Note: MapDeltas must be kept up to date with the parent in all new face creations. See the method CreateDefaultMapFaces for details. - Parameters: - *f A pointer to an array of map faces to be added to the . int num The size of the map face array. - - - - - Creates new "default" map faces, where all the corners are UNDEFINED. (These are later filled in by a call to the parent 's FillInFaces method.) Note: MapDeltas must be kept up to date with the parent in all new face creations. See the method CreateDefaultMapFaces for details. - Parameters: - int num The number of default faces to create. - - - - - Creates 2 new faces, forming a quad. Note: MapDeltas must be kept up to date with the parent in all new face creations. See the method CreateDefaultMapFaces for details. - Parameters: - DWORD *t A pointer to an array of 4 map vertices to be used as corners of the quad. - - - - - Creates a new map face by copying (and optionally remapping) the face given. Note: MapDeltas must be kept up to date with the parent in all new face creations. See the method CreateDefaultMapFaces for details. - Parameters: - & tf The map face we wish to clone. (This is typically generated by the OutFace method.) DWORD remapFlags=0DWORD *v=NULL If we wish to remap any of the corners of this map face while cloning, the appropriate flags and vertices should be passed in these last two arguments. v should point to an array of 3 map vertex indices, although the ones not marked as used by the remapFlags need not be set to anything in particular. See class for more information about face remapping. - - - - - Adds a face remap to this . If the face specified already has a remap record, the two are combined. If the face specified is a face created by this , the remap is applied directly to the fCreate entry instead of being stored in fRemap. - Parameters: - DWORD f The face to remap. DWORD flags Remap flags - these indicate which vertices should be remapped. The possibilities are FR_V0 (1), FR_V1 (2), and FR_V2 (4). (See class for more information.) DWORD *v A pointer to the vertices to remap the face to use. Only the positions indicated in the remap flags need contain meaningful data. Note that the vertices indicated here must be indexed by their positions after all of the current 's creates and clones, but before any vertex deletes - essentially input-based indexing. Vertex index values of 0 through vnum-1 are considered to be the original mesh's vertices; values of vnum through vnum+vCreate.Count()-1 are considered to be this 's newly created vertices; and values above this are cloned vertices. - - - - - Adds a face remap to this . If the face specified in the already has a remap record, the two are combined. If the face specified is a face created by this , the remap is applied directly to the fCreate entry instead of being stored in fRemap. - Parameters: - & fr A that should be appended to this . - - - - - Deletes the specified faces. This only affects the fCreate array, and should generally only be called by the parent 's FDelete method to keep the face create arrays in sync. - Parameters: - int offset Indicates what position in the fdel array corresponds to the first created face. (This is necessary since the BitArrays handed to MeshDelta::FDelete generally are based on the indexing after the previous MeshDelta::fDelete is applied. So this value is less than fnum if there was some previous deletion of original faces in the .) & fdel The faces to delete. The faces are indexed by their output mesh positions. - - - - - Sets an existing map vertex to the value given. (Note that if the same map vertex is set twice, the new set simply replaces the old one - there is never more than one in the vSet array for a single input map vertex.) - Parameters: - int i The index of the map vertex to set. const UVVert & p The value to set the map vertex to. - - - - - Changes the given map by this , in the following manner: First, any maps that are supported by the but not by the mesh are assigned to the mesh in their default form. (Vertex colors are white, other maps are copies of the mesh vertices, and all have the same topology as the mesh). Next, any UNDEFINED mapping verts in the are filled in by FillInFaces. Then the new vertices are added, creates first, followed by clones. The original vertices are then moved. The faces are then modified, by applying all the FaceRemaps, FaceChanges, and FaceSmooths to the appropriate faces. New faces (in fCreate) are appended to the end of the face list. Map changes are applied to all active maps, and map channels not supported by this are removed. After all that is done, the vertices and faces marked in the vDelete and fDelete arrays are deleted. Finally, the vertex data, vertex hide, and selections kept in the are applied to the result. - - - The map vertex array to change. This should be allocated to handle all the new map vertices in the vCreate array. - - The map face array to change. This should be allocated to handle all the new map faces in the fCreate array. - - The actual number of map vertices (which doesn't have to match this 's vnum) in the input map. - - The actual number of map faces (which doesn't have to match this 's fnum) in the input map. - - - - Prints out all the changes in this to the DebugPrint window in Developer Studio. - - - - - The expected number of vertices in the input mesh. - - - - - The expected number of faces in the input mesh. - - - - - This data member stores changes in the mapping vertices given as input. See class for more information. UVVertSets are stored in original map vertex ID order, and there is never more than one per original map vertex. - - - - - This data member stores mapping vertices newly created as part of the . These are stored in the order created. - - - - - This data member stores map faces newly created as part of the . These are stored in the order created. This must match driver fCreate in size. - - - - - This data member stores changes in which map vertices are used by existing map faces. See Class for more information. These are stored in original face order, and there is never more than one per original face. At least one per new vertex. - - - - - Equality operator - makes this just like the one given. - - - - - Appends the given to the current one. - Parameters: - & td The to append. This may be modified to make it suitable, ie the vnum and fnum values will be set to the expected output of the current if they don't already match. (This may result in the loss of some data - see "SetInVNum" and "SetInFNum" for more information.) - - - - - Indicates what parts of a could be changed if this were appended to it. This is useful when backing up the for Restore Objects. For instance, if you had a with lots of face remaps, and you wanted to compose it with one that only added map vertices, there would be no reason to back up the remaps for an undo. - Returns some combination of the following flags, corresponding to the data members that would be changed: MDELTA_VMOVE: Indicates that the vSet array will be altered by this . MDELTA_VCREATE: Indicates that the vCreate array will be altered by this . MDELTA_FREMAP: Indicates that the fRemap array will be altered by this . MDELTA_FCREATE: Indicates that the fCreate array will be altered by this . - - - - - Copies the specified parts of the . (Useful in combination with ChangeFlags to create efficient Restore objects.) - Parameters: - & from The to copy into this. DWORD channels Indicates the parts to copy - some combination of the following flags: MDELTA_VMOVE: Copy the vSet array. MDELTA_VCREATE: Copy the vCreate array. MDELTA_FREMAP: Copy the fRemap array. MDELTA_FCREATE: Copy the fCreate array. - - - - - Description: - A texture map implements this class and passes it into the methods EvalUVMap(), EvalUVMapMono(), and EvalDeriv() to evaluate itself with tiling & mirroring. Each of the methods of this class are used to sample the map at a single UV coordinate. - - - - - This method is required. It is called to sample the map at a single UV coordinate. This method should not try to antialias the map, it should just return the value. Take for example a bitmap texture implementing this method. If the u values passed was 0.5 and the v value passed was 0.5, the plug-in would just return the pixel value at the center of the bitmap as an . - Parameters: - & sc - - The . - - float u - - The U value in the range of 0.0 to 1.0 - - float v - - The V value in the range of 0.0 to 1.0 - The sampled value as an . - - - - - This method is required. It is called to return a value from the map that is the averaged value over the specified region of width du and height dv, centered at u, v. Certain map types may use the du and dv values directly to perform antialiasing of the map. - Parameters: - & sc - - The . - - float u - - The U value in the range of 0.0 to 1.0 - - float v - - The V value in the range of 0.0 to 1.0 - - float du - - This parameter can be considered the width of a small rectangle center on u,v. The u and v value are guaranteed to be inside this rectangle. - - float dv - - This parameter can be considered the height of a small rectangle center on u,v. The u and v value are guaranteed to be inside this rectangle. - The sampled value as an . - - - - - This method is optional as a default implementation is provided. It may be implemented however if a certain map type can be more efficient in evaluating a mono channel. For example a noise function that produces a single floating point value as a function of UV. This method is called to sample the map at a single UV coordinate. This method should not try to antialias the map, it should just return the value. - Parameters: - & sc - - The . - - float u - - The U value in the range of 0.0 to 1.0 - - float v - - The V value in the range of 0.0 to 1.0 - The sampled value as an float. - Default Implementation: - { return Intens(Sample(sc,u,v)); } - - - - - This method is optional. It is called to return a value from the map that is the averaged value over the specified region of width du and height dv, centered at u, v. Certain map types may use the du and dv values directly to perform antialiasing of the map. - Parameters: - & sc - - The . - - float u - - The U value in the range of 0.0 to 1.0 - - float v - - The V value in the range of 0.0 to 1.0 - - float du - - This parameter can be considered the width of a small rectangle center on u,v. The u and v value are guaranteed to be inside this rectangle. - - float dv - - This parameter can be considered the height of a small rectangle center on u,v. The u and v value are guaranteed to be inside this rectangle. - The sampled value as an float. - Default Implementation: - { return Intens(SampleFilter(sc,u,v,du,dv)); } - - - - - This class manages the default settings of a range of 3ds Max features. - - - Description: - A set of default settings can be saved under a certain name. The different sets are then presented by 3ds Max to users to choose from. 3rd party plug-ins can add their own defaults to the current set of settings, but cannot create their own sets. - - - - - The main material class definition. This class describes the properties of a material used by the renderer. - - - - - Ambient color setting. The values for x, y, and z range from 0.0 to 1.0. These correspond to red, green, and blue respectively. - - - - - Diffuse color setting. The values for x, y, and z range from 0.0 to 1.0. These correspond to red, green, and blue respectively. - - - - - Specular color setting. The values for x, y, and z range from 0.0 to 1.0. These correspond to red, green, and blue respectively. - - - - - Shininess setting. This value ranges from 0.0 to 1.0. - - - - - Shininess strength setting. This value ranges from 0.0 to 1.0. - - - - - Opacity setting. This value ranges from 0.0 to 1.0. - - - - - Self Illumination setting. This value ranges from 0.0 to 1.0. - - - - - sided material setting. Nonzero indicates double sided material, otherwise single sided. - - - - - Shading limit setting. See Rendering Modes. - - - - - The textures used by this material. - - - - - Assignment operator. - - The object that will be copied. - - - - Description: - This class defines a 3x2 2D transformation matrix. Methods are provided to zero the matrix, set it to the identity matrix, translate, rotate and scale it, and compute its inverse. Operators are available for matrix addition, subtraction and multiplication. All methods of this class are implemented by the system. - Data Members: - float m[3][2]; - - - - - Compares the elements of this matrix and the one specified element by element for exact equality. - - The matrix to compare against. - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Matrix multiplication between this and M. - - - - - Sets this to the Identity Matrix. - - - - - all elements of this to 0.0f - - - - - Returns the specified row of this matrix. - Parameters: - int i - - Specifies the row to retrieve (0-2). - - - - - Sets the specified row of this matrix. - Parameters: - int i - - Specifies the row to set (0-2). - - p - - The values to set. - - - - - Returns the specified column of this matrix. - Parameters: - int i - - Specifies the column to retrieve (0 or 1). - - - - - Sets the specified column of this matrix. - Parameters: - int i - - Specifies the column to set (0 or 1). - - col - - The values to set. - - - - - This method returns a containing the upper two rows of the specified column. - Parameters: - int i - - Specifies the column to get (0 or 1). - - - - - Sets the specified element of the translation row of this matrix to the specified value. - Parameters: - int i - - Specifies which column to set (0 or 1) - - float v - - The value to store. - - - - - Returns the translation row of this matrix. - - - - - Apply an incremental translation to this matrix. - Parameters: - & p - - Specifies the amount to translate the matrix. - - - - - Apply an incremental rotation to this matrix using the specified angle. - Parameters: - float angle - - Specifies the angle of rotation. - - - - - Apply an incremental scaling to this matrix using the specified scale factors. - Parameters: - & s - - The scale factors. - - BOOL trans = FALSE - - If set to TRUE, the translation component is scaled. If trans = FALSE the translation component is unaffected. When 3ds Max was originally written there was a bug in the code for this method where the translation portion of the matrix was not being scaled. This meant that when a matrix was scaled the bottom row was not scaled. Thus it would always scale about the local origin of the object, but it would scale the world axes. When this bug was discovered, dependencies existed in the code upon this bug. Thus it could not simply be fixed because it would break the existing code that depended upon it working the incorrect way. To correct this the trans parameter was added. If this is set to TRUE, the translation component will be scaled correctly. The existing plug-ins don't use this parameter, it defaults to FALSE, and the code behaves the old way. - - - - - Initializes the matrix to the identity then sets the translation row to the specified values. - Parameters: - & s - - The values to store. - - - - - Initializes the matrix to the identity then sets the rotation to the specified value. - Parameters: - float angle - - The rotation angle in radians. - - - - - This matrix may be used to invert the matrix in place. - - - - - Perform matrix multiplication. - - - - - Perform matrix addition. - - - - - Perform matrix subtraction. - - - - - - - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - - - - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - - - - Description: - This class implements a 4x3 3D transformation matrix object. Methods are provided to zero the matrix, set it to the identity, compute its inverse, apply incremental translation, rotation and scaling, and build new X, Y and Z rotation matrices. Operators are provided for matrix addition, subtraction, and multiplication. All methods are implemented by the system. - - Note: In 3ds Max, all vectors are assumed to be row vectors. Under this assumption, multiplication of a vector with a matrix can be written either way (Matrix*Vector or Vector*Matrix), for ease of use, and the result is the same - the (row) vector transformed by the matrix. - Data Members: - private: - - float m[4][3]; - - Matrix storage. - - uint32_t flags; - - Matrix Identity Flags. - - POS_IDENT - - Indicates the translation row of the matrix is the identity. - - ROT_IDENT - - Indicates the rotation elements of the matrix are the identity. - - SCL_IDENT - - Indicates the scale elements of the matrix are the identity. - - MAT_IDENT - - Indicates the matrix is the identity matrix. This is equivalent to (POS_IDENT|ROT_IDENT|SCL_IDENT). - - - - - - - This clears the MAT_IDENT flag to indicate the matrix is not the identity. Non-const GetAddr() calls this for you. - - - - - Returns the identity flags. - - - - - Returns TRUE if the matrix is the identity matrix (based on the flags); otherwise FALSE. - - - - - This method may be used to recompute the *_IDENT flags for this matrix. For instance, if you call a method, such as INode::GetObjTMAfterWSM(), and it returns a matrix, you cannot use the IsIdentity() method to check if the matrix is indeed the identity. This is because the flags that method checks are not initialized by the method. What you can do however is call this method first. This will validate the flags in the matrix so they accuratly reflect the properties of the matrix. If after calling this method, and then calling IsIdentity(), the proper result would be returned. - - - - - Initializes the matrix with the row data passed and validates the matrix flags. - A reference to this matrix. - - The data for row 0. - The data for row 1. - The data for row 2. - The data for row 3. - - - - Compares the elements of this matrix and the one specified element by element for exact equality. Returns nonzero if they are equal; otherwise zero. - - The matrix to compare against. - - - - Compares the elements of this matrix and the one specified element by element for equality within the specified tolerance epsilon. Returns nonzero if they are 'equal'; otherwise zero. - - The matrix to compare against. - The tolerance for comparison. If the values in the matrix are within this value ( or ) they are considered equal. - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Multiplies this by the specified (*this = (*this)*M;). - Multiply this matrix on the right by Matrix m. - A reference to this matrix - - The matrix multiplied to the right of this matrix - - - - Multiplies each element of this by a float. - a reference to this matrix - - The scale to apply to each element of this matrix - - - - this matrix to the Identity Matrix. - - - - - This method sets all elements of the matrix to 0.0f - - - - - Returns the specified row of this matrix. - - Specifies the row to retrieve. - - - - Sets the specified row of this matrix to the specified values. - - Specifies the row to set. - The values to set. - - - - Returns the 'i-th' column of this matrix. - - Specifies the column to get (0-2). - - - - Sets the 'i-th' column of this matrix to the specified values. Note : Clears the matrix flags. - - Specifies the column to set (0-2). - The values to set. - - - - Returns the upper three entries in the specified column. - - Specifies the partial column to get (0-2). - - - - This method zeros the translation portion of this matrix. - - - - - This method zeros the rotation and scale portion of this matrix. - - - - - This method zeros the scale portion of this matrix without orthogonalization. If the matrix was sheared (skewed) then this method is not able to remove the scale component completely. In that case, use the Orthogonalize() method instead to remove the scale component entirely. Read the SCL_IDENT flag to check whether the NoScale() method was enough to make the matrix to be orthogonal (with perpendicular axes of unit length). - - - - - Ortho-normalize the matrix. This ensures that each axis of the basis is of length 1 and at right angles to the other. This is an "unbiased" orthogonalization, which means that no single axis is used as the basis for the other axis, and all axis will be modified equally. - - This is an iterative process, and should not be used in high-performance situations. It seems to take a maximum of 4 iterations to converge. - - - - - Sets the specified component of the translation row of this matrix to the specified value. The POS_IDENT flag is cleared. - - Specifies the component of the translation row of this matrix to set. - The value to set. - - - - Returns the translation row of this matrix. - The translation row of this matrix. - - - - - Apply an incremental translation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the translation. - - - - Apply an incremental X rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the X rotation in radians. - - - - Apply an incremental Y rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the Y rotation in radians. - - - - Apply an incremental Z rotation transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - Specifies the Z rotation in radians. - - - - Apply an incremental scaling transformation to this matrix. This is equivalent to multiplying on the RIGHT by the transform. - - The scale values. - If set to TRUE, the translation component is scaled. If = the translation component is unaffected. When 3ds was originally written there was a bug in the code for this method where the translation portion of the matrix was not being scaled. This meant that when a matrix was scaled the bottom row was not scaled. Thus it would always scale about the local origin of the object, but it would scale the world axes. When this bug was discovered, dependencies existed in the code upon this bug. Thus it could not simply be fixed because it would break the existing code that depended upon it working the incorrect way. To correct this the parameter was added. If this is set to , the translation component will be scaled correctly. The existing plug-ins don't use this parameter, it defaults to , and the code behaves the old way. - - - - Apply an incremental translation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. param p Specifies the translation distance. - - - - - Apply an incremental X rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the X rotation in radians. - - - - Apply an incremental Y rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the Y rotation in radians. - - - - Apply an incremental Z rotation transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - Specifies the Z rotation in radians. - - - - Apply an incremental scaling transformation to this matrix. This is equivalent to multiplying on the LEFT by the transform. - - The scale values. The translation component is unaffected. - - - - Sets this matrix to the identity and the translation components to the specified values. - - The translation values to store. - - - - Sets this matrix to the identity and the rotation components to the specified X rotation. - - The angle for X rotation (in radians). - - - - Sets this matrix to the identity and the rotation components to the specified Y rotation. - - The angle for Y rotation (in radians). - - - - Sets this matrix to the identity and the rotation components to the specified Z rotation. - - The angle for Z rotation (in radians). - - - - Sets the rotation components of the matrix as specified by the quaternion. The translation and scale components will match the identity matrix. - - Specifies the rotation to use for the matrix. - - - - Sets the rotation components of the matrix as specified by the . The translation and scale components will match the identity matrix. - - Specifies the rotation to use for the matrix. - - - - Sets the rotation components of this matrix using yaw, pitch and roll angles. There are many different conventions for specifying a rotation by means of three Euler angles. This function uses the convention of rotating around the world Z axis, then the X axis, then the Y axis; the three arguments are given in the order Y, X, Z. - - This one is equivalent to: - - M.IdentityMatrix(); - - M.RotateZ(roll); - - M.RotateX(pitch); - - M.RotateY(yaw); - - - Which presupposes Y is vertical, X is sideways, Z is forward - - The yaw angle in radians. - The pitch angle in radians. - The roll angle in radians. - - - - Sets the rotation portion of the matrix to the rotation specified by the angle and axis and sets the translation portion to zeros. - - The axis of rotation. - The angle of rotation about the axis in radians. - - - - Sets the scale components of this matrix to the specified values. The other components to this matrix will match the identity. - - The scale factors for the matrix. - - - - This creates a matrix describing a viewpoint which is at the 'from' location, looking toward the 'to' location; the viewpoint is tilted so that the 'up' vector points to the top of the view. - - This specifies the viewpoint source location. - This vector specifies the direction of view. - This vector points to the top of the view. - - - - This method performs an in-place inversion on this matrix. An inverted matrix, when multiplied by the original, yields the identity. - - - - - Perform matrix multiplication. - - - - - Perform matrix addition. - - - - - Perform matrix subtraction. - - - - - Returns the specified point transformed by this matrix. - - The point to transform by this matrix. - - - - Returns the specified vector transformed by this matrix. - - The vector to transform by this matrix. - - - - Transforms the specified list of points with this matrix. - - The array of points to transform with this matrix. - The number of points in the array. - The size of the increment used when moving to the next point. If you wish to transform an array of data objects which contain x, y, and z coordinates in order (such as a , or a structure containing a as a member) you can specify a 'stride' value (for instance ). - - - - Transforms the specified list of points with this matrix and stores the resulting transformed points in the storage passed. - - The array of points to transform (the source). - The array to store the transformed points (the destination). - The number of points in the source array. - The size increment used when moving to the next source location. - The size increment used when moving to the next storage location. - - - - Transforms the specified list of vectors with this matrix. - - The array of vectors to transform with this matrix. - The number of vectors in the array. - The size of the increment used when moving to the next vector. If you wish to transform an array of data objects which contain x, y, and z coordinates in order (such as a , or a structure containing a as a member) you can specify a 'stride' value (for instance ). - - - - Transforms the specified list of vectors with this matrix and stores the resulting transformed vectors in the storage passed. - - The array of vectors to transform (the source). - The array to store the transformed vectors (the destination). - The number of vectors in the source array. - The size increment used when moving to the next source location. - The size increment used when moving to the next storage location. - - - - Retrieves the yaw, pitch and roll angles represented by the rotation in this matrix. - - The yaw rotation angle is stored here (in radians). - The pitch rotation angle is stored here (in radians). - The roll rotation angle is stored here (in radians). - - - - Save this to disk - IO_OK on success, or a failure code - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - The interface responsible for actually saving the data - - - - Load the data for this . - IO_OK on success, or a failure code - Save and Load are only forward declared in this header! If you need to use Save or Load, you must link with maxutil, which is where these methods are implemented. This way, geom.dll is independent from maxsdk. - - The interface responsible for actually loading the data - - - - Returns the 'parity' of the matrix. Scaling one axis of the matrix negatively switches the 'parity'. However if you scale two axis the parity will flip back. Scaling three axis switches the parity again. - - When rendering a mesh, if you scale something along one axis, it turns 'inside out'. That is the direction when the normals are reversed. This method may be used to detect that case and then reverse the normals. The 3ds Max renderer does this - if this method returns TRUE it flips all the normals so it won't turn inside out. - - - - - Description: - An object of this class represents a . However, its value can be obtained only by invoking the operator(). Derived classes may override this operator to delay its computation until operator() is called. - Data Members: - protected: - - mat; - - The matrix itself. - - - - - Assignment operator. - Default Implementation: - { return mat; } - - - - - the matrix to the specified matrix. - Parameters: - & m - - The matrix to set. - Default Implementation: - { mat = m; } - - - - - Clone the matrix. - A pointer to a new clone of the matrix. - Default Implementation: - ;} - - - - - Pre-translate the matrix by the specified coordinate. - Parameters: - & p - - The coordinate to pre-translate by. - Default Implementation: - { mat.PreTranslate(p);} - - - - - Pre-rotate the X axis by the specified amount. - Parameters: - float x - - The amount of rotation. - Default Implementation: - { mat.PreRotateX(x); } - - - - - Pre-rotate the Y axis by the specified amount. - Parameters: - float y - - The amount of rotation. - Default Implementation: - { mat.PreRotateY(y); } - - - - - Pre-rotate the Z axis by the specified amount. - Parameters: - float z - - The amount of rotation. - Default Implementation: - { mat.PreRotateZ(z); } - - - - - Pre-rotate the matrix by the specified quaternion. - Parameters: - & q - - The quaternion to pre-rotate by. - Default Implementation: - {PreRotateMatrix(mat,q);} - - - - - Description: - A stack of 's (4x3 matrix). All methods of this class are implemented by the system. No error (bounds) checking is performed. - - - - - Replaces the item on the top of the stack with the specified matrix. - Parameters: - &m - - The matrix to replace the matrix at the top of the stack. - Always TRUE. - - - - - Pushes the specified matrix onto the stack. - Parameters: - &m - - The matrix to push on the top of the stack. - TRUE if there is still room on the stack; otherwise FALSE. - - - - - Duplicates the matrix on the top of the stack. - TRUE if there is still room on the stack after the dup; otherwise FALSE. - - - - - Concatenates the specified matrix with the matrix on the top of the stack (performs matrix multiplication). - Parameters: - &m - - The matrix to multiply (m * stack[top]). - Always TRUE. - - - - - Returns the matrix on the top of the stack. - - - - - Pops the matrix from the stack. - The matrix at the top of the stack. - - - - - Removes the matrix at the top of the stack. - TRUE if the number of items on the stack is >= 0 (after removing the matrix); otherwise 0. - - - - - Resets the stack to contain zero items. - Always TRUE. - - - - - Description: - This class is only available in release 5 or later. - - The class provides the interfaces for creating a Texture Baking plugins in 3ds Max. The texture baking plugins are controlled through the Maxscript "Render ToTexture". There are methods available in this class that provide the ability to produce a dynamic UI in Maxscript. - - This class provides the basic infrastructure for the UI and Maxscript interaction, to fully understand the workings of these plugins please look at the RenderElement samples - - For an example of this class in use by Texture Baking plug-ins see /MAXSDK/SAMPLES/RENDER/RENDERELEMENTS/INCLUDE/STDBAKEELEM.CPP - - All methods of this class are virtual. - - - - - - - the size of the bitmap to be created - - - Parameters: - int xSz - - Specifies the width of the output. - - int ySz - - Specifies the height of the output. - - - - - - - Get the size of the bitmap to be created - - - Parameters: - int& xSz - - The new width - - int& ySz - - the new height - - - - - - - Returns the actual filename. See remark above - - - - - - - Returns the filename used for this baked element - See comment above - - - - - - - none - - - - - none - - - - - Returns the bitmap containing the final output - - - - - - - This defines whether the baker uses lighting or not. For example a diffuse texture baker can specify whether the result uses lighting or not. - - - Parameters: - BOOL on - - The state for the lighting parameter - - - - - - - Returns whether lighting is used in the calculation - - - - - - - This defines whether the baker uses shadows or not. For example a diffuse texture bake can specify whether the result uses shadows or not. - - - Parameters: - BOOL on - - The state for the shadow parameter - - - - - - - Returns whether shadows are used in the calculation - - - - - - - Defines whether the texture baking uses Atmosphere in the final result. - - - Parameters: - BOOL on - - Specifies whether Atmospheres are used or not. - - - - - - - Returns whether Atmospheres are used. Most texture baking plugins would return false. - - - - - - - Return the number of parameters to be exposed to the UI - - - - - - - Returns the name used by maxscript for the parameter value passed in. This is a 1 based access, so if GetNParams returned 8 the valid range for will be 1 to 8. - - - Parameters: - int nParam - - The value for the parameter whose name is to be returned. - - - - - - - Returns the index of the parameter based on the pName - - - - - - - Currently only 1 = , 0 = are supported. In release 5 this means that any parameter you have is defined and used as a in maxscript - - - Parameters: - int nParam - - The value for the parameter whose type is to be returned. - - - - - - - The value to set when the Render to Texture tool is loaded - - - Parameters: - int nParam - - The value for the parameter whose value is to be returned. - - - - - - - The Render to Texture Tool will save out the data - Parameters: - int nParam - - The value for the parameter whose value is to be set - - int newVal - - The value to set - - - - - Extention to in 3ds Max 10. - - - Extends , allowing Texture Bake Elements to provide a bitmap background color. - - - - - Get the background color of the bitmap to be created. - - - The background color - - - - - Extention to in 3ds Max 8. - - - Extends , allowing Texture Bake Elements to provide parameters of integer, float, and color types in addition to booleans. The RTT dialog is updated to display spinners and color swatches accordingly - - - - - Allows for getting the bake element parameters as seen in the RTT dialog. - - - Parameter value of TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_FRGBA_BV, or TYPE_VOID on error - - Parameter index, 0-based - - - - Allows for settings the bake element parameters as seen in the RTT dialog. - - - - Parameter index, 0-based - Parameter value of TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_FRGBA_BV - - - - Allows the bake element to specify a minimum value for int and float parameters. - - - Minimum parameter value, of TYPE_INT or TYPE_FLOAT - - The parameter index, 0-based - - - - Allows the bake element to specify a maximum value for int and float parameters. - - - Maximum parameter value, of TYPE_INT or TYPE_FLOAT - - The parameter index, 0-based - - - - Implements icon support for icon images stored as image files on disk, or compiled resources in .rcc files. - - - This class supports two types of icons: legacy icons that are stored as image list ".bmp" files in 3ds Max's UI directory, and multi-resoution icons that support 4K / high DPI displays. - This class is used by the macroScript facility in MAXScript to specify icons. See the MAXScript documentation for "macroScript" for the exact meaning of the filename and index and details. - - - - - Returns the directory of the icon. - - - - - Returns the index of the icon in the image file list. - - - - - Returns the name of the multi-resolution icon. - - - - - Tells the icon to limit color correction. - - - - - Tells the icon to limit color correction. - - - - - /return Returns the full path of a Bmp icon file. - - - - - Description: - This abstract class represents an icon image for toolbar buttons, icons in list boxes, etc. The class is based on Win32 ImageLists. MaxIcons must provide an image list and index into the list for both large (24x24) and small (16x15 or 16x16) icons. - - - - - Returns the handle to the image list for the size of icons that the user has chosen. - - - - - Returns the image list for small icons. - - - - - Returns the image list for large icons. - - - - - Returns the zero based index into the image list for the small version of this particular icon. - Parameters: - bool enabledVersion = true - - Pass true to get the index of the enabled version of the icon; false to get the disabled version. - - GetCustSysColor(COLOR_BTNFACE)COLORREF backgroundColor = - - The background color to use for the icon. - - Specifies the windows color definition. See Standard Color IDs. For a full list of windows color definitions, please refer to the Win32 API, in particular the methods GetSysColor() and SetSysColor(). - - - - - Returns the zero based index into the image list for the large version of this particular icon. - Parameters: - bool enabledVersion = true - - Pass true to get the enabled version of the icon or false to get the disabled version. - - GetCustSysColor(COLOR_BTNFACE)COLORREF backgroundColor = - - The background color to use for the icon. - - Specifies the windows color definition. See Standard Color IDs. For a full list of windows color definitions, please refer to the Win32 API, in particular the methods GetSysColor() and SetSysColor(). - - - - - This method returns true if the icons has an alpha mask that needs to be blended with the background color and false if it doesn't use an alpha mask. - - - - - Helper class for setting locale temporarily. - - - This helper class switches the locale settings to the desired value for the current scope (such as a function call), and restores the previous locale setting at the end of that scope. Use an instance of this class when you need to write or read data such as floating point, date and time values in a locale independent way, but the APIs do not take a locale parameter. - - - - - Resets locale setting to original value, before the object goes out of scope. - - - - - A class that allows a user to access the new max mixers in max 8. - - - This class allows the user to create, access, and remove max mixes from the mixer. The class exists in the scene as a single global variable, TheMaxMixerManager. - - - - - Returns the of Max Mixers in the mixer. - - - The number of Max Mixers in the mixer. - - - - - Get's the Nth max mixer. - - - The mixer interface for this max mixer. - - The index of the interface that's returned. If the index is less than zero or greater than the number of max mixers, then NULL will be returned. - - - - Get's the max mixer that has this node in it. - - - The mixer interface for this max mixer. - - Get the max mixer that this node in it. If this node isn't in any mixers, then NULL will be returned. - - - - Remove the nth max mixer from the mixer, and subsequently either collapse the mixed animation onto the the old max mixer nodes, or replace the animation with the original animation that was there. - - - - The index of the max mixer to be removed. If the index is less than zero or greater than the number of max mixers, then nothing will happen. - If TRUE the mixer will collapse and replace the mixer driven controllers with the values set in the mixer, otherwise it will replace the driven with the original controllers and their values, when the nodes were added to the mixer. - If TRUE the mixer will collapse with a keyperframe, if FALSE, the collapse will try to collapse individual keyframes from the clips instead. - - - - Add a new max mixer to the mixer using a set of nodes. - - - Will return false if the nameOfMix parameter specifies a name of a mix that already exists, and will return true if the max mixer is successfully created. - - The nodes to be added to the mixer. - The name of the max mix. Note that if the name already exists the function will return false and the new max mix won't be created. - - - - Add a new max mixer to the mixer via list of nodes and specific tracks you want to add. - - - Will return false if the nameOfMix parameter specifies a name of a mix that already exists, otherwise if the mix is created successfully it will return true - - A tab of the structures to be added to the mixer. This provides more flexibility in specifying which tracks you really want to be mixed or not. is defined in Note that if a node is found in another mix we will delete it, and the resulting nodeAnims tab after the function call will contain those nodeAnims currently still existing in the maxObject. - - - - Description: - The class serves as the base class for and should be treated as the exception handler when using the Network Rendering API. - - - - - This method returns the error. See the list of error codes for details. - - - - - This method returns the error. See the list of error codes for details. - - - - - This method returns the error description string. - - - - - Description: - If you want to use the call back mechanisms provided by the class, you create your own class derived from and pass it as the argument for MaxNetManager::SetCallBack(). All methods are optional. You need only to implement those you want. - - - - - This method is called whenever a lengthy operation is under way. This includes large block transfers, file transfers, etc. - Parameters: - int total - - A total amount of information to process. - - int current - - From the total amount, this is the current position. - TRUE if you want to cancel the operation, otherwise FALSE. - - - - - This method is called to provide a textual message regarding the current process which is under way (connecting to a Manager, waiting for a reply, etc.) - Parameters: - const MCHAR* message - - The text message. - - - - - This method is called for messages which are sent to indicate that the Manager was shut down and is no longer available to service any requests. - - - - - This method is called to indicate something has changed. This message is sent whenever a new job is sent to the queue, a Server changed its state, an error occurred, etc. This allows you to be kept up to date without the need to poll the Manager from time to time. Note that these messages are queued up. That is, if 10 jobs are deleted at once or any number of changes occur within a short period, you will only receive one Update() call. - - - - - This method is called if someone requests control over the queue. If you do not have control over the queue, you do not need to respond to this message. If you have control over the queue and do nothing when this call is received, the Manager will timeout and take control over the queue. If you have control over the queue, you should respond to this message using MaxNetManager::GrantManagerControl() passing either a true value, indicating you are granting control, or a false value, indicating you do not want to relinquish control. - Parameters: - MCHAR* station - - The name of the computer requesting control. - - - - - This method is called in order to notify that someone took control of the queue. - - - - - Network . - - - - - Description: - The class provides all the methods to interact with the network rendering functions provided and acts as your primary interface. The API provided through the allows clients to connect to the Network Rendering Manager and perform any and all functions available. It encapsulates all the networking details leaving the client code to concentrate on whatever it needs to do. The API handles all networking code and the intricacies of the communication protocols used by the lower layers. This class is derived from the class which is solely used for exception handling as shown below. - - - Sample Code: - - - - - Sets a callback method to receive information updates about various asynchronous events from the API. It is not required to set up this callback. - Parameters: - MaxNetCallBack* mgr - - Points to a object. - - - - - This method will broadcast a message to the local area network in order to look for a Manager. If a Manager is found, the method returns its name in manager. - Parameters: - short port - - Specifies which port will be used to access the Manager. Unless there is a specific reason to use a particular port, use the default DF_MGRPORT. - - char* manager - - A string representing the name of the Manager will be put into this variable. The variable itself should be MAX_PATH in size. - - char* netmask - - Specifies which local area network mask should be used for the scope of the broadcast. The default of 255.255.255.0 should work for most networks that are not divided into subnets. - true if a Manager is found, otherwise false. - - - - - This method allows you to connect to a Network Rendering Manager. - Parameters: - short port - - Specifies which port will be used to access the Manager. Unless there is a specific reason to use a particular port, use the default DF_MGRPORT. - - char* manager - - A string representing the name or IP number of the Manager you want to connect to. The network name requires the network to have some form of name to address translation. It is recommended to use the name provided by MaxNetManager::FindManager(). - - bool enable_callback = false - - This parameter enables or disables asynchronous messages from the Manager. If you connect to the Manager in order to collect information about the network queue then it is recommended to enable (set to true) this parameter in order to keep your lists updated. Otherwise you have to poll the Manager at various times to check for changes. When enabled calls will be received though the mechanism informing you whenever a new job has been completed, an error has occurred, a Server has changed, etc. - - - - - This method will cause a disconnect from the currently connected Manager. - - - - - This method allows basic information about the Manager to be collected. - Parameters: - ManagerInfo* info - - A pointer to the Manager information. - - - - - This method will shut down the Manager and shut off the entire system. - TRUE if successful, otherwise FALSE. A reason for failure might be because this method is called without having the proper Manager rights such as operating in read only mode. Further explanation can be found in the TakeManagerControl() method. - - - - - This method toggles updates from the Manager. For this method to function you will need to enable the enable_callback in MaxNetManager::Connect(). The use of this method allows you to temporarily disable updates from the Manager which might be useful in a situation when you are submitting many jobs at once or executing any other large number of changes. Instead of receiving updates for all changes, you would temporarily disable the callbacks so you could execute your many changes and when done, re-enable the callbacks. - Parameters: - bool enable - - TRUE or FALSE to enable or disable, respectively. - - - - - This method queries the Manager to check if you can take control of the queue. If no one has the queue control, it will immediately return true. If someone else has control, the Manager will ask the controlling client if it wants to relinquish control. If relinquished, the method returns true, if control is not relinquished the method will return false. - Backburner monitor must not be launched as it keeps the queue control while running ! - Parameters: - bool wait - - This parameter can be set to true in order to wait for an answer in case someone has control over the queue, causing this method not to return until it receives an answer from the controlling client. If there is no response from the controlling client, the method will time out in 10 seconds after which it will return true to allow a request for queue control. - TRUE if allowed to request queue control, otherwise FALSE. - - - - - This method allows the acquisition of control of the queue. Actually it does a QueryManagerControl( false); - TRUE if control is granted, otherwise FALSE. - - - - - This method allows you to issue a grant or deny response to a message. If you are the controlling client while another client wants control of the queue by calling the QueryManagerControl() method you will receive a message through the mechanism. If you do not respond, control will be taken away from you automatically after 10 seconds and granted to the requesting client. - Parameters: - bool grant - - This parameter allows you to respond TRUE to relinquish control of the queue or FALSE if you do not want to relinquish control. - - - - - This method allows you to temporarily lock the queue control when performing a series of changes and don't want to get interrupted. While the queue control is locked, no queries are made. They all return false to prevent anyone from taking control of the queue. This method can only be called if you already have queue control. Please, do not forget to unlock the queue control after you are done performing your changes. - Parameters: - bool lock - - this parameter to TRUE if you want to lock the queue or FALSE if you want to unlock the queue. - TRUE if queue control could be locked, otherwise FALSE. - - - - - This method returns the number of clients currently connected to the Manager. - - - - - This method allows you to list all the clients currently connected to the Manager. - Parameters: - int start - - The first client in the list to return. - - int end - - The last client in the list to return. - - ClientInfo* clientList - - The array to receive the list of clients. This array should be large enough to receive the number of clients requested. - The actual number of clients inserted in clientList. This could be either equal to the amount requested or less (if some client disconnected from the Manager). - - - - - This method returns the number of jobs in the queue. - - - - - This method allows you to list all the jobs in the queue. - Parameters: - int start - - The first job in the list to return. - - int end - - The last job in the list to return. If you want the entire list of jobs at once set the start and end to 0 and -1, respectively. - - JobList* jobList - - The array to receive the list of jobs. This array should be large enough to receive the number of jobs requested. - The actual number of jobs inserted in jobList. This could be either equal to the amount requested or less. - - - - - This method allows you to get a single record for the jobList given the specified job handle. - Parameters: - HJOB hJob - - The job handle. - - JobList* jobList - - A pointer to a structure for the received job. - - - - - This method allows you to get an individual job description structure. - Parameters: - HJOB hJob - - The job handle. - - Job* job - - A pointer to a structure for the received job. - - - - - Use this method to request the for a particular job. (See the class description for an explanation). Some job information are random both in number as they are in size. The job description structure () will only show static elements. In order to get dynamic elements or elements with variable length, the class is used. - Parameters: - HJOB hJob - - The job handle. - - CjobText& jobText - - A reference to a class to receive the information. - - int count - - The number of elements you are interested in receiving. The number of elements can be found in Job.jobtextcount. - - - - - This method submits changes to an existing job. Once you collect a job, you can change settings in both the structure as in the elements and send it back so the changes can be applied. - - Note that you must use a Getjob() and SetJob() combination in order to make sure all the elements are correct. The Manager will automatically complete some of the structure members. It is not possible to create a new structure, fill in the data, and submit it. You can only do that when submitting a new job, which is then handled by a different set of methods. - Parameters: - HJOB hJob - - The job handle. - - Job* job - - A pointer to the job description. - - & jobText - - A reference to a class with the description of elements. - - bool reset - - This flag indicates whether or not the job is started from scratch. If set to FALSE it will continue from the current stage. - - - - - This method returns the job priority value for the specified . - Parameters: - HJOB hJob - - The handle to the job for which to obtain its priority - - - - - This method allows you to set the priority of a specified job. - Parameters: - HJOB hJob - - The handle to the job for which to obtain its priority - - int priority - - The priority value you want to assign to the job. - TRUE if the priority as set successfully, otherwise FALSE - - - - - This method allows you to set the job order for a specific job. - Parameters: - HJOB hJob - - The handle to the job for which to obtain its priority - - DWORD count - - The job order index. - - - - - This method will delete a job from the queue permanently and remove all files related to the job. - Parameters: - HJOB hJob - - The job handle. - - - - - This method will suspend a specific job. This method is the opposite of ActivateJob(). - Parameters: - HJOB hJob - - The job handle - - - - - This method will activate a specific job. This method is the opposite of SuspendJob(). - Parameters: - HJOB hJob - - The job handle - - - - - This method will return the number of Servers assigned to a given job. - Parameters: - HJOB hJob - - The job handle - - - - - This method will return a list of the Servers assigned to a given job. - Parameters: - int start - - The first Server in the list to return. - - int end - - The last Server in the list to return. If you want the entire list of servers at once set the start and end to 0 and -1, respectively. - - HJOB hJob - - The job handle. - - JobServer* servers - - The array to receive the list of Servers. This array should be large enough to receive the number of Servers requested. - The actual number of Servers inserted in servers. This could be either equal to the amount requested or less. - - - - - This method allows you to obtain the textual status of a specific Server for a given job. The structure return by GetJobServers() will only describe the status of a Server using a flag. If the flag shows the Server status is "Error", you can use this method to receive a more descriptive text message, like "Could notwrite to d:/path/file.tga". - Parameters: - HJOB hJob - - The job handle. - - hServer - - The Server handle. - - MCHAR* status_text - - A pointer to a string to receive the message. This string should be MAX_PATH long. - - size_t status_text_size - - The size in characters of the status_text buffer. If the buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - - - - - - This method will suspend a specific Server for a given job. The Server will stop working with the given job and start working on another one, provided another job exists. Use the AssignJobServer() to reactive it. - Parameters: - HJOB hJob - - The job handle. - - hServer - - The Server handle. - - - - - This method can be used to assign a Server to a given job. - Parameters: - HJOB hJob - - The job handle. - - hServer - - The Server handle. - - - - - This method will return the number of frames for a given job. - Parameters: - HJOB hJob - - The job handle. - - - - - This method will return a list of frames for a given job. - Parameters: - int start - - The first frame in the list to return. - - int end - - The last frame in the list to return. If you want the entire list of frames at once set the start and end to 0 and -1, respectively. - - HJOB hJob - - The job handle. - - JOBFRAMES* frames - - The array to receive the list of frames with information for each individual frame. This array should be large enough to receive the number of frames requested. - The actual number of frames inserted in frames. This could be either equal to the amount requested or less. - - - - - This method will return the log file for a given job. - Parameters: - int start - - The first log file line to return (base zero, 0 is the first line). - - int count - - The number of lines (rows) to return. If you want the whole file at once, set start to 0 and count to -1. Alternatively, if you want any lines added since the last time you call, set start to the last line you collected + 1 and count to -1. - - HJOB hJob - - The job handle. - - MCHAR** buffer - - A pointer to a MCHAR array to receive the lines of the log file. The buffer will be allocated so it will accommodate the incoming data. This array should be freed using LocalFree() when you are finished. - The size of the allocated buffer. This is the size of the entire buffer including the last NULL terminating byte. If GetJobLog() returns 0, it means there are no new log file lines available. - - - - - When submitting a job, you can use this method to find out if the Manager can write a given output image file. This is usually the case when you have the output image file set to a local drive. The other participants in the network rendering may not be able to "see" this path and they will eventually fail. This test is not guaranteed as the Servers may have a different set of rights than the Manager, in which case the Manager might fail the write test while the Servers would have no problem otherwise. - Parameters: - MCHAR* output - - The output image file name you want to check. This is the full path and filename (i.e. d:/badpath/file.tga). - - MCHAR* err - - A MCHAR string to receive the error message if one exists. This will explain why the test failed (such as path not found, access denied, etc.) - TRUE if the Manager could write to the given path, otherwise FALSE. - - - - - This method allows you to assign a new job to the network queue. - Parameters: - Job* job - - The job structure containing the information about the job. See the structure description for an explanation. - - MCHAR* archive - - The full path and filename of the archive containing the job files. This is the "*.maz" file created by the Maz() function in the API. - - HSERVER* servers - - An array containing the Servers assigned to this job. If the job flag is set to "use all Servers" and job.servercount is zero, this argument can be NULL (ignored). Otherwise it should be an array job.servercount * sizeof(HSERVERS) long with the list of Servers to assign to this job. - - & jobtext - - A reference to a class with the proper elements. - - DWORD blocksize - - An optional alternate block size to use for network transfers. If blocksize is set to zero, the API will use the default DF_READCHUNK. You may want to set this to something smaller if you are running over slow connections such as a modem connection. You may want to make it larger if you have a high performance network. This number will determine how large of a block of data to send at once to the Manager. - - - - - This method will return the number of Servers registered with the Manager. - - - - - This method allow you to list the Servers registered with the Manager. - Parameters: - int start - - The first Server to return. - - int end - - The last Server to return. - - ServerList* serverList - - The array to receive the list of Servers. This array should be large enough to receive the number of Servers requested. - The actual number of Servers inserted in serverList. This could be either equal to the amount requested or less. - - - - - This method allows you to get a Server and retrieve a single record in the serverList given - - the Server handle. - Parameters: - hServer - - The handle to the Server. - - ServerList* serverList - - A pointer to the in which to retrieve the Server. - - - - - This method allows you to delete a Server from the Manager's Server list. You can not delete an active Server (i.e. a Server which is currently working on a job). - Parameters: - HSERVER* hServer - - The Server handle. - TRUE if the server is successfully deleted, otherwise FALSE. - - - - - The Manager keeps a performance index for each Server. This index is computed based on the Server performance while rendering frames. All factors are taken into consideration such as the time it takes to load a job, the time it takes to process requests, the time it takes to render a frame, the memory and CPU load, etc. This index is in turn used internally to determine the best distribution of workload. You can use this method to reset a Server's performance index. - Parameters: - HSERVER* hServer - - The Server handle. - TRUE if resetting the Server's performance index was successful, otherwise FALSE. - - - - - This method allows you to obtain a given Server's weekly schedule structure. - Parameters: - HSERVER* hServer - - The Server handle. - - WeekSchedule* schedule - - A pointer to a structure to receive the schedule. - - - - - This method allows you to set a given Server's weekly schedule structure. - Parameters: - HSERVER* hServer - - The Server handle. - - WeekSchedule* schedule - - A pointer to a structure with the new weekly schedule. - - - - - This method allows you to obtain the network status for a given server. This method mostly serves as means to check network diagnostics. - Parameters: - HSERVER* hServer - - The Server handle. - - NetworkStatus* net_stat - - A pointer to a structure to receive the status data. - - - - - This method will return the number of Server groups. - - - - - This method will return the number of Servers for a given Server group. - Parameters: - int group - - The zero based index into the Server group list. - - - - - This method allows you to obtain a Server group. - Parameters: - int group - - The zero based index into the Server group list. - - int count - - The number of Servers to send, in order to define the size of the grplist. - - HSERVER* grplist - - The array in which the list of Servers will be returned. This array should be large enough to accommodate count Servers. - - MCHAR* name - - The name of the Server group. This string must be at least MAX_PATH long. - The number of Servers collected. - - - - - This method allows you to submit (create) a new Server group. - Parameters: - int count - - The number of Servers in the list. - - HSERVER* grplist - - The array containing count Servers. - - MCHAR* name - - The name of the server group. - - - - - This method allows you to delete a given Server group. - Parameters: - int group - - The zero based index of the Server group to delete. - - - - - Prepare an OpenVDB volume and return a handle to it - Parameters: - true if successful, false if not - - (out) Unique handle that will refer to this volume. Use DisposeVolume to dispose of the volume when you are finished with it. NOTE: All volumes are automatically disposed of on reset. - (in) The voxel size that this volume uses - (in) The half-width for the level set - - - - Copy one OpenVDB volume to another - Parameters: - true if successful, false if not - - The handle of the VDB volume to clone - (out) Unique handle that will refer to the volume's clone - - - - Retrieve information from an OpenVDB .vdb file - Parameters: - true if successful, false if not - - (in) The .vdb file name - Returns the number of grids in the .vdb file - Returns a table with a grid type per grid in the file - - - - Loads a volume grid from a .vdb file - Parameters: - true if successful, false if not - - (in) Handle of the VDB volume that will receive the loaded grid - (in) The .vdb file name - (in) The index of the grid to load into the volume - - - - Save an OpenVDB volume to a .vdb file - Parameters: - true if successful, false if not - - (in) Handle of the VDB volume that contains the grid to save - (in) The .vdb file name - (in) The name to assign the volume grid in the .vdb file - - - - Delete an OpenVDB volume from memory - Parameters: - true if successful, false if not - - Handle of the VDB volume to delete - - - - Perform a operation on OpenVDB volumes - Parameters: - true if successful, false if not - - Handle of the VDB volume that contains operand A and will receive the result - Handle of the VDB volume that contains operand B; empty after the operation. - The operation type. - - - - Dilate a volume by a given amount, with optional masking - Parameters: - true if successful, false if not - - Handle of the VDB volume that will be dilated - Amount to dilate the volume - (Optional) Handle to a volume containing masking data (0-1); should match gridHandle volume topology. - - - - Erode a volume by a given amount, with optional masking - true if successful, false if not - - Handle of the VDB volume that will be eroded - Amount to erode the volume - (Optional) Handle to a volume containing masking data (0-1); should match gridHandle volume topology. - - - - Perform filtering (smoothing) on a volume - Parameters: - true if successful, false if not - - Handle of the VDB volume that will be filtered - The filter type to use. - - - - Clears a volume to empty - Parameters: - true if successful, false if not - - Handle of the VDB volume that will be cleared - - - - Convert a volume to a mesh - Parameters: - true if successful, false if not - - Handle of the VDB volume that will be meshed - (out) The that will receive the meshed result - (in) The transform of the volume - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Create a mask volume to match a given volume - Parameters: - true if successful, false if not - - Handle of the VDB volume that the mask will be created for - The voxel size to use in the meshing operation - (in) The transform of the volume - The threshold value for the map - (in) The texmap that will be the source of the mask data - The time to use for the sampling - The that will receive the resulting mask data - - - - Creates an SDF volume containing points of a fixed size - Parameters: - true if successful, false if not - - (in) A table of pointers, one per point - The radius to use for all points - The voxelsize to use for the volume - The handle of the volume that will receive the resulting data - - - - Creates an SDF volume containing points of a fixed size - Parameters: - true if successful, false if not - - (in) A table of Point3s, one per point - The radius to use for all points - The voxelsize to use for the volume - The handle of the volume that will receive the resulting data - - - - Creates an SDF volume containing points of varying sizes - Parameters: - true if successful, false if not - - (in) A table of pointers, one per point - (in) Table of radii, one per point - The voxelsize to use for the volume - The handle of the volume that will receive the resulting data - - - - Creates an SDF volume containing points of varying sizes - Parameters: - true if successful, false if not - - (in) A table of Point3s, one per point - (in) Table of radii, one per point - The voxelsize to use for the volume - The handle of the volume that will receive the resulting data - - - - Converts a mesh to a volume - Parameters: - true if successful, false if not - - (in) A mesh to convert to a volume - The voxelsize to use for the volume - The handle of the volume that will receive the resulting data - (in) Transform to apply to the mesh - - - - Creates an SDF volume containing points of a fixed size and outputs the result to a mesh - Parameters: - true if successful, false if not - - (in) A table of pointers, one per point - The radius to use for all points - The voxelsize to use for the volume - (out) The mesh that will receive the resulting data - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Creates an SDF volume containing points of a fixed size and outputs the result to a mesh - Parameters: - true if successful, false if not - - (in) A table of Point3s, one per point - The radius to use for all points - The voxelsize to use for the volume - (out) The mesh that will receive the resulting data - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Creates an SDF volume containing points of varying sizes and outputs the result to a mesh - Parameters: - true if successful, false if not - - (in) A table of pointers, one per point - (in) Table of radii, one per point - The voxelsize to use for the volume - (out) The mesh that will receive the resulting data - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Creates an SDF volume containing points of varying sizes and outputs the result to a mesh - Parameters: - true if successful, false if not - - (in) A table of Point3s, one per point - (in) Table of radii, one per point - The voxelsize to use for the volume - (out) The mesh that will receive the resulting data - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Converts a mesh to a volume then back to a mesh (round trip) - Parameters: - true if successful, false if not - - (in) The mesh to convert - The voxelsize to use for the volume - (out) The mesh that will receive the resulting data (may be the same as the input mesh) - The amount of adaptivity to apply during meshing (0-1) - When true, relaxes disoriented triangles during adaptive meshing - - - - Test whether a given point in space is inside a level set - Parameters: - true if successful, false if not - - Handle of the VDB volume to test - (in) The point to test - (out) Returns true if the point is inside the level set; false if not - - - - Test a set of points in space to see which are inside a level set - Parameters: - true if successful, false if not - - Handle of the VDB volume to test - (in) A table of the points to test - (out) Returns a where the corresponding bit for each supplied point is TRUE if the point is inside the level set; FALSE if not - - - - Test a set of points in space to see which are inside a level set - Parameters: - true if successful, false if not - - Handle of the VDB volume to test - (in) A table of pointers to the points to test - (out) Returns a where the corresponding bit for each supplied point is TRUE if the point is inside the level set; FALSE if not - - - - Description: - This is the RenderElement base class for 3ds Max' default scanline renderer. RenderElement plugins that utilize and should sub-class from here. All render elements that support the 3ds Max renderer should derive from this class. The class implements a handler for the ShadeOutputIndex of the elements value in the array. Access to the element's value is accomplished within PostIllum or PostAtmosphere by: - - - - A sample plugin of a Render Element can be found in the SDK samples; /MAXSDK/SAMPLES/RENDER/RENDERELEMENTS. - Data Members: - protected: - - int mShadeOutputIndex; - - The index into element value array in shadeOutput class. - - - - - This method gets the index into the element array in the class. This method is implemented by this base class & need not be re-implemented by derivative classes. Derivative classes access the index either through the interface or directly as mShadeOutputIndex. is used by the system to assign an index to each element. This index persists throughout a single rendering. - - - - - This method will update the element to time timeValue. Note that most elements don't care. - - Update is called to communicate the time to the element. It will be called on each element before the call to PostIllum() is executed. No current render element uses this, but it could prove useful someday. This class provides a default stub implementation, so this need not be implemented unless needed. - Parameters: - TimeValue timeValue - - The timevalue at which the update gets called. - - - - - This method is used to compute the element and store the result in the 's . - - This is the first of the actual computation methods for the render element. PostIllum() is called by the material just after an illumination is computed for a fragment. Some materials, like the multi-materials don't compute illumination themselves but mix illuminations from other leaf materials. Such materials do not call PostIllum(), but need to consider the elements when blending the shadeoutputs from the leaf materials. The is the same shadecontext passed into the material's shade method, & contains the member variable 'out', which is the current output from the full pixel shading and the storage place for renderElement values. - - The other param, , contains detailed information about the shading process. Specifically, the component-wise output from the shading process is available in the . Also the illumParams passed in are dependent on whether the element has requested shadows or not. The standard material keeps two sets of these and supplies the one requested. This method must be implemented, though some elements merely stub it out or clear the output element value. It should put it's output in ShadeOutputIndex() ]. Even if you do not need this function, it is a good idea to clear the element val. - Parameters: - & sc - - A reference to the . - - & ip - - A reference to the . - - - - - This is the second computation method and is only called if the elements has atmospheres applied. If it is applied, then the element value is retrieved from the shadeContext, the atmosphere is applied to it & and the output from the atmosphere is left in sc.out.c and sc.out.t. Last, PostAtmosphere is called with the shadeContext, and the 2 z values used by the atmosphere to compute it. If the point is directly visible to the camera, then prevZ will be 0.0f, otherwise it is the z of the next closest obscuring transparent fragment in front of the fragment being shaded. It is up to the render element to process the output in sc.out.c and save the result in ShadeOutputIndex() ]. Note that when PostAtmosphere is called, the original value set by PostIllum is saved in the element val. This can be overwritten or used in some computation. For example, to separate atmosphere from the composite color, sc.out.c and ShadeOutputIndex() ] can be differenced. - Parameters: - & sc - - A reference to the . - - float z - - The first depth value. - - float prevZ - - The previous depth value. - - - - - Specifies whether this render element is compatible with the Default Scanline and should show up in the Render Element Dialog for the Scanline . - - Several render elements derive from class but are not actually compatible (or useful) in the Default Scanline . In the past, 3ds Max only checked if the class exposed the interface to decide if it should show up in the render element dialog for the Scanline renderer, which cluttered this dialog up with many elements that actually are not applicable. Therefore, this method was added, and it returns TRUE if the element is actually meaningful in Scanline. By returning FALSE here, you can avoid having your render element appear in the render element selection dialog for the Scanline renderer. It only affects visibility in this dialog, and does not affect the functionality. - - - - - Exception thrown if a script calls quitmax resulting in 3ds Max shutting down Code that handles via code looking like: should add handling of : The implementation of ProcessMAXScriptException simply returns if the exception passed is a . So if your catch handling doesn't do anything other than call ProcessMAXScriptException the explicit catch of is not strictly necessary, but is recommended for clarity. The 3ds Max user interface has been taken down by the time this exception has been raised, so plugins must not access it. - - - - - interface class used to access Max volumes for rendering, etc. - - - - - Query for primary volume type. Some volumes may be primarily level sets; others may be primarily fog volumes. This method lets the consumer query for this and, for example, only work with objects which are fog volumes. - true if the primary grid type is a fog volume. - - - - - Fills in the array with the names of the fog volume grids (if any). - Parameters: - MaxSDK::Array<MSTR>& fogVolumeGridNames (out) - is filled in with the names of all fog volume grids - - - - - Fills in the array with the names of the level set grids (if any). - Parameters: - MaxSDK::Array<MSTR>& levelSetGridNames (out) - is filled in with the names of all level set grids - - - - - Fills in the array with the names of the velocity grids (if any). - Parameters: - MaxSDK::Array<MSTR>& velocityGridNames (out) - is filled in with the names of all grids that represent velocity - - - - - Query the object to see if it has an in-memory OpenVDB grid cache that is capable of streaming - true if the object has in-memory grids it can stream. - - - - - Query the object to see if it has its own cache file. - true if the object has OpenVDB grids on disk in .vdb files. - - - - - If the object has its own cache file, this retrieves its name for a given time along with validity. - Parameters : - TimeValue t - The time to use for the data & valid(in/out) - The validity interval of the data (updated for the current time) - the name of the OpenVDB .vdb cache file. - - - - - If the object doesn't have its own cache file, this will build one with all grids for us, placing it in the specified filename - Parameters : - MSTR& filename (in) - The name of the file that should receive the OpenVDB grid data TimeValue t - The time to use for the data & valid(in/out) - The validity interval of the data (updated for the current time) - true if the file was saved, false otherwise. - - - - - If the object doesn't have its own cache file, this will build one with all specified grids for us, placing it in the specified filename. - Parameters : - MaxSDK::Array<MSTR>& channelNames (in) - The names of the grids to save MSTR& filename (in) - The name of the file that should receive the OpenVDB grid data TimeValue t - The time to use for the data & valid(in/out) - The validity interval of the data (updated for the current time) - true if the file was saved, false otherwise. - - - - - Get the shader assigned to this volume (if any). - Parameters : - TimeValue t - The time to use for the shader - The material pointer to the shader if the object has one; nullptr otherwise. - - - - - Get the bounding box for the volume at the specified time. - Parameters : - TimeValue t - The time to use - The bounding box of the object. - - - - - Get the validity interval for the volume at the specified time. - Parameters : - TimeValue t - The time to use - The validity interval for the object. - - - - - Description: This class allows referenceTargets that are not INodes to be mergeable through the File->Merge command. - The referenceTarget that you want to be mergeable must derive from . You just then need to override GetMergeableRef, GetMergeableRefName, and PostMerge. - Code Example to make the Brightness/Contrast effect mergeable. - You would derive your class from the - Then make sure you return the from GetInterface when it is asked - Next just need to implement GetMergeableRef and GetMergeableRefName which return the data needed to do the merge - Finally you just need to implement PostMerge where you do your work to hook back up - your reference after the merge - - - - - This needs to be implemented to return the that will be mergeable. This is the that is derived from . If it does not derive from , PostMerge will not be called on it after merging. - - - - - This returns the name that you want to appear in the merge list box - - - - - This is called after the reference has been merged. At this point it needs to be attached to something otherwise it will be lost. For instance if this was an effect it would have to be attached to scene graphs effects list. - - - - - This is called before saving. If you are in a state where you don't need to be saved, then return false. - Otherwise by default this returns true. - - - - - The name returned from GetMergeableRefName() will be made unique in the merge list box, unless this is implemented to return false. - - - - - The class is provided for use by plug-ins and is used by the system. It is the data structure for meshes in the system and maintains pointers to the vertices, faces, texture vertices, etc. It provides methods to handle most of the functionality that procedural objects must implement. All methods of this class are implemented by the system. See the Meshes section for more information. Note 1 : There is a set of classes for working with parts of a mesh such as its face structure, element structure, and cluster structure. For details see: Class , Class , Class , Class . - List of deprecations from 3dsMax 2024: - - - - - Get the object material. - - - - - Sets the number of geometric vertices in the mesh. - TRUE if storage was allocated and the number of vertices was set; otherwise FALSE. - - Specifies the number of vertices. - Specifies if the previous vertices should be kept. If TRUE the previous vertices are kept; otherwise they are discarded. Defaults to FALSE. - This parameter is available in release 2.0 and later only. If TRUE the selection set BitArrays are resized to fit the number of vertices; otherwise they are left unaltered. Defaults to TRUE. - - - - Returns the number of vertices. - - - - - Sets a single vertex in the verts array. - - A zero based index into the verts array of the vertex to store. - Specifies the coordinate of the vertex. - - - - Sets a single vertex in the verts array. - - A zero based index into the verts array of the vertex to store. - Specifies the X coordinate of the vertex. - Specifies the Y coordinate of the vertex. - Specifies the Z coordinate of the vertex. - - - - Returns the 'i-th' vertex. - - Specifies the index of the vertex to retrieve. - - - - Returns a pointer to the 'i-th' vertex. - - Specifies the index of the vertex address to retrieve. - - - - Returns flags specific to the corresponding vertex in the verts array. Owned by the MaxSDK::MeshGeomChannelData channel. - - Specifies the index of the vertex address to retrieve the flags for. - - - - Sets the number of faces in the mesh. - TRUE if storage was allocated and the number of faces was set; otherwise FALSE. - - Specifies the number of faces. - Specifies if the previous faces should be kept. If TRUE the previous faces are kept; otherwise they are discarded. Defaults to FALSE. - If TRUE the selection set BitArrays are resized to fit the number of faces; otherwise they are left unaltered. Defaults to TRUE. - - - - Returns the number of faces in the mesh. - - - - - Returns the 'i-th' face. - - Specifies the index of the face to retrieve. - - - - Returns a pointer to the 'i-th' face. - - Specifies the index of the face address to retrieve. - - - - Sets the number of texture vertices (in mapping channel 1). - TRUE if storage was allocated and the number of texture vertices was set; otherwise FALSE. - - Specifies the number of texture vertices. - Specifies if the previous texture vertices should be kept. If TRUE the previous texture vertices are kept; otherwise they are discarded. Defaults to FALSE. - - - - Returns the number of texture vertices (in mapping channel 1). - - - - - Sets the number of TVFaces. This method is automatically called if you set the number of faces to keep these two in sync (because the number of TVFaces should be the same as the number of faces). The following rules apply: If you have no TVFaces and keep is TRUE then the TVFaces array stays empty. If you have no TVFaces and keep is FALSE they are allocated. If you have TVFaces and ct = 0 then the TVFaces are freed. - TRUE if storage has been allocated and the number is set; otherwise FALSE. - - The number of TVFaces. - Specifies if the old faces should be kept. - The length of the existing TVFaces array. - - - - Sets a single texture vertex in the tVerts array. - - A zero based index into the tVerts array of the texture vertex to store. - Specifies the coordinate of the vertex. - - - - Sets a single texture vertex in the tVerts array. - - A zero based index into the tVerts array of the texture vertex to store. - Specifies the X coordinate of the texture vertex. - Specifies the Y coordinate of the texture vertex. - Specifies the Z coordinate of the texture vertex. - - - - Returns the 'i-th' texture vertex. - - Specifies the index of the texture vertex to retrieve. - - - - Returns a pointer to the 'i-th' texture vertex. - - Specifies the index of the texture vertex address to retrieve. - - - - Sets the number of color per vertex vertices. - TRUE if the value was set; otherwise FALSE. - - The number of color vertices to set. - If TRUE previous values are kept; otherwise they are discarded. - - - - Returns the number of color per vertex vertices. - - - - - Sets the number of color per vertex faces. - TRUE if storage has been allocated and the number is set; otherwise FALSE. - - The number of color per vertex faces to set. - Specifies if the old faces should be kept if the array is being resized. If FALSE they are freed. - The length of the existing VCFaces array. - - - - This method would typically be called right before display, as with a node display callback, or through an extension object. If mapChan parameter is set to MESH_USE_EXT_CVARRAY then the data in VCArray and is stored for internal use and consequent drawing. If the arrays are NULL then the internal source is used. - - the mapping channel to use. - An external array hosting the vertex colors - An external array of indexing into the color array - - - - the number of texture maps used by this . Note that this call is made automatically if Mesh::setMapSupport() is called. - - - The number of texture maps to use. This is a value between 2 and MAX_MESHMAPS-1. - - TRUE to keep the old mapping information after the resize; FALSE to discard it. - - - - Returns the number of mapping channels in use. - - - - - Returns TRUE if the specified mapping channel is supported; otherwise FALSE. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Sets whether the specified mapping channels is supported or not. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - TRUE to indicate the channel is supported; otherwise FALSE. - - - - Sets the number of texture or vertex color vertices for the specified mapping channel of this mesh. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - The number of vertices to allocate. - - If TRUE previous values are kept; otherwise they are discarded. - - - - Returns the number of texture or vertex color vertices for the specified channel of this mesh. - - - Specifies the channel. See "List of Mapping Channel Index Values". - - - - Sets the number of texture or vertex color faces for the specified channel of this mesh. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - The number of faces to allocate. - - If TRUE previous values are kept; otherwise they are discarded. - - The length of the existing VCFaces array. - - - - Returns the number of texture or vertex color faces for the specified channel of this mesh. - - - Specifies the channel. See "List of Mapping Channel Index Values". - - - - Returns a pointer to the list of UVVerts for the specified channel of this mesh. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Returns a pointer to the list of TVFaces for the specified channel of this mesh. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Sets a single texture or vertex color value for the specified channel of this mesh. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - The zero based index of the vertex to set. - - The value to set. - - - - Applies a simple planar mapping to the specified channel. This is done by copying the mesh topology and vertex locations into the map. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Returns a with a bit set for each isolated vertex (un-referenced by any face) for the specified channel. - - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Deletes the map vertices indicated. - - Specifies the channel. See the page "List of Mapping Channel Index Values". - Indicates which map verts should be deleted. set.GetSize() should equal this mesh's getNumMapVerts(mp). - If non-NULL, this points to a that will be filled in with the faces that will need to be deleted or have new map verts assigned because they used a map vert that was deleted. (The size will be set to this mesh's numFaces.) - - - - This method deletes each isolated vertex (un-referenced by any face) for the all active maps. - - - - - This method deletes each isolated vertex (un-referenced by any face) for the specified channel. - - Specifies the channel. See the page "List of Mapping Channel Index Values". The default value of -1 indicates to do all active maps. - - - - Deallocates the texture or vertex color vertices for the specified channel of this mesh. - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - Deallocates the texture or vertex color faces for the specified channel of this mesh. - - Specifies the channel. See the page "List of Mapping Channel Index Values". - - - - This method returns the map for the specified map channel. - Const reference to a . - - - The map channel. - - - - Sets the number of channels of vertex data used. - - The number of elements of vertex data to set. - If TRUE any old vertex data is kept; otherwise it is discarded. - - - - Returns the number of vertex data channels. - - - - - Returns the number of active vertex data channels. - - - - - Returns TRUE if the specified channel of vertex data is available for this mesh; otherwise FALSE. - - The vertex data channel. See the page "List of Vertex Data Index Options". - - - - Sets if the specified channel of vertex data is supported. - - The vertex data channel. See the page "List of Vertex Data Index Options". - TRUE to indicate the channel is supported; FALSE to indicate it's not. If TRUE is specified then numVerts elements are allocated (if needed). If FALSE is specified the data for the channel is freed. - - - - Returns the vdChannel'th vertex data channels. - - - - - Returns a pointer to the vertex data for the specified channel or NULL if the channel is not supported. If supported then the size of this array is numVerts. - - The vertex data channel. See the page "List of Vertex Data Index Options". - - - - Returns a pointer to the floating point vertex data for the specified channel of this mesh or NULL if the channel is not supported. If supported then the size of this array is numVerts. - - The vertex data channel. See the page "List of Vertex Data Index Options". - - - - Deallocates the vertex data for the specified chanel. - - The vertex data channel. See the page "List of Vertex Data Index Options". - - - - Deallocates the vertex data from all the channels and sets the number of supported channels to 0. - - - - - Returns a pointer to the floating point vertex weight data. - - - - - Sets the channel support for the vertex weights channel (VDATA_WEIGHT). - - - - - Clears (deallocates) the vertex weights channel data. - - - - - Deallocates the vertex weights channel data (same as ClearVertexWeights() above). - - - - - Returns a pointer to the floating point vertex selection weights data. - - - - - Sets the channel support for the vertex weights channel (VDATA_SELECT). - - - - - Clears (deallocates) the vertex selection weights channel data. - - - - - Deallocates the vertex selection weights channel data (same as ClearVSelectionWeights() above). - - - - - Returns the state of the smooth flags. See setSmoothFlags() above. - - - - - Flips the surface normal of the 'i-th' face (this just rearranges the indices for the face structure). This also makes sure the edge flags are rearranged as well. If there are UV coordinates they are rearranged appropriately. - - The index of the face to flip. - - - - Unifies the surfaces normals of this . This may be for selected faces, or the entire mesh. - - If TRUE only the selected faces are unified. - - - - Performs an auto smooth on the mesh, setting the smoothing groups based on the surface normals. - - The minimum angle between surface normals for smoothing to be applied, in radians. - If TRUE only the selected faces are smoothed. - This parameter is available in release 2.0 and later only. TRUE to turn on; FALSE to leave off. This matches the option in the Smooth use this to prevent smoothing 'leaks" when using this method. If you use this method, and portions of the mesh that should not be smoothed become smoothed, then try this option to see if it will correct the problem. Note that the problem it corrects is rare, and that checking this slows the Auto Smooth process. - - - - This method removes faces from the face list with the FACE_WORK flag set. - The number of faces deleted. - - - - - Deletes all selected elements of the current selection level. - - - - - Deletes the vertices as specified by the . - - of bits to indicate the vertices to delete. - - - - Deletes faces as specified by the . - - of bits to indicate the faces to delete. - If non NULL then this method will be setup to flag vertices that were isolated by the face deletion. This set can then be passed to to delete isolated vertices. - - - - This method may be called to determine if an equivalent face already exists. - TRUE if an equivalent face already exists; otherwise FALSE. - - Index of the first vertex. - Index of the second vertex. - Index of the third vertex. - - - - Removes faces that have two or more equal indices. - TRUE if any degenerate faces were found; otherwise FALSE. - - - - - Removes faces that have indices that are out of range - TRUE if any illegal faces were found; otherwise FALSE. - - - - - This method returns the normal of the specified face. If nrmlize is TRUE, it makes this normal unit length. Otherwise, it's the edge cross-product length, which is actually 2 times the area of the face. - - Specifies the face whose normal is returned. - Use TRUE to make the normal unit length. - - - - This method returns the center of the specified face. - - Specifies the face whose center is returned. - - - - Returns the angle between two face surface normals in radians. - - Index of the first face. - - an optional parameter to pass in a precomputed face normal list so you can improve performance Index of the second face. - - - - Computes and returns the barycentric coordinates of a point in the plane of a face relative to that face. - The point p barycentric coordinates. If the point p is inside the face the returned values will sum to one. Note: If the face (or set of 3 points) is degenerate, ie if it has a zero length normal vector ((p1-p0)^(p2-p0)), the methods return (-1,1,1). - - The index of the face to check. - The input point. - - - - Tessellates the mesh (or only the selected faces) using the face/center method. This means each face is subdivided by lines from a new vertex at the center to the original vertices. - - If TRUE the entire mesh is tessellated; otherwise only the selected faces. - A callback that can be used for lengthy operations. If you want to get updated on the progress of the operation being performed, pass a pointer to your callback, and the function will call the methods as it progresses. The object can return FALSE to its method to cancel the operation. - - - - tessellates the mesh using the specified tension parameter. This method can operate on the entire mesh or only the selection set. tessellation means that faces are internally subdivided, with additional faces generated from a new vertex in the middle of each face edge. - - The tension setting. This value can range from -100.0 to 100.0. This value matches the parameter in the Editable user interface when tessellating faces. - If TRUE the entire mesh is tessellated; otherwise only the selected faces. - A callback that can be used for lengthy operations. If you want to get updated on the progress of the operation being performed, pass a pointer to your callback, and the function will call the methods as it progresses. The object can return FALSE to its method to cancel the operation. - - - - Extrudes the selected faces. Note that this is just a topological change. The new extruded faces do not change position but are left on top of the original faces. - - If TRUE the faces are extruded. If FALSE then the selected edges are extruded. - - - - Indents the selected faces, in a manner consistent with the outlining used in Bevel. - - The amount to indent. - - - - Splits the vertices specified in the so that they are only used by a single face. - - This array of bits, one per vertex in the mesh. If the bit is set, the corresponding vertex in the mesh is copied as required so it is only used by a single face. If the bit is not set the vertex is ignored. - - - - This method returns a (of size numVerts), where isolated verts are selected. - - - - - Deletes the vertices that aren't used by any faces. - - - - - Creates a copy of the faces and verts used by those faces as specified by the passed. If texture faces and vertex color faces are present they are cloned as well. - - There is one bit in this array for each face in the mesh. If the bit is set, the corresponding face in the mesh is cloned. If the bit is zero the face is not cloned. - - - - Sets bits for all faces in the same polygon with face f. Faces already selected in set will not be processed - so if f is "set", nothing happens. The definition of a polygon is all faces sharing invisible edges with edge angles below "thresh". - - Specifies which face to evaluate the zero based index into the faces array. - Specifies which faces are not processed. One bit for each face with set bits not considered. - The angle in radians which is the threshold for defining a polygon. A polygon is all faces sharing invisible edges with edge angles below this angle. - If TRUE, the edge visibility is ignored but the threshold is still relevant. - This adjacent face list can be passed if there's one handy; otherwise a new one will be computed by the method. - - - - This method sets bits for all faces in the same "element", or connected component, with face f. Faces already selected in set will be considered "walls" for this processing and will not be evaluated. - - Specifies which face to evaluate the zero based index into the faces array. - Specifies which faces are considered as barriers to the element and are not processed. One bit for each face with set bits not considered. - This adjacent face list can be passed if there's one handy; otherwise a new one will be computed by the method. - - - - When faces are deleted in Edit or Editable , we often want to be able to delete the verts that are isolated by this action. This method generates the list of verts that are used only by the specified set of faces. - - This method finds those vertices used only by the faces indicated in this . - This is completely overwritten with the result, and will be set to the right size (numVerts) if needed. - - - - This method fills in a with the edges in the mesh that are "open" or "one-sided". (This is the same as the Edit "Select OpenEdges" function.) - - This will be set to size numFaces*3, and only the open edge bits will be set. - - - - This method calculates, for each vertex, the sum of the angles of this vertex's corner in each face it's on. So for instance, a point lying in the middle of a grid would always have vertex angle 2*PI, whereas a corner of a box would only have 3*PI/2. - - This should be a pointer to an array of size numVerts. The vertex angle for each vertex is put in this array (in radians). - If non-NULL, this points to a describing which vertices to find angles of. If only some bits are set, some computation time is saved. If NULL, all vertices' angles are found. - - - - Returns the mesh render data hung off this . See Class . This method and SetRenderData() allow the renderer to 'hang' data on a mesh. This data can be anything the renderer wants. The data will automatically be deleted when the mesh is deleted via DeleteThis() . - - - - - Sets a single 'rendered' normal in the rVerts array of instances. - - A zero based index into the rVerts array of the normal to store. - The normal to store in device coordinates. This should be a unit vector. - - - - Returns the 'i-th' 'rendered' normal from the rVerts array. - - A zero based index into the rVerts array of the normal to get. - - - - Sets the 'i-th' face normal. - - A zero based index into the face normal array of the normal to store. - The face normal to store. This should be a unit vector. - - - - Returns the 'i-th' face normal. - - Specifies the index of the face normal to retrieve. - - - - Returns a pointer to the 'i-th' face normal. - - Specifies the index of the face normal to retrieve. - - - - This method resolves the normals on the array. If the already has normals at each vertex, the normal is just moved to the array. See Class and Class . If you are creating a by hand, after you are done specifying all the vertices and faces, this method should be called. This allocates the and database for the . This will allow you to query the and ask about normals on the vertices. Also, if you deform a (i.e. take one of the vertices and move it), you should call this method again. Actually, if you are only moving one normal you only need to smooth the polygons that share the vertex. However, there is no method to smooth a subset of a , you either have to do it by hand or call this method to smooth the entire . This method also builds the face normals for the mesh. - - - - - This method is similar to buildNormals() above, but ignores the material index (mtlIndex). In other words, the difference between this and buildNormals() is that it doesn't look at the mtlIndex of the faces: normals of faces with the same smoothing group are averaged regardless. - - - - - This method can be used to build the normals and allocate RVert space only if necessary. This is a very inexpensive call if the normals are already calculated. When illum is FALSE, only the RVerts allocation is checked (since normals aren't needed for non-illum rendering). When illum is TRUE, normals will also be built, if they aren't already. So, to make sure normals are built, call this with illum=TRUE. - - If TRUE then normals are built. If FALSE then only the RVert array is allocated. - - - - This method returns the 'i-th' . - - Specifies the index of the to retrieve. - - - - This method returns a pointer to the 'i-th' . - - Specifies the index of the to retrieve. - - - - Retrieves the zero based material index of the 'i-th' face. - - Specifies the face index. This is the zero based index into the faces array. - - - - Sets the material index of the 'i-th' face. - - Specifies the face index. This is the zero based index into the faces array. - The material index for the 'i-th' face. - - - - Renders this using the specified graphics window and array of materials. Note: If a display routine makes multiple calls to this method you need to have called: gw->setMaterial(inode->Mtls()[0]); before calling Mesh::render(). If you don't then you may get the wrong material for material ID 0. - Sample Code: - The following code shows this method being used to render the mesh as part of the implementation of the BaseObject::Display() method: - - Points to the graphics window to render to. - The list of materials to use to render the mesh. See Class and the topic "Class INode - Material methods". - Specifies the rectangular region to render. If the mesh should be rendered to the entire viewport pass NULL. - One or more of the following flags: - The number of materials for the mesh. - This pointer to an can be used to get hold of the pointer. And interface can also be obtained from the object by calling (IXTCACCESS_INTERFACE_ID). - - - - Checks to see if there is a snap point near the given mouse point. - Sample Code: - Checks to see if there is a snap point near the given mouse point. - - The graphics window in which to check. - This structure describes the snap settings used, and the results of the snap test. See the title "Structure SnapInfo". - The mouse point to check. - The object transformation matrix. This is the transformation to place the object into the world coordinate system. - - - - Note that there may be more than one normal per vertex if faces that share the vertex are in non-overlapping smoothing groups. In this case, all normals associated with the given vertex are drawn. - - Nonzero to display the normals; zero to turn off normals display. This can be a combination of MESH_DISP_FACE_NORMALS and MESH_DISP_VERTEX_NORMALS. (The arguments may be or'ed together to display both.) For backwards compatibility, MESH_DISP_FACE_NORMALS is defined to be 1, so sending in TRUE will turn on display of face normals, as before. - This specifies the length that should be used (in world units) to display the normals. Since all normals start out with length equal to 1 they probably would be too small to see unless they were scaled - - - - Controls the display of hidden edges of this mesh object. This just sets the in the mesh that controls whether "hidden" edges (for instance the diagonals on the sides of a cube) are displayed. - - Nonzero to display all the hidden edges; otherwise zero. - - - - Call this method after the geometry of this has changed. It invalidates the bounding box, and tosses out the cached normals and edge list. - - - - - Call this method after you alter vertex or face lists or revise edge visibility flags. It will invalidate the edge and strip database maintained by the mesh. - - - - - Cleans up the allocated arrays. This frees the Faces, Verts, TVerts, TVFaces, FaceMtlIndexList and invalidates the geometry cache. - - - - - Divides the edge, creating a new point. The face directly using this edge (face edge/3) is also divided in two, and other faces using the edge may optionally be split to use the split edges. - - The edge to divide. - The proportion along the edge to make the division. An edge can be expressed as ff*3+ee, where ff is a face using this edge and ee represents which pair of vertices the edge is between, faces[ff]->v[ee] and faces[ff]->v[(ee+1)%3]. The new point is created at (1-prop) times the first vertex plus prop times the second. prop may vary from 0 to 1. prop=.5 gives the same result that DivideEdge (DWORD edge) would generate. - Indicates whether the "diagonal" used to split the primary face this edge is on (edge/3) is visible or not. - Indicates whether other faces using this edge should also be split to use the two new edges, or if they should be left as they were. In a typical mesh, there is one other face using this edge, the face on the "other side" of the edge. If fixNeighbors is FALSE, the "other side" in this case would still use the original edge, while the face on this side would be split to use the two new edges. This would create a "hole" in the mesh. - Indicates whether the "diagonals" used to split other faces using this edge are visible or not. This argument is not used if fixneighbors is FALSE. - - - - Cuts a face into three faces, arranged as a quad and a triangle, by slicing from a point on one edge to a point on another. - - The face to be divided. - The index of edges to be cut. For instance, if you wanted to cut from the edge between v[0] and v[1], to the edge between v[2] and v[0], you would use e1=0 and e2=2. - The proportion along edge e1 to start cutting. - The proportion along edge e2 to stop cutting. - Indicates whether faces also using the cut edges should be split to use the new, subdivided edges. - Indicates that the triangle and quad created by this action should use different vertices. If TRUE, the vertices created by the cut are duplicated, with one set being used for faces on one side and the other set being used by faces on the other side. - - - - Turns an edge. The quadrilateral formed by the triangles on either side of this edge essentially has its diagonal switched. - - The edge to be turned. - If non-NULL, this should point to a variable in which the index of the "other side" of this edge should be stored. In essence, the two sides of an edge used by two faces, f1 and f2, are stored in two different locations, f1*3+e1 and f2*3+e2, where e1, e2 are 0, 1, or 2. This argument is provided so you have easy access to the other side of the edge, if desired, to make easy selection or visibility changes to the edge or other changes to the faces on both sides. - - - - Computes the bounding box of the . If surface normals are displayed, they are taken into account in the computation of the box. The bounding box is stored with the object, use getBoundingBox() to retrieve it. - - - - - If the transformed bounding box presently stored by this mesh is invalid, or corresponds to a transformation differing from that defined the specified matrix transformMat, then the stored transformed bounding box is updated to reflect the transformation of the mesh into the space defined by transformMat. The computed bounding box will then be accessible via a call to getBoundingBox with *tm = transformMat. - - transformation matrix, including translation vector, defining the transformation from this mesh's object space, to the space in which the bounding box is to be computed - - - - Retrieves the bounding box of the mesh object. If an up-to-date bounding box corresponding to the specified transformation tm is not available, it will be generated via a call to buildBoundingBox, if tm = nullptr, or BuildTransformedBoundingBox, otherwise. - The bounding box of the . - - The optional TM allows the box to be calculated in any space. NOTE: This computation will be slower because all the points must be transformed. - - - - It builds the strips database inside the mesh. See the method BuildStripsAndEdges() below. - - - - - This method invalidates the strips database. - - - - - This method builds the strips and edges database inside the mesh. When developers create a new mesh for display then this method should be called. See the Stripping topic in the Meshes section for more information about this method. - - - - - Shallow copy the specified channel objects of the specified . This means that the data channel objects are shared between the two meshes. - - - Specifies the source to copy. - - Specifies the channels to copy. See . - - - - Makes a complete copy of the specified channel objects from the specified and store them into this . - - - Specifies the source to copy. - - Specifies the channels to copy. See . - - - - This method clones the specified channel objects and stores those in the channel container. There is no risk of leaking channel objects. - - - Specifies the channels to copy. See . - - - - Drop the channel objects specified by the channels argument. No risk of leaking channel objects. For example if the TOPO_CHANNEL is specified, MeshTopoChannelData is freed, if the GEOM_CHANNEL is specified then MeshGeomChannelData is freed, etc. of maps are always preserved. As of 3ds Max 2024, if any channels are specified, they flags are also reset. - - - Specifies the channels to free. Channels not specified are left intact. See . - - If nonzero then the topo, geom, vert color, tex map and hidden maps are cleared out. - - - - Sets the state of the mesh flags. - - Specifies the flags to set. See - - - - Returns the state of the specified mesh flags. See Data Members: above for a list of the mesh flags. - - Specifies the flags to retrieve. See - - - - Sets the state of the specified mesh flags to 0. - - Specifies the flags to clear. See - - - - Sets the state of the display flags. See Data Members: above for a list of the display flags. - - Specifies the flags to set. - - - - Returns the state of the specified display flags. See Data Members: above for a list of the display flags. - - Specifies the flags to retrieve. - - - - Sets the state of the specified display flags to 0. - - Specifies the flags to clear. - - - - Retrieves the bits representing the vertex selection status. - - - The vertex selection status. - - - - - Retrieves the bits representing the face selection status. - The face selection status. - - - - - Retrieves the bits representing the the selected edges status. - The selected edges status. - - - - - Retrieves the bits representing the hidden flags for vertices. - The hidden vertex status. - - - - - Constructs a vertex selection list based on the current selection level. For example if the selection level is at object level all the bits are set (vertices, faces and edges). If the selection level is at vertex level only the selected vertex bits are set. - A reflecting the current selection level. - Sample Code: - - - - - Allows this to be reduced in complexity by reducing the number of faces based on a surface normal threshold. Adjacent faces whose difference in surface normal angle falls below the specified threshold will be collapsed into a single triangle. The may also have its edge visibility set based on a surface normal threshold. - - When the angle between adjacent surface normals is less than this value the optimization is performed. This angle is specified in radians. - When the angle between adjacent surface normals is less than this value the auto edge is performed (if the OPTIMIZE_AUTOEDGE flag is set). This angle is specified in radians. - When optimizing mesh objects, as the optimization increases, you can get lots of long skinny 'degenerate' triangles (that cause rendering artifacts). Increasing the bias parameter keeps triangles from becoming degenerate. The range of values is from 0 to 1 (where 0 turns bias off). Values close to 1 reduce the amount of optimization in favor of maintaining equilateral triangles. - This parameter is available in release 2.0 and later only. This will prevent the optimize function from creating edges longer than this value. If this parameter is <=0 no limit is placed on the length of the edges. - These flags control the optimization. Specify zero or more of the - A callback used for lengthy optimize operations. See Class . - - - - This method may be called to map this with UVW mapping coordinates. - - The mapping type. One of the following values: - of tiles in the U direction. - of tiles in the V direction. - of tiles in the W direction. - If nonzero the U values are mirrored. - If nonzero the V values are mirrored. - If nonzero the W values are mirrored. - This is used with MAP_CYLINDRICAL. If nonzero, then any face normal that is pointing more vertically than horizontally will be mapped using planar coordinates. - This defines the mapping space. As each point is mapped, it is multiplied by this matrix, and then it is mapped. - This parameter is available in release 2.0 and later only. This indicates which channel the mapping is applied to channel==1 corresponds to the original texture mapping channel. - - - - Checks if the space accelerating data is up-to-date. - Invoking InvalidateGeomCache() or InvalidateTopologyCache() will dirty the space accelerating data. - - - - - Update the space accelerating data. - This function should only be invoked when the plug-in needs to invoke following methods before InvalidateGeomCache() or InvalidateTopologyCache() gets invoked. - - - - - Checks the given hr to see if it intersects this object. - TRUE if the item was hit; otherwise FALSE. - - Points to the graphics window to check. - The list of materials for the mesh. - This describes the properties of a region used for the hit testing. See Class . - If nonzero, the hit testing is complete after any hit; otherwise all hits are checked. - The number of materials for the mesh. - - - - This method may be called to perform sub-object hit testing on this mesh. - TRUE if the item was hit; otherwise FALSE. - - The graphics window associated with the viewport the mesh is being hit tested in. - The list of materials for the mesh. See Class and the topic "Class INode - Material methods". - This describes the properties of a region used for the hit testing. See Class . - Flags for sub object hit testing. One or more of the flags in - The results are stored here. See Class . - The number of materials for the mesh. - - - - This function computes the render normal for the specified face and corner. Unlike the method of buildNormals() and buildRenderNormals(), this function does not rely on whole array to achieve normal computation, which means it is lightweight and it quite efficent to do the normal computation for a given face and corner index. The only limitation is that this function will update the space accelerating structure if it is needed. - - The index to the face. - The corner index within the face(must between 0 and 2 inclusively) - - - - This function computes the interpolated normals regarding the barycentric coordinates. - - The index to the face. - The input barycentric coordinates to compute the interpolated normal. - - - - Calculates the intersection of the specified ray with this mesh object. This allows objects to easily implement the Object::IntersectRay() method. - Nonzero if the ray intersected the mesh object; otherwise 0. Note that this method ignores backfaces when computing the result. - - Specifies the origin and direction of the ray to intersect with the mesh. See Class . - The computed point of intersection on the surface of the mesh. - The face normal at the point of intersection (at). - - - - Calculates the intersection of the specified ray with this mesh object. This new version also returns the face index that was intersected and the barycentric coordinates of that face. Barycentric coordinates are the coordinates relative to the triangular face. The barycentric coordinates of a point p relative to a triangle describe that point as a weighted sum of the vertices of the triangle. If the barycentric coordinates are b0, b1, and b2, then: p = b0*p0 + b1*p1 + b2*p2; where p0, p1, and p2 are the vertices of the triangle. The returned by this method has the barycentric coordinates stored in its three coordinates. These coordinates are relative to the triangular face that was intersected. These barycentric coordinates can be used to interpolate any quantity whose value is known at the vertices of the triangle. - Nonzero if the ray intersected the mesh object; otherwise 0. - - Specifies the origin and direction of the ray to intersect with the mesh. See Class . - The computed point of intersection on the surface of the mesh. - The face normal at the point of intersection (at). - The face index of the face that was intersected is returned here. - The barycentric coordinates of the face that was hit. - - - - Storage for the current mapping channel to use for vertex colors (default = 0). - - - - - Points to storage for a possible external color array (default = NULL). This can be either an external array or one of the mapping channels. See the method Mesh::setVCDisplayData(); - - - - - possible external face array (default = NULL) - - - - - When 3ds Max is rendering the color values come from this variable. This array defaults to the internal vertCol but can be set to an external array, or a map channel. See the method Mesh::setVCDisplayData(); - - - - - When 3ds Max is rendering the vertex color lookup comes from this structure. This defaults to the vcFace data but if a mapping channel is used for color lookup, its structure is used. - - - - - Display attribute flags. They control various aspect of the objects display and may be one or more of the following values: - - - - - Selection level flags. This is the current level of selection. When all the bits are 0, the object is at object level selection. The selection level bits are: - - - - - Nonzero if normals have been built for the current mesh; 0 otherwise. - - - - - Points to the render data used by the renderer. - - - - - depends on topo - - - - - indirection array for fast normal lookup - - - - - total number of normals - - - - - flattened list of normals pointers back in the rverts data. We need to get rid of this or something this is big memory eater - - - - - Derived arrays to contain generated texture coordinates. - - - - - Derived arrays to contain generated texture coordinates. - - - - - Derived table of TriStrips, depends on topology. - - - - - Using a channel mask, request the locks for those channels. - - - This can be used avoid race conditions when modifying many Min parallel when some of them share channels. - - - Which channels to aquire a lock for. - - - - Using a channel mask, release the aquired locks for those channels. - - - - - Which channels to release the locks for. - - - - Returns the channel container which provides access to the channel objects themselves. - - - To modify a channel directly, instead of using the interface, you can fetch the MeshChannelContainer, then grab the appropriate channel object and make the changes directly. This is not recommended, mistakes here could cause crashes and data loss. Example to manually reallocate the faces: - - - - - Assignment operator. Note: This operator does not copy the rVerts array. This means that developers who have specified normals will have to explicitly copy them after a mesh assignment is done using this operator. This is because rVerts are instance-specific. In general, normals are computed from smoothing groups, and hence are "generated data". In the case where normals are specified, 3ds Max stores the data in the rVerts array so as to not waste space. The way 3ds Max uses the mesh = operator assumes that the rVerts are not copied, and thus developers must do the copying themselves. - - Specifies the mesh to copy. - - - - Performs a boolean union operation. - A new resulting from the boolean operation. If the operation fails an empty is returned. - - Specifies the mesh to use as the other operand of the boolean operation. - - - - Performs a boolean difference operation. - A new resulting from the boolean operation. If the operation fails an empty is returned. - - Specifies the mesh to use as the other operand of the boolean operation. - - - - Performs a boolean intersection operation. - A new resulting from the boolean operation. If the operation fails an empty is returned. - - Specifies the mesh to use as the other operand of the boolean operation. - - - - The function first checks if the whole mesh or the face have been flagged as cache invalid (MESH_CACHEINVALID). If none of these is true, it then cycles through the face's vertices and returns true as soon as it finds a vertex flagged with MESH_CACHEINVALID. - faceIndex must be a valid index in the faces (f) array. - true if the face is invalid, else false. - - The index of the face for which you want to determine cache validity - - - - The function flags the specified vertex with the MESH_CACHEINVALID flag, telling the rebuild functions that this vertex, the faces surrounding it and the other vertices of those faces need to have their normals recomputed. It also sets normalsBuilt to 0 to trigger normals' rebuild. This function should be called when one to several vertices have been modified. If all or almost all vertices of the mesh have been invalidated, it's more efficient to call InvalidateGeomCache() instead. - vertex must be a valid index in the vertex (v) array. - - The index of the vertex that needs to be invalidated. - - - - This will set the mesh or as static or not. As static mesh has no animated channels. This allows use to certain display optimization since we know the mesh is not changing. - - Whether the mesh is to tagged static or not. - - - - This will force all the derived data used to display the mesh to be deleted. This data can be things like the gfx normals, the direct x mesh cache, tri stripping data etc. - - - - - This returns whether the Graphics Cache for this object needs to be rebuilt - - the active graphics window - the material array assigned to the mesh - the number of materials in the material array - - - - This builds the graphics window cached mesh - - the active graphics window - the material array assigned to the mesh - the number of materials in the material array - whether when building the cache it can use additional threads. This is needed since the system may be creating many meshes at the same time - - - - Generate a set of render items according to the given render-item-generate context. - Usually plugins use this function in their UpdateDisplay(). If plugins maintain copies of , then they should use this function to convert those mesh instances to render items (RenderItemHandle). This function generates mesh data immediately. Note for instance rendering: instance rendering is a way to draw many objects that use the same geometry. These objects share the same materials and modifiers. The only difference between objects is world transformation. You can specify a matrix array for the mesh, then the mesh will be drawn for many times. Each corresponds to a mesh in the array. - - the container that accept newly generated render items. - contains all the information that is used to generate all the required render items. - - - - This class is used to apply the data to a mesh. It will modify the mesh as required to add the cap. Simply fill in the vertices and faces bordering the cap, then call the CapMesh method. All methods of this class are implemented by the system. - - - - - The number of polygons in the shape. - - - - - One polygon for each polygon in the shape. - - - - - access operator. Returns the as specified by the index. - - - - - This method is used to modify the mesh based on the , the flipped state, the smoothing group and an orientation matrix. - Nonzero if the mesh was modified; otherwise zero. - - - The to modify. - - The describing the properties of the cap. - - A switch to indicate if the cap should be oriented normally or flipped. The is used for both the front and back side of a cap. Either the front or the back will have to be flipped. This switch is used to indicate if a particular one is flipped. - - The smoothing group for all the faces in the cap. - - The orientation matrix. A grid cap generates new vertices inside the shape that make up the grid. In the case of a SurfRev for example, the end cap might be rotated, or scaled in some manner. A matrix is required so the capper knows how to orient the vertices into the correct location. This matrix is ignored for non-grid capping. - - This parameter is available in release 2.0 and later only. Specifies the material ID of the faces that make up the cap. The default for this value is -1, which causes the capper to use material ID 0 for non-flipped caps and ID 1 for flipped caps. Note that these ID values are zero-based, while the display is 1-based. - - - - This method is used to modify the based on the , the flipped state, the smoothing group and an orientation matrix. - Nonzero if the mesh was modified; otherwise zero. - - - The to modify. - - The describing the properties of the cap. - - A switch to indicate if the cap should be oriented normally or flipped. The is used for both the front and back side of a cap. Either the front or the back will have to be flipped. This switch is used to indicate if a particular one is flipped. - - The smoothing group for all the faces in the cap. - - The orientation matrix. A grid cap generates new vertices inside the shape that make up the grid. In the case of a SurfRev for example, the end cap might be rotated, or scaled in some manner. A matrix is required so the capper knows how to orient the vertices into the correct location. This matrix is ignored for non-grid capping. - - This parameter is available in release 2.0 and later only. Specifies the material ID of the faces that make up the cap. The default for this value is -1, which causes the capper to use material ID 0 for non-flipped caps and ID 1 for flipped caps. Note that these ID values are zero-based, while the display is 1-based. - - - - Description: - The information class for mesh capping (MORPH or GRID). All the data members and methods of this class are used internally. Developers must only declare an instance of this class and then call MakeCap() on the shape. - - - - - Used Internally. - - - - - Used Internally. - - - - - Used Internally. - - - - - Assignment operator used internally. - - - - - This method is used internally. - - - - - This method is used internally. - - - - - Description: - A support class for the mesh capper. There is one of these for each polygon in a shape to be capped. All methods of this class are implemented by the system. - Data Members: - int numVerts; - - The number of vertices. - - int *verts; - - List of the verts in the mesh corresponding to the verts in the (1 per vertex). - - - - - This method is used internally. - - - - - This establishes the corresponding vertex for a vertex in the . This should be called for each vertex in the . - Parameters: - int index - - The index into the shape. - - int vertex - - The corresponding index into the mesh. - - - - - Compares this class instance to another one - - - - - Description: - This class contains all the data needed to move points as the user drags a chamfer. It's created by the topological change that happens at the start of the chamfer. It is used to maintain chamfer information between several methods. The strategy is this: The chamfer operation is divided into two parts, the topological change and a later geometric change. (This works well for EditableMesh, where the topology change is completed first, then apply a series of geometry changes as the user spins a spinner or drags a mouse. Each geometry change is undone before the next is applied, but the topology change only happens once.) - - This class is filled in by the topological change with the "directions" for all the geometric and mapping vert changes: - Data Members: - > vdir; - - This table contains the directions of movement for each vertex, scaled in such a manner to produce a consistent chamfer. - - <float> vmax; - - This table contains the limits of motion for each vertex - stopping the vertices at these limits will prevent them from crossing each other or over far edges. - - <UVVert> *mdir; - - For each active map channel mp, mdir[mp] represents the directions of movement of the map verts for that channel. (Map verts need to be moved as well, otherwise the maps get distorted.) - - - - - This method sets up a based on a given mesh, allocating the vertex and mapping vertex tables as appropriate. - Parameters: - &m - - The to init from. - - - - - This method simply allocates the vdir and vmax tables, and initializes the new members of vmax to 0. This method can be applied to an existing to reflect an increase in vertices by VClone or VCreate operations. - Parameters: - int nv - - The number of verts - - bool keep=TRUE - - TRUE to keep if resized; FALSE to discard. - - int resizer=0 - - The number of elements the vdir and vmax tables are resized beyond their current size. - - - - - - - Description: - This class represents the notion of a mesh edit. This is an SDK class that represent some kind of change to a mesh. This "delta" can include topological, geometric, map, and/or selection changes. Most standard mesh "edits" available in the Editable or Edit interface are available through the SDK, giving developers a powerful way to manipulate meshes while not having to "sweat the details" of maintaining maps to match the mesh changes, updating edge selections, etc. The members and methods make use of a number of mesh-related classes, including Class , Class , Class , Class , Class , Class , Class , Class , Class , Class . While we often talk about the characteristics of the "input mesh" that a is based on, all MeshDeltas should be able to cope with any mesh. Note: You must #include "MESHDLIB.H" to use this class as it's not included by default by MAX.H. - Method Groups: - See . - Data Members: - DWORD vnum The expected number of vertices in the input mesh. DWORD fnum; The expected number of faces in the input mesh. > vMove; This data member stores movements of input vertices. Each consists of a vertex ID indicating which vertex should be moved and a offset in object space. VertMoves are stored in vertex ID order, and there is never more than one per original vertex. > vClone; If the vClone[i] record has a vid of UNDEFINED, it's considered a "create", and the coordinates of vClone[i].p are considered to be in object space. If vClone[i].vid is not undefined, it's the index of a vertex "original" in the input mesh, and vClone[i].p is treated as an offset from that vertex. If the vertex is not present in the input mesh, i.e. vClone[i].vid >= mesh::numVerts, the clone will not be created in the output. All creates and clones are stored in the order created.. vDelete; This data member stores deletions of vertices in the input mesh. vDelete's size is vnum. > fCreate; This data member stores faces newly created as part of the . These are stored in the order created. > fRemap; This data member stores changes in which vertices are used by existing faces. See class for more information. These are stored in original face order, and there is never more than one per original face. > fChange; This data member stores changes in input face characteristics, such as material ID, edge visibility, and face hiding. See class for more information. These are stored in original face order, and there is never more than one per original face. > fSmooth; This data member stores changes in input face smoothing groups. See class for more information. These are stored in original face order, and there is never more than one per original face. fDelete; This data member stores deletions of faces in the input mesh. The size of this is fnum. vsel; This data member stores the vertex selection of the output mesh. esel; This data member stores the edge selection of the output mesh. As with class 's edgeSel data member, this information is indexed by side of face: esel[ff*3+k] is the edge selection for face ff, side k. fsel; This data member stores the face selection of the output mesh. vhide; This data member stores the vertex hide information of the output mesh. *map; Points to an array of MapDeltas which maintain any relevant changes to the various map channels. The size of this array is always equal to mapSupport.GetSize(). mapSupport; Indicates which maps are supported by this . *vd; Points to an array of VDataDeltas which maintain any relevant changes to the various vertex data channels. The size of this array is always equal to vdSupport.GetSize(). vdSupport; Indicates which vertex data channels are supported by this . - - - - - Initializes the to the mesh given, setting map and vdata support as appropriate. Does NOT clear out existing changes. - Parameters: - &m The mesh to init from. - - - - - Clears out all existing mesh changes. Zeroes all the vCreate, vMove, etc arrays, as well as those in the active MapDeltas. Does not clear memory. - - - - - Sets the number of map channels used by the - allocates the "map" array. - Parameters: - int num The number of maps to allocate. bool keep=TRUE If TRUE any previous maps are kept; otherwise they are discarded. - - - - - Gets the number of map channels in the - equivalent to mapSupport.GetSize(). - - - - - Data accessor - gets the for the specified map channel. Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual arrays. (Hidden map channels are stored in a new private data member, not as part of the public map array.) - - - - - Indicates whether the specified map channel is supported by this . Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual data members. (Hidden map channel support information is stored in a new private data member, not as part of the public mapSupport .) - - - - - Sets map support in this for the specified map channel. Since in 4.0 we now have "hidden map channels" which are accessed by negative indices (-1 for MAP_SHADING, for example), data accessor methods like this one should be used instead of the actual data members. (Hidden map channel support information is stored in a new private data member, not as part of the public mapSupport .) - - - - - Indicates whether any map channel is supported by this . - - - - - Sets the number of vertex data channels used by the - Parameters: - int num The number of vertex data channels to allocate. bool keep=TRUE If TRUE any previous vertex data channels are kept; otherwise they are discarded. - - - - - Gets the number of vertex data channels in the - equivalent to vdSupport.GetSize(). - - - - - Indicates what data channels of a mesh would be changed by this . For instance, a with vertex moves but no other changes would return GEOM_CHANNEL|SELECT_CHANNEL. GEOM_CHANNEL represents the moves, and SELECT_CHANNEL represents the fact that MeshDeltas always overwrite selection info. Most of the changes in a will alter TOPO_CHANNEL. VERTCOLOR_CHANNEL and TEXMAP_CHANNEL may also be returned. This is especially useful for knowing what parts of a mesh to back up in a restore object for an undo/redo. (See the SDK implementation of Editable for an example of this.) Also, it can be used for invalidating temporary data, as in both Edit and Editable . - - - - - Changes the given mesh by this , in the following manner: First, any maps that are supported by the but not by the mesh are assigned to the mesh in their default form. (Vertex color channels are white, and other maps are copies of the mesh vertices. All have the same topology as the mesh.) Next, any UNDEFINED mapping verts in the are filled in by FillInFaces. Then the new vertices are added, creates first, followed by clones. The original vertices are then moved. The faces are then modified, by applying all the FaceRemaps, FaceChanges, and FaceSmooths to the appropriate faces. New faces (in fCreate) are appended to the end of the face list. Map changes are applied to all active maps, and map channels not supported by this are removed. After all that is done, the vertices and faces marked in the vDelete and fDelete arrays are deleted. Finally, the vertex data, vertex hide, and selections kept in the are applied to the result. - - - - - To make things easy for developers, it's possible to create or remap mapping faces to use UNDEFINED mapping verts. This routine, which is called by Apply below, fills in those UNDEFINED mapping values with the mapping vertices used by neighboring faces, or, if necessary, by new mapping vertices. (These new mapping vertices are always (.5,.5,0) for regular map channels or (1,1,1) for the vertex color channel.) This process does not produce very good maps, but it allows a sort of minimal mapping support that prevents maps from being lost before the user can make their manual corrections. - - - - - Assignment operator - makes this just like the one given. - - - - - Appends the given to the current one. - Parameters: - & td The to append. This may be modified to make it suitable, ie the vnum and fnum values will be set to the expected output of the current if they don't already match. (This may result in the loss of some data - see "SetInVNum" and "SetInFNum" for more information.) - - - - - Appends the given to the current one. - Parameters: - & td The to append. This may be modified to make it suitable, ie the vnum and fnum values will be set to the expected output of the current if they don't already match. (This may result in the loss of some data - see "SetInVNum" and "SetInFNum" for more information.) - - - - - Returns the number of vertex moves that would be applied to a mesh with the specified number of vertices. If that number equals this 's vnum, this is simply vMove.Count(). - Parameters: - DWORD inVNum The number of vertices in the input mesh we're inquiring about. - - - - - Returns the number of vertex clones & creates that would be applied to a mesh with the specified number of vertices. If that number equals this 's vnum, this is simply vClone.Count(). If, however, inVNum is lower than the expected vnum, some of the clones might be eliminated, reducing this number. - Parameters: - DWORD inVNum The number of vertices in the input mesh we're inquiring about. - - - - - Returns the number of vertex deletes that would be applied to a mesh with the specified number of vertices. If that number equals this 's vnum, this is simply vDelete.NumberSet (). - Parameters: - DWORD inVNum The number of vertices in the input mesh we're inquiring about. - - - - - Returns the number of face deletes that would be applied to a mesh with the specified number of faces. If inFNum equals this 's fnum, this is simply fDelete.NumberSet (). - Parameters: - DWORD inFNum The number of faces in the input mesh we're inquiring about. - - - - - Returns the number of face creates in this . - - - - - Returns the number of vertices in the output mesh, assuming that the input mesh is of the expected (vnum) size. - - - - - Returns the number of vertices in the output mesh, assuming that the input mesh has the specified number of vertices. - Parameters: - int inVNum The number of vertices expected in the input mesh. - - - - - Returns the number of faces in the output mesh, assuming that the input mesh is of the expected (fnum) size. - - - - - Returns the number of faces in the output mesh, assuming that the input mesh has the specified number of faces. - Parameters: - DWORD inFNum The number of faces expected in the input mesh. - - - - - Indicates whether or not the specified vertex is created in this . - Parameters: - DWORD i The output-based vertex index. - - - - - Tells you what input vertex the specified output vertex is a clone of. - Parameters: - DWORD i The output-based vertex index. - The index in the input mesh of the original vertex this one's a clone of. If this vertex is not a clone, UNDEFINED is returned. - - - - - No longer used. This method was used in 3.0 and 3.1 to indicate whether the specified vertex was created as a create, not a clone in this . In 4.0, we integrated the clone and create records together, and this method is now set to always return FALSE. - Parameters: - DWORD i The output-based vertex index. - - - - - Indicated whether the specified face was created in this . - Parameters: - DWORD i The face index in the output mesh. - - - - - Obtains the index of the vMove entry that relates to this vertex. - Parameters: - DWORD i The input-based vertex index. - The index in the vMove array of the vertex move corresponding to this vertex, or UNDEFINED if this vertex has no move associated with it. - - - - - Returns the expected location in the output mesh of the specified vertex. - Parameters: - & m The input mesh. DWORD v The vertex you want the output location of. This index is input-based - the vertex index in m, not in the output mesh. - - - - - Obtains the index of the fRemap entry that relates to this face. - Parameters: - DWORD ff The input-based face index. - If there is such an entry, the index is returned, so fRemap[RemapID(ff)].fid == ff. If there is no remap record for this face, the method returns UNDEFINED. - - - - - Tells whether the specified corner of the specified face has been remapped in this . - Parameters: - DWORD ff The input-based face index. DWORD vid The corner of the face - 0, 1, or 2. - If this corner has been remapped, it returns the vertex it's been remapped to. Otherwise, it returns UNDEFINED. - - - - - Returns the specified face as it would appear in the output. Changes, Smooths, and Remaps are applied. - Parameters: - & m The input mesh. DWORD f The index of the face you want the output version of. This index is input-based - - - - - Sets the number of faces in the input mesh. NOTE that if nface is less than the current fnum, the data relating to the extra faces will be lost. (That is, if one of your face remaps is applied to face 32, and you SetInFNum to 30, that face remap will be lost, and will not be recovered if you later SetInFNum to 35.) It is NOT necessary to call this method before applying this to a smaller than expected . - Parameters: - int nface The number of faces expected from the input mesh. - - - - - Sets the number of vertices in the input mesh. NOTE that if nv is less than the current vnum, the data relating to the extra vertices will be lost. (That is, if one of your vertex moves is applied to vertex 32, and you SetInVNum to 30, that vertex move will be lost, and will not be recovered if you later SetInVNum to 35.) It is NOT necessary to call this method before applying this to a smaller than expected . - Parameters: - int nv The number of vertices expected from the input mesh. - - - - - Activates the vertex color , adding whatever new map verts or faces are needed to match the current . After calling this method, applying this to a mesh without vertex colors will result in a vertex color map with all white vertices and a topology identical to the mesh. - - - - - Activates the specified , adding whatever new map verts or faces are needed to match the current . If mapID is 0, the standard vertex colors (white) will be applied (see AddVertexColors). Otherwise, after calling this method, applying this to a mesh without the specified map active will result in a map with the same topology as the mesh and UVVerts that are copies of the mesh vertices. - Parameters: - int mapID The map channel to add. 0 represents vertex colors, 1 is the original map channel (referred to in class by tVerts and tvFaces), and 2-99 are the new map channels (stored in meshes in the class). - - - - - Activates the specified vertex data channel, creating a default set of vertex data to match the output of the current . ("Default" values of vertex data depend on the channel, and are given by VDataDefault (vdChan).) - Parameters: - int vdChan The vertex data channel *m=NULL A pointer to the object. - - - - - Updates the 's internal lookup tables, which make use of all delete and create records to set up a correspondence between output and input vertices and faces. - Parameters: - int extraV If nonzero, this indicates the number of extra spaces that should be added to the lookup table. This is useful for example if you want the lookup table to still be valid after the next <extraV> vertex creates or clones. int extraF If nonzero, this indicates the number of extra spaces that should be added to the lookup table. This is useful for example if you want the lookup table to still be valid after the next <extraF> face creates. - - - - - Invalidates and clears the lookup tables. This usually only needs to be called internally. - - - - - Finds the input mesh index of the vertex with the specified output mesh index. Note that these indices are the same if there are no vertex deletes. - Parameters: - DWORD i The output mesh index. - The input mesh index of the same vertex. If the vertex specified is actually created by this , the return value would be vnum+i for vClone[i]. - - - - - Finds the input mesh index of the face with the specified output mesh index. Note that these indices are the same if there are no face deletes. - Parameters: - DWORD i The output mesh index. - The input mesh index of the same face. If the face specified is actually created by this , the return value would be fnum+i for fCreate[i]. - - - - - Returns the index in the output mesh of the specified input vertex. Note that these indices are the same if there are no vertex deletes. - Parameters: - DWORD i The index of the vertex in the input mesh. - The output mesh index of the same vertex. If the vertex was deleted in this , UNDEFINED is returned. - - - - - Returns the index in the output mesh of the specified input face. Note that these indices are the same if there are no face deletes. - Parameters: - DWORD i The index of the face in the input mesh. - The output mesh index of the same face. If the face was deleted in this , UNDEFINED is returned. - - - - - Creates new vertices. - Parameters: - *p A pointer to an array of points representing the new vertices. int num The size of the point array. *sel=NULL If non-NULL, this points to a of size num that indicates which of these new vertices should be selected. (If NULL, none of the new vertices are selected.) *hide=NULL If non-NULL, this points to a of size num that indicates which of these new vertices should be hidden. (If NULL, none of the new vertices are hidden.) - The index (in the output mesh) of the first of these new vertices. - - - - - Clones some vertices. - Parameters: - DWORD *v A pointer to an array of indices of verts that should be cloned. int num The size of the array. - The index (in the output mesh) of the first of the clones. - - - - - Clones some vertices. - Parameters: - DWORD *v A pointer to an array of ids of vertices that should be cloned. *off A pointer to an array of offsets for the clones. int num The size of the arrays. - The index (in the output mesh) of the first of the clones. - - - - - Clones some vertices. - Parameters: - *vm A pointer to an array of VertMoves indicating which vertices should be cloned and what offsets the clones should use. int num The size of the vm array. - The index (in the output mesh) of the first of the clones. - - - - - Clones a single vertex. - Parameters: - DWORD v The index (in the output mesh) of the vertex you wish to clone. - The index (in the output mesh) of the clone. - - - - - Clones and offsets a single vertex. - Parameters: - DWORD v The index (in the output mesh) of the vertex you wish to clone. off The desired offset from the original vertex. - The index (in the output mesh) of the clone. - - - - - Deletes the specified vertices. - Parameters: - DWORD *v A pointer to an array of (output-based) ids of the vertices that should be deleted. int num The number of vertices to delete (the size of the v array). - - - - - Deletes the specified vertices. - Parameters: - & vdel A , of size OutVNum, indicating which of the vertices should be deleted. Vertices in this array are indexed by output mesh order. - - - - - Creates new faces. Note: MapDeltas must be kept up to date with all new face creations - see CreateDefaultMapFaces. - Parameters: - *f A pointer to an array of faces to be added to the . int num The size of the face array. - The index (in the output mesh) of the first of these new faces. - - - - - Creates new faces. This is what's used to add in face creations in the all-important Compose method. It assumes that the "originals" in the array of FaceCreates are post-indexed, and uses FLut and extracts originals for creates-of-creates as appropriate. Note: MapDeltas must be kept up to date with all new face creations - see CreateDefaultMapFaces. - Parameters: - *f A pointer to an array of face create records to be added to the . int num The size of the face create array. - The index (in the output mesh) of the first of these new faces. - - - - - Creates 2 new faces, forming a quad. Note: MapDeltas must be kept up to date with all new face creations - see CreateDefaultMapFaces. - Parameters: - DWORD *v A pointer to an array of 4 vertices to be used as corners of the quad. DWORD smG=0 The smoothing group desired for the new faces. MtlID matID=0 The material ID desired for the new faces. int orig=UNDEFINED This optional parameter sets the map faces to undefined. - The index (in the output mesh) of the first of these 2 new faces. - - - - - Creates a new face by copying an existing face. The result is put into the fCreate array and treated thereafter like a face create - this is different from vertex clones, which are maintained separately from vertex creates. Note: MapDeltas must be kept up to date with all new face creations - see CreateDefaultMapFaces. - Parameters: - & f The face we wish to clone. (This is typically generated by the outFace method.) DWORD ff The (output-based) index of the face we're cloning. (This is used to copy face and edge selection.) DWORD remapFlags=0DWORD *v=NULL If we wish to remap any of the corners of this face while cloning, the appropriate flags and vertices should be passed in remapFlags and v arguments. v should point to an array of 3 vertex (output) indices, although the ones not marked as used by the remapFlags need not be set to anything in particular. See class for more information about face remapping. BOOL bCopySel=TRUE If want the new edges and face to have their selection bits set from the original face, set this value to TRUE. Otherwise the new face will have their selection state cleared. - The index (in the output mesh) of the new face. - - - - - MapDeltas must always keep their faces in sync with the parent . If the developer creates new faces, but doesn't want to go through the bother of figuring out exactly how the related map faces should look, this method may be used to create map faces with UNDEFINED verts. These can then be filled in automatically later. (See the FillInFaces method for details.) For every face created in the , either CreateDefaultMapFaces should be called, or map faces should be created in every active map channel, using MapDelta::FCreate and related methods. - Parameters: - int num=1 The number of default faces we wish to create in each active map channel. - - - - - Adds face remaps to this . If the face specified in each already has a remap record, the two are combined. If the face specified is a face created by this , the remap is applied directly to the fCreate entry instead of being stored in fRemap. - Parameters: - *f A pointer to an array of that should be appended to this . Note that the faces and vertices in each must be indexed by their positions after all of the current 's creates, clones, etc, but before any vertex or face deletes. Vertex index values of 0 through vnum-1 are considered to be the original mesh's vertices; values above this are cloned or created vertices. Likewise, face index values of 0 through fnum-1 are considered to be the original mesh faces, while fnum through fnum+fCreate.Count()-1 are this 's face creates. int num=1 The number of elements in the array. - - - - - Adds a face remap to this . If the face specified already has a remap record, the two are combined. If the face specified is a face created by this , the remap is applied directly to the fCreate entry instead of being stored in fRemap. - Parameters: - DWORD f The face to remap. Note that this face must be indexed by its position after all of the current 's face creates, but before any face deletes. index values of 0 through fnum-1 are considered to be the original mesh faces, while fnum through fnum+fCreate.Count()-1 are this 's face creates. DWORD flags Remap flags - these indicate which vertices should be remapped. The possibilities are FR_V0 (1), FR_V1 (2), and FR_V2 (4). (See class for more information.) DWORD *v A pointer to the vertices to remap the face to use. Only the positions indicated in the remap flags need contain meaningful data. Note that the vertices indicated here must be indexed by their positions after all of the current 's creates and clones, but before any vertex deletes - essentially input-based indexing. Vertex index values of 0 through vnum-1 are considered to be the original mesh's vertices; values of vnum through vnum+vCreate.Count()-1 are considered to be this 's newly created vertices; and values above this are cloned vertices. - - - - - Appends some face changes to the current . changes can encompass changes to face material IDs, edge visibility, or face hiding. See class for more information. - Parameters: - *f A pointer to an array of new face changes for this . int num=1 The number of elements in the array. - - - - - Changes the characteristics of one face. - Parameters: - DWORD f The output-indexed face to change. DWORD flagsDWORD dat These two parameters describe the change desired. See class for a description of these flags. flags indicates which characteristics should be set, and dat includes the on-or-off state of each flag we're setting. So for example FChange (26, ATTRIB_EDGE_A| ATTRIB_EDGE_B, ATTRIB_EDGE_A) would set face 26 to have the first edge visible and the second invisible, without changing the existing visibility for the third edge. - - - - - Adds smoothing group changes to this . See class for more information. - Parameters: - *f A pointer to an array of smoothing change records. The face IDs in these records should be output-indexed. int num=1 The number of elements in the array. - - - - - Changes the smoothing groups on the specified face. - Parameters: - DWORD f The output-based index of the face to change. DWORD mask The smoothing groups to change. DWORD val The smoothing group values. For instance, FSmooth (32, 7, 2) would set smoothing group 2 and clear groups 1 and 3 for face 32, since mask has bits 0, 1, and 2 set but val only has bit 1 set. - - - - - Sets the material ID for the specified face. If the face is created by this , the fCreate record is amended. If it's an input face, a record is created or amended. - Parameters: - DWORD f The output-indexed face to change. MtlID mt The desired material ID. - - - - - Sets the smoothing groups on the specified face. - Parameters: - DWORD f The output-based index of the face to change. DWORD smG The smoothing groups to set. All bits not set in this parameter are cleared. - - - - - Sets the edge visibility for the specified side of the specified face. If the face is created by this , the fCreate record is amended. If it's an input face, a record is created or amended. - Parameters: - DWORD f The output-indexed face to change. DWORD ed The side of the face to change (0, 1, or 2). BOOL vis=TRUE The desired visibility. - - - - - Deletes the specified faces. - Parameters: - DWORD *f A pointer to an array of output-based indices of faces we wish to delete. Note that all the elements should be based on the output before any deletions occur. So if you wanted to delete what are currently faces 3 and 5, you could pass an array with 3 and 5, you would not have to think, "Ah, 3 will be deleted, so I should use 4 instead of 5." int num=1 The size of the array. - - - - - Deletes the specified faces. - Parameters: - & fdel The faces to delete. The faces are indexed by their output mesh positions. - - - - - Moves a single vertex. (Note that if the same vertex is moved twice, the new move is simply added to the old one - there is never more than one in the vMove array for a single input vertex.) - Parameters: - int i The index of the vertex in the output mesh. & p The vector to move the vertex by. - - - - - Moves the specified vertices. (Note that if the same vertex is moved twice, the new move is simply added to the old one - there is never more than one in the vMove array for a single input vertex.) - Parameters: - & sel Indicates which vertices should be moved. Vertices are indexed based on the output mesh. & p The vector to move the vertices by. - - - - - Adds in the specified vertex moves. (Note that if the same vertex is moved twice, the new move is simply added to the old one - there is never more than one in the vMove array for a single input vertex.) - Parameters: - *vm A pointer to an array of VertMoves to apply to this . Vertices are indexed based on the output mesh. int num The size of the array. - - - - - Saves the to a 3ds Max file. - - - - - Loads the from a 3ds Max file. - - - - - Prints out the to the DebugPrint window in Developer Studio. - Parameters: - bool lut=FALSE If TRUE, the vertex and face lookup tables are printed out. bool mp=FALSE Active map deltas are also printed out if this is TRUE. - - - - - Automatically generates smoothing groups for the selected faces. Existing smoothing groups are ignored. See the AutoSmooth feature in Edit for an example. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The faces to AutoSmooth. float angle The maximum angle between faces that should be smoothed together. *af=NULL A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own . *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Moves the selected vertices along the directions given to produce the movement corresponding to the mouse drags of a Bevel operation in Editable . Note that this method only changes geometry. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. vset The set of vertices to move. float outline The amount of outlining to do in this Bevel move. > *odir The outline direction for each vertex. This should be given by MeshTempData::OutlineDir. See the Edit source for details. float height The amount of extrusion to do in this Bevel move. > *hdir The extrusion direction for each vertex. This should be given by MeshTempData::EdgeExtDir or FaceExtDir. See the Edit source for examples. - - - - - Create a polygon of any size. The polygon may be nonconvex, but should be (roughly) coplanar. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. int deg The number of vertices used by this polygon (its degree). int *v The indices of the vertices in m that this polygon should use. DWORD smG=0 The desired smoothing group for the new polygon. MtlID matID=0 The desired material ID for the new polygon. - - - - - Deletes the specified vertices, along with any faces that used them. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The vertices to delete. Any face that uses any of the vertices selected here will also be deleted. - - - - - Deletes all faces using the specified edges. (Doesn't delete any verts.) - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The edges to delete the faces of. Edges are indexed by face*3+side. - - - - - Deletes the specified faces. (Doesn't delete any verts.) - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The faces to delete. - - - - - Deletes the current subobject selection. If m.selLevel is MESH_OBJECT, nothing is deleted. If it's MESH_VERTEX, the faces using the selected vertices are also deleted. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. - - - - - Deletes the vertices not in use by any faces. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. - - - - - Flips the normal of the specified face (by switching the face's v[0] and v[1]). (Related map faces are also flipped.) - Parameters: - & m The mesh, which should match the output of the current , that should be affected. DWORD face The face to flip. - - - - - Flattens the faces indicated into the same plane. The target plane is determined by the average of all the face centers and the average of all the face normals. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The faces to make coplanar. - - - - - Flattens the vertices indicated into the same plane. The target plane is determined by the average position and normal of the vertices. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The vertices to make coplanar. - - - - - Moves the vertices indicated into the specified plane. (The target plane is defined as all points which, when DotProd'd with N, return offset.) All vertices are moved along the normal vector N. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. sel The vertices to move into the plane. & N The unit normal to the plane. float offset The offset of the plane (also its distance from the origin). - - - - - Like the old standalone method "FitMeshIDsToMaterial", this method limits the material IDs to values between 0 and numMats-1. This is useful eg in matching the number of material Ids to the number of materials used on this node. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. int numMats The number of material ids allowed. - - - - - Sets or clears face selection depending on whether they match a pattern of flags. This is pretty much only useful for selecting or deselecting hidden faces: mdelta.SelectFacesByFlags(*mesh, FALSE, FACE_HIDDEN, FACE_HIDDEN); // deselects hidden faces. - Parameters: - & m The mesh, which should match the output of the current , that should be affected. BOOL onoff Indicates whether faces should be selected or deselected if they match the flag pattern. DWORD flagmask Indicates whether faces should be selected or deselected if they match the flag pattern. DWORD flags Indicates whether faces should be selected or deselected if they match the flag pattern. - - - - - Attaches another mesh to this one. - Parameters: - & m The mesh this should be based on. & attachment The mesh this should attach. & relativeTransform The transform taking the attachment mesh from its object space to ours. int matOffset The offset that should be applied to all the material IDs in the attachment. - - - - - Splits the selected vertices into a separate vertex for every face that uses them. - Parameters: - & m The mesh this should be based on. vset The vertices that should be broken. - - - - - Performs the topological changes needed for an edge chamfer, and creates the information necessary to do the geometric changes. - Parameters: - & m The mesh this should be based on. eset The edges to chamfer. & mcd A class in which the directions and limits of movement for all the vertices involved in the chamfer should be stored. See class . *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Moves the relevant vertices to a specified chamfer value. - Parameters: - & m The mesh this should be based on. & mcd A class in which the directions and limits of movement for all the vertices involved in the chamfer have been stored by a previous ChamferVertices or ChamferEdges call. See class . float amount The amount (in object space units) of chamfering to do. For vertex chamfers, this indicates how far along the edges each point should move. For edge chamfers, it represents how far along each face each edge should move. *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Performs the topological changes needed for a vertex chamfer, and creates the information necessary to do the geometric changes. - Parameters: - & m The mesh this should be based on. vset The vertices that should be chamfered. & mcd A class in which the directions and limits of movement for all the vertices involved in the chamfer should be stored. See class . *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Clones the specified faces, along with the vertices and mapping vertices they use. - Parameters: - & m The mesh this should be based on. fset The faces that should be cloned. - - - - - Clones the specified vertices. More efficient on an initialized than VClone, which has to be able to cope with existing complex MeshDeltas. - Parameters: - & m The mesh this should be based on. vset The vertices that should be cloned. - - - - - Collapses the edges indicated down to a point. - Parameters: - & m The mesh this should be based on. ecol The edges to collapse. *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Cuts the mesh from a point on one edge to a point on another, along a line drawn by looking at the mesh from a particular viewpoint. (See Edit 's Cut feature for an illustration.) - Parameters: - & m The mesh this should be based on. DWORD ed1 The edge that the cut starts on. The edge is indexed by face*3+side, so the start vertex is m.faces[ed1/3].v[ed1%3], and the end vertex is m.faces[ed1/3].v[(ed1+1)%3]. float prop1 The position on the edge to start the cut from. 0 means the start vertex of the edge, and 1 means the end vertex. DWORD ed2 The edge that the cut should end on. float prop2 The position on the edge to finish the cut on. 0 means the start vertex of the edge, and 1 means the end vertex. &norm The direction of view. The cut will take place on this "side" of the mesh, in the plane formed by this vector and the direction from the start to the end. bool fixNeigbors=TRUE Indicates whether the faces on the other side of each end of the cut should be split to prevent splits at the ends. bool split=FALSE Indicates whether the cut should actually split the mesh apart or just refine it by adding geometry. - - - - - Detaches a subset of the geometry from the mesh given, either separating it as a new element or creating a new mesh with it. - Parameters: - & m The mesh this should be based on. *out The new mesh into which the detached portion can be put. (If elem is TRUE, this is not used and may be NULL.) fset The selection to detach. If faces is TRUE, this is a face selection. Otherwise, it's a vertex selection. BOOL faces If TRUE, we should detach the selected faces; otherwise, we should detach the selected vertices. BOOL del Indicates whether the detached portion should be deleted from the original mesh. BOOL elem If TRUE, we're actually just detaching to an element, and the out mesh will not be used. - - - - - Divides the specified edge, adding a point and dividing faces to match. - Parameters: - & m The mesh this should be based on. DWORD ed The edge to divide, indexed as face*3+side. float prop=.5f The proportion along the edge where the division should occur. 0 is the start vertex, m.faces[ed/3].v[ed%3], and 1 is the end vertex, m.faces[ed/3].v[(ed+1)%3]. *el=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own if needed. bool visDiag1=FALSE Indicates whether the diagonal connecting the new point on this edge with the far corner of face ed/3 should be visible. bool fixNeighbors=TRUE Indicates whether the face on the other side of this edge, that is, the face using this edge that isn't ed/3, should be divided as well to prevent the introduction of a seam. bool visDiag2=FALSE Indicates whether the diagonal connecting the new point on this edge with the far corner of the face on the other side of the edge should be visible. (Not used if fixNeighbors is FALSE.) bool split=FALSE Indicates whether the method should create separate vertices for the two halves of the edge, splitting the mesh open along the diagonal(s). - - - - - Divides all the selected edges in half, creating new points and subdividing faces. - Parameters: - & m The mesh this should be based on. eset The edges to divide. *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Divides the selected face into 3, by introducing a new point on the face and splitting the original face along lines from the corners to the new point. - Parameters: - & m The mesh this should be based on. DWORD f The face to divide. float *bary=NULL A pointer to the barycentric coordinates of the new point on the face. If NULL, the center of the face is used. Barycentric coordinates on a triangle are a set of three numbers between 0 and 1 that add up to 1. Any point on a triangle can be uniquely described by a set of these. The point corresponding to barycentric coordinates (a,b,c) on a face with corners A,B,C is a*A + b*B + c*C. - - - - - Divides the selected faces into 3, by creating their center points and splitting the original faces along lines from the corners to the center. - Parameters: - & m The mesh this should be based on. fset The faces to divide. *mop=NULL If non-NULL, this points to an implementation of class which can be used to interrupt the algorithm if it's taking too long. See class for details. - - - - - Tessellates the mesh. This algorithm is exactly the one used in the Tessellate modifier, when operating on "Faces" (triangle icon) and in "Edge" type. - Parameters: - & m The mesh this should be based on. fset The faces to tessellate. float tens The tension for the edge tessellation. This value should be fairly small, between 0 and .5, and corresponds to the value in the Tessellate, Edit , or Editable UI's divided by 400. *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . *af=NULL A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own . *mop=NULL If non-NULL, this points to an implementation of class which can be used to interrupt the algorithm if it's taking too long. See class for details. - - - - - "Explodes" the mesh into separate elements. - Parameters: - & m The mesh this should be based on. float thresh The threshold angle between faces that indicates whether they should be in the same or different element. bool useFaceSel=FALSE Indicates whether the mesh's current face selection should be used or if the whole mesh should be exploded. *af=NULL A pointer to the adjacent face list for this mesh. If NULL, the method constructs its own . - - - - - Performs the topological changes necessary to extrude the indicated edges. (The geometric component is handled later by the Bevel method.) - Parameters: - & m The mesh this should be based on. eset The edges to extrude. > *edir=NULL Fills in the directions for moving all the relevant vertices to handle the geometric part of the extrusion. See the Edit or Editable source in MAXSDK/SAMPLES/MODIFIERS and MAXSDK/SAMPLES/MESH/EDITABLEMESH to see how this is used. - - - - - Performs the topological changes necessary to extrude the indicated faces. (The geometric component is handled later by the Bevel method.) - Parameters: - & m The mesh this should be based on. fset The faces that should be extruded. *el=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - This method resets the vertex corners. - Parameters: - & m The mesh this should be based on. - - - - - Resets all the vertex weights to 1. - Parameters: - & m The mesh this should be based on. - - - - - Sets the indicated faces to have face alpha. - Parameters: - & m The mesh this should be based on. fset The faces that should be affected. float alpha The amount of alpha int mp=MAP_ALPHA The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel. - - - - - Sets the indicated vertices to have face alpha. - Parameters: - & m The mesh this should be based on. vset The vertices that should be affected. float alpha The amount of alpha int mp=MAP_ALPHA The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel. - - - - - Sets the indicated faces to have vertex colors all equal to the color value specified. (This often involves creating new vertex color map vertices, so faces that neighbor the indicated faces are not affected.) - Parameters: - & m The mesh this should be based on. fset The faces that should be affected. VertColor vc The desired color. int mp=0 The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel. - - - - - Sets all vertex color map vertices associated with the indicated vertices to the specified color. - Parameters: - & m The mesh this should be based on. vset The vertices that should be affected. If more than one map vertex is used at this vertex, all of them have their colors set. VertColor vc The desired color. int mp=0 The map channel. Use 0 for normal vertex colors, MAP_SHADING for the illumination channel, and MAP_ALPHA for the alpha channel. - - - - - Sets the weights of the specified vertices. (These weight values are only used in MeshSmooth NURMS mode as of 3ds Max 3.0.) - Parameters: - & m The mesh this should be based on. vset The vertices that should have their weights set. float weight The weight to set. - - - - - "Turns" the specified edge. Only works on edges that have a face on both sides. These two faces are considered as a quad, where this edge is the diagonal, and remapped so that the diagonal flows the other way, between the vertices that were opposite this edge on each face. - Parameters: - & m The mesh this should be based on. DWORD ed The edge to turn, indexed as face*3+side. *ae=NULL A pointer to the adjacent edge list for this mesh. If NULL, the method constructs its own . - - - - - Welds all vertices that are sufficiently close together. - Parameters: - & m The mesh this should be based on. vset The vertices that are candidates for being welded. float thresh The maximum distance (in object space units) between two vertices that will allow them to be welded. - Returns TRUE if any vertices were welded, FALSE if none were within threshold. - - - - - Welds the specified vertices together into one vertex, no matter how far apart they are. - Parameters: - & m The mesh this should be based on. vset The vertices that should be welded. *weldPoint=NULL If non-NULL, this points to the location we'd like to put the weld result. (If NULL, the result is put at the average location of the selected vertices.) - - - - - This method is designed for internal use, in UnifyNormals, but may also be called directly. - Parameters: - & m The mesh this should be based on. fset The faces that should be affected. int face The starting face to propagate normal directions from. & af The adjacent face list corresponding to the mesh. Required, can't be made locally, for efficiency's sake. & done Keeps track of which faces have had their normals unified. Faces that are set here when the call is made will not be processed, and will not be crossed to reach other faces. Faces that are still clear upon completion were not processed, probably because they were on a separate element from "face". BOOL bias=1 Used to keep track of whether the current face has been oriented correctly. For example, if the starting face was not selected in fset, and therefore doesn't have the right orientation, but you still want selected faces in the same element to be corrected, you would submit FALSE here. - - - - - Unifies normals on selected faces, making the normals consistent from face to face. - Parameters: - & m The mesh this should be based on. fset The faces that should be affected. Nonselected faces can be traversed by the algorithm, but they will not be corrected if their normals are pointing the "wrong" way. *af=NULL A pointer to the adjacent face list corresponding to the mesh. If NULL, an adjacent face list is computed by the method. - - - - - Slices the mesh along the specified slicing plane. - Parameters: - & m The mesh this should be based on. N The normal of the slice plane. float off These parameters define the slicing plane as all points p satisfying the equation DotProd(p,N) = off. N should be normalized. bool sep=FALSE Indicates whether the slice should separate the mesh into two separate elements (if TRUE) or just refine the existing mesh by splitting faces (if FALSE). bool remove=FALSE Indicates whether the slice should remove the portion of the mesh "below" the slicing plane, where "below" is defined as the area where DotProd (p,N) - Returns TRUE if any faces were sliced, FALSE if none were sliced. - - - - - Description: - This is a virtual class which both Editable (class EditTriObject) and Edit (class EditMeshMod) subclass off of. It contains interface methods for editable meshes, much like the class contains interface methods for modifiers and objects that can select sub-object parts of meshes. - - - - - This method is used to notify the that at least one of its associated s has changed. - Parameters: - ChannelMask channels This represents the parts of the local data that have changed. One or more of the following values: TOPO_CHANNEL, GEOM_CHANNEL, TEXMAP_CHANNEL, MTL_CHANNEL, SELECT_CHANNEL, SUBSEL_TYPE_CHANNEL, DISP_ATTRIB_CHANNEL, VERTCOLOR_CHANNEL, GFX_DATA_CHANNEL - - - - - This method is used to start up one of the interactive command modes of the editable mesh. - Parameters: - meshCommandMode mode The mode to start. One of the following values: McmCreate, McmAttach, McmExtrude, McmBevel, McmChamfer, McmSlicePlane, McmCut, McmWeldTarget, McmFlipNormalMode, McmDivide, McmTurnEdge - - - - - This method performs the equivalent operation as a button press in the editable mesh UI. - Parameters: - meshButtonOp opcode One of the following values: MopHide, MopUnhideAll, MopDelete, MopDetach, MopBreak, MopViewAlign, MopGridAlign, MopMakePlanar, MopCollapse, MopTessellate, MopExplode, MopSlice, MopWeld, MopShowNormal, MopAutoSmooth, MopRemoveIsolatedVerts, MopSelectOpenEdges, MopCreateShapeFromEdges, MopFlipNormal, MopUnifyNormal, MopVisibleEdge, MopInvisibleEdge, MopAutoEdge, MopAttachList, MopSelectByID, MopSelectBySG, MopClearAllSG, MopSelectByColor - - - - - This method allows you to get the edit spline parameters from the command panel. Currently not in use. - Parameters: - meshUIParam uiCode One of the following values; MuiSelByVert, MuiIgBack, MuiIgnoreVis, MuiSoftSel, MuiSSUseEDist, MuiSSEDist, MuiSSBack, MuiWeldBoxSize, MuiExtrudeType, MuiShowVNormals, MuiShowFNormals, MuiPolyThresh, MuiFalloff, MuiPinch, MuiBubble, MuiWeldDist, MuiNormalSizeint &ret The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit spline parameters from the command panel. Currently not in use. - Parameters: - meshUIParam uiCode One of the following values; MuiSelByVert, MuiIgBack, MuiIgnoreVis, MuiSoftSel, MuiSSUseEDist, MuiSSEDist, MuiSSBack, MuiWeldBoxSize, MuiExtrudeType, MuiShowVNormals, MuiShowFNormals, MuiPolyThresh, MuiFalloff, MuiPinch, MuiBubble, MuiWeldDist, MuiNormalSizeint val The value to set. - Default Implementation: - { } - - - - - This method allows you to get the edit spline parameters from the command panel. Currently not in use. - Parameters: - meshUIParam uiCode One of the following values; MuiSelByVert, MuiIgBack, MuiIgnoreVis, MuiSoftSel, MuiSSUseEDist, MuiSSEDist, MuiSSBack, MuiWeldBoxSize, MuiExtrudeType, MuiShowVNormals, MuiShowFNormals, MuiPolyThresh, MuiFalloff, MuiPinch, MuiBubble, MuiWeldDist, MuiNormalSizefloat &ret The returned value. - Default Implementation: - { } - - - - - This method allows you to set the edit spline parameters from the command panel. Currently not in use. - Parameters: - meshUIParam uiCode One of the following values; MuiSelByVert, MuiIgBack, MuiIgnoreVis, MuiSoftSel, MuiSSUseEDist, MuiSSEDist, MuiSSBack, MuiWeldBoxSize, MuiExtrudeType, MuiShowVNormals, MuiShowFNormals, MuiPolyThresh, MuiFalloff, MuiPinch, MuiBubble, MuiWeldDist, MuiNormalSizefloat val The value to set. - Default Implementation: - { } - - - - - Description: - This class provides a standard interface for modifiers and objects that use mesh deltas - specifically Edit and Editable . Both Edit and Editable have a current "state", which can be modified by MeshDeltas. In Editable , this "state" is an actual mesh, while in Edit , this is one per . This class provides a standard interface to these: "MeshDeltaUser" and "MeshDeltaUserData". - - - - - This method applies the . Everything that happens in Edit and Editable goes through this method. Note that in Edit , the (EditMeshData) is separate from the (EditMeshMod), though in Editable , EditTriObject subclasses from both of them. There's essentially one mesh that can be edited per , so ApplyMeshDelta is the way to edit that mesh. ApplyMeshDelta typically handles adding Restore objects (if theHold.Holding()), clearing out any temporary local caches that are invalidated, and notifying the pipeline that the mesh has changed. - Parameters: - &md The mesh delta to apply. *mdu Points to the mesh delta user. TimeValue t The time to apply the mesh delta. - - - - - Returns a pointer to the object for this application of the Edit modifier. This is only non-NULL in Edit . - Default Implementation: - { return NULL; } - - - - - In 3ds Max 3.0 and later the user may work with more than 2 mapping channels. When the mapping channel is set to a value greater than 1 (by using a UVWMap for example) then an instance of this class is allocated for each channel up to the value specified. It maintains the mapping information for a single channel. An array of instances of this class is carried by the class. All methods of this class are implemented by the system. - - - - - One or more of the flags in Mapping Flags. - - - - - of texture vertices. This stores the UVW coordinates for the mapping channel. Note: typedef UVVert; - - - - - The texture vertex faces. There needs to be one for every face in the , but there can be three indices into the UVVert array that are any UV's. - - - - - The number of elements in the UVVert array. - - - - - The number of elements in the array. - - - - - Returns the number of UVVerts. - - - - - Sets the number of UVVerts allocated to the specified value. - - The new number of UVVerts to allocate. - If TRUE, any previously allocated UVVerts are maintained (up to the maximum set by vn). If FALSE they are discarded. Defaults to False. - - - - Returns the number of TVFaces. - - - - - the number of TVFaces allocated to the specified value. - - The new number of TVFaces to allocate. - If TRUE any previously allocated TVFaces are maintained (up to the maximum set by fn). If FALSE they are discarded. Defaults to FALSE. - The length of the existing TVFaces array. - - - - Clears (deletes) the tv and tf arrays and sets the counts to zero. - - - - - This method returns a with size vnum, where isolated (unused) vertices are selected. - - - - - This method is used to delete vertices from a mesh map. - - The array of bits where mapping vertices you want to delete are set. - This is an optional parameter. If non-NULL, it's filled with a record of which faces, if any, were using the specified map verts and should therefore be deleted or considered invalid. (Note: in normal usage, it's preferable to remove any compromised faces deleting vertices, so this parameter would rarely be used). Defaults to NULL - - - - This method is used to delete faces from a mesh map. NOTE: The number and arrangement of faces in a should always agree with the "parent" mesh. It's safest in most cases to just let this be handled by Mesh::DeleteFaceSet(). - - This is a list of mapping faces to delete. - If non-NULL, this is filled with a list of map vertices that were used by the deleted faces but not by any remaining faces. (This is a list of "newly isolated" map vertices). Defaults to NULL. - - - - Sets the specified flag(s). - - The flags to set. See the public data member flags above. - - - - Clears the specified flag(s). - - The flags to clear. See the public data member flags above. - - - - Returns TRUE if the specified flag(s) are set; otherwise FALSE. - - The flags to check. See the public data member flags above. - - - - Returns TRUE if this mapping channel is being used; otherwise FALSE. - - - - - Exchanges the data between this object and the specified one. The flags, vnum and fnum values are exchanged. The UVVert and pointers are swapped. - - The instance to swap with. - - - - Assignment operator. - - The to assign. - - - - Description: - This class enables the Select and the Editable to share clipboard data for named selection sets. - Data Members: - MSTR name; - - The name of the clipboard. - - <BitArray*> sets; - - This table of pointers stores the selected state for the vertex, edge and face states of the mesh. - - - - - See Also: class This class is used to store specified normal information for a particular face in a . An array of these faces is used in class to match vertex normals to vertices. - - - Each contains a bit indicating whether each corner is specified, and a Normal ID for each specified corner. - - - - - Resets all corners to "unspecified". - - - - - Accessor for normal in a particular corner of the face. - - - The index of the normal (in the owner 's normal array) - - The (zero-based) index of the corner of the face - - - - Setter for the normal used in a particular corner of the face. - - - - The (zero-based) index of the corner of the face - The index of the normal (in the owner 's normal array). - - - - return an array of 3 normal IDs - - - an array of 3 normal IDs - - - - - Indicates whether the normal used in a particular corner is specified or not. - - - - - Sets the normal used by the corner to be specified or not. - - - - - Sets the normal used by the corner to be specified, and to use the particular normal given. - - - - - Sets this face to have all its normals specified. - - - - - Reverses the order of the normals. Corner 0 is unaffected, but corner 1 is switched with corner 2. - - - - - Standard = operator. - - - - - Using DebugPrint, output information about this . If "printAll" is true, it will print normal IDs for both specified and unspecified normals; otherwise it'll print only the specified ones. Typical output for a partially specified face: "_7 3 _5" (printAll==true) or "_ 3 _" (printAll==false). A newline is printed at the end. - - - - - Save to file. - - - - - Load from file. - - - - - This class is an interface used to store user-specified normals (such as those created in the Edit Normals modifier). These normals have very limited pipeline support. They are used for viewport display, but not for rendering. - - - The contains three types of normals: - - - - - Sets flags in the . Generally, the only flag that clients should set is the MESH_NORMAL_MODIFIER_SUPPORT flag. See GetFlag for more details. - - - - - Clears the flags given. See GetFlag for more details on flags. - - - - - Gets flags in the . - - - supports the following flags: MESH_NORMAL_NORMALS_BUILT Indicates that non-specified normals have been constructed using smoothing groups. If not set, non-specified normals may be invalid. MESH_NORMAL_NORMALS_COMPUTED Indicates that non-explicit normals have been computed using geometrically computed face normals. (If not set, only explicit normals may be assumed to be pointing the right direction.) MESH_NORMAL_MODIFIER_SUPPORT This flag should be set by modifiers that want to support the edited normals. See class TriObjectNormalModifier for more details. If this flag is not specifically set in a modifier that alters PART_GEOM or PART_TOPO of a , any specified normals will be cleared after the modifier is evaluated. - - - - - Initializes all data members - do not use if already allocated! - - - - - shrinks allocation down to actual number of normals. - - - - - Deletes everything. - - - - - Deletes everything, frees all memory. - - - - - Returns true if there are any explicit normals set. - - - - - all normals to be explicit. - - - - - If true, all normals will be set to explicit. If false, all normals will be set to non-explicit - - - - This method dumps all unspecified normals. Best to use only from within CheckNormals. - - - - - Fills in the mpSpecNormal data by building all the unspecified normals, and computing non-explicit ones. - - - Does nothing if normal faces not allocated yet! - - Requires an accurate mpParent pointer. - - - - - This method just recomputes the directions of non-explicit normals, without rebuilding the normal list. - - - Requires an accurate mpParent pointer. - - - - - This checks our flags and calls BuildNormals, ComputeNormals as needed. - - - Requires an accurate mpParent pointer. - - - - - For each face index map entry faceIndexMap[f] which is valid, i.e. faceIndexMap[f] >= 0, the face targetFace = faceIndexMap[f] + offset of this object is defined as a copy of source face f of object sourceNormals, which may be the same as this object. In particular, face targetFace is allocated if necessary, and any vertex normals which are set as specified for the source face are copied to the corresponding vertices of the target face. The explicitness of normals is also preserved in the copy. Note that the operation will fail if sourceNormals is the same as this object, and the index map contains undefined copies, i.e. if for any f we have the conditions 0 <= faceIndexMap[f], targetFace < faceIndexMap.Count(), and faceIndexMap[targetFace] >= 0. - Flag indicating whether copy operation was successful. - - specified normals object containing the source face data - map from source to target faces; the condition faceIndexMap[f] < 0 indicates that source face f is not to be copied - index offset to be applied to all valid entries of faceIndexMap in order to obtain the target face index; note that nnegative values are invalid, and will result in failure and a false return value - - - - Transforms the normals. If isGeomTransform is true, the normals are transformed consistent with the transformation defined by matrix transformMat being applied to the geometry, meaning that the normal vectors are multiplied by transpose of the inverse of transformMat. If isGeomTransform is false, then the matrix portion of transformMat is simply applied directly. In both cases, we disregard the translation vector, and renormalize the affected normal vectors. Note that if transformMat represents a rotation, then the result is independent of the choice of isGeomTransform, since the matrix will be orthogonal. - Flag indicating whether any normals were altered. In particular, if the specified values of transformMat and isGeomTransform indicate an identity transformation, we will return false. - - matrix representing the transformation to be applied - when true, only selected normals are altered, otherwise, the transformation is applied to all defined normals - when useSelection is true, the selected normals are defined by normalSelection if not null, or the usual member selection, otherwise - when true, matrix transformMat is interpreted as a transformation applied to the associated geometry, as discussed above - - - - A callback used while doing a lengthy operation to a mesh. A developer creates an instance of this class and passes a pointer to it into the CalcBoolOp() or Optimize() function. - - - - - - This method is called once with the total number of increments. - - The total number of increments. - - - - This method is called over and over with a new value for p. The percentage complete is p/total. - If TRUE processing will continue. If FALSE processing is aborted. - - The number completed so far. - - - - A developer may derive a class from this class, put any required data in it, and then hang this data off a . This is done using the methods of Class : void SetRenderData(MeshRenderData *p); Sets the mesh render data hung off this . * GetRenderData(); Gets a pointer to the . - - - - - - Converts a face selection to an element selection. - - NOTE: This method can only produce accurate results with culling if we are - - certain that the face selection corresponds to the results of the last call to - - the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - Parameters: - & mesh - - The mesh that owns this interface - - *af - - A pointer to an accurate based on this mesh. (This is used to - - construct elements.) - - & faceSel - - The face selection representing actual hits in the viewport. - - & elementSel - - This is where the output Element selection is stored. - - - - - - - Converts a face selection to a polygon selection. - - NOTE: This method can only produce accurate results with culling if we are - - certain that the face selection corresponds to the results of the last call to - - the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - Parameters: - & mesh - - The mesh that owns this interface - - *af - - A pointer to an accurate based on this mesh. (This is used to - - construct elements.) - - & faceSel - - The face selection representing actual hits in the viewport. - - & polygonSel - - This is where the output polygon selection is stored - - float faceThresh - - The angle threshold between faces, in radians, that would mark them as - - belonging to separate polygons. - - bool ignoreVisEdge=false - - If true, this tells the system to ignore visible edges in constructing - - polygons, and instead rely entirely on the face threshold to distinguish them. - - - - - - - Converts a vertex selection to a "By Vertex" edge selection. - - NOTE: This method can only produce accurate results with culling if we are - - certain that the vertex selection corresponds to the results of the last call - - to the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - - - Parameters: - & mesh - - The mesh that owns this interface - - & vertexSel - - The face selection representing actual hits in the viewport - - & edgeSel - - The face selection representing actual hits in the viewport - - - - - - - Converts a vertex selection to a "By Vertex" polygon selection. - - NOTE: This method can only produce accurate results with culling if we are - - certain that the vertex selection corresponds to the results of the last call - - to the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - - (Note that we can't just combine VertexToFace and FaceToPolygon to obtain the - - results of this method, because we won't have accurate culling info.) - Parameters: - & mesh - - The mesh that owns this interface - - *af - - A pointer to an accurate based on this mesh. (This is used to - - construct elements.) - - &vertexSel - - The vertex selection representing actual hits in the viewport. - - & polygonSel - - This is where the output polygon selection is stored - - float faceThresh - - The angle threshold between faces, in radians, that would mark them as - - belonging to separate polygons. - - bool ignoreVisEdge=false - - If true, this tells the system to ignore visible edges in constructing - - polygons, and instead rely entirely on the face threshold to distinguish them. - - - - - - - Converts a vertex selection to a "By Vertex" element selection. - - NOTE: This method can only produce accurate results with culling if we are - - certain that the vertex selection corresponds to the results of the last call - - to the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - - (Note that we can't just combine VertexToFace and FaceToElement to obtain the - - results of this method, because we won't have accurate culling info.) - Parameters: - & mesh - - The mesh that owns this interface - - *af - - A pointer to an accurate based on this mesh. (This is used to - - construct elements.) - - &vertexSel - - The vertex selection representing actual hits in the viewport. - - &elementSel - - This is where the output element selection is stored - - - - - - - Accesses the describing which subobject components were culled in - - last hit-testing. In its usual usage, this data will only be set by - - Mesh::SubObjectHitTest, and will only be used by the other methods of - - . This information does not affect selection conversion - - if the MESH_SELCONV_REQUIRE_ALL flag is not set. - - - - - Description: - This is a class for caching winged edge lists, face adjacency lists, face and edge clusters, vertex normals, and other derived data about a mesh. - - There is a SetMesh() method to set the current mesh that the TempData is based on, then there's a series of methods to update the cache and return some sort of derived data. All of these methods follow the form: DerivedData is the container for the derived data requested (often a simple table, though there are some specialized classes returned from some methods). If the data has already been computed, the parameters are ignored and the cached data is returned. Otherwise, the data is computed from the parameters and the current mesh. - - There are no procedures in place to detect changes in parameters or the mesh since the last time a method was called, so it's the calling routine's responsibility to free invalid structures. If you know that only certain pipeline channel, such as GEOM_CHANNEL, have changed, you can use the Invalidate(ChannelMask channels) method. (GEOM_CHANNEL would free the distances-to-selected-vertices, for example, but not the List.) - - In particular, there is no way for the to know when its mesh pointer is no longer valid, so it's vital that the calling routine clear the mesh (with SetMesh(NULL)) or stop using the when this happens. - - All data members are private. They basically consist of a series of pointers which are initialized to NULL and then filled with allocated derived data as requested. There is also a NULL-initialized, private mesh pointer which is set with SetMesh(). - - Editable and Edit both use this class to hold all the varieties of temporary, cached data they create - examples are vertex normals and face clusters. This is called "ETTempData" in Editable and "EMTempData" in Edit . - - To use , just set it to your mesh and start asking for stuff: - - *m) { - - mtd(m); - - List. - - ae = mtd.AdjEList (); - - } - - - - - Returns an adjacent edge list. See class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - - - - - Returns an adjacent face list. See class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - - - - - Returns a face cluster list, which groups selected faces into "clusters" for transformation. See class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - - - - - Returns an edge cluster list, which groups selected edges into "clusters" for transformation. See class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - - - - - Returns an index of which cluster, if any, each vertex is in. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. - Parameters: - DWORD sl - - Selection level. This should be either MESH_EDGE or MESH_FACE, to indicate whether the vertex cluster information should be based on edge or face clusters. Note that this parameter is ignored if there's already a vertex cluster cache. - A table of DWORD's is returned, one for each vertex. If (*VertexClusters(sl))[i] is UNDEFINED, vertex i is not in any cluster. Otherwise, the value for vertex i is the cluster index. - - - - - Returns average normals for each cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. Note that cluster centers and normals are computed and cached at the same time, when you call either method. - Parameters: - DWORD sl - - Selection level. This should be either MESH_EDGE or MESH_FACE, to indicate whether the clusters we're talking about are the edge or face clusters. Note that this parameter is ignored if there's already a cluster normal cache. - A table of 's is returned, one for each cluster. The values are already normalized to length 1. - - - - - Returns mean centers for each cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. Note that cluster centers and normals are computed and cached at the same time, when you call either method. - Parameters: - DWORD sl - - Selection level. This should be either MESH_EDGE or MESH_FACE, to indicate whether the clusters we're talking about are the edge or face clusters. Note that this parameter is ignored if there's already a cluster center cache. - A table of 's is returned, one for each cluster. - - - - - Uses the current cluster center and normal caches to return the "objectspace to clusterspace" transform. This is the tranform of the "local" axis in moving edge or face clusters in Edit(able) . If the cluster centers & normals have not been cached, the identity matrix is returned; thus the control over whether this is an edge or face cluster is handled by the last call to ClusterCenters or ClusterNormals. - Parameters: - int clust - - The cluster you want the transform for. - - - - - Returns a table of local average normals for vertices. This is equivalent to the average normals computed by the standalone function: - - > & vnormals) - - If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - - - - - Returns Vertex Selection weights (for affect region). If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. Weights are based on an Affect Region type falloff from the current selection. - Parameters: - BOOL useEdgeDist - - If useEdgeDist is TRUE, the distance between vertices is computed along edges. If FALSE, it's computed directly through space. - - int edgeIts - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.) - - WARNING: If useEdgeDist is FALSE, this is an n-squared algorithm: it compares every vertex not in the cluster with every vertex in it. If useEdgeDist is TRUE, the time it takes is proportional to the number of verts in the cluster times edgeIts. - - BOOL ignoreBack - - If TRUE, vertices with a normal (as computed in VertexNormals) that points more than 90 degrees away from the average normal of theselection are not given any partial selections. They're either 1 if selected or 0 otherwise. - - float falloff - - The limit distance of the effect. If distance > falloff, the function will always return 0. - - float pinch - - Use this to affect the tangency of the curve near distance=0. Positive values produce a pointed tip, with a negative slope at 0, while negative values produce a dimple, with positive slope. - - float bubble - - Use this to change the curvature of the function. A value of 1.0 produces a half-dome. As you reduce this value, the sides of the dome slope more steeply. Negative values lower the base of the curve below 0. - Returns a table of float values, one per vertex, that are 1.0 if the vertex is in the current selection, 0.0 if it's more than falloff distance (or more than edgeIts edges, if (useEdgeDist)), and AffectRegionFunction((*SelectionDist(useEdgeDist, edgeIts)), falloff, pinch, bubble) otherwise. - - - - - This computes the distances of the unselected vertices from the selected vertices. - - - Computes the current distance of each vertex from the current selection. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. The term "Selected verts" below refers to the vertices that are selected in the mesh's current selection level. (See the method GetTempSel for details.) - A table consisting of one float value per vertex. If this value is 0, the vertex is either selected or on top of a selected vertex. Otherwise it represents the distance to the closest selected vertex. If useEdgeDist is TRUE, values of -1.0 are returned for vertices with no edgeIts-length path to a selected vertex. - - If TRUE, the distance between vertices is computed along edges. If FALSE, it's computed directly through space. - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.). WARNING: If useEdgeDist is FALSE, this is an n-squared algorithm: it compares every nonselected vertex with every selected one within the falloffLimit. If useEdgeDist is TRUE, the time it takes is proportional to the number of selected vertices times edgeIts. - = -1.0f this limits the number of unselected vertices to check against Only vertices that fall within the selected vertice bounding box + this limit will be computed. If this value is -1.0 all vertcies will be computed - - - - Computes the current distance of each vertex from the specifed cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - Parameters: - DWORD sl - - Indicates whether we should use edges (MESH_EDGE) or faces (MESH_FACE) to construct the clusters, if needed. - - int clustId - - The index of the cluster we're weasuring distance from. - - BOOL useEdgeDist - - If useEdgeDist is TRUE, the distance between vertices is computed along edges. If FALSE, it's computed directly through space. - - int edgeIts - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.) - - WARNING: If useEdgeDist is FALSE, this is an n-squared algorithm: it compares every vertex not in the cluster with every vertex in it. If useEdgeDist is TRUE, the time it takes is proportional to the number of verts in the cluster times edgeIts. - A table consisting of one float value per vertex. If this value is 0, the vertex is either selected or on top of a vertex in the cluster. Otherwise it represents the distance to the closest selected vertex. If useEdgeDist is TRUE, values of -1.0 are returned for vertices with no edgeIts-length path to a vertex in the cluster. - - - - - Returns the direction each vertex should be going, after a topological edge extrusion, to handle the geometric extrusion. This should be obtained after applying a MeshDelta::ExtrudeEdges() to the mesh to obtain valid results. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - Parameters: - > *edir - - This should be the edge direction table filled out by MeshDelta::ExtrudeEdges. It is necessary. - - int extrusionType - - This is one of MESH_EXTRUDE_CLUSTER or MESH_EXTRUDE_LOCAL, to indicate whether vertices should move according to cluster or local face normals. - A table of 's, one per vertex, representing the direction each vertex should move for further extrusion. The size of each nonzero entry is set to 1. - - - - - Returns the direction each vertex should be going, after a topological face extrusion, to handle the geometric extrusion. This should be obtained after applying a MeshDelta::ExtrudeFaces to the mesh to obtain valid results. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - Parameters: - int extrusionType - - This is one of MESH_EXTRUDE_CLUSTER or MESH_EXTRUDE_LOCAL, to indicate whether vertices should move according to cluster or local face normals. - A table of 's, one per vertex, representing the direction each vertex should move for further extrusion. The size of each nonzero entry is set to 1. - - - - - This computes nothing; it merely returns the current extrusion direction cache, if any. The extrusion direction is controlled by the first call to EdgeExtDir or FaceExtDir since the last invalidation. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - - - - - This produces the "Outline" direction of all vertices, based on the current face selection. "Outlining" is the direction vertices move to move edges of the current face selection outward at a constant rate. They are not set to length 1, but rather to whatever "rate" best makes the outline edges movemost consistently, without changing their angles. - Parameters: - int extrusionType - - This is one of MESH_EXTRUDE_CLUSTER or MESH_EXTRUDE_LOCAL, to indicate whether vertices should move according to cluster or local face normals. - - - - - Returns the cache of a ChamferData for use in the methods, - - *ae=NULL); - - *ae=NULL); - - *ae=NULL); - - Unlike other methods, this method makes no calculations based on the current mesh, but merely supplies a memory cache. - - - - - Invalidates all data based on the specified part of the mesh. In the following chart, the columns represent the channels GEOM_CHANNEL (G), TOPO_CHANNEL (T), SELECT_CHANNEL (S), and SUBSEL_TYPE_CHANNEL (U). - - X's indicate dependency of the specified data cache on the given channel. - - Method to get cache G T S U - - AdjEList X - - AdjFList X - - FaceClusters X X - - EdgeClusters X X - - VertexClusters X X X - - ClusterCenters X X X X - - ClusterNormals X X X X - - VertexNormals X X - - SelectionDist X X X X - - ClusterDist X X X X - - VSWeight X X X X - - The extrusion direction methods could also be said to be dependent on all four channels, but is currently handled separately in freeBevelInfo. ChamferData is handled in freeChamferData, and is not based on the - - cached mesh. - - Sample use: Suppose you use a to modify a mesh, twice: - - & m) { - - foo; - - foo.SetMesh (&m); - - md(m); - - md.Op1 (m, foo.AdjEList()); // insert op of choice here - - md.Apply (m); - - foo.Invalidate (md.PartsChanged ()); - - md.ClearAllOps (); - - md.Op2 (m, foo.VSWeights ()); - - md.Apply (m); - - foo.Invalidate (md.PartsChanged ()); - - } - - Only the parts of foo that are dependent on what was changed by the first meshdelta are freed. The other parts, if any, remain cached for further operations. - Parameters: - ChannelMask channels - - One or more of the following channels: - - GEOM_CHANNEL, TOPO_CHANNEL, SELECT_CHANNEL, SUBSEL_TYPE_CHANNEL - - - - - Uncaches (frees) the distance dependent data returned by VSWeight, SelectionDist, and ClusterDist. - - - - - Frees the VSWeight data. This is useful, e.g., if the mesh has not changed, but you wish to change the falloff, pinch, or bubble parameters to get new vertex selection weights. - - - - - Mainly for internal use, this frees just the cluster distance data. - - - - - Frees only the extrusion direction data. - - - - - Frees only the chamfer data structure. - - - - - Frees all cached data. - - - - - Sets the internal mesh pointer to m. - Parameters: - *m - - Points to the mesh to set. - - - - - Extension class that adds functionality to class for parameter block-linked modeless UI. - Vanilla manages only modal ParamMaps, and those are destroyed when EndEditParams is called. This extension allows plugins to support modeless user interface rollups that are tied to parameter blocks. - The plugin developer may implement this method by deriving a plugin's class descriptor from this class alongside . - A pointer to this extension interface may be retrieved through a dynamic_cast from a . - - - - - Implemented by the System. - - Returns the number of modeless parameter map2s, which are maintained by the class. - - - - - Implemented by the System. - - Gets the modeless parameter map indicated by the index. - - - A pointer to the modeless parameter map2 requested. - - The index of the desired modeless parameter map. - - - - Implemented by the System. - - Returns a pointer to the parameter map2 as specified by the parameter block2 pointer and optional map ID index passed. - - Points to the parameter block descriptor2 associated with this parameter map. - This parameter specifies the ID of the map/rollout to get. - - - - Implemented by the System. - - Adds a parameter map to the list of modeless maps being managed. - - Points to the parameter map2 to add to the list. - - - - Implemented by the System. - - Removes a parameter map from the list of modeless maps being managed. - - Points to the parameter map2 to remove from the list. - - - - Implemented by the System. - - Removes a parameter map from the list of modeless maps being managed using its id. - - Provides the id of the map to remove from the list. - - - - Implemented by the System. - - Destroys any parameter map associated with the given parameter block and ID. - This only destroys the parameter map associated with the ID, not the Qt widget. - - Gives the parameter block of the map to be destroyed - Gives the unique ID of the map to be destroyed - - - - This is the class from which you may derive Space and Space Warp (World Space) plug-ins. This class is subclassed off of so the modifier can put up a graphical representation in the viewport to use as a gizmo. - - - - - Implemented by the System. Returns the name of the modifier. - - If true, then the name returned should be localized in the language 3ds is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - - - - Implemented by the System. Sets the name of the modifier to the name passed. - - Specifies the name to set. - - - - This method is used internally. - - - - - This method is used internally. - - - - - Implemented by the System. This disables the modifier in the history browser (modifier stack). - - - - - Implemented by the System. This enables the modifier in the history browser (modifier stack). - - - - - Implemented by the System. This returns the status (enabled or disabled) of the modifier in the history browser. - Nonzero if enabled; otherwise 0. - - - - - Implemented by the System. Disables the modifier in the viewports (it remains active in the renderer unless DisableMod() above is used). - - - - - Implemented by the System. Enables the modifier in the viewports. - - - - - Implemented by the System. Returns nonzero if the modifier is enabled in the view ports; otherwise zero. - - - - - Implemented by the System. This turns off the modifier in the renderer - - - - - Implemented by the System. This turns on the modifier in the renderer - - - - - Implemented by the System. This returns the status (enabled or disabled) of the modifier in the renderer. - Nonzero if enabled; otherwise 0. - - - - - This method returns the validity interval of a modifier. It is simply the combination of the validity of all the modifier's parameters. It's used to determine when to cache in the pipeline, but is not directly responsible for determining when ModifyObject() is called. ModifyObject() is called when the pipeline needs to be evaluated either because someone sent a REFMSG_CHANGE message or the validity of the object does not include the current time. - If a modifier is not animated it's OK to simply return FOREVER from - this method. In the case where the modifier changes because a user changes a non-animated control in the user interface (for instance a check box), you can cause reevaluation by notifying your dependents of the change, i.e.: - - The time to calculate the . - - - - These are channels that the modifier needs in order to perform its modification. This should at least include the channels specified in ChannelsChanged() but may include more. Note that ChannelsUsed() is called many times but the channels returned should not change on the fly. - The channels required. See Object Channels. - Sample Code: - - - - - These are the channels that the modifier actually modifies. Note that ChannelsChanged() is called many times but the channels returned should not change on the fly. - The channels that are changed. See Object Channels - - - - - If a modifier want to make it possible to switch dynamically between changing the selection type that flows up the stack, or leaving it like it is, it can overwrite this. The default implementation indicates that it changes the selection type, if the SUBSEL_TYPE_CHANNEL is part of ChannelsChanged(). Note that ChannelsChanged() can not dynamically changed for various reasons. - - - - - Returns the same value as ChannelsUsed() above except GFX_DATA_CHANNEL will be ORed in if the TOPO_CHANNEL or the TEXMAP_CHANNEL are being used. - - - - - Returns the same value as ChannelsChanged() above except GFX_DATA_CHANNEL will be ORed in if the TOPO_CHANNEL, the TEXMAP_CHANNEL , or the VERTCOLOR_CHANNEL are being changed. - - - - - This is the type of object that the modifier knows how to modify. Simple modifiers that just modify points of an object can operate on generic 'Deformable' objects. Deformable objects are any type of object that has points. A modifier could also work on a particular type of object such as a or . - The of the item. You can request any for your input type. For example, . See Class IDs defined in plugapi.h>. - - - - - When InputType() returns anyObjectClassID, this method is used to determine whether the modifier can be applied to a specific object. An usage case of this would be a modifier that can only be applied to Arnold lights. The modifier could then modify the parameters of the Arnold light instance passing through it. - True if the modifier can be applied to the object - - The object to test. - - - - This method is called when an item in the modifier stack before this modifier sends a REFMSG_CHANGE message via NotifyDependents(). Consider the following example: Assume the modifier stack contains a Sphere , then a Bend, then a Edit . The Edit modifier does not have a reference to the Bend or the Sphere because it does not officially depend on these items. However it does depend on them in a certain sense, because it modifies the data that these items produce. So, if they change it may affect the modifier. A modifier may build a cache based on its input object. The modifier needs a way to know when to discard this cache because the input object has changed. Whenever one of the items before this modifier in the stack sends out a REFMSG_CHANGE message via NotifyDependents() to indicate it has changed this method is called. The modifier may respond in a way appropriate to it, for example by discarding its cache of the input object. It is not legal, to issue a NotifyDependent()'s in the NotifyInputChanged() method of a modifier, without checking for reentrancy. Imagine, you have an instanced modifier applied to the same object in the stack. Sending a refmsg from the NotifyInputChanged method will cause an endless loop. Simply putting a guard in, that checks for reentrancy should get rid of the problem. - - This is the interval from the message. It is reserved for future use - now it will always be FOREVER. - This is the partID from the message. - This is the message sent. - The for the pipeline that changed. If a modifier is applied to multiple objects, then there are ModApps in each pipeline that it is applied to. These ModApps are pointing to the same modifier. Consider the following example: Say you apply a Bend modifier to a Sphere, a Cylinder and a Box object. There are three ModApps but only one Bend modifier. Then you go to the Sphere and adjust its Radius. This will cause to be called on the Bend because the Bend's input changed. However only one of its inputs changed - only the Sphere changed and not the Cylinder or the Box. Therefore will be called once, and the passed in will be for the Sphere's changed pipeline. It is possible that all three objects could change at the same time. If an instanced float controller was assigned to the radius, width, and height - one parameter for each object - then the controller was adjusted in the function curve editor, all three items would change. In this case would be called three times on the Bend. Once for each pipeline, once with each . - - - - This is the method that actually modifies the input object. This method is responsible for altering the object and then updating the validity interval of the object to reflect the validity of the modifier. - - The time at which the modification is being done. - A reference to the . - The object state flowing through the pipeline. This contains a pointer to the object to modify. - The node the modifier is applied to. This parameter is always NULL for Space Modifiers and non-NULL for World Space Modifiers (Space Warps). This is because a given WSM is only applied to a single node at a time whereas an OSM may be applied to several nodes. This may be used for example by particle system space warps to get the transformation matrix of the node at various times. - - - - Modifiers that place a dependency on topology should return TRUE for this method. An example would be a modifier that stores a selection set base on vertex indices. This modifier depends on the indices being intact for it to operate correctly. - TRUE if the modifier depends on topology; otherwise FALSE. - - Reference to the . - - - - When a 3ds Max file is being saved, this method is called so that the modifier can save the localData structure that is hung off each . If the modifier doesn't store any data in the it can ignore this method. - One of the following values: IO_OK, IO_ERROR. - - You may use this pointer to call methods of to write data. - Pointer to the for the modifier. - - - - When a 3ds Max file is being loaded, this method is called so that the modifier can load the structure that is hung off each . If the modifier doesn't store any data in the it can ignore this method. - One of the following values: IO_OK, IO_ERROR. - - You may use this pointer to call methods of to read data. - A pointer to a pointer in the . The modifier must set this pointer to point at a new derived class. - - - - In cases where a modifier does not exist in the specified save version returned by GetSavingVersion(), or where a modifier employs new functionality which cannot be retained in the specified save version, it may return true to indicate that the owning object should be saved in a state with its modifier stack collapsed at least up to this modifier. - Flag indicating whether this modifier should be saved in a collapsed state for the specified save version. - - - - - Implemented by the System. This method will call the callback object proc method once for each application of the modifier. - - The callback object whose proc method is called. - - - - This method will retrieve the and index of this modifier for a given modifier context. - - Points to the for the modifier. - A pointer to the is returned here. - The zero based index of the modifier in the derived object is returned here. - - - - In case the modifier changes the object type (basically the os->obj pointer in ModifyObject) and changes the ExtensionChannel, it has to overwrite this method and copy only the channels that it doesn't modify/added already to the new object. - - - - - - - This function allows modifiers to find the nodes they are modifying. Normally, object-space modifiers don't have information on the node being modified. Modifiers may want to have the node's transform or material, for example, so it is necessary to search through the modifier stack to find the node. This method performs that operation. - In the Modifier::ModifyObject method, after constructing the and placing it in ModContext.localData, call GetNodeFromModData to get the node that is being modified. The returned pointer can be cached in the so that it is readily available for later use. - The node being modified (nullptr if none found) - - The pointer - The index of the node in the list of ReferenceMakers returned by DoEnumDependents, considering only nodes. - - - - This function allows modifiers to find the nodes they are modifying. Normally, object-space modifiers don't have information on the node being modified. Modifiers may want to have the node's transform or material, for example, so it is necessary to search through the modifier stack to find the node. This method performs that operation. - In the Modifier::ModifyObject method, call GetNodeFromModContext to get the node that is being modified. The returned pointer can be cached in the so that it is readily available for later use. - The node being modified (nullptr if none found) - - The pointer - The index of the node in the list of ReferenceMakers returned by DoEnumDependents, considering only nodes. - - - - The stores information about the space the modifier was applied in, and allows the modifier to store data is needs for its operation. All methods are implemented by the system. - - - - - This matrix represents the space the modifier was applied in. The modifier plug-in uses this matrix when it deforms an object. The plug-in first transforms the points with this matrix. Next it applies its own deformation. Then it transforms the points back through the inverse of this transformation matrix. - - - - - The Bounding Box of the Deformation. This represents the scale of the modifier. For a single object it is the bounding box of the object. If the modifier is being applied to a sub-object selection it represents the bounding box of the sub-object selection. If the modifier is being applied to a selection set of objects, then this is the bounding box of the entire selection set. For a selection set of objects the bounding box is constant. In the case of a single object, the bounding box is not constant. - - - - - A pointer to an instance of a class derived from the class. This is the part of the that the plug-in developer controls. It is the place where a modifier may store application specific data. - - - - - Callback object used with Modifier::EnumModContexts(). The proc() method is called by the system. - - - - - - This is called by Modifier::EnumModContexts(). - Return FALSE to stop, TRUE to continue. - - The . - - - - A modifier may be applied to several objects in the scene. The Interface::GetModContexts() method retrieves a list of all the ModContexts for the current place in the history. This class is used as a table to hold the list of ModContexts. - - - - - Description: - This is a special control base class for controllers that control morphing of geometry. - - For the 3ds Max morph system, the morph object itself doesn't do much except provide the front end UI in the create and modify branches. It just allows the user to add targets, delete targets, etc., but it doesn't really do any of the work - it just passes everything on to the morph controller. - - The morph controller has references to the objects (one for each target) and stores keys in whatever form it wants, and interpolates between the objects. In 3ds Max 1.x there was only one morph controller. In 3ds Max 2.0 there is the new Barycentric one. Both of these work with any type of object as long as its Deformable. It just deforms the points. - - The key to the way this works is that the controller just takes the targets and creates a new object from some combination of the targets. Basically the morph object calls GetValue() on the controller and passes it an . The morph controller then computes the new object and drops it down into the passed. This can be any object. - - The val pointer used with GetValue() will point to an . This would be the result of evaluating a combination of targets and producing a new object that is some combination of the targets. - - The val pointer used with SetValue() will point to a data structure. This has a pointer to an object (entire pipeline) and the name of the target. - - The Morph is not really an object. Rather it has a reference to the Morph Controller which is the thing that actually generates the object. The Morph Controller needs to call Object::HasUVW() and Object::SetGenUVW() on each of the targets. - - - - - Returns the number of morph targets managed by this controller. - Default Implementation: - {return 0;} - - - - - Returns a pointer to the 'i-th' object managed by this morph controller. Note that these are pointers to the pipelines, not the result of evaluating the pipelines. - Parameters: - int i - - The index of the morph target. This value may be 0 through NumMorphTargs()-1. - Default Implementation: - {return NULL;} - - - - - Deletes the 'i-th' target. - Parameters: - int i - - The index of the morph target. This value may be 0 through NumMorphTargs()-1. - Default Implementation: - {} - - - - - Retrieves the name of the specified morph target. - Parameters: - int i - - The index of the morph target whose name is returned. This value may be 0 through NumMorphTargs()-1. - - MSTR &name - - The name is returned here. - Default Implementation: - {name.printf(_M("Target #%d"),i);} - - - - - Sets the name of the specified morph target. - Parameters: - int i - - The index of the morph target whose name is set. This value may be 0 through NumMorphTargs()-1. - - MSTR &name - - The to set is passed here. - Default Implementation: - {} - - - - - Retrieves the transformation matrix of the 'i-th' morph target. - Parameters: - int i - - The index of the morph target whose TM is returned. This value may be 0 through NumMorphTargs()-1. - Default Implementation: - {};} - - - - - This method checks the object passed to see if it is an acceptable target. - Parameters: - TimeValue t - - The time to check the object. - - *obj - - The object to check. - TRUE if the object is a valid target; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - When a 3ds Max reference REFMSG_SELECT_BRANCH message is received the morph controller should mark the target indicated and be prepared to return its ID from this method. This way the morph object can set the branch to that target. See this message in Reference Messages. - The ID of the morph target. - Default Implementation: - {return -1;} - - - - - Allows the developer to capture and process the mouse events entered by the user. To create a mouse call back, derive a sub class of this class and implement the proc() function. - - - - - - Called to handle the mouse event processing whenever a mouse event happens. - TRUE, indicating the proc should continue to process points; or FALSE, meaning to stop processing points. If a plug-in supplied a large number of points in a command mode that uses this mouse proc, FALSE can be returned to abort the processing before all the points have been entered. - - The window handle of the window in which the user has clicked. It is one of the viewports to which an interface can be obtained from the system. To get such interface, the window handle should be passes to the functions Interface::GetViewport() as the input. Developers should call Interface::ReleaseViewport() once they are done with the viewport interface. - This message describes the type of event that occurred. See . - The point number. this is 0 for the first click, 1 for the second, etc. - These flags describe the state of the mouse buttons. See . - The 2D screen point on which that the user has clicked. Methods in the viewport interface allow this point to be converted into a world space ray or a 3D view space point. A world space ray can be intersected with the active construction plane which results in a point on the active construction plane. See Class . - - - - Override the default drag mode. Most plug-ins will not need to replace the default implementation of this method. This function changes the way the messages are sent based on the sequence of mouse inputs by the user. The normal flow of the messages is described as follows: First the user clicks the mouse button and a MOUSE_POINT message is generated. The user then drags the mouse with the button down, resulting in a series of MOUSE_MOVE messages to be sent. When the user releases the mouse button, a MOUSE_POINT messages is generated. Then the mouse is moved again, resulting in a new series of MOUSE_MOVE messages to be sent again. Unlike the first time, when the user clicks the mouse button here, a point message is NOT generated at this point until the button is released. All future points are then only sent after the mouse button has been pressed and released. The default implementation is { return mode; }, and a sample program using the override method (using CLICK_DOWN_POINT) can be found in /MAXSDK/SAMPLES/OBJECTS/SPLINE.CPP. - The given mouse drag mode. - - The current drag mode from the list . - - - - Transform Gizmo . Returns TRUE if the mouse proc supports a transform gizmo, FALSE if not. This method and DeactivateTransformGizmo() are normally implemented by the selection processor and the existing mouse procs. However, special implementation is possible as well. For that, because the transform gizmo depends on the Command Mode, the MouseCallback itself decides if it supports the use of the transform gizmo or not. When the node axis (or transform gizmo) is redrawn, the system will ask the command mode's mouse proc whether or not it supports transform gizmos. If it does, it will draw a gizmo instead of the regular node axis. The same procedure happens with the main selection processor in 3ds Max. When the mouse is moved, the selection processor itself asks if the MouseCallback supports transform gizmos or not. If so, it will hit test the gizmo in a MOUSE_FREEMOVE or MOUSE_POINT message. If any of the transform gizmos hit test flags are passed into the mouse procs hit tester, the transform gizmo should be hit tested as well (using Interface::HitTestTransformGizmo()). The default Implementation of this function is {return FALSE;}. When hit testing the gizmo, different flags will be passed in: - - - - - Deactivates the transform gizmo. See the note in SupportTransformGizmo(). - - - - - Returns FALSE by default, and needs to be overridden by the mouse procs wishing to utilize the AutoGrid feature. If overridden, it should return TRUE and also make the appropriate calls to the ViewExp::TrackImpliciGrid(), ViewExp::CommitImplicitGrid() and ViewExp::ReleaseImplicitGrid() from the body of their classes proc() method. For sample code see /MAXSDK/SAMPLES/MODIFIERS/SURFWRAP/SURFWRAP.CPP. - - - - - Returns FALSE by default. Should return TRUE if Ortho Mode makes sense for this creation, FALSE otherwise. In general it returns TRUE only - for splines and such. - - - - - To get a mouse callback when the button index was indicated by SetMouseProc function. - a mouse callback corresponding to the given button index. If an invalid button index is given, the corresponding mouse callback will be NULL. - - The button index maps one mouse button. - - - - Description: - This is the base class for the creation of material plug-ins. This class provides methods to do things such as compute the properties of the material for a given location, return the number of sub-materials and access the properties of the material for the interactive renderer. - Plug-In Information: - Class Defined In IMTL.H - - Super Class ID MATERIAL_CLASS_ID - - Standard File Extension DLT - - Extra Include File Needed IMTL.H - - - - - Implemented by the System. Returns a pointer to the active texture map used in the interactive renderer. Returns NULL if there isn't any. - - - - - Returns the ambient color of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the diffuse color of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the specular color of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the shininess value of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the shininess strength value of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the transparency value of the specified material for use in the interactive renderer. - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns TRUE if the Self Illumination is on (checked) for the specified material; otherwise FALSE. - Default Implementation: - { return TRUE; } - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the self illumination value of the specified material for use in the interactive renderer. - Default Implementation: - { return 0.0f; } - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the Self Illumination of the specified material for use in the interactive renderer. - Default Implementation: - c( .0f,.0f,.0f); return c; } - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns a pointer to the used for the specified sub-material. - Default Implementation: - { return NULL; } - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - Returns the wire size of the material. - Default Implementation: - { return 1.0f; } - - This is the material index for mult-materials. - If the surface normal of the face is pointing away from the viewer this will be TRUE; otherwise FALSE. - - - - This method returns the auxiliary data attached to the material by the renderer. - Default Implementation: - { return renderData; } - - - - - This method returns TRUE if the evaluated color/value (output) is constant over all possible inputs described by the shade context. If it cannot determine the correct answer, it returns FALSE. - Default Implementation: - { return FALSE; } - - This describes the context of the question. - The ID of the channel in question. See . - - - - This method saves the specified color at the specified time. - - The color to store. - The time to set this color. - - - - This method saves the specified color at the specified time. - - The color to store. - The time to set this color. - - - - This method saves the specified color at the specified time. - - The color to store. - The time to set this color. - - - - This method saves the specified shininess at the specified time. - - The shininess value to store. - The time to set this color. - - - - This method allows the renderer to attach auxiliary data to each material. - Default Implementation: - { renderData = rdata; } - - The auxiliary data you wish to attach. - - - - This is the main method of the material. This is called by the renderer to compute the color and transparency output returned in sc.out. - - Describes properties of the pixel to be shaded. The result of this method is returned in the data member of . - - - - Returns the number of sub-materials managed by this material. - Default Implementation: - { return 0; } - - - - - Returns a pointer to the 'i-th' sub-material of this material. - Default Implementation: - { return NULL; } - - The index of the material to return. - - - - Stores the 'i-th' sub-material of this material. - Default Implementation: - {} - - The index of the material to store. - The material pointer to store. - - - - This method returns which sub-mtl is to display in the viewport, a return value of:-1 indicates not implemented. - - Note that when a material, such as Blend, has a method of selecting which sub-map is to be shown in the viewport, and implements this method, the materials editor lets you turn on Show Map In Viewport (SMIV) in all the sub maps at once. When the material, such as top-bottom, doesn't have a selector, and doesn't implement this method, then the materials editor will only let you turn on SMIV for one map/mtl in the entire sub-tree of the material. - Default Implementation: - { return -1; } - - - - - This method returns the slot name of the 'i-th' sub-material. This name appears in the materials editor dialog. For instance, if you are in a material and then you go down into a sub-material, this is the name that appears just below the 'Get ' icon. For example, in the Multi/Sub-Object material when you choose one of the sub-materials, the map name appears to let you know which slot you are working on. For the Multi/Sub-Object material, this is the number of the slot, i.e."#1:", "#2:", "#3:", etc. - - The index of the sub-materials whose slot name should be returned. - If true, then the slot name returned should be localized in the language 3ds is currently using. Otherwise it should be the slot name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the slot name in English. - - - - Returns the name of the 'i-th' sub-material that should appear in track view. - - The index of the sub-material whose track view name should be returned. - If true, then the sub-material TV name returned should be localized in the language 3ds is currently using. Otherwise it should be the sub-material TV name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the sub-material TV name in English. - - - - Returns the amount of displacement along the normal of the surface at the point as specified by the . - Default Implementation: - { return 0.0f; } - - This contains the details of the point being displaced. - - - - Returns the validity interval of the displacement mapping around the specified time. - Default Implementation: - { return FOREVER; } - - The returned reflects the validity around this time. - - - - Return TRUE to prevent the Replace (Discard old material? / Keep old material as sub-material?) dialog from being presented to the user; FALSE to allow it to be presented. This allows a plug-in to control the display of this dialog when being created in a Editor slot. - Default Implementation: - { return FALSE; } - - - - - - - - This describes the context in which the material should be evaluated. - The ID of the channel to perform evaluation on. - The result of the evaluation. - - - - Resolves any wrapper materials and returns the actual material that you should use. This method is used to get rid of "wrapper" materials, like the XRef material and the bake shell material, that usually have no effect on the output of the material. This method can be used by renderer or exporter plugins to get to the actual material that should be used for rendering or exporting. - - - - - to true to get a material to be used in the viewport, false for any other uses. This affects, for example, which sub-material of the bake shell material will be used. - - - - This method returns TRUE if the material supports shaders, otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - Returns true if it supports render elements. - - - - - Description: - This is the base class from which materials and textures are subclassed. Methods are provided to access the name, flags, and sub-materials/maps. There is also a method that is called when the material or texture is to be displayed in the material editor parameters area. - - Note the following about dialog proc processing of sub-map buttons: - - When you post the message: - - PostMessage(hwmedit, WM_TEXMAP_BUTTON, i,(LPARAM)theMtl); - - You are telling the system that the user clicked on the button for the 'i-th' sub-map of theMtl. The message doesn't propagate up - it goes directly to the materials editor. It then uses calls on SetSubTexmap()theMtl-> and GetSubTexmap()theMtl-> to assign the new map. So even if your material has some complicated internal hierarchical structure of references, to the system it is still a simple "logical" hierarchy of a material with some sub-texmaps. - Data Members: - meditRotate; - - This data member is available in release 2.0 and later only. - - This describes the rotation of the sample geometry in the materials editor. - - ULONG gbufID; - - This is the G-Buffer ID of the material or texmap. This is a "effects number" assigned in the materials editor to a map or material, and it will be written into the effects channel of the G-Buffer when a pixel with that material on it is rendered. To implement this, each map or material, in the beginning of its Shade(), EvalColor(), or EvalMono() methods should have the code: - - if (gbufID) sc.SetGBufferID(gbufID); - - - - - Implemented by the System. - - Returns the name of the material or texture. - - - - - Implemented by the System. - - This method returns the name that appears in the track view. It returns the "Instance Name(class Name)". For example "Green Glass (Standard)". The default implementation should be used. - - If true, then the name returned should be localized in the language 3ds is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - - - - Implemented by the System. - - Alters the flags, either setting or clearing them, using the mask and method passed. - - The flags to alter. See . - If TRUE the mask is ORed into the flags (); otherwise (). - - - - Implemented by the System. - - Clears the specified flags. - - The flags to clear. See . - - - - Implemented by the System. - - Tests the specified flags. Returns nonzero if the flags are set; otherwise zero. See Material Flags. - - The flags to test. - - - - This method is called for a plug-in to do any work it needs to do prior to rendering. For example this is used by the 3ds Max Mirror and Auto Reflect materials to render their bitmaps. - Nonzero on success; zero on failure. In the case of failure the renderer is halted (rendering is cancelled). - - The current time. - Provides information about the view being rendered and can provide access to the global rendering environment information via . See Class and Class . - - - - This method returns the cumulative requirements of the material and its sub-materials and maps. The default implementation just ORs together the local requirements of the material with the requirements of all its children. Most materials will only need to implement LocalRequirements(). - See Material Requirements Flags. - Default Implementation: - The default implementation automatically traverses the sub-material/map tree. On any that returns TRUE for IsMultiMtl() it will only recursively call the sub material (or map) for the subMtlNum called. The exception to this is when subMtlNum<0: in this case all sub-mtls and submaps are enumerated. Therefore the LocalRequirements() method below only needs to consider the material or map itself, not the sub-mtls and sub-maps. - - Specifies the number of the sub-material whose requirements should be returned. may be used to return a value generated by looping over all the sub-materials and ORing together the requirements. - - - - Specifies various requirements for this material. The value returned from this method should not include requirements of its sub-materials and sub-maps. - See Material Requirements Flags. - Default Implementation: - { return 0; } - - Specifies the number of the sub-material whose requirements should be returned. - - - - This method gives the UVW channel requirements of the material and its tree. The default implementation just OR's together the local mapping requirements of the material with the requirements of all its children. For most materials, all they need to implement is the LocalMappingsRequired() method. - - Specifies the number of the sub-material whose mapping information is retrieved. - This array of bits is initialized to an empty set with MAX_MESHMAPS elements. Each bit corresponds to a mapping channel. a bit to one to indicate the material requires the corresponding UVW channel. - This array of bits is initialized to an empty set with MAX_MESHMAPS elements. Each bit corresponds to a mapping channel. a bit to one to indicate the material requires the corresponding bump mapping channel. - - - - This method specifies UVW channel requirements for the material: This method should not include UVW channel requirements of any sub-materials and sub-maps. - Default Implementation: - {} - Sample Code: - All 2D textures that use or otherwise select mapping channels need to implement this method Here's an example: - - All 3D textures that use the to put up a coordinates rollup must implement this method. Here's an example: - - Specifies the number of the sub-material whose mapping information is retrieved. - This array of bits is initialized to an empty set with MAX_MESHMAPS elements. Each bit corresponds to a mapping channel. a bit to one to indicate the material requires the corresponding UVW channel. - This array of bits is initialized to an empty set with MAX_MESHMAPS elements. Each bit corresponds to a mapping channel. a bit to one to indicate the material requires the corresponding bump mapping channel. - - - - This method returns TRUE for materials or textures that select sub-materials based on submaterial number (for example a mesh faceMtlIndex). - - The only materials for which this method should return TRUE are those that choose to use one of their sub-maps or sub-mtls based on the submaterial number. For the majority of materials and maps, they should return FALSE, and in that case all of the submaterials and maps are enumerated by MtlBase::Requirements(). - Default Implementation: - { return FALSE; } - - - - - Implemented by the System. - - This method must be called on a sub-material or sub-map when it is removed, in case it or any of its sub-maps are active in the viewport. - - - - - A material has a Shade() method, and a texture map has a EvalColor() method. These are called by the renderer for every pixel. This method is called before rendering begins to allow the plug-in to evaluate anything prior to the render so it can store this information. In this way this information does not need to be calculated over and over for every pixel when Shade() or EvalColor() is called. This allows texture and material evaluation to be more efficient. It is generally called once at the start of each frame, or during interactive playback when the time changes. It is not guaranteed to get called on every frame, because if you returned a validity interval that covers several frames, your parent material won't bother to call you if the current frame is still in that interval. - - The current time. - The validity interval to update to reflect the validity interval of the material or texture at the time passed. - - - - This method is called to reset the material or texmap back to its default values. This should be done by calling the Reset method of the material or texture map plugin's class descriptor (ClassDesc2::Reset). In addition, the plugin can execute any other initialization code it has. Example from maxsdk\samples\materials\dblsided.cpp - When migrating plugins from to and , do not forget to update this method to call the class descriptor's Reset method. If the plugin's Reset tries to replace parameter block objects based on that use the P_AUTO_UI flag, the UI code will continue to hold a pointer to the replaced parameter block, and this will lead to problems. - - - - - This method is called to determine the validity interval of the material or texture. - The validity interval of the item at the specified time. - - Specifies the time about which to compute the validity interval. - - - - This method gets called when the material or texture is to be displayed in the material editor parameters area. The plug-in should allocate a new instance of a class derived from to manage the user interface. - - Note: The following is a discussion of this CreateParamDlg() method, and the SetDlgThing() method, and the way they relate to the ParamMap2 system. A good example for this discussion is a texture map which typically has several rollouts, say its texmap parameters, a UVW coordinates rollout, and an Output rollout. - - The normal way for a texmap to implement these other (common) rollouts is for the it to create a instance and a instance as 'sub-objects' in the map and then ask them to put up their rollouts when it is asked to do so by the Materials Editor (in CreateParamDlg()). The Materials Editor requires a pointer back from the CreateParamDlg() on which it calls methods to control the UI, such as time change updates or loading up a new texmap of the same class into the UI when the user switches them, so that the whole UI doesn't need to be rebuilt. - - Prior to the ParamMap2 system, a texmap would implement its own subclass and would keep track of the and ParamDialogs and pass on any time change or SetThing() calls to them. ParamMap2 introduced its own subclass (Class ) that you can ask it to build for you and have manage all interaction with the Materials Editor automatically. As before, this still needs to know about the other (sub-object) ParamDlgs, and so it has the ability to keep a list of 'secondary' ParamDlgs to which it passes on the SetTime()s and SetThing()s. - - When the Materials Editor asks the texmap to CreateParamDlg(), the texmap asks its to build one of these (ClassDesc2::CreateParamDlgs()). If the texmap itself has multiple ParamBlock2s, CreateParamDlgs() builds one per pblock/rollout, makes the first of them a 'driver' and adds the rest as secondary ParamDlgs. The texmap then asks the and objects to CreateParamDlg() for their rollouts and adds them to the driver also. - - Now consider the need for the SetDlgThing() method below. It is related to the SetThing() method that the Materials Editor calls on the 'driver' to switch into the UI a texmap of the same class as that currently in the UI. Normally, the driver IAutoParamDlg would propagate the SetThing() to its registered secondary ParamDlgs. In the case of multiple paramblock2s in the texmap, this would be correct, since the 'thing' in this case is the incoming texmap. But this doesn't work for the secondary and ParamDlgs; their 'things' are the and subobjects of the incoming map. So, IAutoParamDlg first calls SetDlgThing() on the incoming texmap so that it gets a chance to call the correct SetThing()s on the sub-object ParamDlgs with the appropriate incoming sub-objects. A clear example of this is in Gradient::SetDlgThing() in /MAXSDK/SAMPLES/MATERIALS/GRADIENT.CPP. It is called once for each secondary . For those ParamDlgs that have special SetThing() requirements, it does the appropriate sub-object SetThing() and returns TRUE. If it does no special handling for a particular , it returns FALSE, signalling to the that it should do the standard SetThing() propagation for that dialog. - - The Render Effects dialog has a similar arrangement to the Materials Editor for controlling UI and so there is an that works exactly the same way as the IAuotMParamDlg. - A pointer to the created instance of a class derived from . - - The window handle of the materials editor. - The interface pointer for calling methods in 3ds . - - - - Implemented by the System. - - Returns the G-buffer ID of this material. - - - - - Implemented by the System. - - Returns a pointer to the postage stamp image for the file. - - One of the following values: for small (32x32) images. for large (88x88) images. for tiny (24x24) images. - - - - Implemented by the System. - - Creates a postage stamp image and returns a pointer to it. If the postage stamp image already exists then it is simply returned. - - Here's an example using this method to display a small material sample. - - - - One of the following values: for small (32x32) images. for large (88x88) images. for tiny (24x24) images. - If set to true, the postage stamp bitmap will have the rendered into it automatically. The bitmap can then be retrieved using , for drawing in the . - - - - Implemented by the System. - - Discards the postage stamp image. - - One of the following values: for small (32x32) images. for large (88x88) images. for tiny (24x24) images. - - - - Returns TRUE if this texture supports being used in the interactive renderer; otherwise FALSE. If the texture does return TRUE it is expected to implement the methods ActivateTexDisplay() and GetActiveTexHandle(). - Default Implementation: - { return FALSE; } - - - - - This method is called to retrieve a texture handle to this texture map. - The texture handle. - Default Implementation: - {return 0;} - - The time to return the texture handle. - This class provides methods for creating a texture handle from a 3ds bitmap and a Windows DIB. It also has a method to retrieve the required size of the texture map. See Class . - - - - This method is used internally. - - - - - This method is used internally. - - - - - This method is used internally. - - - - - This method is called when the usage of the texture the interactive renderer changes. This method must only be implemented if SupportTexDisplay() returns TRUE. This method does not cause the texture map to be drawn in the viewport but should be called with TRUE as the argument before this can occur. For viewport drawing of textures refer to Interface::ActivateTexture() and Interface::DeActivateTexture() instead. - Default Implementation: - {} - - TRUE if the texture is being used; FALSE if it is no longer being used. - - - - Returns TRUE if this material supports the display of multi-maps in the viewports (interactive renderer); FALSE if it doesn't. - Default Implementation: - { return FALSE; } - - - - - This method is called to initialize the interactive renderer passed with the properties of this . - - If a (material or texmap) wants to display multiple textures in the viewports, it implements - - SupportsMultiMapsInViewport() to return TRUE, and implements SetupGfxMultiMaps to store the necessary information in the passed in, including the 's for each texture. - - The passed in to SetupGfxMultiMaps provides functions to help in setting up the "Material" data structure. The function NumberTexturesSupported() lets you know the capabilities of the current hardware, so you can adapt accordingly. The function GetGfxTexInfoFromTexmap fills in the fields of a except the texHandle and texture ops. - - The implementation of SetupGfxMultiMaps must create the "texHandle" for each of the textures described in its array. It typically does this by calling the submap's GetVPDisplayDIB() method, and then creates the texHandle by calling the callBack function MakeHandle(bmi). To avoid doing this calculation when not necessary it is best to save the texHandles along with their validity intervals. Then when SetupGfxMultiMaps is called, if valid texHandles are already in hand they can just be used without recomputing. - Default Implementation: - {} - - The time at which to evaluate the material. - Points to the interactive renderer material to update. - This callback object is provided as a helper to fill in the properties above. See Class . - - - - This method is used internally. - - - - - This method is used internally. - - - - - Implemented by the System. - - This method may be called to recursively determine if there are any multi-materials or texmaps in the tree. - TRUE if the material or texture map has any mult-materials; otherwise FALSE. - - - - - This method is used internally. - - - - - - - Implemented by the System. - - Materials and Texmaps must use this operator to copy the common portion of themselves when cloning. - - - - - Get the active . - - - Previous to r9, activeMB was held as a raw pointer. Due to problems where the was deleted without clearing this pointer, activeMB is now held indirectly. Methods GetActiveMB and SetActiveMB are used to get/set the activeMB; - The active - - - - - Transparency hint indicates whether the material is potentially transparent for both rendering and viewport display, so that the renderers or viewport can decide whether to optimize it or not. - Nonzero if this material is potentially transparent; Zero if it isn't. - Default Implementation: - { return TRUE; } - - The time to get the transparency hint at. - The validity interval of the returned value. - - - - Description: - This class is a library of entries. To get a list of the currently loaded materials use: - - & . - - When you load a material library, you can enumerate all the materials that it contains. is subclassed off of which is a <MtlHandle>, so for example, you can do the following to work with each material: - - for (int i=0; i<mlib.Count(); i++) { DoSomething(mlib[i]); } - - For additional information on this class see the Advanced Topics section ~{ Materials, Textures and Maps }~. All methods of this class are implemented by the system. - - - - - Removes all MtlBases from the library and deletes all references. - - - - - Removes the specified from the library. - Parameters: - *m - - The to remove. - - - - - Adds the specified to the library. - Parameters: - *m - - The to add. - - - - - Removes all duplicate MtlBases from the library. - - - - - Simple list of . - - - A simple list of MtlBases. All methods of this class are implemented by the system. - - - - - - - Adds the specified to the list. - - - Nonzero if the was added; otherwise zero. - - - The to add. - - If TRUE this method checks to make sure the is unique, and will only add it if so. - - - - Finds the specified in this material list and returns its index. Returns -1 if not found. - - - - - The to find. - - - - Finds the specified material by name and returns its index. Returns -1 if not found. - - - - - The name to find. - - - - Removes the specified from the list. - - - - - The index of the to remove. - - - - Removes all MtlBases from the list. - - - - - Description: - All methods of this class are implemented by the system. - - Use this class to implement drag and drop functionality for materials sub-materials. . It provides implementations of the methods of . If this class is used the method FindSubMtlFromHWND() must be implemented. - - - - - Description: - A materials library. All methods of this class are implemented by the system. - - - - - Removes all Mtls from the library and deletes all references. - - - - - Removes the specified material from the library. - Parameters: - *m - - The material to remove. - - - - - Adds the specified material from the library. - Parameters: - *m - - The material to add. - - - - - Description: - A simple list of materials. All methods of this class are implemented by the system. - - Note the following typedefs: - - typedef MtlBase* MtlBaseHandle; - - typedef Mtl* MtlHandle; - - typedef Texmap* TexmapHandle; - - - - - Adds the specified material to this list of materials. - Parameters: - *m - - The material to add. - - BOOL checkUnique=TRUE - - If TRUE this method checks to make sure the material is unique, and will only add it if so. - Nonzero if the material was added; otherwise zero. - - - - - Finds the specified material in this material list and returns its index (0 through the number of materials in the library). Returns -1 if not found. - Parameters: - *m - - The material to find. - - - - - Finds the material whose name is passed in this material list and returns its index (0 through the number of materials in the library). Returns -1 if not found. - Parameters: - MSTR& name - - The material to find. - - - - - Removes the material whose index is passed. - Parameters: - int n - - The index of the material to remove. - - - - - Empties (clears) the material list. - - - - - Description: - This is the callback used with the new multi-texture interface provided by method MtlBase::SetupGfxMultiMaps(). - - - - - This method updates all the fields of the instance exept the texture handle and the texture ops. - Parameters: - TimeValue t - - The time at which the texture is evaluated. - - & texinf - - The texture info which is updated. - - *txm - - Points to the texmap as the source for the texture info update. - - - - - This method returns the number of textures that the hardware+driver supports. - - - - - Description: - This class provides access to the developer alterable properties of the 3ds Max Multi/Sub-Object material. - - - - - Sets the number of sub-materials for the multi-material. - Parameters: - int n - - The number of sub-materials. - - - - - - - Retrieves the name of the sub-material whose ID is passed. - Parameters: - int mtlid - - The zero based index of the sub-material. - - MSTR &s - - The name is returned here. - - - - - Retrieves the name and pointer to the material for the specified sub-material. - Parameters: - int mtlid - - The zero based index of the sub-material. - - *m - - Points to the sub-material. - - MSTR &subMtlName - - The name is returned here. - - - - - Add a sub material with the specified material ID - - - The material to add as our sub-material - - The ID to add rt at - - The name of the new sub material. - - - - Remove the sub-material at the specified ID - - - the ID of the material to remove - - - - This is the callback object used to perform the [de]selection via :: SvGetMultiSelectCallback(). Schematic view supports multiple selection. When the user selects a set of objects in the schematic view and then "transfers" that selection set to the rest of max (either by having "synchronize selection" on or by manually moving the selection out), there are a number of ambiguities that can arise. For example, some of the objects in the schematic view cannot be selected in the viewports, material editor, or modifier stack. Another example: the material editor only supports one active material/map but many materials and maps can be selected simultaneously in the schematic view. The "MultiSelectCallback" system exists order to handle these cases and to handle selection synchronization between SV and future editors in 3ds Max. When the schematic view attempts to synchronize selection by moving the SV selection set to the "outside" world, it follows this procedure: - - - - - - - Returns the priority of the callback. 's with a higher priority (lower value) are called before those with a lower with a higher priority (lower value) are called before those with a lower priority (higher value). - - - - - Called to begin the multi-selection process. This is the spot where any "pre-selection" operations take place. - - - Points to the schematic view window manager. - - true to clear the previous selection; false to leave intact. - - - - Selects or de-selects the node passed. - - Points to the schematic view window manager. - Points to the node in schematic view. - true if select; false if deselect. - - - - Called when done. ! This is the spot where any "post-selection" operations take place. - - Points to the schematic view window manager. - - - - Description: - This class provides access to the developer settable properties of the 3ds Max multi-textures such as Composite, Tint and Mix. All methods of this class are implemented by the system. - - - - - Sets the number of sub-texmaps for this texmap. - Parameters: - int n - - The number of sub-texmaps. - - - - - Sets the color of the 'i-th' sub-texmap to the specified color at the time passed. - Parameters: - int i - - The index of the sub-texmap to set. - - c - - The color to set. - - TimeValue t=0 - - The time at which to set the color. - - - - - Description: - This class is a list of multiplier curves. - - The macro used to access this class is defined as follows: This may be used to access the methods of this class as follows: All methods of this class are implemented by the system. - - - - - This method starts with a value of 1.0f, multiplies it by each enabled multiplier curve value in the list, and returns the resulting value. - - - The time at which to get the multiplier values. - - The interval into which the validity of the evaluated parameters is intersected. - - - - Adds the specified multiplier curve to the end of the multiplier curve list. - Parameters: - *cont - - Points to the multiplier curve to append. - - - - - Deletes the 'i-th' multiplier curve. - Parameters: - int i - - The index of the multiplier curve to delete. - - - - - Disables the 'i-th' multiplier curve. - Parameters: - int i - - The index of the multiplier curve to disable. - - - - - Enables the 'i-th' multiplier curve. - Parameters: - int i - - The index of the multiplier curve to enable. - - - - - Returns TRUE if the 'i-th' multiplier curve is enabled; otherwise FALSE. - Parameters: - int i - - The index of the multiplier curve to check. - - - - - Returns the 'i-th' multiplier curve. - Parameters: - int i - - The index of the multiplier curve to return. - - - - - Returns the number of multiplier curves in the list. - - - - - Description: - Publishing interface functions can now report fatal error conditions to callers by using C++ exception-handling. This base class, , can be thrown directly, or subclassed as needed for error grouping. The class contains a message buffer and an optional error code. You would signal an error using the MAXException() constructor and the C++ throw statement, as in the following example: - - ... - - if (discrim < 0.0) // oh-oh, not good - - ("Unable to find root.", -23); - - ... - - This signals a fatal error with the message and code shown. If the error occurs during a call to the function by MAXScript code, it will be trapped by MAXScript and the error message will be displayed and the running script will be terminated (but 3ds Max will continue running). If the error occurs during a C++-level call, typically the outer 3ds Max error catcher will catch and report the error and then exit 3ds Max, or clients of the interface can install their own catch code. - Data Members: - MSTR message; - - The exception message. - - int error_code; - - The exception error code. - - - - - Description: - This class allows a custom file open dialog to be used. This object is set using the method Interface::SetMAXFileOpenDlg(). - - - - - This method is called to bring up the custom file open dialog. It request a file name from the user and stores the result in fileName. - Parameters: - MSTR& fileName - - this to the file name chosen by the user. - - MSTR* defDir - - The default directory to look in. - - MSTR* defFile - - The default file name to use. - TRUE if the user OKed the dialog; FALSE on cancel. - - - - - Description: - This class allows a custom file save dialog to be used. This object is set using the method Interface::SetMAXFileSaveDlg(). - - - - - This method is called to bring up the custom file save dialog. It request a file name from the user and stores the result in fileName. - Parameters: - MSTR& fileName - - this to the file name chosen by the user. - TRUE if the user OKed the dialog; FALSE on cancel. - - - - - 3ds Max security exception class for function published exceptions. published functions can throw instances of this class or subclasses to signal error conditions related to software security. For example, the 3ds Max Python Host FPS interface throws an instance of this class when attempting to evaluate a python string or file, and evaluation of python string or file from MAXScript is disabled by ISceneScriptSecurityManager. A exception caught by MAXScript is rethrown as a , and its message is always displayed in and logged to the 3ds Max log file. - - - - - Description: - An instance of this class is created when a motion capture controller binds one of its parameters to a device. The main purpose of this class is to store any parameters that describe the binding. - - - - - Returns a pointer to the bound input device. - - - - - Returns the name of the bound input device. - - - - - A device binding is the thing that the controller evaluates to get the value of the device. Everything is simply a scalar parameter. So for example even for a device like a mouse that has X and Y motion the device binding will break down into simply X or Y. This method is used to return the value of the device at the instant this method is called. - Parameters: - TimeValue t - - The time at which this method is called. - - - - - This method is called to allow the binding to put up any user interface it has into the command panel via rollup pages. - Parameters: - *dlg - - The data member of this class may be used to add the rollup page. - Sample Code: - - - - - This method is called to allow the plug-in to update the values in its user interface rollup. - Parameters: - *iRoll - - The interface into the command panel rollups. The GetPanelDlg() method may be used to return the window handle of the dialog and this HWND may be used to update the controls. - - - - - This method is called when the binding becomes active. - Parameters: - BOOL reset=TRUE - - If TRUE 3ds Max is being reset; otherwise this is the first time the binding is becoming active. - Default Implementation: - {} - - - - - This method is called when the binding has been released. - Default Implementation: - {} - - - - - This method is called 50 times per second during motion capture. - - To understand how this is used consider the following two situations for a motion capture device: - - - Parameters: - TimeValue t - - The current time when this method is called. - Default Implementation: - {} - - - - - Description: - This class represents the mcg (*.mcg) and is available through the built-in type instance mcgFileDropType. - - - - - Description: - This is the base class for an input device plug-in. All methods of this class are virtual. - - In terms of the motion capture system, the basic item that is plug-able is the motion capture device. This is something like a mouse, joystick, or midi device. Developers implement two classes, this one, , and . There is usually only one instance of . This is like the virtual mouse, or the joystick. This represents the actual device. An instance of the device binding represents an instance where a motion capture controller has been bound to a device, i.e. the user has picked the device and assigned it to a parameter. Thus there may be many instances of the device binding. The device binding is part of the reference hierarchy. The device itself doesn't usually have any parameters for the user to adjust - these are rather part of the device binding. - - Some simple sample code for the mouse motion capture device is available in /MAXSDK/SAMPLES/MOCAP/MCDEVICE.CPP. - - - - - Returns the name for the input device. - - - - - The motion capture utility creates a list of all the MCInputDevices in the system. When the user wants to pick one it will call this method. It returns a new instance of the class. - - - - - This method is called when the user enters the utility. - Parameters: - *im - - This is an interface into the motion capture manager. - Default Implementation: - {} - - - - - This method is called when the user leaves the utility. - Parameters: - *im - - This is an interface into the motion capture manager. - Default Implementation: - {} - - - - - This method is called when the user is in 'Record' (capture) mode or 'Test' mode. It is called once per millisecond. For instance the joystick device uses this method. To understand this method consider the following example: - - With MIDI you don't call a function to see if a key has been pressed or not - rather it is a message based system where you're notified if something happens. In contrast to this is the joystick. If the user moves the joystick the program is not notified. Rather a developer must poll the joystick to get its current position. During motion capture one could poll the joystick at every frame to get its current position. However this approach leads to jittering (aliasing). The problem is that, on average, the joystick is providing a smooth series of values, but instantaneously, the values jump around a bit. So, the joystick motion capture plug-in implements this method to stores the values returned at every millisecond. Then later, when needing to sample the joystick at a certain time, the stored table of values can be averaged and this provides a level of smoothing. - Parameters: - UINT tick - - The time of this call in milliseconds. - Default Implementation: - {} - - - - - Description: - This class describes a single edge of a mesh object that is adjacent to a vertex. This is an edge that is coming out of the vertex. This is used in adjacency lists. - Data Members: - DWORD f[2]; - - The indices into the meshes face table of the two faces that share this edge. - - DWORD v[2]; - - The indices into the meshes vertex table of the two vertices of this edge. - - - - - - Returns the index of the edge in the face on side side. So: given a mesh and an *me, int eid = me->EdgeIndex (mesh.faces, 0); then mesh.faces[me->f[0]].v[eid] and mesh.faces[me->f[0]].v[(eid+1)%3] are the endpoints of the edge. - - In particular, mesh.EdgeSel()[me->f[0]*3+eid] tells whether this edge is selected. - Parameters: - *faces - - The list of faces from the mesh. - - int side - - Either 0 or 1, indicating whether we should find this result for the face on side 0 or on side 1. - - - - - Returns TRUE if this edge is selected on either side; or FALSE if it is not selected on either. - Parameters: - *faces - - The list of faces from the mesh. - - &esel - - The edge selection from the mesh. - - - - - Returns TRUE if this edge is visible on either side; or FALSE if it is not visible on either. - Parameters: - *faces - - The list of faces from the mesh. - - - - - Returns TRUE if all the faces using this edge are hidden; otherwise FALSE. - Parameters: - *faces - - The list of faces from the mesh. - - - - - Returns the center of this edge. - Parameters: - *verts - - The list of vertices from the mesh. - - - - - Returns TRUE if one (or both) of the faces sharing the edge is selected; otherwise FALSE. - Parameters: - &fsel - - The face selection bit array. - - - - - Returns a point suitable for use in standard tessellation. - Parameters: - *mesh - - A pointer to the associated mesh. - - *af - - A pointer to the associated . - - float tens - - The tension parameter, as seen in the Tessellate modifier. - - - - - This method creates a map vertex for the middle of this edge using the Butterfly tessellation scheme. Designed to create map vertices to go with the vertex created by ButterFlySubdivide(). - Parameters: - *mesh - - A pointer to the associated mesh. - - *af - - A pointer to the associated . - - float tens - - The tension parameter, as seen in the Tessellate modifier. - - int mp - - The map channel we want to get a result for. - - bool & seam - - If this is set to true by the algorithm, then there's a mapping seam on this edge, and different map vertices should be used on each side. - - UVVert & side2 - - If there's a seam, this contains the mapping result for the second side. The return value matches the mapping scheme on face f[0]; side2 matches the scheme on face f[1]. - The desired mapping coordinates. - - - - - Returns the index of the other vertex using this edge. - Parameters: - DWORD vv - - The index of a vertex using the edge. - - - - - Returns the index of the other face using this edge. - Parameters: - DWORD ff - - The index of a face using this edge. - - - - - Contains all the data needed to move points (and map vertices) as the user drags a chamfer or extrude. It's created by the topological change that happens at the start of the chamfer or extrude. The strategy is this: The chamfer/extrude operation is divided into two parts, the topological change and a later geometric change. (This works well for Editable Poly, where the topology change is completed first, then apply a series of geometry changes as the user spins a spinner or drags a mouse. Each geometry change is undone before the next is applied, but the topology change only happens once.) - - This class is first initialized to a mesh. Then its data is filled in by the topological change. This data is used to find "directions" for all the geometric and mapping vert changes over the course of the geometric modification. - For convenient caching, it is recommended that you use this class through the class. - - - - - The related direction vectors for mapping vertices in all active mapping channels. - - - - - The maximum amount each vector may be applied (before vertices start crossing over each other. - - - - - The related direction vectors for mapping vertices in all active mapping channels. - - - - - This method sets up the based on a given mesh, allocating the vertex and mapping vertex tables as appropriate. - Parameters: - const & m - - The to initialize from. - - - - - This method allocates the vdir and vmax tables, and initializes the new members of vmax to 0. (Note: this method can be applied to an existing to reflect an increase in vertices in the as topological changes occur.) - Parameters: - int nv - - The number of vertices. - - bool keep=TRUE - - TRUE to keep old data if resized; FALSE to discard old data. - - int resizer=0 - - The number of extra elements the vdir and vmax tables are resized beyond their current size. (Extra allocation space to prevent excessive reallocation.) - - - - - Clears all the vmax limits to -1 (no limit). - - - - - Uses vectors and limits to obtain the offsets corresponding to a certain extrude or chamfer amount. - Parameters: - float amount - - The amount of the extrude or chamfer. - - > & delta - - A table (with size set equal to the number of vertices, aka vdir.Count()) containing the geometric offset for each vertex in the mesh. - - - - - Uses map vectors and limits to obtain the mapping offsets corresponding to a certain extrude or chamfer amount. - Parameters: - & mm - - The mesh this is based on. - - int mapChannel - - The index of the map channel (from -NUM_HIDDENMAPS to mm.MNum()). - - float amount - - The amount of the extrude or chamfer. - - <UVVert> & delta - - The offsets for each mapping vertex in this map in the mesh. - - - - - Data accessor. This method returns the appropriate map info. If mp >= 0, it returns the member of the mdir array. If mp < 0, it returns the member of the hmdir array (in keeping with "hidden map channel" indexing conventions). - - - - - for use with IMNMeshUtilities10::ChamferEdges. - - - Some well-defined pointers: - First, effect the topological change with IMNMeshUtilities10::ChamferEdges: - After making the topological change, modify the mesh geometry with the desired chamfer amount: - Do not do this: - - - - - Decorator for MNChamferData::GetDelta. This function also interpolates between vertices created. - - - - - Decorator for MNChamferData::setNumVerts. - - - - - Decorator for MNChamferData::InitToMesh. - - - - - Decorator for MNChamferData::ClearLimits. - - - - - Decorator for MNChamferData::GetMapDelta. This function also interpolates between mapping vertices created on segmented edges. - - - - - Decorator for MNChamferData::MDir. - - - - - Returns MNChamferData::vdir. - - - - - Returns MNChamferData::vmax. - - - - - Returns MNChamferData::mdir. - - - - - This class is used for hit-testing diagonals of polygons in Editable Poly and Edit Poly. When this data is logged with the system, the memory is owned and freed by the System. See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly, as well as in the Edit Poly modifier, in maxsdk\samples\mesh\EditPoly - - - - - mFace and mDiag are the data members describing the face and diagonal hit. (For each face with degree "deg", there are deg-3 diagonals.) - - - - - An edge used with the mesh. MNEdges are winged-edge structures, which means they keep track of a start vertex, an end vertex, and the (unique) face that uses the start and end vertices in that order. If there is a face that uses the end and start vertices in that order, i.e. that travels this edge in the other direction, it is also recorded. All methods of this class are implemented by the system. - - - - - The start vertex index into the parent 's list of MNVerts. - - - - - The end vertex index into the parent 's list of MNVerts. - - - - - The (unique) face that references this edge in the forward direction. This value is an index into the parent 's list of MNFaces. - - - - - The face (if any) that references this edge in the backward direction. Faces with f2=-1 are considered "one-sided", and lie on the boundary of a hole in the mesh. This value is an index into the parent 's list of MNFaces. - - - - - Initializes v1, v2 and f1 to 0, f2 to -1 and track to -1. - - - - - Assuming that ff is one of the faces using this edge, OtherFace will return the other. If the edge is one-sided, -1 will be returned. If ff is not one of the faces, f2 (which may be -1) will be returned. - - - - - Assuming that vv is one of the vertices on this edge, OtherVert will return the other. If vv is not one of the faces, v2 will be returned. - - - - - Flips the edge around, so that it now goes from what was v2 to what was v1. f1 and f2 are also switched. This should not be called on one-sided edges. - - - - - Replaces face of with face nf in the edge records. NOTE that this method causes an assertion failure if face of is not currently used by the edge. If of is on both sides of the edge, which is possible on some valid NONTRI meshes, a nonnegative vv1 is used to specify which side is replaced. Vv1 should be the "starting vertex" for the edge on face of. Assertion failures will also result if vv1 is nonnegative and is not either of the edge's verts, or if vv1 indicates that of should be the edge's f1, but it is not, etc. - - - - - Replaces vertex ov in the edge records with vertex nv. NOTE that this method causes an assertion failure if vertex ov is not used by this edge - - - - - If this edge has the MN_EDGE_NOCROSS flag set, or if it has no second face, this method returns TRUE. Otherwise, it returns FALSE. It's a shorthand equivalent for (GetFlag(MN_EDGE_NOCROSS) || (f2<0)). - - - - - Comparison operator. - - - - - Vertex access operator. - - - - - Uses DebugPrint to print out edge information to the Debug Results window in DevStudio. The information consists of the vertices and faces using this edge. It is generally a good idea to put in a DebugPrint immediately before this with the index of the edge, so you know which one is being printed out: - - - - - Represents a list of edge "clusters" for a given . A typical application would be in Editable Poly, where the user has selected a two separate groups of edges on different parts of the mesh and wants to rotate both around their local centers. Each "cluster" is a contiguous group of selected edges (ie they all touch each other). This class is only defined in relation to some . - For convenient caching, it is recommended that you use this class through the class. - - - - - The cluster IDs of all the edges - this table has size MNMesh::nume. clust[i] is UNDEFINED if edge i is not in any cluster. - - - - - The total number of clusters. - - - - - Index operator to access cluster data. - - - - - This method will create a list of cluster IDs for vertices. - Parameters: - &m - - The mesh associated with these . - - <int> & vclust - - This is where the output goes: vclust is set to size MNMesh::numv, and the value of each entry in this table tells which cluster the vertex has been assigned to, based on the edges using it. If vertex "v" is not in any clusters (i.e. none of the edges that use it are in any clusters), vclust[v] is UNDEFINED. - - - - - This method extracts normal and center information for each of the edge clusters. - Parameters: - &m - - The mesh associated with these . - - > & norm - - This table has its size set to the number of clusters in the cluster list. Normals are computed as the normalized average of the normal vectors of all edges in the cluster. - - > & ctr - - This table has its size set to the number of clusters in the cluster list. Centers are the average location of the edge centers - thus a point on three edges in the same cluster has more weight than a point on only one edge in the cluster. - - - - - The face structure used with the mesh. are not necessarily triangles. They also may contain hidden vertices which are used in converting the face back to triangles. This triangulation is always maintained in the face. - - - - - This is the degree: the number of vertices and edges that this face has. - - - - - This is the list of vertices that make up the corners of this face. Each value is an index into the parent 's list of MNVerts. - - - - - This is the list of edges that border this face, in order. Each edg[i] goes between vtx[i] and vtx[(i+1)deg]. Each value is an index into the parent 's list of MNEdges. These values may not be valid if the 's MN_MESH_FILLED_IN flag is not set. - - - - - This is where the triangulation is stored. The number of triangles in a face is given by deg - 2 + hdeg*2. This array contains three times this number, for all the corners of all the sub-triangles. The triangle values are indices into the vtx and hvtx arrays of this face. Hidden vertices are indicated by values less than zero: hvtx[i] is represented by -1-i. Thus a triangle (1, 2, -2) would represent a triangle using vtx[1], vtx[2], and hvtx[-1]. The diag array's allocated size is always (dalloc-3)*2. If dalloc==3 (triangle), this pointer is NULL. - - - - - This contains the smoothing groups assigned to this face. - - - - - This is the material ID assigned to this face. - - - - - Generally for internal use, but may be used to track faces created by several methods. - - - - - Contains a visibility bit for each edge on this face. See the note on edge selection & visibility for more information. - - - - - Contains a selection bit for each edge on this face. See the note on edge selection & visibility for more information. - - - - - Boundary Edges - - - - - Initialize the face. - - - - - the number of edges and vertices this face has. - Parameters: - int d - - of vertices and edges. - - - - - Frees all arrays, setting them to NULL, and resets degree. - - - - - Returns the number of triangles in this face. - - - - - Given the index of a particular edge, this routine returns the point (distinct from edge and (edge+1)deg) that forms a triangle with the edge, given the current scheme of diagonals. - Parameters: - int edge - - An index into the vertex array (in the range 0 to deg-1) that indicates the starting vertex of the edge. (In other words, the edge falls between vertex vtx[edge] and vtx[(edge+1)deg].) - The index of the desired vertex, again in the (0,deg-1) range, or edge if there's an error. - - - - - Given two verts that form a diagonal in the polygon, this method finds the vertex between them that connects by a diagonal or an outer edge to both of them. (Here, "between them" means after a and before b in sequence around the outside of the polygon. If we have an octagon where a=6 and b=2, the result would be 7, 0, or 1. To get the other result, in the 3,4,5 range, call the method with a=2 and b=6.) - Parameters: - int a, b - - Two vertices, "internally indexed" in the 0 to deg-1 range. This method is only guaranteed to work if the vertices share a diagonal. (Otherwise, there may be no solution.) - The index of the desired vertex, again in the (0,deg-1) range, or a if there's an error. - - - - - This method fills in the table with the full triangulation for the face, based on the internal diagonal list. The table is set to size (deg-2)*3. - Parameters: - <int> &tri - - The table of triangles. - - - - - Allocates enough memory in the arrays for the face to have degree d, but does not actually set the degree. If the arrays are already large enough (or larger), it does not reallocate them. You generally don't need to use this method separately; MakePoly, Insert, and other methods which may require additional memory will call this if needed. - - - - - Makes this face into a polygon with the specified vertices and other information. This routine also supplies a default triangulation for the face; however, since this MNFace-level routine cannot access the vertex positions contained in the parent , this triangulation may not work for non-convex faces. If the face may not be convex, a call to MNMesh::RetriangulateFace for this face will correct the triangulation. - Parameters: - int fdeg - - The degree to set this face to. - - int *vv - - The list of vertices for this face. There must be at least fdeg of these. These values should be indices into the parent 's array of MNVerts. - - bool *vis=NULL - - The edge visibility flags for the edges of this face. If this is NULL, it is ignored; otherwise, there must be at least fdeg of these. vis[i] represents the visibility of the edge going from vv[i] to vv[(i+1)fdeg]. See the note on edge selection & visibility for more information. - - bool *sel=NULL - - The edge selection flags for the edges of this face. If this is NULL, it is ignored; otherwise, there must be at least fdeg of these. sel[i] represents the selection bit of the edge going from vv[i] to vv[(i+1)fdeg]. See the note on edge selection & visibility for more information. - - - - - Inserts space for more vertices and edges on this face. This is used, for example, when two faces are joined, to add room for the vertices & edges of one face to the other. This routine also renumbers the existing vertices and corrects the existing face triangulation, although it cannot provide the triangulation for the new vertices. It reserves space for the new triangles at the end of the triangle array. If you do not want to compute the triangulation for the new vertices yourself, you may use the RetriangulateFace method after filling in the new vertices. - Parameters: - int pos - - The location within the face where the new vertices and edges should be added. - - int num - - The number of new vertices and edges. - - - - - Deletes vertices & edges from this face. This routine also corrects the face triangulation, removing those triangles that include the deleted edges and re-indexing the rest. However, delete may cause the triangulation to become invalid, by causing one or more of the corrected triangles to have a flipped normal. - Parameters: - int pos - - The position of the first vertex to be deleted. - - int num=1 - - The number of vertices & edges to delete. - - int edir=1 - - There are two choices for the edges to be deleted: we can delete the edges going from pos to pos+1, pos+1 to pos+2, ... pos+num-1 to pos+num, or we can delete pos-1 to pos, pos to pos+1, ... pos+num-2 to pos+num-1. (pos+num-1 is the last vertex deleted.) That is to say, we can delete the edges "before" the vertices we're deleting, or we can delete the edges "after" them. If edir is positive, we delete the edges after the vertices. If it's negative, we delete the edges before. Keep in mind that this also affects edge visibility and selection information on this face. - - bool fixtri=TRUE - - This argument indicates how far Delete should go in fixing the triangulation. Delete will always correct the values of the tri array to correspond to the reduced-degree face. If fixtri is true, it will also delete those triangles that have collapsed because they had two vertices in the deleted region. If not, it will leave these triangles with overlapping vertices, as in (0,0,2). - Delete returns TRUE if fixtri is FALSE. If fixtri is TRUE, Delete will return TRUE if it successfully corrected the triangulation, or FALSE if there was a problem. If FALSE is returned, the triangulation will need to be revised with a call to RetriangulateFace. - - - - - Searches the edge list for this face for "null" edges, defined as edges with identical start and end vertices. These edges are excised from the face edge list, and the associated duplicate vertices are removed from the vertex list. The face is retriangulated if any null edges are encountered. If removing null edges would result in a degenerate face of degree less than three, the face simply flags itself as MN_DEAD and returns the identified edges in nullEdges. - - list of indices in the owning container of null edges identified in this face; if the same null edge was present N times in this face's edge list, it will appear N times in nullEdges - list of local indices, in face vtx container at entry to function, of duplicate vertices removed due to excision of a null edge - mesh container in which this face resides - - - - Re-indexes the vertices and edges so that the vertex in position newstart becomes the new first vertex. Triangulation is also corrected. Mapping coordinates and vertex colors are corrected automatically. - - - - - Reverses order of verts, effectively inverting the face. vtx[0] remains unchanged, but vertex deg-1 becomes vertex 1, etc. Note that this operation wreaks havoc on nearby edges and should be used with caution. - - - - - Returns the position of vertex vv in this face's list of vertices. For a given face fc, if fc.vtx[i] = vv, fc.VertIndex (vv) = i. Sometimes a single vertex from the 's list can be referenced more than once by a single face. The picture below illustrates this problem. The small triangle is actually outside of the face, and the vertex at the top of it is referenced twice by the face. Thus an additional edge parameter can be accepted. If ee is -1, it is ignored, and the first instance of vv is used. If ee>-1, this method looks for the instance of vv that starts out edge ee. Thus if fc.vtx[i] = vv and fc.vtx[j] = vv, but fc.edg[i] != ee and fc.edg[j] = ee, j is returned. IMPORTANT: If no vertex is found matching the given parameters, this method generates an assertion failure. Please be sure that vertex vv is actually on the face (and that edge ee follows it if ee is not -1) before using this method. - - - - - Returns the position of edge ee in this face's list of edges. For a given face fc, if fc.edg[i] = ee, fc.EdgeIndex (ee) = i. Sometimes a single edge from the 's list can be referenced more than once by a single face. The small rectangle is actually outside of the face, and the edge above it is referenced twice by the face, once in each direction. Thus an additional vertex parameter can be accepted. If vv is -1, it is ignored, and the first instance of ee is used. If vv>-1, this method looks for the instance of ee that starts out with vertex vv. Thus if fc.edg[i] = ee and fc.edg[j] = ee, but fc.vtx[i] != vv and fc.vtx[j] = vv, j is returned. IMPORTANT: If no edge is found matching the given parameters, this method generates an assertion failure. Please be sure that edge ee is actually on the face (and that vertex vv follows it if vv is not -1) before using this method. - - - - - Replaces vertex ov with vertex nv in the list of vertices. It is possible for a face to reference the same vertex more than once, however the combination of a vertex followed by a specified edge is unique. Therefore if ee<0, all instances of ov are replaced by nv, but if not, only the instance of ov followed by ee is replaced. - - - - - Replaces edge oe with edge ne in the list of edges. It is possible for a face to reference the same edge twice, however the combination of an edge preceded by a specified vertex is unique. Therefore if vv<0, all instances of oe are replaced by ne, but if not, only the instance of oe preceded by vv is replaced. - - - - - Assignment operator. Copies all information from "from", including triangulation, hidden vertices, flags, smoothing & material info, and "track". - - - - - Comparison operator - - - - - Access operator. - - - - - Uses DebugPrint to print out face information to the Debug Results window in DevStudio. The information consists of the vertices and edges used by this face. It is generally a good idea to put in a DebugPrint immediately before this with the index of the edge, so you know which one is being printed out: - Parameters: - bool triprint=FALSE - - Print out triangulation information. - - bool hinfo=TRUE - - Print out hidden vertex information. - - - - - Used for grouping faces in an into clusters for applying transformations. Depending on the constructor used, it may group faces into clusters based on minimal angles between faces, on face selections, or on both. The class contains a list of face "clusters" for a given mesh. A typical application would be in Editable Poly, where the user has selected two separate groups of faces on different parts of the mesh and wants to extrude them both, or rotate both around their local centers. Each "cluster" is a contiguous group of selected faces. This class is only defined in relation to some . - For convenient caching, it is recommended that you use this class through the class. - All methods of this class are implemented by the system. - - - - - The cluster number, one for each face. Note that non-selected faces have UNDEFINED for their id. - - - - - The total number of clusters in the . - - - - - Index operator for accessing cluster data. - - - - - This method will create a table indicating which face cluster each vertex in the mesh is in. - Parameters: - &mesh - - The mesh this face cluster is based on. - - <int> & vclust - - The table of vertex clusters. This is set to size mesh.VNum(). Values of UNDEFINED (0xffffffff) in the table indicate that a vertex is not in any cluster. If a vertex is in two clusters (because it's a point where corners of two clusters touch), the higher-indexed face's cluster is dominant. - - - - - Computes average normals and centers for each of the face clusters. - Parameters: - &mesh - - The mesh this face cluster is based on. - - > & norm - - The tables where the normals should be put. Each of these tables has its size set to the number of clusters, and is indexed by cluster. - - > & ctr - - The tables where the centers should be put. Each of these tables has its size set to the number of clusters, and is indexed by cluster. - - - - - This method will finds the edge list that borders this cluster. This edge list is a set of closed loops of edges, which may be empty. For instance, if the mesh is a sphere, and all the faces are in the cluster, there are no border edges for the cluster. But if one horizontal row of faces, such as the faces just above the equator, are in the cluster, then the edges above those faces form one loop, while the edges below form another. - Parameters: - &mesh - - The mesh this face cluster is based on. - - int clustID - - The ID of the cluster we want to get the border of. - - <int> & cbord - - The table for putting the border output. This table is set up as follows: each border loop is represented by a series of edge indices, followed by a -1 to indicate a separation between loops. So a result of size 10 with data 1, 4, 6, 9, -1, 2, 10, 15, 14, -1, would indicate two border loops consisting of four edges each. The order of the edges in the loops is chosen so that as you look from outside the mesh and follow the path of the edges, the face cluster will always be on the left. - - - - - This method will retrieve the "outline" direction for the border of the cluster. This is the direction used in the "Outline" feature in Editable Poly face level, as well as in the Bevel command mode. - Parameters: - &m - - The mesh this face cluster is based on. - - > & cnorms - - The cluster normals, as computed in the GetNormalsCenters method. (This data is input, not output.) - - > & odir - - This is where the outline vectors are stored. This table is set to size mesh.VNum(), and stores one direction vector for each vertex. Most direction vectors are usually zero, since most vertices are not on the cluster's border. All vectors are scaled so that moving along them moves the cluster's border edges by one unit. (For instance, the length of a vector at a right angle between two border edges would be sqrt(2), so that each edge can move by 1 unit "out" from the cluster.) - - - - - Used to assist in the process of sorting faces into separate elements. - - For convenient caching, it is recommended that you use this class through the class. - Data Members: - <int> elem; - - The list indicating which element each face is in. The size is the number of faces in the associated . - - int count; - - The total number of elements in the associated . - - - - - Index operator for accessing elements. - - - - - Holds the mapping information for a particular map channel of the . As with regular maps, the holds an array of map vertices and an array of map faces that define how those mapping vertices are applied to the . The number (numf) of mapping faces should always match the number of faces in the parent , and each gives the map vertices for the related . The number of map vertices may be different from the number of MNVerts in the parent . - - - - - Initializes the map - sets numv and numf to 0, and sets the pointers to NULL. Also initializes private allocation related data members. - - - - - Allocates the specified number of UVVerts in the v array. (If you're creating a number of map verts, but you're not sure exactly how many, it's good to pre-allocate a large number using this method.) This method doesn't affect MNMap::numv, only the allocation amount. - Parameters: - int num - - The number of UVVerts to allocate. - - bool keep=TRUE - - If TRUE any previous verts are kept; otherwise they are discarded. - - - - - Allocates the specified number of map faces in the f array. This method doesn't affect MNMap::numf, just the number allocated. - Parameters: - int num - - The number of map verts to allocate. - - bool keep=TRUE - - If TRUE any previous map faces are kept; otherwise they are discarded. - - - - - Returns the current number of UVVerts. - - - - - Returns the 'i-th' UVVert. - Parameters: - int i - - The zero based index into the v array of the UVVert to return. - - - - - Returns the number of map faces. - - - - - Returns a pointer to the 'i-th' map face. - Parameters: - int i - - The zero based index of the map face to return. - - - - - Assignment operator. - - - - - Appends the specified object onto this . - Parameters: - const &from - - The source . - - - - - Appends a default planar map corresponding to the mesh passed onto this map. This is typically used when joining two MNMeshes together when one has a map channel active but the other doesn't. Rather than eliminate the map channel, we just use the object coordinates of the other mesh to generate a planar map for its faces. - Parameters: - const &from - - The source . - - - - - The array of map faces. - - - - - The array of UVVerts. - - - - - The number of vertices in the v array. - - - - - The number of map faces in the f array. - - - - - Like MNMesh::NewTri, this creates a new mapping face, of degree 3, with the specified map vertices. - Parameters: - int a - - int b - - int c - - The mapping vertices for the new triangle. - - - - - Like MNMesh::NewTri, this creates a new mapping face, of degree 3, with the specified map vertices. - Parameters: - int *vv - - The mapping vertices for the new triangle. - - - - - Like MNMesh::NewQuad, this creates a quad, with the specified map vertices. - Parameters: - int a - - int b - - int c - - int d - - The mapping vertices for this quad. (The two faces are formed with mapping verts (a,b,c) and (c,d,a). - - - - - Like MNMesh::NewQuad, this creates a quad, with the specified map vertices. - Parameters: - int *vv - - The mapping vertices for this quad. (The two faces are formed with mapping verts (vv[0],vv[1],vv[2]) and (vv[2],vv[3],vv[0]). - - - - - Like MNMesh::NewFace, this creates a new mapping face with the specified degree and map vertices. - Parameters: - int degg=0 - - The degree of the new face. (Note that this should match the degree of the associated .) - - int *vv=NULL - - The new mapping vertices, in order around the perimeter. - - - - - Sets the number of map faces keeping any previously allocated faces. - Parameters: - int nfnum - - The number of faces to set. - - - - - Allocates storage for a new specified UVVert. An optional offset to the UVVert may be supplied. (The offset is useful when you want to create a new UVVert which is on the other side of a seam in U or V from some existing UVVert p.) - Parameters: - UVVert p - - The UVVert to store. - - int uoff=0 - - If non-zero this is an offset applied in U when p is stored. - - int voff=0 - - If non-zero this is an offset applied in V when p is stored. - - - - - Sets the number of UVVerts keeping any previously allocated UVVerts. - Parameters: - int nvnum - - The number of UVVerts to set. - - - - - Eliminates the mapping vertices not used by any active mapping faces in this map. (Analogous to the Mesh::DeleteIsoMapVerts method.) - Parameters: - *faces - - This should point to the array of the parent . This allows the method to find out if any faces should be considered MN_DEAD, so that it won't mark such faces' map verts as used. (The MN_DEAD flag is stored in the , but not in the related MNMapFaces.) - - - - - Eliminates the MN_DEAD map faces from the array. This should be called immediately before calling CollapseDeadFaces on the parent , to keep the face arrays in sync. - Parameters: - *faces - - The parent 's array of MNFaces. This array is used to find out which faces are MN_DEAD. - - - - - Sets the number of UVVerts and map faces to 0. - - - - - Sets the number of UVVerts and map faces to 0 and deallocates the memory. - - - - - Transforms each UVVert with the specified matrix. - Parameters: - &xfm - - The matrix to transform the UVVerts by. - - - - - Copies pointers. To avoid memory errors, this method should only be used by the pipeline. - Parameters: - const & from - - The map to copy pointers from. - - - - - Creates new pointers and copies over all the data. To avoid memory errors, this method should only be used by the pipeline. - - - - - Uses DebugPrint to print out information about this to the Debug Results window in DevStudio. This includes all map verts and faces, one per line. - Parameters: - *faces - - This should be the array of the parent . It's used to prevent the DebugPrinting of MN_DEAD faces. - - - - - Checks the for internal errors, such as a referring to an out of range map vertex. If an error is found, an error message is DebugPrinted, and a the method returns FALSE. This is strictly a debugging tool of no use in releases - a good way to use it is to say , so it won't be called when not in a Debug build, and so it'll throw up an assertion failure if something's wrong. Error messages generated: Map d: Wrong number of faces. Should be d, is d. (Sent if nf != MNMap::numf) Map d, d has wrong degree. Should be d, is d. (Sent if f[i].deg != faces[i].deg) Map d, d has wrong hdegree. Should be d, is d. (Sent if f[i].hdeg != faces[i].hdeg) Map d, d has an out-of-range map vertex: d. Map d, d has an out-of-range hidden map vertex: d - Parameters: - int mp - - The map channel this represents - used to give more helpful debug information. - - int nf - - The number of faces of the parent . - - *faces - - The parent 's face array. This is used to prevent checking of MN_DEAD faces, which may safely be invalid. - - - - - Used internally to save this to the 3ds Max file. - - - - - Used internally to load this from the 3ds Max file. - - - - - Used to store map vertex information for a given face and map channel. - By way of analogy: is to as is to . is to as is to as is to as is to . - - - - - Degree of this face, and size of the arry of mapping vertices (MNMapFace::tv). Must match degree of related in . - - - - - Mapping vertices used by this mapping face. This array has size MNMapFace::deg - - - - - Initializes . deg is set to 0, pointers set to NULL. - - - - - Clears and frees . - - - - - Allocates enough memory in the arrays for the face to have degree d, but does not actually set the degree. If the arrays are already large enough (or larger), it does not reallocate them. - Parameters: - int d - - The degree for this map face. - - - - - Allocates enough memory in the arrays for the face to have degree d, and then sets the degree. If the arrays are already large enough (or larger), it does not reallocate them. You generally don't need to use this method separately; MakePoly, Insert, and other methods which may require additional memory will call this if needed. - - - - - Makes this face into a polygon with the specified vertices and other information. - Parameters: - int fdeg - - The degree to set this face to. - - int *tt - - The list of vertices for this face. - - - - - Inserts space for more vertices at the specified position. - Parameters: - int pos - - The location within the map face where the new vertices should be added. - - int num=1 - - The number of new vertices to add. - - - - - Deletes vertices from this map face. - Parameters: - The location within the map face where the vertices should be deleted. - - int num=1 - - The number of vertices to delete. - - - - - Re-indexes the vertices and edges so that the vertex in position newstart becomes the new first vertex. Triangulation is also corrected. - Parameters: - int newstart - - The new first vertex. - - - - - Reverses order of verts, effectively inverting the face. - - - - - Returns the position of vertex vv in this face's list of vertices. - Parameters: - int vv - - The vertex whose index is returned. - - - - - Replaces vertex ov with vertex nv in the list of vertices. - Parameters: - int ov - - The vertex to replace. - - int nv - - The vertex to replace it with. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - Debug print statement. - - - - - This class is used to "preserve" mapping coordinates while moving vertices. The "Preserve" name is actually a little confusing; what this class helps us do is modify map vertices such that the overall map on a surface looks about the same, even though the regular vertices have moved. For instance, if you start with a object, and move the middle vertex to the right, the map is typically distorted even though all the original map vertices are unaffected. This class will help by adjusting the middle map vertex so that the overall regular texture pattern is preserved. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Clears out all allocated data, and resets to empty. - - - - - Creates caches of data based on the mesh given and the set of maps to be preserved. Sets the "initial state" which the maps should try to adhere to. - - The mesh whose maps should be preserved - A indicating which map channels should be preserved. See class for more details. - - - - Given a mesh and a set of offsets for vertices, manipulate map channels to preserve the initial UV mapping. - - The mesh being affected. Note that this algorithm uses the face information in the mesh, and affects the maps in the mesh, but it doesn't use the vertex information at all. (All relevant vertex information was digested in Initialize.) So this method may be called before or after applying the offsets given in pDelta. - The set of offsets for the vertices. - The length of the pDelta array - - - - The class is provided for temporary use by plug-ins, to help with complex topology-based modifications to Meshes. It has certain capabilities, such as the ability to recognize faces with more than 3 sides, that are useful in some applications. It is not suitable for use as a pipeline object. All methods of this class are implemented by the system. - has a winged-edge structure and a highly interlinked topology. This is very useful for some modifiers, but requires far more memory and processing time than an equivalent normal mesh. It's convenient for the programmer, but may be sluggish for the user. - Although some methods can be a bit slow, none of them are non-linear in the amount of time they take. Even the tessellation algorithms, which can as much as quadruple the size of the meshes, operate locally, vertex by vertex, so they are order-of-n algorithms. - supports the interface and supports the flags listed at MNMesh Flags. - List of deprecations from 3dsMax 2024: - - - - - The current selection level. See PMeshSelLevel. - - - - - Display flags. See MNMesh Display Flags - - - - - Clears all flags. - - - - - The data members are initialized as follows: - - - - - Allocates and inits the specified number of MNVerts. - Parameters: - int num - - The number of verts to allocate. - - bool keep=TRUE - - If TRUE any previous verts are kept; otherwise they are discarded. - - - - - Shrinks the nv_alloc size of the array to the specified size. - Parameters: - int num=-1 - - The new size of the array. The default -1 means to shrink array allocation to numv. - - - - - Deallocates any MNEdges in the vedg table and sets the vedg pointer to NULL. - - - - - Allocates the vedg array. - - - - - Deallocates the vfac array. - - - - - Allocates the vfac array. - - - - - Allocates the data array e with the specified size. - Parameters: - int num - - The number of MNEdges to allocate. - - bool keep=TRUE - - If TRUE any previously allocated edges are kept; otherwise they are discarded. - - - - - Reduces the ne_alloc size of the data array e to the specified number of elements. - Parameters: - int num=-1 - - The new size for the array. The value -1 means to use the current number of edges, nume. - - - - - Allocates the array f with the specified size. - Parameters: - int num - - The number of MNFaces to allocate. - - bool keep=TRUE - - If TRUE any previously allocated faces are kept; otherwise they are discarded. - - - - - Reduces the nf_alloc size of the data array f to the specified number of elements. - Parameters: - int num=-1 - - The new size for the array. The value -1 means to use the current number of faces, numf. - - - - - Returns the number of vertices. - - - - - Returns a pointer to the i'th . - - - - - Returns the point in the i'th . P(i) is the same as V(i)->p. - - - - - Returns the number of edges. - - - - - Returns a pointer to the i'th . - - - - - Returns the number of faces. - - - - - Returns a pointer to the i'th . - - - - - Returns the number of MNMaps. Access the maps with M() - - - - - of triangles. - - - - - This accessor accepts a value in the range -NUM_HIDDENMAPS to MNum(). - Parameters: - int mp - - The map channel - - - - - Allocates and initializes the specified number of elements in the m array. Initializing sets the number of verts and faces in the map to zero and sets the MN_DEAD flag. - Parameters: - int mpnum - - The number of MNMaps to allocate and initialize. - - - - - Allocates and initializes basic planar map, or a white map for the vertex color channel. - Parameters: - int mp - - The map channel to initialize: - - 0: Vertex channel. - - 1: Default mapping channel. - - 2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0. - - - - - Clears and frees the specified map channel, setting the MN_DEAD flag. - Parameters: - int mp - - The map channel to clear. - - 0: Vertex channel. - - 1: Default mapping channel. - - 2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0. - - - - - Returns the specified UVVert from the specified mapping channel. - Parameters: - int mp - - The map channel. - - 0: Vertex channel. - - 1: Default mapping channel. - - 2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0. - - int i - - The zero based index of the UVVert to return. - - - - - Returns a pointer to the specified from the specified mapping channel. - Parameters: - int mp - - The map channel: - - 0: Vertex channel. - - 1: Default mapping channel. - - 2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0. - - int i - - The zero based index of the to return. - - - - - Returns the total number of triangles; this is a sum of the number of triangles in each face that does not have the MN_DEAD flag set. Extrapolate map information about a point near a face. Given a point near a given edge of a given face, but near to it, this method will extrapolate what that point's mapping coordinates would be in the mapping scheme used by the face. - Parameters: - int face - - The face we want to base mapping information on. - - int edge - - The index of the edge we're closest to on the face. (This should be the face-based index, in the range (0, deg-1), not the index of the edge in the .) - - & pt - - The object-space coordinates of the point. - - int mp - - The map channel we're analyzing. - - - - - Detaches the texture vertices on the border edges of the fclust. Similar to the Detach() function but instead of being applied to the geometry vertices it is applied to the texture vertices. The border edges texture vertices of the cluster will not be shared with any other faces outside the cluster after this operation - Returns true if the operation was successful or false otherwise. - - A set of face clusters. - The ID of the cluster to operate on. - - - - Returns whether an edge is a seam or not. Am edge is a seam if that edge only has 1 texture face connected to it, in other words it is an open texture edge - Returns true if the operation was successful or false otherwise. - - The map channel to look at the texture of.. - The edge number. - - - - Returns map verts for both ends of each edge (from f1's perspective) (Very useful for creating new faces at borders.) mv[j*2] is the map vertex corresponding to edge j's v1. - Parameters: - <int> & lp - - A loop of border edges, such as is generated by MNMesh::FindBorders. - - <int> & mv - - The table into which the map vertices should be put. The size is set to 2*lp.Count(). - - int mp - - The map channel we're analyzing. - - - - - Sets the specified number of vertex data elements. - Parameters: - int ct - - The number of vertex data elements to set. - - BOOL keep=FALSE - - If TRUE any previously allocated elements are kept; otherwise they are discarded. - - - - - Returns the number of vertex data channels maintained by this . - - - - - Returns the number of active vertex data channels maintained by this . - - - - - Returns TRUE if the specified channel of vertex data is available for this ; otherwise FALSE. - Parameters: - int vdChan - - The vertex data channel. See Vertex Data Index Options. - - - - - Sets if the specified channel of vertex data is supported by this . - Parameters: - int vdChan - - The vertex data channel. See Vertex Data Index Options BOOL support=TRUE - - TRUE to indicate the channel is supported; FALSE to indicate it's not. If TRUE is specified then elements are allocated (if needed). If FALSE is specified the data for the channel is freed. - - - - - Returns the vdChannel'th vertex data channels maintained by this . - - - - - Returns a pointer to the vertex data for the specified channel or NULL if the channel is not supported. - Parameters: - int vdChan - - The vertex data channel. See Vertex Data Index Options. - - - - - Returns a pointer to the floating point vertex data for the specified channel of this mesh or NULL if the channel is not supported. - Parameters: - int vdChan - - The vertex data channel. See Vertex Data Index Options. - - - - - Deletes (deallocates) the vertex data for the specified channel. - Parameters: - int vdChan - - The vertex data channel. See Vertex Data Index Options. - - - - - Deallocates the vertex data from all channels and sets the number of supported channels to 0. - - - - - Returns a pointer to the floating point vertex weight data. - - - - - Sets the channel support for the vertex weights channel (VDATA_WEIGHT). - - - - - Frees (deallocates) the vertex weight channel data. - - - - - Returns a pointer to the floating point vertex selection weight data. - - - - - Sets the channel support for the vertex weights channel (VDATA_SELECT). - - - - - Frees (deallocates) the vertex selection weight channel data. - - - - - Sets the specified number of edge data elements. - Parameters: - int ct - - The number of edge data elements to set. - - BOOL keep=FALSE - - If TRUE any previously allocated elements are kept; otherwise they are discarded. - - - - - Returns the number of edge data channels maintained by this . - - - - - Returns the number of active edge data channels maintained by this . - - - - - Returns TRUE if the specified channel of edge data is available for this ; otherwise FALSE. - Parameters: - int edChan - - The edge data channel. See Edge data channel index values. - - - - - Sets if the specified channel of edge data is supported by this . - Parameters: - int edChan - - The edge data channel. See Edge data channel index values. - - BOOL support=TRUE - - TRUE to indicate the channel is supported; FALSE to indicate it's not. - - - - - Returns the vdChannel'th edge data channels maintained by this . - - - - - Returns a pointer to the edge data for the specified channel or NULL if the channel is not supported. - Parameters: - int edChan - - The edge data channel. See Edge data channel index values. - - - - - Returns a pointer to the floating point edge data for the specified channel of this or NULL if the channel is not supported. - Parameters: - int edChan - - The edge data channel. See Edge data channel index values. - - - - - Deletes (deallocates) the edge data for the specified channel. - Parameters: - int edChan - - The edge data channel. See Edge data channel index values. - - - - - Deallocates the edge data from all channels and sets the number of supported channels to 0. - - - - - Returns a pointer to the floating point edge knot data. - - - - - Sets the channel support for the edge knot channel (EDATA_KNOT). - - - - - Frees (deallocates) the edge knot channel data. - - - - - Clears and frees the flags and face/edge lists for the specified vertex. - - The vertex to clear. - - - - Initializes the specified , clearing its flags and emptying its face & edge lists (if vfac & edg are allocated). - Parameters: - int vv - - The vertex to initialize. - - - - - Returns the index of face ff in the vfac[vv] table. - - NOTE that if this face cannot be found, or if it cannot be found accompanied by edge ee>-1, it will cause an assertion failure. - Parameters: - int vv - - The vertex to check the face list of. - - int ff - - The face to look for. - - int ee=-1 - - In cases where the same face touches this vertex more than once, and is therefore represented twice in the vfac table, an optional edge parameter is used to specify which instance of the face you want the index of. However, if the parent doesn't have its vertices ordered (as indicated by the MN_MESH_VERTS_ORDERED flag), the extra edge parameter is meaningless and should not be used. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::EdgeIndex method. - - Finds the position of edge ee in this 's vedg table. Unlike VFaceIndex (and 's VertIndex and EdgeIndex), each vertex can only touch an edge once, so there's no need for an additional parameter. (There's no such thing as an edge with both ends at the same vertex.) - Parameters: - int vv - - The vertex whose edge list should be searched. - - int ee - - The edge to find. - Returns -1 if edge ee is not in the edge table. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::DeleteEdge method. - - Finds edge ee in the vedg[vv] table and removes it. - Parameters: - int vv - - The vertex from whose edge list the edge should be deleted. - - int ee - - The edge to delete from the vertex's edge list. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::DeleteFace method. - - Finds face ff in the vfac[vv] table and removes it. NOTE that this method causes an assertion failure if face ff is not in the vfac table. If ff occurs more than once, which is possible on some valid NONTRI meshes, only the first ff is removed. - Parameters: - int vv - - The vertex from whose face list the face should be deleted. - - int ff - - The face to delete from the vertex's face list. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::ReplaceEdge method. - - Finds edge oe in the vedg[vv] table and replaces it with ne. NOTE that this method causes an assertion failure if edge oe is not in the vedg table. - Parameters: - int vv - - The vertex in whose edge list the edge should be replaced. - - int oe - - The edge to replace. - - int ne - - The replacement edge. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::ReplaceFace method. - - Finds face of in the vfac[vv] table and replaces it with nf. NOTE that this method causes an assertion failure if face of is not in the vfac table. If of occurs more than once, which is possible on some valid NONTRI meshes, only the first of is replaced. - Parameters: - int vv - - The vertex in whose face list the face should be replaced. - - int of - - The face to replace. - - int nf - - The replacement. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::operator= by allowing the developer to copy face and edge adjacency information as well as vertex location and flags. - - Copies the data from ov to nv. The face and edge data is copied too if appropriate (ie if MN_MESH_FILLED_IN is set and vfac and vedg are allocated). - Parameters: - int nv - - The destination index. - - int ov - - The source index. - - - - - This method is available in release 3.0 and later only. It replaces the old MNVert::MNDebugPrint method. - - Uses DebugPrint to print out vertex information to the Debug Results window in DevStudio. The information consists of the position, edge list, and face list. It is generally a good idea to put in a DebugPrint immediately before this with the index of the vertex, so you know which vertex is being printed out: - - DebugPrint(_M("Vertex %d: "), vid); - - MNVDebugPrint(vid); - Parameters: - int vv - - The zero based index of the to debug print. - - - - - Creates a new tri-face. Note that no mapping coords or vertex colors can be specified. - Parameters: - int a,b,c - - The indices of the vertices that form this triangle. - - DWORD smG=0 - - The smoothing group(s) assigned to the new face. - - MtlID mt=0 - - The material ID assigned to the new face. - Returns the index of the new face created. - - - - - Creates a new face of degree 3. selection and visibility flags are set to the default: all visible and not selected. - Parameters: - int *vv - - The indices of the vertices that form this face. (There must be 3 of these.) - - DWORD smG - - The smoothing group(s) assigned to this face. - - MtlID mt - - The material ID assigned to this face - The index of the face created. - - - - - This method will create a new quad. - - Previous to 4.0 this method used two tri-faces that shared and invisible edge. - Parameters: - int a, b, c, d - - The indices of the vertices that form this quad. - - DWORD smG=0 - - The smoothing group(s) assigned to the new faces. - - MtlID mt=0 - - The material ID assigned to the new faces. - Returns the index of the quad face created. - - - - - This method will create a new quad. - - Previous to 4.0 this method used two tri-faces that shared and invisible edge. - Parameters: - int *vv - - The indices of the vertices that form this face. (There must be 4 of these.) - - DWORD smG - - The smoothing group(s) assigned to this face. - - MtlID mt - - The material ID assigned to this face - Returns the index of the quad face created. - - - - - This method creates a (single) new face with the characteristics given. The default triangulation for a face of this degree is used; if the face is not convex, this triangulation may be inappropriate. If this is the case, call RetriangulateFace() on this face after it's created. - Parameters: - int initFace - - A current face from which smoothing groups, material ID, and flags should be copied. If this is NULL, these values are left at their default values. - - int degg - - The degree of the face to be created. - - int *vv - - The indices of the vertices that form the new face. (There must be degg of these.) - - bool *vis - - This is an array of visibility bits for the edges of the new face. If this is NULL, the default of all edges being visible is used. If this is not NULL, there must be degg values. - - bool *sel - - This is an array of selection bits for the edges of the new face. If this is NULL, the default of all edges not being selected is used. If this is not NULL, there must be degg values. - - - - - Creates a new face, using the vertices given. - - Note that this method, unlike the similar NewFace() method, maintains all topological links. If there's an edge between vv[0] and vv[1] which is already used by some other face (on the other side), that edge is modified to use this face on its "f2" side. If there's an edge between two sequential vertices with faces on both sides, the creation fails, because it would create an illegal condition. - - This method also creates map faces in any active map channels to maintain the validity of the mesh. These map faces use the map vertices that other faces use for the vertices passed in, or if there are no corresponding map vertices yet, use newly created map vertices with the value (1,1,1). - Parameters: - int degg - - The degree of the new face. - - int *vv - - A pointer to an array of degg vertices for the new face. - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - The index of the new face, or -1 if the method was unable to create that face. - - - - - Appends the specified number of MNFaces to f. - Parameters: - int nfnum - - The number of MNFaces to append. - The index of the first appended face (ie the old numf). - - - - - Sets the specified number of MNFaces allocated in f. - Parameters: - int nfnum - - The number of MNFaces to set. - - - - - creation tool. If there is no edge currently joining vertices v1 and v2, it creates such an edge. If there is an edge starting at v2 and ending on v1, it registers face f as being on the "other side" of the edge. - Parameters: - int v1, v2 - - The start & end vertices of the edge you wish to register. - - int leftFace - - The face on the "left" side of this edge, if you're looking from v1 towards v2 with the surface normal above. - - int fpos - - The index of this edge in face f. This is used to extract visibility and selection information from the face. - The index of the new edge, or -1 if the edge already exists in the specified direction. - - - - - creation tool. Simply makes a new edge from v1 to v2, without worrying about whether such an edge may already exist, or what faces may be on either side. Since edges are required to have at least one valid face on them, using this method obligates the developer to assign f1 on the new edge themselves. - The index of the new edge. - - - - - creation tool. Requires the developer to previously ascertain that there is no edge from v1 to v2 or from v2 to v1. - Parameters: - int v1, v2 - - The start & end vertices of the edge you wish to create. - - int leftFace - - The face on the "left" side of this edge, if you're looking from v1 towards v2 with the surface normal above. - - int fpos - - The index of this edge in face f. This is used to extract visibility and selection information from the face. - The index of the new edge. - - - - - Appends the specified number of edges. - Parameters: - int nenum - - The number of edges to append. - - - - - Sets the number of MNEdges allocated in e. - Parameters: - int nenum - - The number of MNEdges to set. - - - - - Creates a new vertex (increasing numv) and sets it to the specified point. - Parameters: - &p - - The point to which the new vert should be initialized. - - - - - This method is available in release 3.0 and later only. It replaces the old MNMesh::NewVert ( &p, *mv=NULL) method. - - Creates a new vertex (increasing numv) and initializes it to the point p and the flags and other characteristics of vertex vid. - Parameters: - &p - - The point to which the new vert should be initialized. - - int vid - - The index of the existing from which flags and info should be copied. (Only the MN_SEL and MN_TARG flags are copied.) - - - - - Creates a new vertex and initializes it to location, flags and other characteristics of vertex vid. - Parameters: - int vid - - The index of the existing from which location, flags and info should be copied. (Only the MN_SEL and MN_TARG flags are copied.) - - - - - Creates a new vertex which is a linear combination of two existing vertices. The new vertex has the MN_SEL and MN_TARG flags of whichever vertex it's closest to. The location and info is interpolated. - Parameters: - int v1 - - The first vertex to combine. - - int v2 - - The second vertex to combine. - - float prop - - The proportion along the segment from v1 to v2 where the new vertex should be located. - - - - - Appends the specified number of MNVerts. - Parameters: - int nvnum - - The number of MNVerts to append. - The index of the first appended vertex (ie the old numv). - - - - - Sets the number of verts, allocating if needed. - Parameters: - int nvnum - - The desired number of vertices in the mesh. - - - - - Creates a spur on the face at vertexIndex. This creates a new vertex, and an edge to it at the specified corner of the face. - The new vertex is collocated at the old and the edge between the two is referenced twice. - - The mesh should not be left in this state. This is just a helper function for other operations. - - - - - Removes all MNVerts with the MN_DEAD flag from the list of vertices. Also, it re-indexes all the faces' and edges' vertex references to maintain mesh integrity. - - - - - Removes all MNEdges with the MN_DEAD flag from the list of edges. Also, re-indexes all the faces' and vertices' edge references to maintain mesh integrity. - - - - - Removes all MNFaces with the MN_DEAD flag from the list of faces. Also, re-indexes all the edges' and vertices' face references to maintain mesh integrity. - - - - - Performs all 5 of the above collapse functions, safely removing all unused components from this mesh. - - - - - Reinitializes all verts, faces, and edges, freeing the data members of these components, but not freeing the vertex, edge, and face arrays themselves. This option is suitable if you need to clear a you will be reusing. numv, etc, are set to 0. - - - - - Deletes everything and frees all relevant memory. Leaves you with an empty with the default flags. - - - - - Deletes the array and frees any corresponding vertex data. - - - - - Deletes the array and frees and corresponding edge data. - - - - - Deletes the array. - - - - - Deletes the on the specified map channel. - Parameters: - int mp - - The map channel. - - 0: Vertex channel. - - 1: Default mapping channel. - - 2 through MAX_MESHMAPS-1: The new mapping channels available in release 3.0. - - - - - Deletes and frees all the MNMaps. - - - - - Deletes faces with any of the death flags set, as well as delete vertices and edges surrounded by faces with death flags, and correct the mesh components remaining. - Parameters: - DWORD deathflags - - The collection of flags marking the faces you wish to kill. - - DWORD nvCopyFlags=0x0 - - If the NO_BAD_VERTS flag is set on this mesh, DeleteFlaggedFaces will preserve this property. This may involve duplicating some vertices. (See EliminateBadVerts for more information.) If you have vertex flags that you want preserved in this duplication, indicate them in nvCopyFlags. MN_SEL and MN_TARG are always copied, but all other flags are cleared on the new vertex. - - - - - Kills the edge and joins the faces on either side. Does not work with one-sided edges. Re-indexes triangulation in the resulting face to maintain MN_MESH_FILLED_IN integrity. This routine also checks the resulting face for "dangling" edges: if two faces share a common boundary of 3 edges, and the middle edge is removed, the other two edges will actually have the same face on both sides. This is silly, so such edges are also removed & killed, reducing the degree of the face and adding a hidden vertex. - - - - - This routine scans through a mesh from which invisible edges have been removed, looking for vertices that essentially seem to lie in the middle of edges. Such "collinear vertices" actually lie between two edges that are parallel, with the same faces on either side, and with no other edges incident on them. These are easily removed, and if not removed, they can cause unpleasant artifacts in some tessellation algorithms. - - The removal of these vertices consists of deleting them, merging the parallel edges into one (longer) edge, and correcting the faces on either side to have one less vertex and edge. - - Note that this is essentially the opposite of the method SplitEdge. - - - - - This merges vertices that lie extremely close together, similar to what's done in Edit 's Weld function, but it only affects vertices that are joined by an edge. Another way of looking at it is that it uses weld to remove extremely small edges. - Parameters: - float thresh=MNEPS - - This is the maximum length of an edge that will be welded away. The default value of MNEPS is defined in MNCommon.h to be .0001 - generally we use this to delete edges of more or less zero length. - - - - - Clears all specified flag bits in all MNVerts. - - - - - Clears all specified flag bits in all MNEdges. - - - - - Clears all specified flag bits in all MNFaces. - - - - - Recursively sets flag on given face and all faces connected to it. - Parameters: - int ff - - The face to begin painting the face flag on. - - DWORD fl - - The flag to set on these faces. - - DWORD fenceflags=0x0 - - If nonzero, this represents flags of edges that should not be crossed. In this way you can set up a "fence" of edges and set a particular face flag on all the faces within that fence. - - - - - This allows the developer to set flags in one type of component based on what the nearby flags of another type of component are. For instance, you might want to set MN_TARG on all vertices that are used by faces with the MN_SEL flag set; that would be PropegateComponentFlags (MESH_VERTEX, MN_TARG, MESH_FACE, MN_SEL); - - Another example: - - PropegateComponentFlags (MNM_SL_OBJECT, MN_MESH_FILLED_IN, MNM_SL_EDGE, MN_DEAD, FALSE, FALSE); - - This would clear the MN_MESH_FILLED_IN flag from the if any of its MNEdges were dead. - Parameters: - DWORD slTo - - The selection level of the components you wish to set. This would be one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flTo - - The flag to set. - - DWORD slFrom - - The selection level of the components you wish to base the selection upon. This would be one of MNM_SL_OBJECT, MNM_SL_VERTEX, MNM_SL_EDGE, or MNM_SL_FACE. - - DWORD flFrom - - The flag to test. - - bool ampersand=FALSE - - When slFrom and slTo are different, this indicates whether the flags of the nearby components should be "or'd" or "and'd". If it's false, then any flagged components in the "from" level will cause the component in the "to" level to be affected. If true, then all the components in the "from" level that touch a component in the "to" level must be flagged in order for the "to" level component to be affected. (i.e., if from is faces and to is vertices, a vertex would only be modified if all faces that use it have the flFrom flag set.) - - bool set=TRUE - - If TRUE (as would be usual) the slTo components have flags flTo set. If FALSE, these flags would be cleared instead. - Returns the number of slFrom components that tested positive for the flFrom flags. (If 0, nothing happened.) - - - - - Updates the MN_BACKFACING flag in all components based on the specified view. - Parameters: - *gw - - A pointer to the current graphics window. - - bool force - - If the gw points to the same that it did last time this method was called, it doesn't necessarily need to update the flags. If force is true, it will update them anyway. (Useful if you think the perspective may have changed.) - - - - - Selects or deselects the vertices as specified by on bits in the given bit array. If the bit array size is smaller than the number of vertices then only those vertices in the bit array are modified. - Parameters: - const & vsel - - Specifies which vertices to select or deselect. - - - - - Selects or deselects the edges as specified by on bits in the given bit array. If the bit array size is smaller than the number of edges then only those edges in the bit array are modified. - Parameters: - const & esel - - Specifies which edges to select or deselect. - - - - - Selects or deselects the faces as specified by on bits in the given bit array. If the bit array size is smaller than the number of faces then only those faces in the bit array are modified. - Parameters: - const & fsel - - Specifies which faces to select or deselect. - - - - - Fills the given bit array with the current vertex selection state. - Parameters: - & vsel - - The results are stored here. Bits which are on indicate selected vertices. - - - - - Fills the given bit array with the current edge selection state. - Parameters: - & esel - - The results are stored here. Bit which are on indicate selected edges. - - - - - Fills the given bit array with the current face selection state. - Parameters: - & fsel - - The results are stored here. Bit which are on indicate selected faces. - - - - - Using the current edge selection this returns the original selection and the edge loop defined by those selections. If you have 4 ordered edges connected to a vertex the edge loop is the opposing edge to the selected edge. - - An argument of type &. - - - - Using the current edge selection this returns the original selection and the ring loop defined by those selections. - Ring loop is defined as the opposing edge from the selected edge on a quad face. - - An argument of type &. - - - - Gets the current vertex selection, based on the current selection level. That is, if the current selection level is MNM_SL_VERTEX and the parameters are at their defaults, it'll return the current vertex selection, but if the selection level is MNM_SL_FACE, for instance, it'll return the vertices used by currently selected faces. - - This method is used, e.g. in PolyObject::Deform to determine which vertices to affect by pipeline modifiers. - Parameters: - DWORD fmask=MN_DEAD|MN_SEL - - Indicates the flags we're trying to match in the components at the current selection level. - - DWORD fset=MN_SEL - - Indicates which flags (from fmask) we want to see set. The default values mean "find components with MN_SEL set and MN_DEAD cleared". - - - - - Creates a of all vertices using the specified flags. - Parameters: - & vset - - The which is filled in. vset is set to size numv. - - DWORD flags - - The flags to search for. - - DWORD fmask=0x0 - - This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds vertices with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find vertices that have MN_SEL set, but don't have MN_DEAD set. - - - - - Creates a of all edges using the specified flags. - Parameters: - & eset - - The which is filled in. eset is set to size nume. - - DWORD flags - - The flags to search for. - - DWORD fmask=0x0 - - This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds edges with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find edges that have MN_SEL set, but don't have MN_DEAD set. - - - - - Creates a of all faces using the specified flags. - Parameters: - & fset - - The which is filled in. fset is set to size numf. - - DWORD flags - - The flags to search for. - - DWORD fmask=0x0 - - This optional parameter allows the user to look for particular combinations of on and off flags. For instance, if flags is MN_DEAD and fmask is 0, the method finds faces with the MN_DEAD flag set. But if flags is MN_SEL and fmask is MN_SEL|MN_DEAD, it would find faces that have MN_SEL set, but don't have MN_DEAD set. - - - - - Sets bits for all faces in the same "element", or connected component, with face ff. Faces already selected in fset will be considered "walls" for this processing and will not be evaluated. That is, if ff is not selected, but there's a ring of faces around it that is, the algorithm will stop at that ring. - Parameters: - int ff - - The zero based index of the face. - - & fset - - The bits of the faces in the element are selected in this array. - - - - - Takes a one-sided edge and sets the bits representing this edge's "border". (All one-sided edges in MNMeshes can be grouped into chains, end to end, that represent boundaries of the mesh. For instance, in a box with one side deleted, all the one-sided edges are part of the chain that goes around the hole. - Parameters: - int ee - - The edge to start looking from. (Note that edge ee should be one-sided - e[ee].f2 should be -1. - - & eset - - The bitarray to return the border's edge set in. - - - - - This not only sets the edge's MN_EDGE_INVIS flag, it also sets the visedg state of the faces on either side. This is the proper way to set edge visibility permanently, as the flag will be lost if the edge list needs to be reconstructed. - Parameters: - int ee - - The edge whose visibility should be set. - - BOOL vis=TRUE - - The desired visibility - TRUE for visible, FALSE for invisible. - - - - - This not only sets the edge's MN_SEL flag, it also sets the edgsel state of the faces on either side. This is the proper way to set edge selection permanently, as the flag will be lost if the edge list needs to be reconstructed. - Parameters: - int ee - - The edge whose selection state should be set. - - BOOL sel=TRUE - - The desired selection state. - - - - - Clears out all current information, and copies in new faces and vertices from the from argument. - - - - - Adds vertices and faces in "from" to current . This algorithm has O(N) complexity. - - - - - Outputs current into the mesh given. This algorithm has been multithreaded. Note that even if the was originally taken from this , the internal processing may have changed PART_TOPO, PART_GEOM, PART_SELECT, PART_MAPPING, or PART_VERTCOLOR. - - - - - If this mesh does not have the MN_MESH_FILLED_IN flag, this method completely recomputes all combinatorial information. It re-creates all MNEdges and MNFace::edg, MNVert::edg, and MNVert::fac lists based on the information in the MNFace::vtx lists. - - Since this routine completely reconstructs the combinatorics, it clears the MN_MESH_VERTS_ORDERED flag. Complexity of O(N). - - - - - Fills in the faces' edge arrays based on the edge list. Complexity of O(N). - - - - - Fills in the vertex edge and face lists based on the edge list. Complexity of O(N). - - - - - A "bad" vertex in this context is one which is shared between two distinct boundaries for this mesh. As an example, imagine a union between two circles, converted to meshes, that touch at a single vertex. This causes a vertex to exist which is on two faces, but four edges. Since most vertices are on equal numbers of faces and edges (if they're not on a boundary) or on one more edge than face (if they are on a boundary), these types of vertices can mess up some forms of processing. This method eliminates such vertices by duplicating them, assigning one vertex to each boundary. A that has gone through this method will have the MN_MESH_NO_BAD_VERTS flag set until a method (such as NewFace) is called that could conceivably create bad vertices. - - EliminateBadVerts requires a filled in mesh, and will call FillInMesh if the MN_MESH_FILLED_IN flag is not set. - Parameters: - DWORD flag: - - This parameter is available in release 4.0 and later only. - - If nonzero, it indicates that only flagged vertices should be split up if "bad". bool doNullEdgeCheck: - - When true, this function calls EliminateNullEdges before processing vertices, as such edges can confuse the algorithm. - False if nothing changed, true if at least one bad vertex was found and split. - - - - - - - Eliminates from the mesh any "null" edges, defined as edges with identical start and end vertices. In particular, RemoveNullEdges is called for each face of the mesh, and if any edges are identified, they are removed from their vertex edge list and flagged as MN_DEAD. The corresponding duplicate vertices are also removed from the related entities. As EliminateBadVerts may have previously introduced improper split vertices as a result of null edges, if any null edges are identified, then all vedg and vfac lists are checks against face edge lists and edge face lists for consistency. If inconsistencies are found, then they are remdiated by re-unifying split vertices, and flagging the superfluous copies as MN_DEAD. Note that EliminateNullEdges has no effect if null edge checks have been disabled via the MN_MESH_DIASBLE_NULL_EDGE_CHECK flag. - Returns a flag indicating whether any null edges were identified. - - - - - This routine organizes the face and edge lists of each vertex such that going counterclockwise around the vertex (with the surface normal pointing up), you'll encounter edg[0], fac[0], edg[1], fac[1], etc, ending in either the last face if the vertex is not on a boundary or the last edge if the vertex is on a boundary. (If the vertex is on a boundary, the first & last edges are part of that boundary.) - - OrderVerts requires a filled-in mesh with no bad vertices, so it will call FillInMesh and/or EliminateBadVerts as needed. - - - - - This routine organizes the face and edge lists of the specified vertex such that going counterclockwise around the vertex (with the surface normal pointing towards you), you'll encounter edg[0], fac[0], edg[1], fac[1], etc, ending in either the last face if the vertex is not on a boundary or the last edge if the vertex is on a boundary. (If the vertex is on a boundary, the first & last edges are part of that boundary.) - - NOTE: OrderVert requires a filled-in mesh with no "bad" vertices. Failing to adequately prepare your mesh may result in a crash. (See the methods FillInMesh and EliminateBadVerts for details.) - - - - - Converts a MN_MESH_NONTRI mesh, with polygon faces and possibly hidden vertices, into a completely triangulated mesh, wherein all faces have degree 3. This routine is called from OutToTri if the MN_MESH_NONTRI flag is set. Has complexity O(N) - - - - - Triangulates the specified face, splitting it into as many faces as are needed (deg-2+hdeg*2) to represent all the triangles. Has complexity of O(N) where N is the number of triangles. - Parameters: - int ff - - Specifies the face to triangulate. - - - - - Divides a face by creating a point in the face's interior and creating an edge from that point to each of the face's vertices. An n-gon becomes n triangles by this method. - Parameters: - int ff - - The face to divide. - - <float> & bary - - The generalized barycentric coordinates of the point that should be created. (See FacePointBary for details on barycentric coordinates.) - The index of the newly created vertex, or -1 if there's an error. - - - - - Identical to DivideFace but should only be used to load parametric divides for file 2015 and lower - - - - - Finds the bounding box of all vertices and hidden vertices used by face ff. - - - - - Calculates the bounding box of the vertices & hidden vertices of this mesh. - Parameters: - & bbox - - The computed bounding box is placed here. - - bool targonly - - If this is TRUE, only targeted vertices are used to compute the bounding box. Hidden vertices, which are also normally used, will be ignored in this case, since they cannot be targeted. - - - - - Retrieves a bounding box for the . - Parameters: - *tm - - Like the corresponding method in class , this method takes an optional transform, so the user can get a bounding box in any desired space (with a slower calculation, as all the points must be transformed). - - bool targonly - - If set, only vertices with the MN_TARG flag set are used to compute the bounding box. - - - - - Sets vertex MN_TARG flags based on the existing MN_SEL flags. - Parameters: - int iSelLevel - - Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all vertices are targeted. If selLevel is MNM_SL_VERTEX, the vertices with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_FACE or MNM_SL_EDGE, vertices that touch selected faces or edges, respectively, have their MN_TARG flags set. This is algorithm has O(N) complexity. - The (highly) approximate number of targeted vertices. - - - - - Sets edge MN_TARG flags based on the existing MN_SEL flags. - Parameters: - int iSelLevel - - Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all edges are targeted. If selLevel is MNM_SL_EDGE, the edges with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_FACE or MNM_SL_VERTEX, edges that touch selected faces or vertices, respectively, have their MN_TARG flags set. - The (highly) approximate number of targeted edges. - - - - - Sets face MN_TARG flags based on the existing MN_SEL flags. - Parameters: - int iSelLevel - - Specifies which components to check for MN_SEL flags. If selLevel is MNM_SL_OBJECT, all faces are targeted. If selLevel is MNM_SL_FACE, the faces with MN_SEL flags set also have their MN_TARG flags set. If selLevel is MNM_SL_EDGE or MNM_SL_VERTEX, faces that touch selected edges or vertices, respectively, have their MN_TARG flags set. This algorithm has O(N) complexity. - The (highly) approximate number of targeted faces. - - - - - Clears the MN_TARG flag on vertices representing relatively flat areas, keeping the flag on vertices at sharper corners. The purpose of this method is to avoid working on smooth areas of the mesh in, for instance, tessellation algorithms which are designed to smooth an area. An example of this is the sharpness option in 3ds Max's MeshSmooth modifier, although the parameter there is 1.0 - this value. - - Note that this method requires filled in geometry and ordered vertices, and will call FillInMesh and OrderVerts as needed. This algorithm has complexity O(N*deg). - Parameters: - float sharpval - - The threshold for determining whether a vertex is sharp enough to continue being targeted. A value of 0 indicates that all vertices are sharp enough; a value of 1 would de-target all vertices. The actual determination is made by comparing the dot product of any two consecutive face normals is less that 1 - 2*sharpval. - - The following "fence" methods are useful for algorithms such as SabinDoo wherein you don't want to mix faces with different characteristics. - - - - - Finds the centers of all the faces, using repeated calls to ComputeCenter. - Parameters: - *ctr - - An array of at least FNum() points for storing the centers. - - bool targonly - - If this is TRUE, centers will only be computed for targeted faces. (The rest of the ctr array will remain unmodified.) - - - - - Finds the center of face ff by finding the average of all its vertices. - - - - - Computes a "balanced" normal, in that the normal takes the contribution of all vertices equally. (This is significant in the case of nonplanar polygons.) - Parameters: - int ff - - The face you want the normal of. - - & N - - The place to store the computed normal. - - *ctr - - If not NULL, it points to a place where ComputeNormal should put the face center. - - - - - Finds the "safe" centers of all the faces, using repeated calls to ComputeSafeCenter. - Parameters: - *ctr - - An array of at least FNum() points for storing the centers. - - bool targonly - - If this is TRUE, centers will only be computed for targeted faces. (The rest of the ctr array will remain unmodified.) - - bool detarg - - If TRUE, this will remove the MN_TARG flag from faces where safe centers could not be found. - - - - - Finds the "safe" center of face ff, if possible. For non-convex faces, the average point found in ComputeCenter is unsuitable for some applications because it can lie outside the face completely, or in a region where it cannot "see" all the faces' vertices. (I.e., line segments from the center to the corner pass outside of the face.) - - This routine provides a better solution in some cases by finding the center of the convex hull of the face. The convex hull is defined as the region in a face with a clear line-of-sight to all the corners. Some faces, such as the top face in an extruded letter M, have an empty convex hull, in which case this routine fails and merely provides the regular center given by ComputeCenter. This algorithm has complexity of O(deg^2). - Returns TRUE if a safe center was found, FALSE if no such center could be found. - - - - - Computes the triangulation for face f[ff], employing the specified retriangulation algorithm. Note that the specified face is not required to possess a valid triangulation on entry. - - index, in the member f array, of the face for which a triangulation is to be computed - triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration - - - - Finds a diagonal of face ff that does not include any hidden vertices. This can be used with the method FindFacePointTri to get a sub-triangle and barycentric coordinates for a hidden vertex, so that vertex can be kept in the face when the non-hidden vertices are moved in some way. Employs the legacy algorithm TRIANGULATE_LEGACY, as detailed in the description of the MNMeshTriangulationType enumeration. - Parameters: - int ff - - The face to get an external diagonal of. - - int *diag - - An array of at least (F(ff)->deg-2)*3 elements to store the diagonals in. - - - - - This method finds diagonals for this sequence of vertices, creating a triangulation for the polygon they form. Employs the legacy algorithm TRIANGULATE_LEGACY, as detailed in the description of the MNMeshTriangulationType enumeration. - Parameters: - int deg - - The number of vertices in the sequence. - - int *vv - - The array of vertices. - - int *diag - - A pointer to an array of size (deg-3)*2 where the diagonals can be put. - - - - - If the given face is convex, this will often produce a better diagonals than RetriangulateFace would. The diagonals are less likely to overuse any single vertex. The face is not checked for convexity, but if it is not convex the diagonals produced will probably be self-overlapping. - Parameters: - int ff - - The face to find a diagonal for. - - int *diag=NULL - - If NULL, the new diagonals are put into the face's tri array. If this tri is non-NULL, the diagonals are put here instead. Be sure that tri is allocated with space for at least (deg-2+hdeg)*3 elements. - - - - - Uses a triangulation scheme optimized for convex polygons to find a set of diagonals for this sequence of vertices, creating a triangulation for the polygon they form. - Parameters: - int deg - - The number of vertices in the sequence. - - int *vv - - The array of vertices. - - int *diag - - A pointer to an array of size (deg-3)*2 where the diagonals can be put. - - - - - Imposes a diagonal on face f[ff] with endpoints at vertices(f[ff]).vtx[d1] and (f[ff]).vtx[d2], adjusting any pre - existing diagonals which would have topologically intersected the new diagonal, if face ff is not MN_DEAD, and the diagonal defined by vertices d1 and d2 is valid. The diagonal is judged to be valid if it does not correspond to an edge of the face, and if d2 != d1. If face ff is dead, or the proposed diagonal is invalid, the face is unmodified. - true if the diagonal is actually imposed on face ff, otherwise, false - - face on which the diagonal defined by vertices d1 and f2 is to be imposed - indices, in the(f[ff]).vtx array, of the endpoint vertices defining the diagonal to be imposed - - - - Unifies triangles into polygons across invisible edges. Turns a mesh with triangle faces into a mesh with (fewer) polygon faces by removing all hidden edges. This method can take unusually long if there are faces of ridiculously high degree, such as the top of a cylinder with 200 sides but only 1 cap segment. (It can be up to an n-squared routine where n is the number of invisible edges removed to make a given face.) - - This routine is essentially a bunch of calls to RemoveEdge(), followed by a call to EliminateCollinearVerts(). - - - - - Unifies triangles into polygons across invisible edges. Turns a mesh with triangle faces into a mesh with (fewer) polygon faces by removing all hidden edges. Calculation is only performed on the specified face range. - Parameters: - int startFace - - The starting face to work on - int endFace - - The one greater than the last face to be processed. Generally number of faces in the mesh. - - - - - Turns a mesh with triangle faces into a mesh with (fewer) convex polygon faces by removing all hidden edges that aren't necessary to maintain convexity. As of the 2.5 release this method has not been thoroughly tested to ensure that the result is indeed always convex and that it doesn't leave edges that should ideally be removed. Therefore a call to MakeConvex is recommended after use. What we can say about it is that it will not produce any hidden vertices, as MakePolyMesh does, and that if you're going to use MakeConvex anyway, MakeConvexPolyMesh and MakeConvex are more efficient than MakePolyMesh and MakeConvex are. - - MakeConvex essentially undoes a lot of the work done by MakePolyMesh. MakeConvexPolyMesh gives it much less (if anything) to undo. - - - - - Finds an edge connecting these two vertices, if one exists. This algorithm is relatively fast, since it just checks the edges in V(vrt1)'s edge list. However, it requires that the be filled in, and it WILL call the much slower FillInMesh routine if the MN_MESH_FILLED_IN flag is not set. - The index of the desired edge, or -1 if no such edge could be found. - - - - - Chooses a suitable "local space", and sets tm's rotation to match that space. Does not set tm's translation component. (This is easily done by setting tm.SetRow (3, v[vrt].p).) - - The purpose of this method is to support a consistent definition of "localspace" around a given vertex. As usual, Z comes from the local normal; the X direction is chosen to be a particular edge, but then this direction is modified to balance the contribution of the other edges. (Thus it points roughly in the direction of one edge, but moving other edges' far endpoints will rotate which way is considered "X" just as much as moving that edge will.) - Parameters: - int vrt - - The vertex index. - - & tm - - The transformation matrix. Chooses a suitable "local space", and sets tm's rotation to match that space. Does not set tm's translation component. This is easily done by setting tm.SetRow (3, v[vrt].p). - Parameters: - int vrt - - The vertex index. - - & tm - - The transformation matrix. - - - - - Returns the surface normal at the vertex vrt. It computes the normal by taking the average of the face normals from faces that V(vrt) is on, weighted by the angles of the vrt corners of each of those faces. That is, if vrt is at a very acute angle on one face, but a very obtuse angle on the next, the face with the obtuse vrt corner will count much more heavily. The return value has a length of 1. - - This normal is not related to the normals used in rendering. - - - - - Returns the surface normal at the edge edgeIndex. This is just the average of the face normals on either side, or, if this is an edge with only one face, it's just that face's normal. The return value has a length of 1. - - This normal is not related to the normals used in rendering. - - - - - Returns the surface normal of face fc. If this face has degree 3, this is the same as the regular 3ds Max normal for this face. However, if the face is more complex, the normal may not be the same as the ones for the component triangles. - Parameters: - int fc - - The index of the face to find the normal for. - - bool nrmlz - - Whether or not to scale the result to length 1. If this is FALSE, the length of the return value corresponds (in planar faces) to the area of the face, times 2. - - - - - This merely combines GetEdgeNormal (int ed) with FindEdge (int vrt1, int vrt2). It returns the normal of the edge connecting vrt1 to vrt2, if such an edge can be found. (If there is no such edge, it returns (0.0f, 0.0f, 0.0f).) - - - - - Computes the angle at the given edge. (In other words, the angle between the planes of the faces on either side.) Note that in the case of nonplanar polygons, these planes are the "average" planes for the polygon, not the plane of the triangle nearest the edge. - Parameters: - int edgeIndex - - The edge index. - const Point3* faceNormals Optional performance parameter to pass in a precomputed face normals list - The angle in radians. - - - - - Flips the normal of the specified face, as well as the corresponding map faces in active maps. Note that doing this on an isolated face with neighbors will cause an illegal condition. Use the FlipElementNormals method to safely and completely flip the normals of entire elements to avoid this problem. - - This method uses the and methods "Flip", which changes the order of the vertices from (0,1,2...,deg-1) to (0, deg-1, deg-2,...1) and rearrange the edge and diagonal information accordingly. - Parameters: - int faceIndex - - The face index. This method flips the normal of the indicated face. This is done by reordering the vertices. The faces for any assigned texture map is handled as well. - Parameters: - int faceIndex - - The index of the face for which to flip the normal. - - - - - This method can be used to build the normals and allocate RVert space only if necessary. This is a very inexpensive call if the normals are already calculated. When illum is FALSE, only the RVerts allocation is checked (since normals aren't needed for non-illum rendering). When illum is TRUE, normals will also be built, if they aren't already. So, to make sure normals are built, call this with illum=TRUE. - Parameters: - BOOL illum - - If TRUE normals are built. If FALSE only the RVert array is allocated. - - - - - This method resolves the normals on the array. If the already has normals prescribed on each vertex, the normal is just moved to the array. See Class and Class . - - If you are creating or modifying a , after you are done specifying all the vertices and faces, this method should be called. This allocates the and database for the . This will allow you to query the and ask about normals on the vertices. - - This method also builds the face normals for the mesh if needed. - - - - - This method is similar to buildNormals() above, but ignores the material index (mtlIndex). In other words, the difference between this and buildNormals() is that it doesn't look at the mtlIndex of the faces: normals of faces with the same smoothing group are averaged regardless. - - - - - Flips the normals of the specified elements in the mesh. - Parameters: - DWORD flag=MN_SEL - - Indicates which elements should be flipped, in the following way: any element that has at least one flagged face is completely flipped. Elements without any flagged faces are not. - Returns true if anything was flipped, false otherwise. - - - - - This flips the face normals of the tagged faces and also reverses the face winding. - - - - - Applies new smoothing (or removes smoothing groups) from selected areas of the . With the default parameters, it smooths all faces with the same group. - Parameters: - bool smooth - - If TRUE, Resmooth will generate a new smoothing group (using GetNewSmGroup) to apply to the relevant faces. All smoothing groups previously assigned to the faces will be removed. If FALSE, Resmooth will strip all smoothing groups, leaving the faces faceted. - - bool targonly - - If TRUE, Resmooth will not affect faces that are do not have the MN_TARG flag set. - - DWORD targmask - - Resmooth will only affect faces whose smoothing groups are included in targmask. Some examples: with the default value of ~0x0, this is no restriction at all. With a value of 0, Resmooth will only affect faces that previously had no smoothing group assigned. With a value of 0x02, Resmooth will only affect faces that either had smoothing group 2 (and nothing else) or no smoothing group. - - Note: if targonly is TRUE and targmask is not at the default, a face must both be targeted and have its smoothing groups fall into targmask in order to be affected. - - - - - Finds what smoothing groups, if any, are common to all faces in this . - Parameters: - bool targonly - - If this is TRUE, this routine will find smoothing groups that are common to all faces with MN_TARG set, ignoring the rest. - - - - - Produces a single smoothing group that is not currently used in the . If this is impossible because all smoothing groups are used (a rare condition), it produces the least commonly used group. - Parameters: - bool targonly - - If TRUE, this routine will find a smoothing group not used by any of the faces with MN_TARG set. If this is impossible because all smoothing groups are used in targeted faces, it produces the least commonly used group. - - - - - Produces the lowest material ID not used in any faces in the . - Parameters: - bool targonly - - If TRUE, this routine will instead find the lowest material ID not used in the targeted faces of this . - - - - - Returns a smoothing group that is currently used somewhere in the mesh, or returns zero if all faces have no smoothing. - Parameters: - bool targonly - - If TRUE, this routine will find a smoothing group used in one of the targeted faces, or return zero if all targeted faces have no smoothing. - - - - - Find all smoothing groups used in this mesh. - Parameters: - bool targonly=FALSE - - If TRUE, this method will return only smoothing groups set in targeted faces, i.e. those with the MN_TARG flag set. - The return value is a DWORD with every used smoothing bit set. - - - - - Finds available smoothing groups you can use to replace the given smoothing group without messing up the mesh's shading. This method recursively looks at the entire region of faces sharing this smoother with this face, and it finds all smoothing groups used by neighboring faces. Then it returns the bits which are not used by any of them. - - This is useful if, for instance, you want to attach two separate mesh components, but you don't want smooth shading across the join. It's used internally by SeparateSmGroups. - Parameters: - int ff - - The face to start the examination on. - - DWORD os - - The old smoothing group you wish to replace. - All bits that are available to replace the old smoothing group with. - - - - - Recursively replaces the old smoothing group with the new smoothing group. The recursion traverses all faces with the old smoother that share an edge or a vertex. - Parameters: - int ff - - The face to begin the replacement on - - DWORD os - - The old smoothing group - - DWORD ns - - The new smoothing group - - - - - Changes the smoothing groups on faces using v2 so that they are distinct from any smoothing groups on faces using v1. This is used, for instance, in joining the seam between the operands MakeBoolean. Before welding each pair of vertices, this method is called to prevent smoothing across the boolean seam. - If, due to overuse of the 32 smoothing groups, the algorithm can't find enough new ones to replace the overlapping smoothing groups around v2, it will do the best it can and return FALSE. If it succeeds, it returns TRUE. - - - - - Applies new smoothing groups to the whole mesh or to selected faces based on angles between faces. - Parameters: - float angle - - The threshold angle in radians. Edges with angles above this amount will not be smoothed across. - - BOOL useSel - - Indicates if the auto-smoothing should be done only on selected faces. - - BOOL preventIndirectSmoothing - - Sometimes even though two neighboring faces are more than "angle" apart, there may be a path from one to the other via other faces, crossing only edges that are less than "angle" apart, so they'll wind up sharing the same smoothing group anyway. To prevent this sort of "indirect" smoothing, set this value to TRUE. This method performs an auto smooth on the mesh, setting the smoothing groups based on the surface normals. - Parameters: - float angle - - The minimum angle between surface normals for smoothing to be applied, in radians. - - BOOL useSel - - If TRUE only the selected faces are smoothed. - - BOOL preventIndirectSmoothing=FALSE - - TRUE to turn on; FALSE to leave off. This matches the option in the Smooth UI - use this to prevent smoothing 'leaks" when using this method. If you use this method, and portions of the mesh that should not be smoothed become smoothed, then try this option to see if it will correct the problem. Note that the problem it corrects is rare, and that checking this slows the Auto Smooth process. - - - - - Return a DWORD of smoothing groups that a face can use without smoothing to any adjacent face (either across shared edges or shared vertices). - A DWORD containing a bit for each available smoothing group. 0 indicates that none are available. - - The index of the face to check - A bit mask with a bit set for each smoothing group to exclude from the returned smoothing groups. - - - - Return a DWORD containing the lowest-order smoothing group that a list of faces can use without smoothing to any adjacent face (either across shared edges or shared vertices). - A DWORD containing a bit for each available smoothing group. 0 indicates that none are available. - - An IntTab of face indexes to check - A bit mask with a bit set for each smoothing group to exclude from the returned smoothing groups. - - - - Process the specified faces and eliminate any redundant smoothing group usage. - true if smoothing groups were altered, false if no smoothing group alteration occurred. - - A containing bits with a bit set for each face that should be processed. - - - - These methods make fences for the MNMesh::SabinDoo() algorithm. They set NOCROSS flags and deleting INVIS flags. Sets the MN_EDGE_NOCROSS flag on all edges that lie between faces with different material IDs. - - - - - Sets the MN_EDGE_NOCROSS flag on all edges that lie between faces with exclusive smoothing groups. - - - - - Sets the MN_EDGE_NOCROSS flag on all edges that lie between selected & non-selected faces. (This checks the MN_SEL, not the MN_TARG, flags on the faces.) - - - - - Sets the MN_EDGE_NOCROSS flag on all edges that are on the boundary. - - - - - Sets MN_EDGE_NOCROSS flags on edges between faces that aren't in the same plane. - Parameters: - float thresh=.9999f - - This is the threshold used to determine if two adjacent faces have the same normals, i.e. lie in the same plane. If the dot product between the normals is less than thresh, they are considered different, otherwise they're considered the same. The threshold angle between faces is the arc cosine of this amount, so for instance to set a threshold angle of .5 degrees, you would call FenceNonPlanarEdges with a thresh of cos(.5*PI/180.). The default value is equivalent to about .81 degrees. - - bool makevis=FALSE - - Indicates whether nonplanar edges should be made visible, i.e. have their MN_EDGE_INVIS flag cleared. (This is sometimes done before MakePolyMesh, so it can be used to influence whether nonplanar faces are joined together.) - - - - - Sets the MN_EDGE_MAP_SEAM on all edges that are "seams" for any active map(s). A map seam is an edge where the faces on either side use different mapping vertices for at least one end. - - - - - Sets the MN_EDGE_MAP_SEAM on all edges that are "seams" for the specified map(s). A map seam is an edge where the faces on either side use different mapping vertices for at least one end. - Parameters: - int mp - - The map to use to set the seams. If left at the default -1, it'll check all active maps. - - - - - These functions are for querying details about a point on a face. Finds the sub-triangle and (optionally) barycentric coordinates within that triangle of a point that lies on this face. For faces that are not themselves triangles, this helps in particular to create mapping coordinates or vertex colors for new points on this face. To use this method, you must now call MNFace::GetTriangles to get a triangle table, then pass the contents of that table to this method. Note that the optional size of the triangulation array was removed; this is assumed to be (f[ff].deg-2)*3. - Parameters: - int ff - - The face. - - & pt - - The point. - - double *bary - - An array of 3 double-precision values to store the barycentric coordinates in. If this is NULL, barycentric coordinates are not computed. - - int *tri - - An optional alternative triangulation, such as that produced by FindExternalTriangulation. (If NULL, the face's regular triangulation is used.) - 3 times the index of the triangle the point is found in, or -1 if this point doesn't seem to lie on this face. That is, if this point is found in the triangle represented by tri[6], tri[7], and tri[8], this routine will return 6. - - - - - This method is available in release 3.0 and later only. It's the generalized version of the old FindFacePointCV and FindFacePointTV. - - Uses FindFacePointTri and the mapping coordinates of the endpoints of the relevant triangle to compute a map vertex corresponding to the point pt. If the point is not on face ff, UVVert (0,0,0) is returned. - - This method is useful e.g. for getting map coordinates to match a new vertex when dividing up a face. - Parameters: - int ff - - The face to find map coordinates on. - - & pt - - The point (lying on the face) to find map coordinates for. - - int mp - - The map channel to get map coordinates in. - - - - - Finds border loops composed of all one-sided edges. (One-sided edges on a mesh must necessarily be organizable into closed loops along the borders of the mesh.) - Parameters: - & brd - - The class in which to put the border loops. See Class for details. - - DWORD targetFlag - - The selection level in the mesh to use to decide whether the border loops are targeted or not. For instance, with the default MNM_SL_OBJECT, all border loops are targeted, but with a value of MNM_SL_VERTEX, only those border loops containing at least one selected vertex will be targeted. Same for MNM_SL_EDGE. For MNM_SL_FACE, those loops touching at least one selected face will be targeted. - - - - - Finds border loops composed of all one-sided edges for which all of the vertices are also selected. (One-sided edges on a mesh must necessarily be organizable into closed loops along the borders of the mesh.) - Parameters: - & brd - - The class in which to put the border loops. See Class for details. - - - - - - - Fills in all the borders of a mesh. This is what the 3ds Max CapHoles modifier does. It creates new faces on the other side of each of the loops. - Parameters: - MNMeshBorder* b - - If b = nullptr, FillInBorders finds all the borders with a call to GetBorders. If you have already found the borders, however, you can save time by passing a pointer to the class here. (This is especially convenient if you wish to modify the border targeting; only targeted borders are filled in.) - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - - Scans mesh to determine what parts of it are open or closed. Consider a "submesh" to be one connected components of faces and edges. Each submesh is open if it has any holes, i.e. if there's at least one edge which has only one face. (The hole is on the other side.) A submesh is closed if it doesn't have any. This method sets the MN_FACE_OPEN_REGION flag on all faces in open submeshes, and sets the MN_MESH_HAS_VOLUME flag if at least one submesh is closed. - Examples: - A 3ds Max box has one submesh, itself, and it is closed. - - A 3ds Max teapot has four distinct submeshes (handle, spout, lid, and body), and they are all open. - - - - - mapped vertexes are individual map vertices that are used to correspond to different regular vertices. - - For example, the standard map on the box object uses the same mapping vertices on the top as on the bottom. This can be a problem if the user wants to change the map in one region, but not the other. It also causes problems in NURMS MeshSmooth, where the user can change weights in one region but not in the other. So the following methods detect and fix such vertices. This method is a debugging tool. All doubled mapped vertexes are DebugPrinted. Return value is TRUE if there is at least one doubled mapping vertex (on at least one map channel). FALSE if the mesh is clean. Note that this method is not significantly faster than EliminateDoubledMappingVerts, so you should not use it to determine if EliminateDoubledMappingVerts - - - - - Eliminates double mapped vertices in linear time. - - - - - Deletes isolated mapping vertices. - - - - - Deletes isolated mapping vertices on a specific channel - - - - - Assignment operator. Allocates space & copies over all data from "from". - - - - - Union operator. Adds all data from "from" to this . Flags MN_MESH_NONTRI and MN_MESH_RATSNEST are or'd together, while flags MN_MESH_FILLED_IN, MN_MESH_NO_BAD_VERTS, MN_MESH_VERTS_ORDERED and MN_MESH_USE_MAX2012_WELD_MATH are and'd together. (Uniting a rat's nest with a non-rat's nest makes a rat's nest, but uniting a mesh with mapping coordinates and one without makes one without.) - - - - - - - Uses DebugPrint to print out information about all the edges, faces, and vertices in the immediate vicinity of vertex vv. - Parameters: - int vv - - The vertex whose information is output. - - bool triprint=FALSE - - Controls whether or not triangulation information is printed out for each face. Usually this information isn't desired. - - - - - Thoroughly checks a to make sure that no components refer to dead components; that when one component refers to another, the other refers back to the first; and that orientation is correctly matched between faces and edges. If everything checks out, TRUE is returned. If any errors are detected, DebugPrint is used to send a message to the DevStudio Debug Results window and FALSE is returned. Be careful not to leave CheckAllData calls in your final build; they will slow down your effect to no purpose. - - Here is the sort of debug output you can expect. CheckAllData always outputs one of the following messages: - - Checking all data in filled-in : (if the mesh has the MN_MESH_FILLED_IN flag set) - - Checking all data in : (if the mesh does not) - - These errors will be detected for any mesh: - - d has an out-of-range vertex: d - - d has an out-of-range tvert: d - - d has an out-of-range cvert: d - - d refs dead edge d. - - d has bad triangulation index: d - - These errors will be detected only for filled-in meshes: - - d has an out-of-range edge: d - - d uses dead edge d. - - d refs edge d, but edge doesn't ref face. - - d refs edge d from vert d to vert d, but edge doesn't go there. - - Orientation mismatch between face d and edge d. - - d refs vertex d, but vertex doesn't ref face. - - d refs dead vertex d. - - d refs vertex d, but vertex doesn't ref edge. - - d has no face-1 - - d refs dead face d. - - d refs face d, but face doesn't ref edge. - - Vertex d refs dead edge d. - - Vertex d refs edge d, but edge doesn't ref vertex. - - Vertex d references more faces than edges. - - Vertex d refs dead face d. - - Vertex d refs face d, but face doesn't ref vertex. - - - - - Creates a new vertex in the middle of an edge, splitting the edge into two edges. Unlike SplitEdge, this routine requires a triangle face on each side. Since it has this, it also creates new edges connecting the new vertex with the point opposite the split edge on each face. This in turn splits the faces. So two triangles sharing this single edge become four triangles with four shared edges meeting at a single new vertex. - - This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely. - Parameters: - int ee - - The edge to split. Note that if the faces on either side do not have deg=3 and hdeg=0, an assertion failure will result. - - float prop - - The proportion along the edge for the new vertex to be located. This ranges from 0, at v1, to 1, at v2. A value of .3, for instance, would create a new vertex at .7*P(v1) + .3*P(v2). - - float thresh - - If prop is less than thresh or more than 1-thresh, the method will not split the edge, and will return v1 or v2 respectively. This is so that calling routines can safely pass values anywhere from 0 to 1, without worrying about creating tiny "shard" faces. - - bool neVis - - This tells whether the new edges that split the faces should be visible. (The new edge formed from part of the old edge takes such characteristics from the old edge.) - - bool neSel - - This tells whether the new edges that split the faces should be selected. (The new edge formed from part of the old edge takes such characteristics from the old edge.) - The index of the new vertex created, or the index of the old vertex you can use instead if you're within thresh of the endpoints. - - - - - Adds a vertex somewhere in a triangle face, and also adds edges from that vertex to each of the corners, splitting the face into 3 smaller triangle faces. The triangle face used here can have hidden vertices, as long as it is of degree 3. However, if the threshold parameter comes into play and this routine calls SplitTriEdge, both this face and the one across the relevant edge will need to have both degree 3. (Otherwise there's an assertion failure.) - - This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely. - Parameters: - int ff - - The face to split. - - double *bary - - The barycentric coordinates of the new point you wish to add. If this is NULL, the default values of (1/3, 1/3, 1/3) (the middle of the triangle) are used. These values MUST all fall between 0 and 1, and they MUST add up to 1 (give or take a floating point error) to get a sensible result. - - float thresh - - If one of the barycentric coordinates is greater than 1-thresh, that vertex dominates completely. No splitting is done, and that vertex is returned. If not, but if one of the barycentric coordinates is less than thresh, the new point must fall on the opposite edge. SplitTriEdge is therefore called on that edge, and passes along the value this returns. - - bool neVis - - Whether or not the new edges connecting the new vertex to the corners should be visible. - - bool neSel - - Whether or not the new edges connecting the new vertex to the corners should be selected. - The index of the new vertex created, or the index of the old vertex you can use instead if you're within thresh of one of the corners. - - - - - This is another way to subdivide a face on a triangular mesh into sub-triangles. In this case, 4 new vertices are produced, and this face becomes 6 new faces. MN_MESH_FILLED_IN is required and preserved, and MN_MESH_NONTRI cannot be true when this method is called. - - The subdivision technique is as follows: a new point is added at the barycentric coordinates given on the face given. New points are also added in each edge of the original face, such that a line from each of these three new edge points to the opposite original vertex passes through the new center point. These three edge points have edges drawn between them, and have edges to the new center point, dividing the face into 3 large outer triangles and 3 smaller inner triangles. Neighboring faces are split into 2 triangles, since the common edge is divided. This is a useful subdivision technique when you know you're going to want to add a lot of detail to a specific region of a face. - Parameters: - int ff - - The face to split. - - double *bary=NULL - - The barycentric coordinates for the center point. If bary is NULL, the default barycentric coordinates of (1/3, 1/3, 1/3) are used. - - int *nv=NULL - - This is a pointer to an array of at least 4 int's in which the 4 new vertex indices should be stored. (This is mainly if the calling routine needs to know what these new vertices are.) If this is NULL, it is ignored. - - - - - Creates a new vertex somewhere in the middle of an edge, splitting the edge into two edges. Incident faces are updated in their vertex, edge, mapping coordinate, and vertex color lists, as well as in their triangulation. This method requires that MN_MESH_FILLED_IN be set (otherwise it will cause an assertion failure), and maintains the combinatorics completely. - Parameters: - int ee - - The edge to split. - - float prop=.5f - - The proportion along the edge where the new vertex should go. This proportion should be between 0 and 1. The new vertex location is P(E(ee)->v1)*(1.0f-prop) + P(E(ee)->v2)*prop. - The index of the new vertex. - - - - - This new SplitEdge variant allows you to recover information about the new map vertices created at the point where the edge is split. Everything else is the same as the existing SplitEdge (int ee, float prop=.5f) method. - Parameters: - <int> *newTVerts - - Pointer to a table in which the new map vertices can be stored. This table is set to size (NUM_HIDDENMAPS + MNum())*2. The two entries for each map channel are used to store the two new map vertices at this edge split: newTVerts[(NUM_HIDDENMAPS+mp)*2+0] is the map vertex for map channel mp on the "f1" side of the edge, and newTVerts[(NUM_HIDDENMAPS+mp)*2+1] is the map vertex for the "f2" side if f2>=0 (or otherwise left uninitialized). (These values are often, but not always, the same. They are different if the map has a seam along this edge.) - - - - - Splits an edge that is specified from the face level, and splits off triangles from the adjacent faces. This method is often preferable in convex meshes, when it's important that no nonconvex faces are introduced. The other SplitEdge methods leave faces with three vertices in a line, which is not strongly convex. This version makes a triangle out of half of the split edge, the next face edge, and a diagonal. - - Note: This method absolutely requires that the faces on either side of the edge being split are Convex. Use MakeFaceConvex if needed. - Parameters: - int ff - - One of the faces which uses the edge you wish to split. - - int edgeIndex - - The index of the edge in face ff. - - float prop - - The proportion along the edge where the new vertex should go. This proportion should be between 0 and 1. The new vertex location is P(E(ee)->v1)*(1.0f-prop) + P(E(ee)->v2)*prop. - - bool right - - If FALSE, the new triangle is formed from the lower or "left" half of the split edge. If TRUE, it's formed from the higher or "right" half. (These orientations make sense if you imagine viewing the face from above with the split edge on the bottom, as pictured.) If you want the triangle to be formed from the smaller half, use (prop<=.5f) for this argument. - - int *nf=NULL - - If non-NULL, this should point to an array of at least 2 elements where the new face indices should be put. Nf[0] is set to the new face created from face ff, while nf[1] is set to the new face created from the face on the other side of the edge, if any. - - int *ne=NULL - - If non-NULL, this should point to an array of at least 3 elements where the new edge indices should be put. Ne[0] is set to the new edge created from the second half of the edge we're splitting. Ne[1] represents the diagonal edge on face ff, while ne[2] represents the diagonal edge on the face on the other side of the split edge (if any). - - bool neVis=FALSE - - Indicates whether the new edges ne[1] and ne[2] should be visible. - - bool neSel=FALSE - - Indicates whether the new edges ne[1] and ne[2] should be selected. - - bool allconvex=FALSE - - Indicates whether the original faces on both sides of the edge are guaranteed to be convex. If so, these faces are retriangulated with BestConvexTriangulation; otherwise, RetriangulateFace is employed, in conjunction with the TRIANGULATION_LEGACY algorithm. - The index of the new vertex. - - - - - Uses a new vertex to "indent" one of the sides of the face. The indentation triangle is split off as a new face, which is returned. - Parameters: - int ff - - The face to be "indented". - - int ei - - The index of the edge which will be replaced by the indentation. - - int nv - - The index of the new vertex. This vertex should lie within the face, in the face's plane, and should not be connected to any faces or edges. - - int *ne=NULL - - If non-NULL, this should point to an array of at least 2 elements where the new edges should be stored. - - bool nevis=TRUE - - Indicates whether the new edges should be visible. - - bool nesel=FALSE - - Indicates whether the new edges should be selected. - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - The index of the new face representing the indentation triangle. - - - - - This routine takes a larger face and divides it into two smaller faces, creating a new edge in the process. It is crucial that the face given to SeparateFace has a valid triangulation. - - - The face to divide. - - The first index (in the face's vtx list) of the vertices used to divide the face. Note that a and b should be at least two units apart in each direction: a can't be (b+1) mod deg, and b can't be (a+1) mod deg. Also, the straight line connecting MNVerts V(vtx[a]) and V(vtx[b]) should not cross any of the edges of the face, otherwise the results will not be valid. - - The second index (in the face's vtx list) of the vertices used to divide the face. Note that a and b should be at least two units apart in each direction: a can't be (b+1) mod deg, and b can't be (a+1) mod deg. Also, the straight line connecting MNVerts V(vtx[a]) and V(vtx[b]) should not cross any of the edges of the face, otherwise the results will not be valid. - - A variable to hold the new face created by this division. (Half the face remains as face ff, the other half is the new face nf.) - - A variable to hold the new edge created by this division. - - Indicates whether the new edge should be visible. (The other version of SeparateFace always leaves the edge invisible.) - - Indicates whether the new edge should be selected. (The other version of SeparateFace always leaves the edge unselected.) - - When true, the two faces resulting from this operation will have the same 'track' value as the original so that they can later be associated, if desired. - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - Slices the along a specified plane, splitting edges and faces as needed to divide faces into those above and those below the plane. Equivalent to the Slice modifier. - Parameters: - & N - - The normal to the slice plane. This should be a unit vector. - - float off - - The offset of the slice plane. For any point X in the plane, DotProd(N,X) = off. - - float thresh - - If a vertex lies within thresh of the splitting plane, ie if absf(DotProd (N,X) - - - - - Splits the flagged vertices into a clone for each face using the vertex. For example, if used on the front top left corner of a standard 3ds Max box, it splits the vertex into 3, one for the front face, one for the top face, and one for the left face. - Parameters: - DWORD flag=MN_SEL - - The flag that indicates which vertices to split. - TRUE if anything happened, FALSE if none of the vertices were split. (Note that this method will return FALSE if no vertices are flagged, but also if there are flagged vertices but they're all on 1 or 0 faces already.) - - - - - "Splits" edges by breaking vertices on two or more flagged edges into as many copies as needed. In this way, any path of flagged edges becomes an two open seams. - Parameters: - DWORD flag=MN_SEL - - Indicates which edges should be split. (Left at the default, selected edges are split.) - True if any topological changes happened, false if nothing happened. - - - - - Splits an edge into multiple edges. - - An argument of type int. - The number of new segments to create out of the original edge. - - - - Calls MakeFaceConvex() on all (non-dead) faces, producing a mesh with 100% convex faces. - - - - - Makes face ff convex, essentially by chopping off corners. The corners themselves become new faces. This routine is actually recursive: if this face is already convex, it returns without affecting it. If not, it finds a suitable line (between outside vertices) to divide the face along, and then calls MakeFaceConvex() again on both of the smaller faces. It is crucial that the face given to MakeFaceConvex has a valid triangulation. - - - - - Subdivides polygons as needed so that no polygon has degree larger than maxdeg. (For instance, if maxdeg was 4, an octagon would have edges added until it was composed of 3 quads, or some combination of quads and tris.) - Parameters: - int maxdeg - - Maximum degrees. - - - - - Makes all faces planar, within the angle threshold given, by subdividing them as necessary. (See MakeFacePlanar.) - - - The planar angle threshold. - - Indicates whether to track faces that are split by this method. When true, the faces of all pieces of any nonplanar faces split by this method will have the same 'track' value as the original so that they can later be associated, if desired. - - - - Makes the specified face planar by subdividing if necessary. planarThresh represents an angle in radians. If the angle across any of the face's diagonals is larger than this amount, the face is divided on that diagonal. - - - The face of the index to make planar - - The planar angle threshold. - - Indicates whether to track faces that are split by this method. When true, the faces of all pieces of any nonplanar faces split by this method will have the same 'track' value as the original so that they can later be associated, if desired. - - - - Welds vertices a and b, correcting the mesh topology to match. All references to b are moved to a, and b is killed. If there is a topological problem preventing the weld from occurring, the method does nothing and returns FALSE. If there is no such problem, the weld goes ahead and returns TRUE. Note that if a and b are joined by an edge, this method just calls WeldEdge on that edge. - - - - - Welds the endpoints of edge ee, correcting the mesh topology to match. All references to E(ee)->v2 are moved to E(ee)->v1, and both ee and E(ee)->v2 are killed. If there is a topological problem preventing the weld from occurring, the method does nothing and returns FALSE. If there is no such problem, the weld goes ahead and returns TRUE. - - - - - Welds vertices v1 and v2 together. Both vertices must be on borders, and they cannot share an edge. If destination isn't NULL, it indicates where the welded vertex should be located. (If it is NULL, the welded vertex is placed at the midpoint of the inputs.) - Parameters: - int v1, v2 - - The vertex indices to wel. - - *destination - - The destination of the welded vertex. - TRUE if something was welded, FALSE otherwise. - - - - - Welds the specified border edges together. - Parameters: - int e1, int e2 - - The edges to be welded. They must be border edges, in the sense that each of them must be open (used by only one face). The result is located where edge e2 was. e[e1].v1 is joined to e[e2].v2, and e[e1].v2 is joined to e[e2].v1. - True if anything was welded, false if the operation could not proceed. This method welds edges e1 and e2 together. Both edges must be on borders. - Parameters: - int e1, e2 - - The two edges you want to weld. - TRUE if something was welded, FALSE otherwise. - - - - - Welds the specified border vertices together. - Parameters: - float thresh - - The welding threshold. Vertices further apart than this distance (in object space) will not be welded. - - DWORD flag=MN_SEL - - Indicates which vertices should be welded. (Non-border vertices, those in the "interior" of the surface, are ignored even if flagged.) - True if anything was welded, false otherwise. This method welds all flagged border vertices within "thresh" of each other. Vertices are only welded pairwise. If vert A's closest target is vert B, but vert B is closer to vert C, verts B and C are welded and A is left out in the cold. - Parameters: - float thresh - - The threshold. - - DWORD flag=MN_SEL - - This indicates the vertices we look at. If left at the default, selected vertices' colors are analyzed. If flag were to equal MN_WHATEVER, then vertices with the MN_WHATEVER flag would have their colors analyzed. - TRUE if something was welded, FALSE otherwise. - - - - - This method welds the closest two vertices within "thresh" of each other which have non-matching flags (flag1, flag2). Vertices are only welded pairwise. - Parameters: - float thresh - - The welding threshold. Vertices further apart than this distance (in object space) will not be welded. - - DWORD flag1 - - Indicates vertex flag value which represents side 1 of border. (Non-border vertices, those in the "interior" of the surface, are ignored even if flagged.) DWORD flag2 - - Indicates vertex flag value which represents side 2 of border. (Non-border vertices, those in the "interior" of the surface, are ignored even if flagged.) - True if anything was welded, false otherwise. - - - - - Welds pairs of one-sided edges between the same two vertices. - - - - - This is a tessellation routine similar to AndersonDo(). It produces the same topology, but bulges new vertices outward to maintain even curvature instead of bringing the original vertices inward. For a demonstration of the effect this algorithm has on meshes, apply 3ds Max's Tessellate modifier with the "Edge" and "Operate On: Polygons" options selected. Note that this algorithm roughly quadruples the size of the . - Parameters: - float bulge - - The factor to "push out" new vertices by in the direction of the surface curvature. Values of about .25 are reasonable. This value is equivalent to one hundredth of the value specified as "Tension" in the Tessellate modifier. - - *mop=NULL - - A pointer to a . See Class for details. - - - - - It breaks every into deg new faces with four sides. The four vertices of each of these new quads come from the center point of the original face, one corner of the original face, and the middles of the two edges on either side of that corner. For a demonstration of the effect this algorithm has on meshes, apply 3ds Max's MeshSmooth modifier with the "Quad Output" box checked. Note that this algorithm roughly quadruples the size of the . - Parameters: - float interp - - This is the proportion of relaxation applied to the original vertices to produce a smoothed result. Vertices in the result correspond to three sources: all the original vertices are still included, new vertices are produced at the center of each face, and new vertices are produced in the middle of each edge. Face-vertices are always at the exact center of the original faces, but edge-vertices and vertex-vertices are relaxed into the mesh to improve smoothness. - - int iSelLevel - - The selection level that the we're modifying was set to. If this selection level is MNM_SL_FACE, we'd want to keep non-selected faces as unmodified as possible, whereas if the selection level is MNM_SL_OBJECT or MNM_SL_VERTEX, we could break off chunks of some unselected faces that touch modified vertices. Again, observe the result of MeshSmooth, with Quad Output, on various selection sets of a mesh for examples of this behavior. - - *mop=NULL - - This optional parameter points to an instance of the virtual class , which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See class . - - DWORD subdivFlags=0 - - This parameter is available in release 4.0 and later only. - - There is currently only one flag for the extra argument, MNM_SUBDIV_NEWMAP. If this flag is set, the new mapping scheme will be used. - - - - - Note that this algorithm roughly triples the size of the . For an example of how it works, apply 3ds Max's Tessellate modifier with the "Face" and "Operate On: Polygons" options selected. This algorithm splits each face into deg triangles, where each triangle contains the center of the face and one edge from the perimeter. - - - - - Note that this algorithm roughly triples the size of the . For an example of how it works, apply 3ds Max's MeshSmooth modifier with "classic" MeshSmooth Type. - - This technique for tessellation is based on a paper, "A Subdivision Algorithmfor Smoothing Down Irregularly Shaped Polygons", published by D. W. H. Doo of Brunel University, Middlesex, England, in IEEE in 1978. It essentially creates a new face for every vertex, face, and edge of the original mesh. The new vertices this technique requires are made by creating one vertex for each corner of each original face. These vertices are located on a line from the original face corner to its center. All the faces around a given (targeted) vertex will create such a point; these points form the corners of the face created from this vertex. The original faces become smaller, as they use the new points instead of their old corners. And the four new points created on the faces on either side of an edge, for the endpoints of that edge, become the four corners of the new face representing the edge. Apply a MeshSmooth with default values to a 3ds Max box to see how this plays out. - Parameters: - float interp - - The position along the line from a vertex to the center of each face to create the new vertex at. If this value is near 0, the original faces will shrink very little, and the new faces at the vertices and edges will be very small. If this value is near 1, the original faces will shrink to almost nothing, and the new vertex faces will be dominant. Again, adjust the Strength parameter in MeshSmooth to gain an understanding of this parameter. - - int iSelLevel - - This parameter is included so that special handling can be applied to selected faces, if we're at the MNM_SL_FACE selection level. Generally, this algorithm works on all targeted vertices, affecting all faces that contain at least one targeted vertex. However, if the vertices are targeted by whether or not they're on selected faces, we'll wind up "spilling" the algorithm over into the non-selected faces. Generally in such routines as MeshSmooth, the user would want non-selected faces not to be affected at all. If this is the case, setting this value to MNM_SL_FACE will prevent faces without the MN_SEL flag from being affected. - - *mop=NULL - - This optional parameter points to an instance of the virtual class , which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See Class . - - > *offsets=NULL - - The SabinDoo algorithm is typically used to go from one polygonal approximation of a smooth surface to another polygonal approximation of 4 times the size, but it never actually returns the vertices as they would appear on the "limitsurface". If this parameter is non-NULL, it's filled in with offsets that will, when added to the vertices in the SabinDoo result, take those vertices onto the limit surface. This makes a smoother result that matches better between different iterations. - - - - - This applies the Sabin-Doo tessellation technique to a single vertex. The vertex is split into as many new vertices as there are faces using this vertex. The incident faces are shrunk back to make use of these new vertices, and a new face is created from them representing the vertex. Incident edges are split into triangles using their other end and the appropriate edge from the new vertex-face. To see the result of this algorithm, apply MeshSmooth (with default parameters) to an EditableMesh with a single vertex selected. - Parameters: - int vid - - The vertex to SabinDoo. - - float interp - - The proportion from this vertex to the center of each of the incident faces to put the new vertex for that face. - - int iSelLevel - - If this is equal to MNM_SL_FACE, faces without the MN_SEL flag will not be affected. - - *ctr - - This is a list of centers of all the faces, which cannot be NULL. Since this algorithm changes the original faces, merely computing face centers on the fly won't work. (When SabinDooing two vertices on a given face, the second vertex will get bad center information.) Thus the user should compute all the face centers in advance using ComputeCenters or (preferably) ComputeSafeCenters. - - *mop=NULL - - This optional parameter points to an instance of the virtual class , which is used to allow the user to abort out of lengthy calculations. (SabinDoo is a lengthy calculation.) See Class . - - > *offsets=NULL - - The SabinDoo algorithm is typically used to go from one polygonal approximation of a smooth surface to another polygonal approximation of 4 times the size, but it never actually returns the vertices as they would appear on the "limitsurface". If this parameter is non-NULL, it's filled in with offsets that will, when added to the vertices in the SabinDoo result, take those vertices onto the limit surface. This makes a smoother result that matches better between different iterations. - - (In SabinDooVert, the offsets for the vertices created by this method are filled in. The offsets table is resized if necessary to accommodate this.) - - - - - Non-uniform rational mesh smooth. This is a tessellation routine. Note that this algorithm roughly quadruples the size of the . For an example of how it works, apply 3ds Max's MeshSmooth modifier with "NURMS" MeshSmooth Type. - - This technique for tessellation is based loosely on a 1998 SIGGraph paper, "Non-Uniform Recursive Subdivision Surfaces", by Sederberg, Zheng, Sewell, and Sabin, with additional work by Autodesk staff. Topologically, it's quite simple, as it creates a vertex in the center of every edge and face and connects these vertices with quads. However, the geometry is a non-uniform rational extension of the old Catmull-Clark standard cubic subdivision. - - To set the vertex and edge weights used by the algorithm, use the EdgeKnots and VertexWeights methods of . Like other subdivision routines, this routine only subdivides areas of the indicated by the MN_TARG flag on vertices, and uses the MNEdge::Uncrossable method to determine where the regional boundaries should be. - Parameters: - *mop=NULL - - See Class - provides a way to abort the calculation. - - > *offsets=NULL - - Unused for now. - - DWORD subdivFlags=0 - - This parameter is available in release 4.0 and later only. - - There is currently only one flag for the extra argument, MNM_SUBDIV_NEWMAP. If this flag is set, the new mapping scheme will be used. - - - - - Prepares a for a operation. This is required for successful Booleans. Generally, it makes the mesh into a convex poly mesh, removing any hidden vertices, finds open regions, and collapses dead structures. - - - - - BooleanCut uses the same techniques as MakeBoolean to cut the faces of this with the faces of m2. As with , both this and m2 should be prepared with the PrepForBoolean method. - Parameters: - & m2 - - The to use to cut this one. - - int cutType - - One of the following: - - BOOLOP_CUT_REFINE - - Slice the faces of this with the surface of m2, but do not separate the mesh along the seam. - - BOOLOP_CUT_SEPARATE - - Slice and separate the faces of this along the surface of m2. - - BOOLOP_CUT_REMOVE_IN - - Slice the faces of this with the surface of m2, then remove all the faces of this that are inside m2. - - BOOLOP_CUT_REMOVE_OUT - - Slice the faces of this with the surface of m2, then remove all the faces of this that are inside m2. - - int fstart=0 - - Indicates the face (of this) we should start checking for cuts by m2. This can be useful if, for example, you know that the first 100 faces of this are nowhere near m2. - - *mop=NULL - - See Class . Provides a way to abort the calculation. - TRUE if finished successfully; FALSE if aborted by the . - - - - - Makes this into a result of the given MNMeshes. The operands are not modified during this process. The algorithm is identical to the one used in the 2 compound object. Notice that there are no transform arguments, as there are in the previously used CalcBoolOp - transforms should be applied to the operands beforehand using the MNMesh::Transform method. - Parameters: - & m1 - - The first operand mesh, which should have had PrepForBoolean called. - - & m2 - - The second operand mesh, which should have had PrepForBoolean called. - - int type - - The type of . The types are defined in mesh.h, and are one of MESHBOOL_UNION, MESHBOOL_INTERSECTION, or MESHBOOL_DIFFERENCE. If MESHBOOL_DIFFERENCE is selected, operand m2 is subtracted from operand m1. (To get the opposite result, just switch the order of m1 and m2.) - - *mop=NULL - - A pointer to a . See Class for details. The mop is initialized with the number of faces in mesh 1 plus the number of faces in mesh 2 plus 10. MakeBoolean aborts acceptably if mop->Progress returns FALSE, in which case the partially Booleaned is returned. (Usually this consists of mesh 1 partially cut by mesh 2, or mesh 1 fully cut and mesh 2 partially cut, with no faces removed.) This argument may safely be left at NULL if you do not wish to be updated on the progress or have the capability to abort. - Returns FALSE if the operation was cancelled by the or if it was unable to match the seams of the two operands at the end, resulting in a mesh with holes. It returns TRUE if everything went well, producing a solid, hole-free mesh. - - Note that it will always return FALSE if one of the operands has holes. - Sample Code: - Sample code: the following code can be used to replace the old CalcBoolOp method. - - - - - - - Connect automatically figures out which loops in the given would make good candidates for connecting, and calls ConnectLoop on them all to connect them. Good candidates are pairs of loops that face each other. Centers and normals of each of the "holes" are compared to find the best matches. - Parameters: - & borderList - - The boundary information for the mesh. - - int segs - - The number of segments in each bridge. - - float tension - - The tension of each bridge - this controls how much the surface tangents at each end of the bridge affect the bridge's shape. - - bool sm_bridge - - If TRUE, each bridge should be smoothed with some unused smoothing group. - - bool sm_ends - - If TRUE, additional smoothing groups are applied to the end faces of each bridge to ensure that the bridge smooths with the existing faces around each border loop. - - <int> *vsep=NULL - - If not NULL, this points to a "separation list" of vertices. Frequently the user wishes to connect two distinct object (as with the Connect compound object). In these cases, the vertices of the different connected components are often grouped in distinct sets: vertices 0 through 26 come from the first component, 27 through 118 from the second, etc. Generally the user would not want a component to connect to itself, but rather only to other components. So if non-NULL, this is assumed to point to a list describing the vertex ranges for each component - (0, 27, 119, etc). The list should have size (number of components+1), and the last element should be MNMesh::numv. Given such an input, the Connect algorithm will only connect loops to loops in other components. - - - - - Connects two border loops by filling in new geometry between them, as is done in the Connect compound object. - Parameters: - <int> & loop1 - - <int> & loop2 - - These parameters, which are interchangeable, are lists of edges that represent border loops in the . It is assumed that the is filled in, that each of the edges in the loops is in fact one-sided (e[loop1[i]].f2 == -1), and that the edges go in counterclockwise order when looking from outside the mesh (so e[loop1[i]].v1 == e[loop1[i+1]].v2). (These are the sort of border loops you find in an class.) - - int segs - - The number of segments in the bridge. - - float tension - - The tension of the bridge - this controls how much the surface tangents at each end of the bridge affect the bridge's shape. - - DWORD smGroup - - These smoothing group(s) should be applied to the entire bridge. (Use 0 for a faceted bridge.) - - MtlID mat - - This is the material used for the bridge faces. - - bool sm_ends - - If TRUE, additional smoothing groups are applied to the end faces of the bridge to ensure that the bridge smooths with the existing faces around each border loop. - - - - - Connect the marked edges of a polygon if they are opposing. Returns true is successful. - This is the same as calling IMeshUtilities8::ConnectEdges() - Returns true if the operation was successful or false otherwise. - - Identifies the kinds of edges to connect. For example for selected edges set use MN_SEL. - Segments is the number of times to segments to split the original edge into. - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - Connects tagged vertices across a polygon - Returns a value of type bool. - - Indicates the type of vertices to connect. to MN_SEL to operate on selected edges. - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - Clones flagged vertices, creating new vertices that aren't used by any faces. - Parameters: - DWORD cloneFlag = MN_SEL - - Indicates which vertices should be cloned. - - bool clear_orig = TRUE - - If true, the original vertices should have the cloneFlag cleared. (The clones will always have this flag set.) - - - - - Clones the flagged faces, as well as all the vertices and edges that are used by the faces. - Parameters: - DWORD cloneFlag = MN_SEL - - Indicates which faces should be cloned. - - bool clear_orig = TRUE - - If true, the original faces should have the cloneFlag cleared. (The clones will always have this flag set.) - - - - - Copies bare geometry only - no per-vertex data, maps, or normals. Useful for keeping low-memory local caches of a mesh where map, vertex data, edge data, normals, and other interfaces are not required. - Parameters: - const & from - - The mesh to copy into this mesh. - - bool copyEdges = false - - Indicates if the winged-edge array, as well as vertex and face - - references to edges, should be copied. If false, the - - MN_MESH_FILLED_IN flag is cleared in this mesh. - - - - - Moves the flagged components into their "average plane". ( computed using average component positions and normals.) - Parameters: - int selLev - - Selection level, one of MNM_SL_VERTEX, MNM_SL_EDGE, MNM_SL_FACE, or MNM_SL_OBJECT. - - DWORD flag=MN_SEL - - The flag that indicates which components to align. Ignored if msl is set to MNM_SL_OBJECT. - - *delta=NULL - - If non-NULL, this is presumed to point to an array of size equal to MNMesh::numv, and instead of actually moving the vertices, the algorithm stores offsets in this array such that v[i].p + delta[i] is in the plane. - Indicates whether anything was moved. (Or if delta is non-NULL, if any deltas are nonzero.) - - - - - Projects the flagged vertices into the specified plane, or produces an array of offsets which would do so. - Parameters: - & norm, float offset - - The definition of the plane: DotProd (norm, x) - offset = 0. - - DWORD flag=MN_SEL - - The flag that indicates which vertices to move. - - *delta=NULL - - If non-NULL, this is presumed to point to an array of size equal to MNMesh::numv, and instead of actually moving the vertices, the algorithm stores offsets in this array such that v[i].p + delta[i] is in the plane. - Indicates whether anything was moved. (Or if delta is non-NULL, if any deltas are nonzero.) - - - - - Detaches specified faces to a separate element, cloning vertices and edges as necessary on the boundary between flagged and unflagged faces. - Parameters: - DWORD flag=MN_SEL - - Indicates which edges should be split. (Left at the default, selected edges are split.) - True if any faces were detached, false if nothing happened. (Note that the algorithm will return false if, for instance, all flagged faces form elements which are already distinct from those formed from non-flagged faces.) - - - - - Detaches specified faces (and related vertices and edges) to a new . As indicated by the name, the specified region should be a single element; crashes will occur if faces that are flagged share vertices or edges with nonflagged faces. - Parameters: - & nmesh - - The new mesh. This is assumed to be empty. The flagged elements are put here, and reindexed so there are no unused components. (This occurs for all map channels as well - only the necessary map vertices are copied over.) - - DWORD fflags - - The flags that indicate the faces which compose the element we want to detach. - - bool delDetached=true - - Indicates whether the specified element should be deleted from this . - true if anything was detached, false otherwise. - - - - - Performs the topological component of an extrusion on all face clusters. Each cluster is "extruded", which means that vertices and edges on the boundary of the cluster are cloned and new faces and edges are created to connect the clones to the originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.) - True if any faces were extruded, false if nothing happened. - - A list of face clusters. See the constructors in class and the face cluster related methods of class for information on how to set up these clusters based on edge angles and face flags. - - - - Performs the topological component of an extrusion on the specified face cluster. This means that vertices and edges on the boundary of the cluster are cloned and new faces and edges are created to connect the clones to the originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.) - True if any faces were extruded, false if nothing happened. - - A list of face clusters. See the constructors in class and the face cluster related methods of class for information on how to set up these clusters based on edge angles and face flags. - The cluster we wish to extrude. - - - - Same as ExtrudeFaceCluster, but also accepts the of borders. Since MNFaceClusters::GetBorder is expensive, use this overload if you've previously computed borders. - - - - - Performs the topological component of an extrusion on each flagged face individually. (This differs from ExtrudeFaceClusters in that each face is treated like its own cluster.) Extrusion means that the vertices and edges used by each flagged face are cloned, and new faces and edges are created on the "sides" to connect the clones to their originals. (Note that nothing is moved in this process - movement is handled separately. See GetExtrudeDirection for details.) - Parameters: - DWORD flag=MN_SEL - - The flag that identifies the faces we wish to extrude. - True if any faces were extruded, false if nothing happened. - - - - - Finds the direction vectors for the geometric component of an extrusion after the topological component has been completed. (See methods ExtrudeFaceClusters, ExtrudeFaceCluster, and ExtrudeFaces for details on the topological component.) - - The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well-defined way to modify mapping values during an extrusion drag.) - The face clusters. - = The cluster normals. This information is only needed if we're extruding by cluster normals. If we're extruding clusters by local normals or just extruding faces separately, these parameters can be left at NULL. See class for handy methods to obtain cluster normals. - - - - A version of GetExtrudeDirection where a faceFlag can be passed in when there are no relevant face clusters. Use MNMeshUtilities14::GetExtrudeDirection if you want an option to use the distance perpendicular to the surface versus along the normal - - The data structure in which the extrusion directions are stored. (Note that there is no map support for this operation, as there is no well-defined way to modify mapping values during an extrusion drag.) - which flag to use that defines the extrusion. - - - - This computes the new extruded vertices from the selected vertices using the using the current vertex selection. - Returns true is the extrude operation is completed successfully. - - Determines what vertices to extrude. To work on the selected edges set this to MN_SEL. - The chamfer information which can be obtained from . - The offset vector for the extrusion for each vertex. - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - Same as ExtrudeVertices() but is applied to the edges. Computes the new extruded edges from the selected edges using the using the current edge selection. - - Returns true is the extrude operation is completed successfully. - - Determines what edges to extrude. To work on the selected edges set this to MN_SEL. - The chamfer information which can be obtained from . - The offset vector for the extrusion for each vertex. - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - - - - Extrudes a group of faces along a path defined by tFrenets. - Returns true if the operation was successful or false otherwise. - - A spline that has been sampled down and at each sample a transform is computed. - A set of face clusters. - The ID of the cluster to operate on. - Determines whether to align the extrusion to the cluster normal or the spline. - - - - Sets vertex colors for the specified vertices. This is done by finding all map vertices in the specified vertex color channel that correspond to each flagged vertex and setting them to the color given. - Parameters: - UVVert clr - - The color to set the vertices to. - - int mp - - The map channel - use 0 for the standard vertex color channel, MAP_SHADING for the vertex illumination channel, or MAP_ALPHA for the alpha channel. (Note that alpha color values should always be shades of grey - clr.r should equal clr.g and clr.b.) - - DWORD flag=MN_SEL - - Indicates which vertices to modify the colors of. - Returns true if any vertex colors were modified. - - - - - Sets vertex colors for the specified faces. This is done by finding all map vertices used by flagged faces and setting them to the color given. In cases where a map vertex is used by both a flagged and an unflagged face, the map vertex is split so that the unflagged faces' colors are unaffected by this change. - Parameters: - UVVert clr - - The color to set the faces to. - - int mp - - The map channel - use 0 for the standard vertex color channel, MAP_SHADING for the vertex illumination channel, or MAP_ALPHA for the alpha channel. (Note that alpha color values should always be shades of grey - clr.r should equal clr.g and clr.b.) - - DWORD flag=MN_SEL - - Indicates which faces to modify the colors of. - Returns true if any vertex colors were modified. - - - - - Performs the topological component of a vertex chamfer on the flagged vertices, and provides the data needed to do the geometric component. That is to say, this method clones the flagged vertices and creates the new edges and faces needed in a chamfer operation. It also determines the direction each vertex and mapping vertex will go as the user drags out the chamfer - but it doesn't actually move any vertices. - Parameters: - DWORD flag=MN_SEL - - Indicates which vertices to chamfer. - - *mcd=NULL - - If non-NULL, this points to a data structure which should be filled with information needed to perform the geometric component of the chamfer, such as vertex directions and limits. See class for additional information. - True if any vertices were chamfered, false otherwise. - - - - - Performs the topological component of an edge chamfer on the flagged edges, and provides the data needed to do the geometric component. That is to say, this method clones the flagged edges and creates the new vertices and faces needed in the edge chamfer operation. It also determines the direction each vertex and mapping vertex will go as the user drags out the chamfer - but it doesn't actually move anything. - Parameters: - DWORD flag=MN_SEL - - Indicates which edges to chamfer. - - *mcd=NULL - - If non-NULL, this points to a data structure which should be filled with information needed to perform the geometric component of the chamfer, such as vertex directions and limits. If NULL, then this method returns false. See Class for additional information. - True if any edges were chamfered, false otherwise. Returns false if mcd == NULL. - - - - - Performs a Quad Chamfer operation on the flagged edges using the original Max 2015 options and Max 2015 version of the Quad Chamfer algorithm. To use a specific version of the Quad Chamfer algorithm (for backwards compatibility, for example), use the alternate method, below, which includes an optional 'version' parameter (see QCHAM_VERSION_XXX, above). - True if any edges were chamfered, false otherwise. New chamfer faces are flagged with MN_FACE_CREATED flags. Edges created from original edges being chamfered are flagged with MN_EDGE_WAS_PROCESSED flags. - - - Indicates how much distance to chamfer - - Indicates how many segments to create on the chamfered edges (>0 for quads) - - Indicates how much tension to apply to chamfer (0.0 - 1.0) - - Indicates what result is desired. QCHAM_CHAMFEREDOBJECT=chamfered object, QCHAM_NOCHAMFERS=object with chamfered edges removed, QCHAM_CHAMFERSONLY=object with chamfered edges only - - Indicates which vertices to chamfer. - - - - Performs a Quad Chamfer operation on the flagged edges with options and versioning. - True if any edges were chamfered, false otherwise. New chamfer faces are flagged with MN_FACE_CREATED flags. Edges created from original edges being chamfered are flagged with MN_EDGE_WAS_PROCESSED flags. - - - Indicates how much distance to chamfer - - Indicates how many segments to create on the chamfered edges (>0 for quads) - - Indicates how much tension to apply to chamfer (0.0 - 1.0) - - Supplies chamfering options (see QCHAM_OPTION_XXX above). - - Indicates what result is desired. QCHAM_CHAMFEREDOBJECT=chamfered object, QCHAM_NOCHAMFERS=object with chamfered edges removed, QCHAM_CHAMFERSONLY=object with chamfered edges only - - Indicates which vertices to chamfer. - - Indicates the version to use (see QCHAM_VERSION_XXX above). Optional; defaults to the latest version - - - - Implements the Editable Poly Cut algorithm from the face level - cuts from a point on one face to a point on another face. - Parameters: - int f1 - - The starting face of the Cut. - - & p1 - - The starting point of the Cut, which should lie on face f1. - - & p2 - - The end point of the Cut. - - & Z - - The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector p2-p1. All new vertices created by the cut are in this plane. - - bool split - - If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom. - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - The last vertex created by the cut, or -1 if the cut was unable to finish. - - - - - Implements the Editable Poly Cut algorithm from the edge level - cuts from a point on one edge to a point on another edge. - Parameters: - int e1 - - The starting edge of the Cut. - - float prop1 - - The proportion along edge e1 where the cut should begin. That is, the first point should be located at (1-prop1)*v[e[e1].v1].p + prop1*v[e[e1].v2].p. - - int e2 - - The ending edge of the Cut. - - float prop2 - - The proportion along edge e2 where the cut should end. That is, the last point should be located at (1-prop2)*v[e[e2].v1].p + prop2*v[e[e2].v2].p. - - & Z - - The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector between the start and end points. All new vertices created by the cut are in this plane. - - bool split - - If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom. - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - The last vertex created by the cut, or -1 if the cut was unable to finish. - - - - - Only call this method when you need to go back to a previous version of the code to load older files to maintain procedurality - - - - - Implements the Editable Poly Cut algorithm from the vertex level - cuts from one vertex to another. - Parameters: - int startv - - The starting vertex of the Cut. - - & end - - The location of the end vertex of the Cut. - - & Z - - The view direction. All Cut algorithms require a view direction to establish the plane that the cut occurs in. This plane is defined by this Z vector and by the vector between the start and end points. All new vertices created by the cut are in this plane. - - bool split - - If true, the faces on the top and bottom of the cut should have an open seam between them. All the edges and vertices along the cut (except for the first and last vertex) are split into two parts, one copy for the top and one for the bottom. - - MNMeshTriangulationType triangulationType - - Triangulation algorithm to employ, as discussed in the description of the MNMeshTriangulationType enumeration. - The last vertex created by the cut, or -1 if the cut was unable to finish. - - - - - Only call this method when you need to go back to a previous version of the code to load older files to maintain procedurality - - - - - Applies UVW Mapper to create the desired mapping in the specified channel. - Parameters: - & mp - - The mapping scheme. See class for details. - - BOOL channel=0 - - The channel to apply the map to. Channel 0 is normally the vertex color channel. Channels 1-99 are the normal user-accessible mapping channels. Channels MAP_SHADING and MAP_ALPHA are used for vertex illumination and alpha. - - BOOL useSel=FALSE - - Indicates whether the specified mapping should be applied only to selected faces (instead of the whole object). In cases where the map channel was previously unused, a default map will be applied to nonselected faces, and the specified map will be applied to the selected faces. - - - - - Invalidates information, like bounding box and face normals, that's dependent on Geometry. Call after changing the geometry. - - - - - Clears out topology-dependent cache information. Note that this method clears topology-dependent flags such as MN_MESH_FILLED_IN, and thus invalidates the edge list. If you have taken pains to preserve the integrity of your edge list, you should set the MN_MESH_FILLED_IN flag immediately after calling InvalidateTopoCache(). - - - - - This method is used to manage the display of vertex colors from any channel (or those that are passed in by some calling routine). For instance, to set the mesh to display the Illumination channel as the current vertex colors, you would call SetDisplayVertexColors (MAP_SHADING). (Normally, it shows the standard vertex color channel, channel 0.) UpdateDisplayVertexColors() is used to refresh the vertex color pointers just before the displays itself. - - - - - This method is used to manage the display of vertex colors from any channel (or those that are passed in by some calling routine). For instance, to set the mesh to display the Illumination channel as the current vertex colors, you would call SetDisplayVertexColors (MAP_SHADING). (Normally, it shows the standard vertex color channel, channel 0.) UpdateDisplayVertexColors() is used to refresh the vertex color pointers just before the displays itself. - Parameters: - int chan - - The channel you wish to use. - - - - - If you have cached your own vertex color information that isn't in any of the map channels provided, you can use this method to set the internal pointers to use your data. - Parameters: - UVVert *mv - - The array of UV vertices. - - *mf - - The map face data. - - - - - This method reconciles flags with arrays, checks and modifies data, ensures that the caches are consistent, and prepares the pipeline. For instance, if the MN_MESH_FILLED_IN flag is absent but there is still an edge array, this will free the edge array. This method is important to call if a has been subjected to topology changing operations and should be called at the end of any operation on an . Prepares for pipeline. This just does a few basic checks and modifies data caches to be consistent. In particular it throws away the edge list if the MN_MESH_FILLED_IN flag is not set, and it frees any data in MN_DEAD map channels. This is a good method to call at the end of any operation on an . - - - - - Allocates the "render vertices" used to optimize display routines. Called by the system as needed. - - - - - Fills in the render vertices with display coordinates based on the specified view. - - - - - Frees the "render vertices" used to optimize display routines. - - - - - This method allows you to set the display flags. See MNMesh Display Flags. - - - - - This method returns the displFlags & f. See MNMesh Display Flags. - - - - - This method allows you to clear the specified display flags. See MNMesh Display Flags. - - - - - Causes the to display itself in the indicated . - Parameters: - *gw - - Points to the graphics window to render to. - - *ma - - The list of materials to use to render the mesh. See Class . - - RECT *rp - - Specifies the rectangular region to render. If the mesh should be rendered to the entire viewport pass NULL. - - int compFlags - - One or more of the following flags: - - COMP_TRANSFORM - - Forces recalculation of the model to screen transformation; otherwise attempt to use the cache. - - COMP_IGN_RECT - - Forces all polygons to be rendered; otherwise only those intersecting the box will be rendered. - - COMP_LIGHTING - - Forces re-lighting of all vertices (as when a light moves); otherwise only re-light moved vertices - - COMP_ALL - - All of the above flags. - - COMP_OBJSELECTED - - If this bit is set then the node being displayed by this mesh is selected. Certain display flags only activate when this bit is set. - - int numMat=1 - - The number of materials for the . - - - - - Displays the indicated face in the . This method is usually called only by MNMesh::render(). - Parameters: - *gw - - The in which to display this face. - - int ff - - The face to display. - - - - - Displays the indicated face in the using hardware acceleration for texture and lighting if available. This method is usually called only by MNMesh::render(). - Parameters: - *gw - - The in which to display this face. - - int ff - - The face to display. - - - - - Displays all face diagonals in the using hardware acceleration for texture and lighting if available. See the render method for a description of the parameters. This method is usually called only by MNMesh::render(). - - - - - Displays all face diagonals in the . See the render method for a description of the parameters. This method is usually called only by MNMesh::render(). - - - - - Displays diagonals for the specified face in the . This method is usually called only by MNMesh::render(). - Parameters: - *gw - - The in which to display these diagonals. - - int ff - - The face to display the diagonals of. - - bool useSegments = false - - Indicates if we are in segment-drawing mode. See class , method segment() for details. - - bool *lastColorSubSel=NULL - - If non-NULL, it points to a bool variable which should be true if the last color set was the subobject selection color (GetSubSelColor()), and false if the color is set to the selected object color (GetSelColor()). This saves processing time that would be needed to switch between the two colors. - - - - - Displays all edges in the using hardware acceleration for texture and lighting if available. See the render method for a description of the parameters. This method is usually called only by MNMesh::render(). - - - - - Displays all edges in the . See the render method for a description of the parameters. This method is usually called only by MNMesh::render(). - - - - - Displays an edge in a . This method is usually called only by MNMesh::render(). - Parameters: - *gw - - The in which to display this edge. - - int ee - - The edge to display. - - bool useSegments = false - - Indicates if we are in segment-drawing mode. See class , method segment() for details. - - bool *lastColorSubSel=NULL - - If non-NULL, it points to a bool variable which should be true if the last color set was the subobject selection color (GetSubSelColor()), and false if the color is set to the selected object color (GetSelColor()). This saves processing time that would be needed to switch between the two colors. - - - - - Shallow copy the specified channel objects of the specified . This means that the data channel objects are shared between the two meshes. - - - Specifies the source to copy. - - Specifies the channels to copy. See . - - - - This method clones the specified channel objects and stores those in the channel container. There is no risk of leaking channel objects. - - - Specifies the channels to copy. See . - - - - Drop the channel objects specified by the channels argument. No risk of leaking channel objects. For example if the TOPO_CHANNEL is specified, MeshTopoChannelData is freed, if the GEOM_CHANNEL is specified then MeshGeomChannelData is freed, etc. of maps are always preserved. As of 3ds Max 2024, if any channels are specified, they flags are also reset. - - - Specifies the channels to free. Channels not specified are left intact. See . - - If nonzero then the topo, geom, vert color, tex map and hidden maps are cleared out. - - - - Forces all the derived data used to display the mesh to be deleted. This data can be things like the gfx normals, the direct x mesh cache, tri stripping data etc. - - - - - This returns whether the Graphics Cache for this object needs to be rebuilt. - - - Parameters: - *gw the active graphics window - *ma the material aray assigned to the mesh - int numMat the number of materials in the material array - - - - - - Builds the graphics window cached mesh - Parameters: - *gw the active graphics window - *ma the material aray assigned to the mesh - int numMat the number of materials in the material array - BOOL threaded whether when building the cache it can use additional threads. This is needed since the system may be creating many meshes at the same time - - - - - - This method can be used to invalidate any display-technology-specific caches of the . In particular, it's currently used to invalidate the DirectX cache of the mesh. This is important to call, for example, after changing Vertex Colors or Texture coordinates, if you don't already call InvalidateGeomCache (). "DWORD keepFlags" should be zero. We may someday add flags indicating that some parts of the hardware mesh cache should be kept, but for now, the whole cache is invalidated. (An example usage is in maxsdk/samples/mesh/EditablePoly\PolyEdOps.cpp.) - - - - - the mesh or as static or not. As static mesh has no animated channels. This allows certain display optimization since we know the mesh is not changing. - - Whether the mesh is to tagged static or not. - - - - Returns a pointer to the user-specified normal interface, if present. - - - A pointer to this mesh's interface, or NULL if the interface - - has not been created in this mesh. - - - - - - - Returns a non-NULL interface pointer only if the interface - - is present, and is prepared for use in display - otherwise, it returns - - NULL, and we fall back on the smoothing groups. - - A is considered "prepared for display" only if the - - MNNORMAL_NORMALS_BUILT and MNNORMAL_NORMALS_COMPUTED flags are set. - - (See the methods BuildNormals and ComputeNormals.) - - - - - - - Clears out the specified normal interface, if present. Removes it - - completely, so it won't flow up the stack, etc. - - - - - Creates the user-specified normal interface in this mesh. Initializes - - the 's "Parent" to this mesh, but does not allocate normal faces - - or otherwise prepare the normals. Note that this interface will flow - - up the pipeline, in the GEOM_CHANNEL and TOPO_CHANNEL channels. - - - - - Transforms all vertices & hidden vertices by the Matrix xfm. - - - - - Figures out if this mesh is completely closed. Meshes with the MN_MESH_RATSNEST flags are automatically considered open. Otherwise, each edge is checked to see if it has a face on both sides. If so, the mesh is closed. Otherwise, it's open. - - - - - Similar to the 3ds Max "Relax" modifier: this modifier moves each towards the average of all vertices to which it is connected (by MNEdges). This is useful for tessellation algorithms. - Parameters: - float relaxval - - The proportion to move it. If p is the original location of this vertex and q is the average point of all vertices it's connected to, this vertex is moved to p*(1-relaxval) + q*relaxval. A value of 0 generates no "relaxation", 1 is maximum relaxation, and values below 0 or above 1 generate non-relaxing results. - - bool targonly - - If this is set, only those MNVerts with the MN_TARG flag set will be moved. - - - - - Detaches the face cluster and rotates its around the hinge edge and fills in the gap. Similar to MNMeshUtilities::HingeFromEdge() but requires a edge index instead of a point. - - Returns true if the operation was successful or false otherwise. - - The index of the edge that the face cluster is going to be hinged around. - An argument of type float. - The number of segments for the sides of the extrusion. - A face cluster set. - The specific face cluster to operate on. - - - - This is an auto-smooth algorithm that allows the developer to specify exactly which edges should be creases and which should be smoothed across. All face smoothing groups are rewritten by this algorithm. This algorithm is used, for example, in MeshSmooth, NURMS style, when the user turns on "smooth result" and applies crease values to some edges. - Parameters: - DWORD creaseFlag - - Indicates which edges should be treated as creases. Edges that have the flag (or flags) set should be creases. Those that don't should not be creases. - - - - - Generate a set of render items according to the given render-item-generate context. - Usually plugins use this function in their UpdateDisplay(). If plugins maintain copies of , then they should use this function to convert those instances to render items (RenderItemHandle). Converting to via MNMesh::OutToTri() and then use the version of GenerateRenderItems is possible but not recommended because it causes unnecessary conversions and is very slow. This function generates mesh data immediately. - - the container that accept newly generated render items. - contains all the information that is used to generate all the required render items. - - - - Returns the number of dead edges. - - - - - Returns the number of dead verts. - - - - - Returns the number of dead faces. - - - - - Create a map and list of faces adjacent to a given face's edges. - Given a face index, set bits in the provided corresponding to the faces that are adjacent to that face, sharing edges. Also append indexes of those faces to the provided IntTab. - - The index of the face to find adjacent faces for. - of faces, where bits will be set to indicate those faces which are adjacent. This should be initialized with the number of bits set to the number of faces in the mesh prior to calling the method, and the bits should be cleared, if desired. This method does NOT clear the bits itself, allowing the caller to call this method several times with different face indexes, building up an array and list of faces for later processing. If sequential calls to this method are made using different faceIndex parameters but reusing the adjacentFaces and adjacentFaceIndexes objects, DO NOT clear or alter the adjacentFaces between calls or the adjacentFaceIndexes list can contain duplicates. - IntTab that will have adjacent face indexes appended to it as they are found. This list is not sorted, and there will only be one entry per adjacent face (no duplicates). - When true, include 'faceIndex' face in adjacentFaceIndexes list. Defaults to false (doesn't include it). - - - - Create a map and list of faces adjacent to a given face. Given a face index, set bits in the provided corresponding to the faces that are adjacent to that face, sharing either edges or vertices. Also append indexes of those faces to the provided IntTab. - - The index of the face to find adjacent faces for. - of faces, where bits will be set to indicate those faces which are adjacent. This should be initialized with the number of bits set to the number of faces in the mesh prior to calling the method, and the bits should be cleared, if desired. This method does NOT clear the bits itself, allowing the caller to call this method several times with different face indexes, building up an array and list of faces for later processing. If sequential calls to this method are made using different faceIndex parameters but reusing the adjacentFaces and adjacentFaceIndexes objects, DO NOT clear or alter the adjacentFaces between calls or the adjacentFaceIndexes list can contain duplicates. - IntTab that will have adjacent face indexes appended to it as they are found. This list is not sorted, and there will only be one entry per adjacent face (no duplicates). - When true, include 'faceIndex' face in adjacentFaceIndexes list. Defaults to false (doesn't include it). - - - - Create a map and list of faces adjacent to a vertex. Given a vertex index, set bits in the provided corresponding to the faces that use that vertex. Also append indexes of those faces to the provided IntTab. - - The index of the vertex to find adjacent faces for. - of faces, where bits will be set to indicate those faces which are adjacent. This should be initialized with the number of bits set to the number of faces in the mesh prior to calling the method, and the bits should be cleared, if desired. This method does NOT clear the bits itself, allowing the caller to call this method several times with different vertex indexes, building up an array and list of faces for later processing. If sequential calls to this method are made using different vertexIndex parameters but reusing the adjacentFaces and adjacentFaceIndexes objects, DO NOT clear or alter the adjacentFaces between calls or the adjacentFaceIndexes list can contain duplicates. - IntTab that will have adjacent face indexes appended to it as they are found. This list is not sorted, and there will only be one entry per adjacent face (no duplicates). - - - - Checks if the space accelerating data is up-to-date. - Invoking InvalidateGeomCache() or InvalidateTopologyCache() will dirty the space accelerating data. - - - - - Update the space accelerating data. - This function should only be invoked when the plug-in needs to invoke following methods before InvalidateGeomCache() or InvalidateTopologyCache() gets invoked. - - - - - Checks the given to see if it intersects this object. - Parameters: - *gw - - Points to the graphics window to check. - - *ma - - The list of materials for the mesh. - - *hr - - This describes the properties of a region used for the hit testing. See Class . - - int abortOnHit = FALSE - - If nonzero, the hit testing is complete after any hit. Note that although there is only one object to hit, setting this to TRUE prevents the algorithm from finding the closest hit on the . - - int numMat=1 - - The number of materials for the mesh. - TRUE if the item was hit; otherwise FALSE. - - - - - This method may be called to perform sub-object hit testing on this mesh. - Parameters: - *gw - - The graphics window associated with the viewport the mesh is being hit tested in. - - *ma - - The list of materials for the mesh. See Class - - *hr - - This describes the properties of a region used for the hit testing. See Class . - - DWORD flags - - Flags for sub object hit testing. One or more of the following values: - - SUBHIT_MNUSECURRENTSEL - - When this bit is set, the sel only and unsel only tests will use the current level (edge or face) selection when doing a vertex level hit test.) This is like the hit-testing flag SUBHIT_USEFACESEL. - - SUBHIT_MNVERTS - - SUBHIT_MNFACES - - SUBHIT_MNEDGES - - SUBHIT_MNTYPEMASK (SUBHIT_MNVERTS|SUBHIT_MNFACES|SUBHIT_MNEDGES) - - & hitList - - The results are stored here. See Class . - - int numMat=1 - - The number of materials for the mesh. - TRUE if the item was hit; otherwise FALSE. - - - - - Provides the intersection point and normal for the ray with this mesh. - Parameters: - & ray - - The ray we want an intersection point for. - - float & at - - This is filled in with a value giving the intersection point along the ray. (The actual point is computed by ray.p + ray.dir*at.) - - & norm - - Filled in with the surface normal at the intersection point. - Returns TRUE if an intersection point was found, or FALSE if the ray doesn't intersect this . - - - - - Provides the intersection point and normal for the ray with this mesh. - Parameters: - & ray - - The ray we want an intersection point for. - - float & at - - This is filled in with a value giving the intersection point along the ray. (The actual point is computed by ray.p + ray.dir*at.) - - & norm - - Filled in with the surface normal at the intersection point. - - int & fi - - Filled in with the face index for the face that was hit by the ray. - - <float> & bary - - Filled in with the "generalized barycentric coordinates" of the intersection point on the face. This is a table of floats of size f[fi].deg, where each float represents the contribution of the corresponding face vertex, and where the floats all sum to 1. - Returns TRUE if an intersection point was found, or FALSE if the ray doesn't intersect this . - - - - - Similiar to above overrided function with the difference of having the barycentric coordinates as the function returned result. In case of no hit it will return nullptr. This function guarantees the returned array has enough space that matches the degree of the face. It is suggested to use this function because it does not require intermediate memory allocation. This function is implemented to be thread safe. - - - - - This function computes the render normal for the specified face and corner. Unlike the method of buildNormals() and buildRenderNormals(), this function does not rely on whole array to achieve normal computation, which means it is lightweight and it quite efficent to do the normal computation for a given face and corner index. The only limitation is that this function will update the space accelerating structure if it is needed. - - The index to the face. - The corner index within the face(must between 0 and 2 inclusively) - - - - This function computes the interpolated normals regarding the barycentric coordinates. - - The index to the face. - The input barycentric coordinates to compute the interpolated normal. It must point to an array of float that have large size than face degree. - - - - Sets flags. Each bit that is set in fl is assigned the value val. - - - - - Clears flags. Each bit that is set in fl is cleared. - - - - - Checks if flags are set. - TRUE if any of the bits set in fl are set in this . FALSE if none of them are. - - - - - Sets FlagUserFlags to 0, clearing all flag bits. - - - - - Copies all flag bits over from fl. Same as ImportFlags. - - - - - Copies all flag bits over from fu. - - - - - Copies all flag bits over from *fu. - - - - - Copies from fl only those bits set in mask. - - - - - Copies from fu only those bits set in mask. - - - - - Copies from *fu only those bits set in mask. - - - - - Sets all flags that are set in fu. - - - - - Sets all flags that are set in *fu. - - - - - Clears all flags that are clear in fu. - - - - - Clears all flags that are clear in *fu. - - - - - Checks whether all the bits that are set in fmask are the same in this and in fl. - - - - - Checks whether all the bits that are set in fmask are the same in this and in fu. - - - - - Checks whether all the bits that are set in fmask are the same in this and in *fu. - - - - - Returns a DWORD equal to FlagUserFlags. - - - - - Sets FlagUserFlags equal to fl. Same as CopyFlags (fl), but it's included for "linguistic completeness". - - - - - Using a channel mask, request the locks for those channels. - - - This can be used avoid race conditions when modifying many Min parallel when some of them share channels. - - - Which channels to aquire a lock for. - - - - Using a channel mask, release the aquired locks for those channels. - - - - - Which channels to release the locks for. - - - - Returns the channel container which provides access to the channel objects themselves. - - - To modify a channel directly, instead of using the interface, you can fetch the MNChannelContainer, then grab the appropriate channel object and make the changes directly. This is not recommended, mistakes here could cause crashes and data loss. Example to manually reallocate the faces: - - - - - Finds "Generalized Barycentric Coordinates" for the point given. Generalized barycentric coordinates are not uniquely determined for polygons of degree greater than 3, but this algorithm should find a reasonable balance, where for instance a point in the center of a polygon would have a significant contribution from all vertices. - - Generalized barycentric coordinates are a set of floats, one per vertex in the polygon, such that the sum of all the floats is 1, and the sum of all the floats times the corresponding vertices comes out to the point given. - Parameters: - int ff - - The face we're finding barycentric coordinates on. - - & p - - The point we're trying to find barycentric coordinates for. If this point is not in the plane of the polygon, the coordinates produced should represent its projection into the polygon's plane. Points outside the boundary of the polygon should be acceptable; some of the barycentric coordinates will be negative in this case. - - <float> & bary - - The table to put the results in. This table is set to size f[ff].deg. - - - - - boundary information for an mesh. The principal data contained is a table of tables of int's, which represent edge lists in the . These edge lists form closed loops of one-sided edges: boundaries, or borders, of the mesh. These edges are stored in order such that E(loop(i)[j])->v1 is the same as E(loop(i)[j+1])->v2, E(loop(i)[j+1])->v1 == E(loop(i)[j+2])->v2, and so on. (This is the right-hand, counterclockwise order when looking down on the hole from outside the mesh.) - - Most 3ds Max primitives have no borders, but the Grid, when converted to a mesh, is an example of one with a single border All methods of this class are implemented by the system. - - - - - Frees all reserved memory and reinitializes the data, producing an empty border. - - - - - Returns the number of border loops for the analyzed. - - - - - Returns a pointer to the i'th border loop. - - - - - Indicates whether border loop i is targeted or not. - - - - - Uses DebugPrint to print out the borders to the Debug Results window in DevStudio. This can be useful for tracking down bugs. Be careful not to leave MNDebugPrint calls in your final build; they will slow down your effect to no purpose. - Parameters: - *m - - The to which this refers is required to give more details about the border. - - - - - When a object or modifier (such as Editable , Edit , or Select) handles viewport subobject selection, the flow is basically as follows from Editable . - - EditTriObject::HitTest is called with window information. - - - - - - - Converts a face selection to an element selection. This method can only produce accurate results with culling if we are certain that the face selection corresponds to the results of the last call to - - the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - Parameters: - & mesh - - The mesh that owns this interface - - & faceSel - - The face selection representing actual hits in the viewport. - - & elementSel - - This is where the output Element selection is stored. - - - - - - - Converts a vertex selection to a "By Vertex" edge selection. This method can only produce accurate results with culling if we are certain that the vertex selection corresponds to the results of the last call - - to the owner 's SubObjectHitTest method. (To turn off culling, use GetCull ().ClearAll(). Culling is not relevant if the MESH_SELCONV_REQUIRE_ALL flag - - is turned off.) - - - Parameters: - & mesh - - The mesh that owns this interface - - & vertexSel - - The face selection representing actual hits in the viewport - - & edgeSel - - The face selection representing actual hits in the viewport - - - - - - - Provides a number of utility functions for working with . - - - - - Given a one-sided edge in the , retrieves the border loop which that edge forms with other one-sided edges. The border loop produced will be in sequential order going CCW around the hole, starting with the edge given. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The edge to start from. (If it is not a border edge, the "border" table will be left empty. - A reference to a table into which the border loop edge indices can be written. - - - - Applies new smoothing groups to the , smoothing between any faces that share an edge with an edge angle less than "threshold". - Similar to MNMesh::AutoSmooth, but allows the use of any flag or flags, not just MN_SEL - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The threshold angle for smoothing across edges, in radians. - If nonzero, this indicates that only faces with this flag set should have their smoothing groups affected. (If faceFlag has multiple bits set, any flag matches are considered a match.) - - - - Applies new smoothing groups to the , smoothing between any faces that share an edge with an edge angle less than "threshold", but unsmooths any edges on the border of the flagged face group. If faceFlag is zero, this works just like AutoSmooth - no border to leave unsmoothed. - Similar to MNMesh::AutoSmooth, but allows the use of any flag or flags, not just MN_SEL - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The threshold angle for smoothing across edges, in radians. - If nonzero, this indicates that only faces with this flag set should have their smoothing groups affected. (If faceFlag has multiple bits set, any flag matches are considered a match.) - - - - Indicates whether the hinge angle should be multiplied by -1, based on the local topology and geometry of the mesh. When users pick hinge edges, they may pick edges oriented in either direction, with the result that rotating around the edge by the hinge angle can produce inconsistent results. This method analyses the hinge orientation and indicates whether a correction should occur. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - New version of old "MNMesh::LiftFaceClusterFromEdge" method which doesn't require a hinge edge. Does a "hinged extrusion", where selected face clusters are rotated around a hinge axis, and new faces are created connecting the selected faces to the unselected ones. - This extrusion has a slightly different topology from a regular extrusion, in that no new faces are created for edges between selected and unselected faces that lie exactly along the hinge. - br>Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The origin point for the hinge - The axis direction for the hinge - The amount to rotate, in radians - The number of segments for the sides of the extrusion - The current set of Clusters - The ID of the cluster to rotate - - - - Determines an average plane of the flagged subobjects, and moves vertices toward it according to their soft selection value. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Moves soft-selected vertices toward the plane given according to their soft selection value, or produces an array of offsets which would do so. (Similar to MNMesh::MoveVertsToPlane, but with soft selection support.) - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Edge-based collapse function - all edges with the given flag will be collapsed, which means their vertex endpoints will be joined into a single vertex. - True if any edges were actually collapsed, else false. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The edge flag that marks the edges to be collapsed. - - - - Edge-based collapse function - all edges with the given flag will be collapsed, which means their vertex endpoints will be joined into a single vertex. The pointDest is populated with information about which vertices were collapsed and which vertices they were collapsed onto. If pointDest[i] >= 0, vertex i was collapsed onto vertex pointDest[i]. If pointDest[i] == -1, vertex i was not collapsed. If pointDest[i] < -1, (-pointDest[i]) vertices were collapsed onto vertex i (including itself). - True if any edges were actually collapsed, else false. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The edge flag that marks the edges to be collapsed. - The in which to return the collapse information. - - - - Constrains the vectors given for each vertex so that they are limited to travel along a neighboring edge. It's acceptable for deltaIn to be equal to deltaOut. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Constrains the vectors given for each vertex so that they are limited to travel along a neighboring face. It's acceptable for deltaIn to be equal to deltaOut. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Extrude method which creates new faces along open edges. - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The edges which should be extruded. (Non-open edges that have this flag set always have it cleared.) - If true, the "edgeFlag" is cleared on the edges used as the base of the extrusion. - If true, the new edges at the "top" of the extrusion have their "track" data member set to the edge at the base of their extrusion. - - - - Creates a bridge between two border loops - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - An edge on the first border loop - The twist for the first border loop. (The edge which is "twist1" edges around the loop from "edge1" will be bridged to the edge which is "twist2" edges around the loop from "edge2". - An edge on the second border loop - The twist for the second border loop. (The edge which is "twist1" edges around the loop from "edge1" will be bridged to the edge which is "twist2" edges around the loop from "edge2". - The threshold angle, in radians, for smoothing between successive columns of the bridge. - The number of segments for the bridge - The amount that the bridge should taper in - The bias for the location of the most tapered-in spot on the bridge. Range: -100 to 100, with 0 indicating that the taper should fall naturally in the middle of the bridge. - - - - Creates a bridge between two polygons. - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The first polygon - The twist for the first polygon. (The twist1'th edge of polygon face1 will be bridged to the twist2'th edge on polygon face2.) - The second polygon - The twist for the second polygon. (The twist1'th edge of polygon face1 will be bridged to the twist2'th edge on polygon face2.) - The threshold angle, in radians, for smoothing between successive columns of the bridge. - The number of segments for the bridge - The amount that the bridge should taper in - The bias for the location of the most tapered-in spot on the bridge. Range: -100 to 100, with 0 indicating that the taper should fall naturally in the middle of the bridge. - - - - Creates bridges between polygon clusters. - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The flag indicating faces in the clusters. - The threshold angle, in radians, for smoothing between successive columns of the bridge. - The number of segments for the bridge - The amount that the bridge should taper in - The bias for the location of the most tapered-in spot on the bridge. Range: -100 to 100, with 0 indicating that the taper should fall naturally in the middle of the bridge. - The twist for each "start" cluster. - The twist for each "end" cluster. - - - - Identical to BridgePolygonsClusters but should only be used to load parametric bridges from 2015 and lower. - - - - - Creates bridges between flagged borders. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - Any borders with at least one edge that has this flag set will be considered for bridging. (Only borders that match up in pairs will be bridged, of course.) - The threshold angle, in radians, for smoothing between successive columns of the bridge. - The number of segments for the bridge - The amount that the bridge should taper in - The bias for the location of the most tapered-in spot on the bridge. Range: -100 to 100, with 0 indicating that the taper should fall naturally in the middle of the bridge. - The twist for each "start" cluster. - The twist for each "end" cluster. - - - - Returns a good default twist for face2, when bridging between face1 and face2 with no twist for face1. Default twist is based on an analysis of local geometry. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The first polygon - The second polygon - - - - "Turns" the diagonal by removing it and creating a new one going across it. This is like the traditional "Turn Edge" in Editable . (Any "diagonal" in a polygon separates two triangles. If you remove that diagonal, you're left with a quad; this algorithm replaces the original diagonal with the diagonal you'd get by connecting the other two vertices of that quad.) - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The polygon face in which to turn the diagonal - The index of the diagonal to turn. A polygon of degree "deg" has (deg-3) diagonals. - - - - This is a new version of the MNMesh::Relax method, which is designed to move all vertices a little closer to their neighbors. Neighbors are defined as vertices that share an edge. This variation on the Relax method also accepts a soft selection. - True if any relaxing occurred, false in cases where nothing happened, for instance because no vertices were selected. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - If "softSel" is NULL, only vertices with this flag set are relaxed. - This is an optional soft selection. It may be NULL. If not, it should point to an array of floats representing the selection value for each vertex. - This indicates the proportion of relaxing. If it's zero, nothing happens; if it's one, each vertex is moved to the average of its neighbors. Values of less than zero or more than one are accepted, but lead to unstable results. The default in Editable Poly is .5f. - This is the number of iterations of relax. This is the number of times the relaxation is applied. The more iterations, the more relaxed the result. - If true, "boundary" points should be held in place, unaffected by the Relax. "boundary" points are defined as those that are used by more edges than faces, which basically means they're on some sort of border of the mesh. This is turned on by default in Editable Poly, because if it's off, boundary points recede into the mesh very quickly. - If true, "outer" points should be held in place. "outer" points are defined as those where the sum of all the face angles is less than 2Pi (360 degrees). This basically means the point is some sort of outer corner. All the points on a 1-segment Box or on a Geosphere are "outer" points. On a multiple-segment plane, none of the interior points are "outer" points. This parameter is most important in models like the Geosphere, which could relax down into nothing if outer points are not fixed in place. - If non-NULL, this should point to an array into which the effect of this relax should be placed, in the form of a offset per vertex. - - - - Starting with the polygon given, this algorithm creates a selection of all polygons it can get to without crossing any edges whose angle is greater than the angle given. - The number of newly-selected polygons - This method can be called multiple times with the same polySel parameter, for instance to turn a set of face hits from hit-testing into a select-by-angle region, and is designed to be used in Editable Poly and Edit Poly's "Select by angle" feature - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - The polygon to start on. If this polygon is already set in "polySel", nothing will happen. - The maximum crossable edge angle, in radians - The where polygons should be selected - - - - This method is used at the beginning of a series of cuts. It sets things up so that "CutCleanup" will work. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - This method is used after a series of cuts, to "clean up" any extra edges which are necessary to have while cutting, but which aren't what the user actually intended to create. "CutPrepare" should be called at the beginning of the series of cuts. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - This stores specified normal information for a given face. An array of these faces is used as a data member of class , in much the same way as an array is a data member of class . - - - - - Initializes data members. This is useful in situations where the default constructor may not have been properly called, such as - - *fc = new [10]; - - It should not be called on an with data allocated, or that memory will leak. - - - - - - - Frees all allocated data, sets degree to 0. - - - - - - - Returns the face's degree. - - - - - - - Accessor for normal in a particular corner of the face. - - - Parameters: - int corner - - The (zero-based) index of the corner of the face. (A quad face has corners 0, 1, 2, and 3.) - - - Index of normal (in parent 's normal array), or -1 if "corner" is out of range. - - - - - - - Sets the normal ID used in a particular corner. - - - Parameters: - int corner - - The (zero-based) index of the corner of the face. (A quad face has corners 0, 1, 2, and 3.) - - int norm - - The index of the normal (in the parent 's normal array). - - - - - Return a pointer to the internal array of normal IDs. This array has length == GetDegree(). - - - - - Indicates whether the normal used in a particular corner is specified or not. - - - Parameters: - int corner - - The (zero-based) index of the corner of the face. (A quad face has - - corners 0, 1, 2, and 3.) - - - - - - - Controls whether the normal used in a particular corner of the face is specified or not. - - - Parameters: - int corner - - The (zero-based) index of the corner of the face. (A quad face has corners 0, 1, 2, and 3.) - - - Parameters: - bool value - - Whether the corner should have a specified (true) or unspecified (false) normal. - - - - - - - all normals on this face to be specified. - - - - - Specifies that a particular corner of the face should use a given normal index. - - - Parameters: - int corner - - The (zero-based) index of the corner of the face. (A quad face has corners 0, 1, 2, and 3.) - - - Parameters: - int norm - - The index of the normal (in the parent 's normal array). - - - - - - - Inserts space for more normals into an existing face. (Designed to be used in conjunction with MNFace::Insert, to increase the size of a polygon and add new vertices & normals.) - Parameters: - int pos - - The location within the face where the new normals will be added. - - - Parameters: - int num=1 - - The number of new normals to add. - - - - - - - Identical to the Insert function, with the exception that the new normal entries for vertices [pos, pos + num) are initialized to be unspecified, rather than retaining the values from the vertices shifted to positions [pos + num, deg), where deg is the degree of the face after insertion. - Parameters: - int pos - - The location within the face where the new normals will be added. - - - Parameters: - int num=1 - - The number of new normals to add. - - - - - - - Deletes normals from this map face. (Designed to be used in conjunction with MNFace::Delete, to decrease the size of a polygon and remove vertices & normals.). - Parameters: - int pos - - The location within the face where the new normals will be deleted. - - - Parameters: - int num=1 - - The number of new normals to delete. - - - - - - - Deletes normals from this map face. (Designed to be used in conjunction with MNFace::Delete, to decrease the size of a polygon and remove vertices & normals.). - Parameters: - int newstart - - The new first normal - - - - - - - Reverses order of normals, effectively inverting the face. (Designed to be used in conjunction with MNFace::Flip.) - - - - - - - Typical = operator - calls SetDegree to make this face the same size as "from", then copies the specification data and the normalIDs. - - - - - - - Sets the degree of this NormalFace to that of the given. - - - - - - - "Shallow-copies" data from "from". This is dangerous to use - the pointer to the normal ID array is the same in both faces after this is called. - - It's typically used by MNNormal::FAlloc, when resizing the whole face array. - - - - - - - Uses "DebugPrint" to output information about this to the Debug buffer in DevStudio. Output is formatted as follows: suppose we have a 5-sided face, with normals {4,5,6,7,8}, and only the normals in corners 1 and 2 (i.e. normals 5 and 6) are specified. - - MNDebugPrint (true) would generate: - - _4 5 6 _7 _8 - - MNDebugPrint (false) would generate: - - _ 5 6 _ _ - - This is mainly used as part of MNNormalSpec::MNDebugPrint. - - - - - - - Called by the system. Saves the face's data to the stream given. - - - - - - - Called by the system. Loads the face's data from the stream given. - - - - - Description: - This class is an interface used to store user-specified normals - - (as created in the Edit Normals modifier). These normals have very - - limited pipeline support. They are used for viewport display, but not - - for rendering. - - The contains three types of normals: - - - This interface is not available when you have used the NURMS conversion from Editable Poly as it computes normals, so any user specified normals will be erased. - - - Flags: - MNNORMAL_NORMALS_BUILT - - Indicates that non-specified normals have been constructed using - - smoothing groups. If not set, non-specified normals may be invalid. - - MNNORMAL_NORMALS_COMPUTED - - Indicates that non-explicit normals have been computed using geometrically - - computed face normals. (If not set, only explicit normals may be assumed - - to be pointing the right direction.) - Data Members: - All data members are private. - - int mNumNormalAlloc, mNumFaceAlloc; - - The current allocation length of the mpNormal and mpFace arrays. - - int mNumNormals, mNumFaces; - - The number of normals and faces in the mpNormal and mpFace arrays. - - (May be less than the actual allocation above.) - - *mpFace; - - The array of normal faces. - - *mpNormal; - - The array of normals, all of which should be either length 1 or (occasionally) 0. - - mNormalExplicit; - - Indicates whether mpNormal[i] is explicit or computed from face normals. - - mNormalSel; - - Current normal selection. - - float mDisplayLength; - - The length to use when displaying, hit testing, or moving normals. - - *mpParent; - - A pointer to the "parent" that owns this . This parent - - information is required for some operations, such as display. (Such - - operations should indicate below where parent information is required.) : - - - - - - Initializes all data members. Do not call if memory has already been - - allocated, or that memory will be leaked. - - - - - - - Sets the size of the normal array - - - True if successful; false indicates a failed memory allocation. - - - - - - - Reduces the allocation size down to the actual number of normals. - - - - - - - Sets the size of the face array. - - - True if successful; false indicates a failed memory allocation. - - - - - - - Reduces the allocation size down to the actual number of faces. - - - - - - - Clears out all data, but doesn't necessarily free array memory. - - - - - - - Clears out all data and frees all memory. - - - - - - - Returns the current number of faces in the - - - - - - - Sets the current number of faces in the , - - increasing the allocation size as needed. - - - True if successful; false indicates a failed memory allocation. - - - - - - - Returns the current number of normals in the - - - - - - - Sets the current number of normals in the , - - increasing the allocation size as needed. - - - True if successful; false indicates a failed memory allocation. - - - - - - - Returns the normal indicated. Since it returns a reference, - - you can use it as a set method as well: - - Normal(i) = Normalize (); - - (Note that all normals should be normalized to a length of 1.) - - - - - - - Returns a pointer to the whole normal array. - - - - - - - Indicates whether a given normal is explicit or not. - - - - - - - Returns true if there are any explicit normals set - - - - - Sets a particular normal to be explicit or not. Note that if - - you make a normal non-explicit, it may need to be recomputed, - - so you may want to call ComputeNormals or at least clear the - - MNNORMAL_NORMALS_COMPUTED flag. - - - Parameters: - int normID - - The index of the normal - - bool value - - True to make the normal explicit; false to make it non-explicit. - - - - - - - all normals in this to be explicit. - - - - - Returns the indicated face. - - - - - - - Returns a pointer to the whole face array. - - - - - - - Tells the what "owns" it. - - This "Parent" is used in methods such as - - Display, Hit-Testing, and certain operations like - - Unify to get information about the vertices that - - normals are based on. (There's no vertex info - - in the itself.) - - If you have an isolated which doesn't - - really have an associated "parent", you can - - temporarily set this to a mesh with the right sort - - of faces and vertices, but you should clear it - - afterwards by calling SetParent (NULL). See the - - Edit Normals modifier source in - - maxsdk/SAMPLES/mesh/EditablePoly/EditNormals.cpp - - for an example of this sort of usage. - - - - - - - Returns the normal used by the indicated face, in the indicated corner. - - - - - - - Creates a new (explicit) normal and uses it in the indicated - - corner of the indicated face. If "normal" is not already - - normalized, this method will take care of it. - - - - - - - Returns the index of the normal used in the indicated corner - - of the indicated face. - - - - - - - Sets the index of the normal used in the indicated corner of - - the indicated face, and marks it as specified. - - - - - - - Creates a new normal at the end of the normal array. - - - Parameters: - & normal - - The desired normal direction. Will be normalized to a length - - of 1 by the method if needed. - - bool explic=true - - Indicates whether the new normal should be considered explicit - - or not. - - - - - - - Returns the current normal selection. - - - - - - - Returns the current length used for normal display, hit-testing, and Translations. - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - This method is used in conjunction with the parent 's - - CollapseDeadFaces method to keep the normal faces in synch with - - the parent faces. It removes any normal face whose - - equivalent face in the parent mesh is considered "Dead". - - Called by MNMesh::CollapseDeadFaces, so you generally don't - - need or want to call it separately. - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - Displays the current normals in the graphics window indicated. - - If "showSel" is true, selected normals are displayed in the - - usual subobject selection color. - - - - - - - Requires an accurate "parent" pointer (see SetParent). Hit-tests on the current normals. - - - Parameters: - *gw - - The window to hit-test in. - - *hr - - A hit region, typically generated by a call like MakeHitRegion(hr,type, crossing,4,p); - - DWORD flags - - Hit testing flags. Please see BaseObject::HitTest for a description of - - these flags and of the "type" and "crossing" variables used to generate - - the . - - & hitList - - Where the hits get stored. - - - True if a hit was found; false if not. - - - - - - - Requires an accurate "parent" pointer (see SetParent). Computes the bounding box of the normals. - - - Parameters: - tm=NULL - - An optional transform for computing the bounding box in a different - - space (such as world space). - - bool selectedOnly=false - - Indicates whether all normals should be included in the bounding box, - - or only selected ones. - - - - - - - This method dumps all unspecified normals. Best to use only from within BuildNormals, - - since it leaves all unspecified normals in faces initialized to -1. - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - Fills in the mpSpecNormal data by building all the unspecified normals, - - and computing non-explicit ones. Does nothing if face array is not - - allocated yet! - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - This method just recomputes the directions of non-explicit normals, - - without rebuilding the normal list. - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - This checks our flags and calls BuildNormals or ComputeNormals as needed. - - - - - - - Adjusts the number and topology of the normal faces to match the parent mesh. For new faces added, or if doCheckDegree is true, for any faces encountered whose degree does not match the corresponding face of the parent mesh, all normals are set unspecified. If the parent mesh pointer is not set, does nothing. - - when true, the degree of each already-created normal face is checked against the corresponding face in the parent mesh - - - - Typical = operator. Allocates arrays in this, and makes copies of all - - the data in "from". Does NOT copy "Parent" pointer. - - - - - - - This is similar to operator=, but copies only the specified and explicit - - information from "from". Result will need to have BuildNormals and ComputeNormals - - called. - - - - - - - For each face index map entry faceIndexMap[f] which is valid, i.e. faceIndexMap[f] >= 0, the target face faceIndexMap[f] of this object is defined as a copy of source face f of object sourceNormals, which may be the same as this object. In particular, face faceIndexMap[f] is allocated if necessary, set to the same degree as the source face, and any vertex normals which are set as specified for the source face are copied to the corresponding vertices of the target face. The explicitness of normals is also preserved in the copy. Note that the operation will fail if sourceNormals is the same as this object, and the index map contains undefined copies, i.e. if 0 <= faceIndexMap[f] < faceIndexMap.Count() for any f, and faceIndexMap[faceIndexMap[f]] >= 0. - Flag indicating whether copy operation was successful. - - specified normals object containing the source face data - map from source to target faces; the condition faceIndexMap[f] < 0 indicates that source face f is not to be copied - - - - Adds the faces and normals from "from" to our normal spec, renumbering the - - normals so they don't conflict with existing ones. Called by the - - "AppendAllChannels" method below (which itself is called by MNMesh::operator+=). - - - - - - - Uses "DebugPrint" to output information about this MNNormalSpece to the - - Debug buffer in DevStudio. - - - Parameters: - bool printAll=false - - If false, only explicit normals and faces using specified normals will be - - printed out. If true, all normals and faces will be completely printed out. - - Here is what the output looks like on a box with mostly default (non-specified) - - normals, but with one corner "Unified" into a single specified normal: - - If printAll = true, you'll see: - - Debug Output: 22 normals, 6 faces - - Normal (Non ) 0: 0.577350, -0.577350, 0.577350 - - Normal (Non ) 1: 0.000000, 0.000000, -1.000000 - - Normal (Non ) 2: 0.000000, 0.000000, -1.000000 - - Normal (Non ) 3: 0.000000, 0.000000, -1.000000 - - Normal (Non ) 4: 0.000000, 0.000000, -1.000000 - - Normal (Non ) 5: 0.000000, 0.000000, 1.000000 - - Normal (Non ) 6: 0.000000, 0.000000, 1.000000 - - Normal (Non ) 7: 0.000000, 0.000000, 1.000000 - - Normal (Non ) 8: 0.000000, -1.000000, 0.000000 - - Normal (Non ) 9: 0.000000, -1.000000, 0.000000 - - Normal (Non ) 10: 0.000000, -1.000000, 0.000000 - - Normal (Non ) 11: 1.000000, 0.000000, 0.000000 - - Normal (Non ) 12: 1.000000, 0.000000, 0.000000 - - Normal (Non ) 13: 1.000000, 0.000000, 0.000000 - - Normal (Non ) 14: 0.000000, 1.000000, 0.000000 - - Normal (Non ) 15: 0.000000, 1.000000, 0.000000 - - Normal (Non ) 16: 0.000000, 1.000000, 0.000000 - - Normal (Non ) 17: 0.000000, 1.000000, 0.000000 - - Normal (Non ) 18: -1.000000, 0.000000, 0.000000 - - Normal (Non ) 19: -1.000000, 0.000000, 0.000000 - - Normal (Non ) 20: -1.000000, 0.000000, 0.000000 - - Normal (Non ) 21: -1.000000, 0.000000, 0.000000 - - Normal Selection: - - 0 6 13 17 - - Normal faces: _ before normal index means non-specified. - - 0: _1 _2 _3 _4 - - 1: _5 0 _6 _7 - - 2: _8 _9 0 _10 - - 3: _11 _12 _13 0 - - 4: _14 _15 _16 _17 - - 5: _18 _19 _20 _21 - - If printAll is false, you'll just see: - - Debug Output: 22 normals, 6 faces - - Normal Selection: - - 0 6 13 17 - - 1: _ 0 _ _ - - 2: _ _ 0 _ - - 3: _ _ _ 0 - - - - - - - Performs a series of internal checks to verify that the normal - - data is consistent. If there are any problems, messages are - - sent out via DebugPrint. - - - Parameters: - int numParentFaces - - The number of faces in the parent . (This method does not - - require an accurate "parent" pointer, but it does require this - - number to be accurate. - - - True if everything checks out ok, false if not. - - - - - - - Called by the system. Saves the to the buffer. - - - - - - - Called by the system. Loads the from the buffer. - - - - - - - Transforms the normals. If isGeomTransform is true, the normals are transformed consistent with the transformation defined by matrix transformMat being applied to the geometry, meaning that the normal vectors are multiplied by transpose of the inverse of transformMat. If isGeomTransform is false, then the matrix portion of transformMat is simply applied directly. In both cases, we disregard the translation vector, and renormalize the affected normal vectors. Note that if transformMat represents a rotation, then the result is independent of the choice of isGeomTransform, since the matrix will be orthogonal. - Flag indicating whether any normals were altered. In particular, if the specified values of transformMat and isGeomTransform indicate an identity transformation, we will return false. - - matrix representing the transformation to be applied - when true, only selected normals are altered, otherwise, the transformation is applied to all defined normals - when useSelection is true, the selected normals are defined by normalSelection if not null, or the usual member selection, otherwise - when true, matrix transformMat is interpreted as a transformation applied to the associated geometry, as discussed above - - - - This is used to give a translation-like effect to normals. It's used in the Edit - - Normals "Move" mode. Essentially it drags the "top" of the normals by the amount - - given, and then renormalizes the vectors to unit length. It uses the current - - display length as well, so the formula is basically - - mpNormal[i] = Normalize (mpNormal[i]*mDisplayLength + translate); - - This gives a fairly natural result in Edit Normals Move. - - - Parameters: - & translate - - The desired translation. - - BOOL useSel=false - - Indicates whether all normals should be translated, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to translate. - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals in the spec or because none were selected. - - - - - - - "Breaks" normals so that none are shared between faces. Broken normals are set to Specified (but not explicit.) - - - Parameters: - BOOL useSel=false - - Indicates whether all normals should be affected, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to affect. (Irrelevant if - - useSel=false.) - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals present or because none were selected, - - or because selected normals were already fully broken and specified. - - If the return value is true, the MNNORMAL_NORMALS_BUILT and - - MNNORMAL_NORMALS_COMPUTED flags are cleared, because the newly broken - - normals need to be rebuilt and computed. - - - - - - - Requires an accurate "parent" pointer (see SetParent). - - This method unifies selected normals so that there's a maximum of one - - per vertex. For instance, a default box has 3 normals at every vertex. - - You can select 2 or 3 of them and click "Unify" in Edit Normals, and - - the normals will be shared across the faces that use them. See Edit - - Normals documentation for more information. - - This method does not unify normals that are based at different vertices. - - If you want separate vertices to use the same normal, you must use more - - direct, low-level methods like SetNormalIndex. - - Unified normals are set to specified (but not explicit). - - - Parameters: - BOOL useSel=false - - Indicates whether all normals should be affected, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to affect. (Irrelevant if - - useSel=false.) - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals present or because none were selected, - - or because selected normals were already fully unified and specified. - - If the return value is true, the MNNORMAL_NORMALS_BUILT and - - MNNORMAL_NORMALS_COMPUTED flags are cleared, because the newly unified - - normals need to be rebuilt and computed. - - - - - - - Specifies the indicated normals. DOESN'T remove the explicitness of the normals. - - (That should be done separately with MakeNormalsExplicit, value=false.) - Parameters: - BOOL useSel=false - - Indicates whether all normals should be affected, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to affect. (Irrelevant if - - useSel=false.) - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals present or because none were selected, or because - - they were all already specified. - - - - - - - Makes the indicated normals both specified and explicit. - Parameters: - BOOL useSel=false - - Indicates whether all normals should be affected, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to affect. (Irrelevant if - - useSel=false.) - - bool value=true - - I Indicates whether the normals should be set to explicit, or non-explicit. - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals present or because none were selected. - - If value=false and the return value is true, the MNNORMAL_NORMALS_COMPUTED - - flag is cleared, because the newly nonexplicit normals need to be computed - - . - - - - - - - Resets the indicated normals to be completely non-explicit and non-specified. - Parameters: - BOOL useSel=false - - Indicates whether all normals should be affected, or only selected ones. - - *normalSelection=NULL - - If non-NULL, this represents a selection of normals that should be used instead of - - the usual selection, when deciding which normals to affect. (Irrelevant if - - useSel=false.) - - - True if something was modified. False would indicate that no normals were changed, - - perhaps because there are no normals present or because none were selected. - - If the return value is true, the MNNORMAL_NORMALS_BUILT and - - MNNORMAL_NORMALS_COMPUTED flags are cleared, because the newly nonspecified - - normals need to be rebuilt and computed. - - - - - This is a simple derived class of used to encapsulate the new parameters added to the Universal Quad Chamfer interface in . These parameters represent additional functionality of the underlying quad chamfer operations introduced in 3ds Max 2020 Update 1, and should eventually be moved into the main class above when SDK considerations allow. - - - - - Returns the radius bias factor. - - - - - This class is used to provide parameters to the Universal Quad Chamfer interface in . - The parameter set includes all applicable parameters for Quad Chamfer operations and allows for specifying version numbers (See Quad Chamfer Version Values). In this way the interface can be used for any Quad Chamfer operations now and into the future - Various constructors are provided for ease of use, and as parameters are added in the future, constructors will be added to access that functionality. - - - - - This class encapsulates the parameters defining the quad vertex chamfer operation accessed via the interface defined in . Definitions of each parameter are given below. - - - - - Used for caching face and edge clusters, vertex normals, and other derived data about an . There is a SetMesh() method to set the current mesh that the TempData is based on, then there's a series of methods to update the cache and return some sort of derived data. All of these methods follow the form: - DerivedData is the container for the derived data requested (often a simple table, though there are some specialized classes returned from some methods). If the data has already been computed, the parameters are ignored and the cached data is returned. Otherwise, the data is computed from the parameters and the current mesh. - There are no procedures in place to detect changes in parameters or the mesh since the last time a method was called, so it's the calling routine's responsibility to free invalid structures. If you know that only certain pipeline channels, such as GEOM_CHANNEL have changed, you can use the Invalidate(ChannelMask channels) method. (GEOM_CHANNEL would free the distances-to-selected-vertices, for example, but not the Clusters.) - In particular, there is no way for the to know when its mesh pointer is no longer valid, so it's vital that the calling routine clear the mesh (with SetMesh(NULL)) or stop using the when this happens. - All data members are private. They basically consist of a series of pointers which are initialized to NULL and then filled with allocated derived data as requested. There is also a NULL-initialized, private mesh pointer which is set with SetMesh(). Editable Poly uses this class to hold all the varieties of temporary, cached data it creates - examples are vertex normals and face clusters. - To use , just set it to your mesh and start querying the member functions. - - - - - This method returns a face cluster list, which groups selected faces into "clusters" for transformation. See Class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - Parameters: - DWORD clusterFlags=MN_SEL - - The face flags to cluster the faces by. For instance, with the default value, faces are clustered by their selection. - - - - - Returns an edge cluster list, which groups selected edges into "clusters" for applying transforms. See Class for more information. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh. - Parameters: - DWORD clusterFlags=MN_SEL - - The edge flags to cluster the edges by. For instance, with the default value, edges are clustered by their selection. - - - - - This method returns an index of which cluster, if any, each vertex is in. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. - Parameters: - int sl - - The selection level. This should be either MNM_SL_EDGE or MNM_SL_FACE, to indicate whether the vertex cluster information should be based on edge or face clusters. Note that this parameter is ignored if there's already a vertex cluster cache. - - DWORD clusterFlags=MN_SEL - - The edge or face flags to cluster the edges or faces by. For instance, with the default value, edges or faces are clustered by their selection. Note that this parameter is ignored if there's already a vertex cluster cache. - A table of DWORD's is returned, one for each vertex. If (VertexClusters(sl))[i] is UNDEFINED, vertex i is not in any cluster. Otherwise, the value for vertex i is the cluster index. - - - - - Returns average normals for each cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. Note that cluster centers and normals are computed and cached at the same time, when you call either method. - Parameters: - int sl - - The selection level. This should be either MNM_SL_EDGE or MNM_SL_FACE, to indicate whether the vertex cluster information should be based on edge or face clusters. Note that this parameter is ignored if there's already a cluster normal cache. - - DWORD clusterFlags=MN_SEL - - The edge or face flags to cluster the edges or faces by. For instance, with the default value, edges or faces are clustered by their selection. Note that this parameter is ignored if there's already a cluster normal cache. - A table of 's is returned, one for each cluster. The values are already normalized to length 1. - - - - - Returns mean centers for each cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameter. Note that cluster centers and normals are computed and cached at the same time, when you call either method. - Parameters: - int sl - - Selection level. This should be either MNM_SL_EDGE or MNM_SL_FACE, to indicate whether the clusters we're talking about are the edge or face clusters. Note that this parameter is ignored if there's already a cluster center cache. - - DWORD clusterFlags=MN_SEL - - The edge or face flags to cluster the edges or faces by. For instance, with the default value, edges or faces are clustered by their selection. Note that this parameter is ignored if there's already a cluster center cache. - A table of 's is returned, one for each cluster. - - - - - Uses the current cluster center and normal caches to return the "objectspace to clusterspace" transform. This is the transform of the "local" axis in moving edge or face clusters in Editable Poly. If the cluster centers and normals have not been cached, the identity matrix is returned; thus the control over whether this is an edge or face cluster is handled by the last call to ClusterCenters or ClusterNormals. - Parameters: - int clust - - The cluster you want the transform for. - - - - - Computes the current distance of each vertex from the specified cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - - NOTE: If useEdgeDist is FALSE, this is an n-log-n algorithm: it compares every vertex not in the cluster with every vertex in it. If useEdgeDist is TRUE, the time it takes is proportional to the number of verts in the cluster times edgeIts. - Parameters: - int sl - - Indicates whether we should use edges (MNM_SL_EDGE) or faces (MNM_SL_FACE) to construct the clusters, if needed. - - DWORD clusterFlags - - The edge or face flags to cluster the edges or faces by. For instance, if clusterFlags==MN_SEL, edges or faces are clustered by selection. - - int clustId - - The ID of the cluster we're measuring distance from. - - BOOL useEdgeDist - - If set to TRUE, the distance between vertices is computed along edges. If set to FALSE, it's computed directly through space. - - int edgeIts - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.) - A table consisting of one float value per vertex. If this value is 0, the vertex is either selected or on top of a vertex in the cluster. Otherwise it represents the distance to the closest selected vertex. If useEdgeDist is TRUE, values of -1.0 are returned for vertices with no edgeIts-length path to a vertex in the cluster. - - - - - Sets the internal mesh pointer to m. - Parameters: - *m - - The internal mesh pointer to set. - - - - - Returns a table of local average normals for vertices. These normals are computed using the MNMesh::GetVertexNormal() method, wherein each face's contribution to the vertex normal is weighted by the face angle at the vertex. - - - - - Returns Vertex Selection weights (for soft selection). If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. Weights are based on the standard soft selection falloff from the currently selected vertices. - - Note: If useEdgeDist is FALSE, this is an n-log-n algorithm: it compares every vertex not in the cluster with every vertex in it. If useEdgeDist is TRUE, the time it takes is proportional to the number of verts in the cluster times edgeIts. - Parameters: - BOOL useEdgeDist - - If set to TRUE, the distance between vertices is computed along edges. If set to FALSE, it's computed directly through space. - - int edgeIts - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.) - - BOOL ignoreBack - - If set to TRUE, vertices with a normal (as computed in VertexNormals) that points more than 90 degrees away from the average normal of the selection are not given any partial selections. They're either 1 if selected or 0 otherwise. - - float falloff - - The limit distance of the effect. If distance > falloff, the function will always return 0. - - float pinch - - Use this to affect the tangency of the curve near distance=0. Positive values produce a pointed tip, with a negative slope at 0, while negative values produce a dimple, with positive slope. - - float bubble - - Use this to change the curvature of the function. A value of 1.0 produces a half-dome. As you reduce this value, the sides of the dome slope more steeply. Negative values lower the base of the curve below 0. - - DWORD selFlags=MN_SEL - - Indicates what flag defines the hard selection we're basing this soft selection on. - A table of float values, one per vertex, that are 1.0 if the vertex is in the current selection, 0.0 if it's more than falloff distance (or more than edgeIts edges, if (useEdgeDist)), and AffectRegionFunction((*SelectionDist(useEdgeDist, edgeIts)), falloff, pinch, bubble) otherwise. - - - - - Computes the distances of the unselected vertices from the current selection within a falloff. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mnmesh and the parameters. The term "Selected verts" below refers to the vertices that are selected in the mesh's current selection level. (See the method GetTempSel for details.) - A table consisting of one float value per vertex. If this value is 0, the vertex is either selected or on top of a selected vertex. Otherwise it represents the distance to the closest selected vertex. If useEdgeDist is TRUE, values of -1.0 are returned for vertices with no edgeIts-length path to a selected vertex. - - If TRUE, the distance between vertices is computed along edges. If FALSE, it's computed directly through space. - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.). WARNING: If useEdgeDist is FALSE, this is an n-squared algorithm: it compares every nonselected vertex with every selected one within the falloffLimit. If useEdgeDist is TRUE, the time it takes is proportional to the number of selected vertices times edgeIts. - The flags used to dertermine what edges are considered selected. - = -1.0f this limits the number of unselected vertices to check against Only vertices that fall within the selected vertices bounding box + this limit will be computed. If this value is -1.0 all vertices will be computed. Any vertex outside this limit will be set to a distance of the limit. - - - - Produces the "Outline" direction of all vertices, based on the current face selection. "Outlining" is the direction vertices move to move edges of the current face selection outward at a constant rate. They are not set to length 1, but rather to whatever "rate" best makes the outline edges move most consistently, without changing their angles. - Parameters: - int extrusionType - - This is one of MESH_EXTRUDE_CLUSTER or MESH_EXTRUDE_LOCAL, to indicate whether vertices should move according to cluster or local face normals. - - DWORD clusterFlags=MN_SEL - - The face flags to cluster the faces by. For instance, if left at the default value, faces are clustered by selection. Note that this parameter is ignored if the extrusionType is LOCAL. - - - - - Rreturns the cache of a ChamferData for use in the Chamfer methods. Unlike other methods, this method makes no calculations based on the current mesh, but merely supplies a memory cache. (Computing this information is left to the methods GetExtrudeDirection, ChamferVertices, and ChamferEdges.) - - - - - This method invalidates all data based on the specified part of the mesh. In the following chart, the columns represent the channels GEOM_CHANNEL (G), TOPO_CHANNEL (T), SELECT_CHANNEL (S), and SUBSEL_TYPE_CHANNEL (U). X's indicate dependency of the specified data cache on the given channel. - NOTE: ChamferData and the Outline direction info are handled separately in freeChamferData and freeBevelInfo. - Parameters: - ChannelMask channels - - One or more of the following channels: GEOM_CHANNEL, TOPO_CHANNEL, SELECT_CHANNEL, SUBSEL_TYPE_CHANNEL. - - - - - Uncaches (frees) the distance dependent data returned by VSWeight, SelectionDist, and ClusterDist. - - - - - This method frees the VSWeight data (but not the underlying distance-from-selection info). This is useful, e.g., if the mesh has not changed, but you wish to change the falloff, pinch, or bubble parameters to get new vertex selection weights. - - - - - This method is mainly for internal use, this frees just the cluster distance data. - - - - - This method frees only the outlining data. - - - - - This method frees only the chamfer data structure. - - - - - This method frees all cached data of any kind. - - - - - The vertex class used with the mesh. MNVerts have a location and flags. - - - - - The location of the vertex. - - - - - Getter for the point this vertex comes from. Used for tracability of a vertes after some manipulation operators. - - - Comparison operator. - - - - - Setter for the point this vertex comes from. Used for tracability of a vertes after some manipulation operators. - - - - - - - - - Description: - This class represents the script zip package file (*.mzp) and is available through the built-in type instance msZipPackageFileDropType. - Data Members: - MSTR extract_dir; - - The path string representing the directory to extract into. - - MSTR drop_file; - - The drop file string. - - DropType* drop_file_type; - - The if the drop_file is not a dropScript. - - - - - Class that uses the RAII idiom to push/pop the thread local current_locals_frame. This ensures that the thread local current_locals_frame is always properly restored and memory is freed, even in the event of an exception. mpAllocPtr points to memory allocated by _malloca. Instances of this class are automatically created via the value_local_array and value_local_array_tls macros below. - - - - - Class that uses the RAII idiom to push/pop the thread local current_locals_frame. This ensures that the thread local current_locals_frame is always properly restored, even in the event of an exception. Instances of this class are automatically created via the various XXX_value_local(s) and xxx_typed_value_local(s) macros below. If validateFrame is false, no validation of thread_local(current_locals_frame) is done. This is normally true, only false in Name::intern. Lots of places intern names w/o setting up a local scope. - - - - - Description: - This class provides a method AddMapName() that is called when a is attempting to load its map and it cannot be found. - - - - - Implemented by the System. - - This method is called to add the name of a map that was not found. - Parameters: - MCHAR *name - - The name to add. - - - - - Creates unique names. - - - Use this class to generate unique names for various scene entities such as materials, layers, etc. The generated names consist of a root string ("Layer") and a numeric suffix (001, 002, etc), as in "Layer001", "Layer002", etc. This class is most useful when client code has a list of root strings that can be used to initialize the name maker before asking it to create new names. Although this class can be used to create node names that are unique within the current scene, method Interface::MakeNameUnique() delivers equivalent results to this class with identical performance. Clients can use the Interface::NewNameMaker() factory method to create an instance of this class. All methods of this class are implemented by the system. - - - - - Creates a unique version of a given name Note that gaps in the numeric suffixes are not filled in. For example if "name001" and "name003" already exist, the next unique name that has the root "name" will be "name004" as opposed to "name002". The number of digits used in the numeric suffix can be set via Interface13::SetNameSuffixLength(). - - - - The name that is to be made unique - - - - Sets the root name used by the name maker for generating new unique names. - - - - The name to be added. Numeric suffixes are stripped off before the name is added to the name maker. - - - - Verifies if a root name exists already. - - - TRUE if the root name is known to the name maker, FALSE otherwise - - [in] name The root name to look for. - - - - This class is used to store a table of names. - - - For example, this class is used by lights for their "Inclusion" and "Exclusion" lists. - This class maintains an 'include' flag that specifies whether the list of names is things to be included, or things to be excluded. There is no reason the class can't be used for other things where inclusion/exclusion is not relevant: in that case one can just ignore the 'include' flag. All methods are implemented by the system. - - - - - Assignment operator. - - - - - Sets the specified flag to the specified value. - - - - - The flag(s) to set. One or more of the following values: - NT_INCLUDE - This bit is used to indicate "Include" mode. - - The value to set. - - - - Checks if a flag is set or not. - - - - - The flag(s) to set. One or more of the following values: - NT_INCLUDE - This bit is used to indicate "Include" mode. - - - - Appends a copy of the specified name to the end of the list. - - - - Returns the number of items in the list prior to appending. - - - The name to add. - - - - Sets a name in the list. - - - Stores the specified name at the specified position in the list. - - - The position in the list for the name. - - The name to store. If the name is NULL, the 'i-th' entry is set to NULL. - - - - Sets the size of the list. - - - If the new size is smaller than the current size, the entries are deleted. - - - Specifies the size of the list. - - - - Removes the 'i-th' name from the list. - - - - - Specifies the index of the name to remove. - - - - Finds the index of the name passed in. - - - - Returns the index of the name passed; otherwise returns -1. - - - The name to find. - - - - Loads this from disk. - - - - - Provides methods to load data from disk. - - - - Saves this to disk. - - - - - Provides methods to save data to disk. - - - - A class that holds a node and a list of anims under that node that can be used for loading,saving, mapping animation, or putting specific tracks into the mixer. Provides a lower level of control than just specify a node by itself. - - - This class gets filled out via the ILoadSaveAnimation::SetUpAnimsForSave, ILoadSaveAnimation::SetUpAnimsForLoad, and ILoadSaveAnimation::SetUpAnimsForMapping. It's the users responsibility to delete this item by calling DeleteThis, since it doesn't delete it's own data on deconstruction. - - - - - Assignment operator. - - - - - Compares this class instance to another one - - - - - Get the list. - - - The object - - - - - Get the node. - - - The node (may be null) - - - - - Gets the IKNodeName. - - - The IKNodeName (may be null) - - - - - Sets the IKNodeName. - - - - - Description: - A callback to allow plug-ins that aren't actually objects (such as utilities) to control a Node's display. - - This class enables you to display extra information on top of a node in a viewport. Once activated, a plug-in will control the display (on/off) of a node's world space representation as well as add data in a viewport on a per node basis. This approach allows you to replace the drawing code of every node without adding modifiers on top of each of them. - - - - - This method is called just before 3ds Max draws the nodes in the scene. - Parameters: - TimeValue t - - The time at which the nodes are being drawn. - - *vpt - - Points to an interface for the viewport the node is being drawn in. - - int flags - - These flags are used internally. - - - - - This method is called just after 3ds Max draws the nodes in the scene. - Parameters: - TimeValue t - - The time at which the nodes were drawn. - - *vpt - - Points to an interface for the viewport the node is being drawn in. - - int flags - - These flags are used internally. - - - - - This method is called for every node to allow it display itself. - Parameters: - TimeValue t - - The time at which the node is to be drawn. - - *vpt - - Points to an interface for the viewport in which the node is being drawn in. - - int flags - - The display flags, which are; - - USE_DAMAGE_RECT - - If this flag is set, only the damaged area needs to be displayed. The damaged rectangle may be retrieved using INode::GetDamagedRect(). See Class . - - DISP_SHOWSUBOBJECT - - This indicates if an item should display its sub-object selection state. The system will set this flag is the item is selected, the user is in the modify branch, and the item is in sub-object selection mode. - - *node - - Points to the node being drawn. - true if displayed, otherwise false. - - - - - This method is called to determine if the node mesh should be displayed. It should return true; otherwise return false. - Parameters: - TimeValue t - - The time at which to check if the node should be displayed. - - *node - - The node to check. - - - - - This method will ask the callback to participate in the bounding box calculation. - Parameters: - TimeValue t - - The time at which to calculate the bounding box. - - *node - - The node to calculate the bounding box for. - - *vpt - - Points to an interface for the viewport in which the node is being drawn in. - - & box - - A reference to the bounding box. - - - - - This method hit tests the callback's mesh. - Parameters: - TimeValue t - - The time at which to hit test. - - *node - - A pointer to the node to test. - - int type - - The type of hit testing to perform. See Scene and Node Hit Test Types.. - - int crossing - - The state of the crossing setting. If TRUE crossing selection is on. - - int flags - - The hit test flags. See Scene and Node Hit Testing Flags for details. - - *p - - The screen point to test. - - ViewExp* vpt - - An interface pointer that may be used to call methods associated with the viewports. - true if the item was hit, otherwise false. - - - - - This method is called when the callback gets activated. It is up to the callback to invalidate the screen. - - - - - This method is called when the callback is deactivated. - - - - - This method returns the name of the callback which is used for display in the menu. The user must delete the string returned. - - - - - Description: - This class contains the data for a single note of a Note track in Track . This includes the time, text and flags for the notes. - Data Members: - TimeValue time; - - The time of the note. - - MSTR note; - - The text of the note. - - DWORD flags; - - The note flags. One or more of the following values: - - NOTEKEY_SELECTED - - The key is selected. - - NOTEKEY_LOCKED - - The key is locked. - - NOTEKEY_FLAGGED - - The key is flagged. - - - - - Assignment operator. - - - - - Equality operator. - - - - - Inequality operator. - - - - - Sets the specified flags. - Parameters: - DWORD mask - - The flags to set. - - - - - Clears (sets to zero) the specified flags. - Parameters: - DWORD mask - - The flags to clear. - - - - - Tests the specified flags. Returns TRUE if set; otherwise FALSE. - Parameters: - DWORD mask - - The flags to test. - - - - - Description: - This class is table of pointers to objects which store data about a Note Track in Track . See Class for details on manipulating this table. - - - - - Deletes all the keys in the table. - - - - - Deletes the specified key. - Parameters: - int i - - The zero based index of the key to delete. - - - - - Assignment operator. - Parameters: - &keys - - The table of keys to assign. - - - - - This method is used internally to sort the keys by time. - Operators: - - - - - Description: - Whenever the modifier stack is collapsed the code has to notify all objects in the stack with a Pre and a Post notification. In order to do this, this class can be used in conjunction with the method EnumGeomPipleine(). In the constructor one can specify, if it is a pre- or post- collapse notification. In case it is a post collapse the object that represents the result of the collapse has to be provided as well. The pointer to the beginning of the pipeline that was collapsed has to be provided in both cases. - - All methods of this class are implemented by the System. - - - - - Class used by EnumGeomPipeline to notify the pipeline of a collapse as well as maintaing the Custom Attributes. (Obsolete) - - - This class is used in conjunction with . The calling code needs to make sure they call the correct version of the enumeration. - Note: this class is superceded by as it does not provide the capability for handling cloning of the node's base object correctly. - - - - - Class used by EnumGeomPipeline to notify the pipeline of a collapse as well as maintaing the Custom Attributes. - - - This class is used in conjunction with . The calling code needs to make sure they call the correct version of the enumeration. The following is a code example of its usage. - * iCM = ICustAttribCollapseManager::GetICustAttribCollapseManager(); - if(iCM && iCM->GetCustAttribSurviveCollapseState()) { PostNCEP(false,oldObj,true,obj); //use the CA safe version EnumGeomPipeline(&PostNCEP,oldObj); } else { PostNCEP(false,node,obj); //use the original EnumGeomPipeline(&PostNCEP,oldObj); } - - - - - Description: - This class maintains a simple list of integer numbers. All methods of this class are implemented by the system. - - - - - Adds the number to the list. - Parameters: - int j - - The number to add. - - BOOL checkUnique=TRUE - - If TRUE the number will be added only if it is not in the table already. - The index in the table of the added number, or the index where it was found already if checkUnique is used. - - - - - Returns the index in the table of the number passed. - Parameters: - int j - - The number to find. - - - - - Description: - This class provides access to the 1-Rail Sweep Surface. A 1-Rail Sweep Surface uses at least two curves. One curve, the "rail," defines one edge of the surface. The other curves define the surface's cross sections. The cross-section curves should intersect the rail curve. If the cross sections don't intersect the rail, the resulting surface is unpredicable. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the rail curve. - - - - - Returns the NURBSId of the rail curve. - - - - - Returns the number of cross-section curves used. - - - - - Adds a curve to the end of the list of cross-section curves by specifying the index in the . - Parameters: - int index - - The index in the of the cross-section curve to append. - - BOOL flip - - TRUE to reverse (or flip) the direction of the curve; FALSE to use the non-reversed orientation. - The number of cross-section curves prior to appending. - - - - - Adds a curve to the end of the list of cross-section curves by specifying a NURBSId. - Parameters: - NURBSId id - - Specifies the cross-section curve to append. - - BOOL flip - - TRUE to reverse (or flip) the direction of the curve; FALSE to use the non-reversed orientation. - The number of cross-section curves prior to appending. - - - - - Specifies the curve to use as a cross-section via its index in the . - Parameters: - int pnum - - The zero based index of the curve to set. - - int index - - The index in the of the curve. - - - - - Specifies the curve to use as a cross-section via its NURBSId. - Parameters: - int pnum - - The zero based index of the curve to set. - - NURBSId id - - The id of the curve. - - - - - Returns the index in the of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve to get. - - - - - Returns the NURBSId of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve to get. - - - - - Sets the reversed (or flipped) state of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve. - - BOOL flip - - TRUE to reverse the direction; FALSE for the normal direction. - - - - - Returns the reversed (or flipped) state of the specified cross-section curve. TRUE is reversed; FALSE is not. - Parameters: - int pnum - - The zero based index of the curve. - - - - - Returns the state of the parallel flag. When TRUE, 3ds Max ensures that the sweep surface's normal is parallel to the rail. - - - - - Sets the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to set the start point. - - int pnum - - The zero based index of the curve in the set of cross sections. - - double startpoint - - The start point in the range 0.0 to 1.0. - - - - - Returns the start point of the specified parent curve. - Parameters: - TimeValue t - - The time at which to get the start point. - - int pnum - - The zero based index of the curve in the set of cross sections. - - - - - - - Returns TRUE if snap to Cross Section is on; otherwise FALSE. - - - - - Returns TRUE if the roadlike setting is on; otherwise FALSE. - - - - - Sets the axis of the sweep. - Parameters: - TimeValue t - - The time at which to set the axis. - - & ray - - The axis system to set. - - - - - Returns the axis of the sweep. - Parameters: - TimeValue t - - The time at which to get the axis. - Operators: - - - - - Description: - This class provides access to the 2-Rail Sweep Surface. A 2-Rail Sweep surface uses at least three curves. Two curves, the "rails," define the two edges of the surface. The other curves define the surface's cross sections. A 2-Rail Sweep surface is similar to a 1-Rail sweep. The additional rail gives you more control over the shape of the surface. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the number of cross-section curves used. - - - - - Adds a curve to the end of the list of cross-section curves by specifying the index in the . - Parameters: - int index - - The index in the of the cross-section curve to append. - - BOOL flip - - TRUE to reverse (or flip) the direction of the curve; FALSE to use the non-reversed orientation. - The number of cross-section curves prior to appending. - - - - - Adds a curve to the end of the list of cross-section curves by specifying a NURBSId. - Parameters: - NURBSId id - - Specifies the cross-section curve to append. - - BOOL flip - - TRUE to reverse (or flip) the direction of the curve; FALSE to use the non-reversed orientation. - The number of cross-section curves prior to appending. - - - - - Specifies the curve to use as a cross-section via its index in the . - Parameters: - int pnum - - The zero based index of the curve to set. - - int index - - The index in the of the curve. - - - - - Specifies the curve to use as a cross-section via its NURBSId. - Parameters: - int pnum - - The zero based index of the curve to set. - - NURBSId id - - The id of the curve. - - - - - Returns the index in the of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve to get. - - - - - Returns the NURBSId of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve to get. - - - - - Sets the reversed (or flipped) state of the specified cross-section curve. - Parameters: - int pnum - - The zero based index of the curve. - - BOOL flip - - TRUE to reverse the direction; FALSE for the normal direction. - - - - - Returns the reversed (or flipped) state of the specified cross-section curve. TRUE is reversed; FALSE is not. - Parameters: - int pnum - - The zero based index of the curve. - - - - - Returns the state of the parallel flag. - - - - - Returns TRUE if the cross section curves are scaled uniformly; FALSE for non-uniformly. - - - - - Returns TRUE if snap cross sections is on; otherwise FALSE. - - - - - Specifies the index in the of the first or second rail curve to use. - Parameters: - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - - int index - - The index in the of the curve to use as a rail. - - - - - Specifies the NURBSId of the first or second rail curve to use. - Parameters: - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - - NURBSId id - - The id of the curve to use as a rail. - - - - - Returns the index in the of the specified parent rail curve. - Parameters: - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - - - - - Returns the NURBSId of the specified parent rail curve. - Parameters: - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - - - - - Sets the start point for the specified parent curve at the time passed. - Parameters: - TimeValue t - - The time at which to set the start point. - - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - - double startpoint - - The start point in the range of 0.0 to 1.0. - - - - - Returns the start point for the specified parent curve at the time passed. - Parameters: - TimeValue t - - The time at which to get the start point. - - int pnum - - Pass 0 for the first rail curve; 1 for the second rail curve. - Operators: - - - - - Description: - This class defines a dependent blend curve. A blend curve connects the specified end of one curve to the specified end of another, blending the curvature of the parents to create a smooth curve between them. Methods are available to get/set the parent indices and ids, to get/set the ends of the curves used for the blend, and to get/set the tension values used. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index into the of the parent object. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Sets if the beginning or end of the specified curve is used for the blend. - Parameters: - int pnum - - The parent number: 0 or 1. - - BOOL end - - TRUE to use the end of the curve; FALSE to use the beginning. The beginning of the curve has lesser parameter values than the end. - - - - - Indicates if the beginning or end of the specified curve is used for the blend. - Parameters: - int pnum - - The parent number: 0 or 1. - TRUE if the end of the curve is used; FALSE if the beginning is used. - - - - - Sets the tension value for the specified parent curve. - Parameters: - TimeValue t - - The time at which to set the tension - - int pnum - - The parent number: 0 or 1. - - double ten - - The tension value to set. - - - - - Returns the tension value for the specified parent curve. - Parameters: - TimeValue t - - The time at which to get the tension - - int pnum - - The parent number: 0 or 1. - Operators: - - - - - Description: - This class defines a dependent blend surface. A blend surface connects the edge of one surface to the edge of another, blending the curvature of the parents to create a smooth surface between them. Methods are available to get/set the parents, parent Ids, tension parameters and surface normal matching state. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index into the of the parent surface. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Sets which edge of the specified surface is used for the blend. - Parameters: - int pnum - - The parent number: 0 or 1. - - int edge - - One of the following values: - - 0: The low U edge. - - 1: The high U edge. - - 2: The low V edge. - - 3: The high V edge. - - - - - Returns an integer that determines which edge of the specified surface is used for the blend. - Parameters: - int pnum - - The parent number: 0 or 1. - One of the following values: - - 0: The low U edge. - - 1: The high U edge. - - 2: The low V edge. - - 3: The high V edge. - - - - - Sets the tension value for the specified parent surface. - Parameters: - TimeValue t - - The time at which to set the tension value. - - int pnum - - The parent number: 0 or 1. - - double ten - - The tension value to set. - - - - - Returns the tension value for the specified parent surface. - Parameters: - TimeValue t - - The time at which to return the tension value. - - int pnum - - The parent number: 0 or 1. - - - - - This allows one to control the matching of parent surface normals when creating the blend surface. For example, normally when you create a blend surface between two parent surfaces you don't want a 'bow tie' surface (one with the ends rotated 180 degrees so it crosses on itself in the middle). If you simply match the parent normals you'll occasionally get a 'bow tie' surface. To prevent this you use this method to set a state indicating that one or the other should be flipped before it's used. In this way, when the blend is created, a 'bow tie' won't occur. - Parameters: - int pnum - - The number of the parent surface: 0 or 1. - - BOOL flip - - TRUE to match the parent surface normal; FALSE to not match it. - - - - - Returns the flip state of the specified parent surface. - Parameters: - int pnum - - The number of the parent surface: 0 or 1. - - - - - Sets the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to set the start point. - - int pnum - - The number of the parent surface: 0 or 1. - - double startpoint - - The start point in the range 0.0 to 1.0. - - - - - Returns the start point of the specified parent curve. - - Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to get the start point. - - int pnum - - The number of the parent surface: 0 or 1. - Operators: - - - - - Description: - This class provides access to the Cap Surface. A Cap Surface is a surface that caps a closed curve or the edge of a closed surface. Caps are especially useful with extruded surfaces. - protected: - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the curve or surface that's capped. - - - - - Returns the NURBSId of the curve or surface that's capped. - - - - - Returns the edge of the closed parent surface is capped. - One of the following values: - - 0: The low U edge. - - 1: The high U edge. - - 2: The low V edge. - - 3: The high V edge. - - - - - Sets the start point for the curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time to set the start point. - - double startpoint - - The start point to set. - - - - - Returns the start point for the curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time to get the start point. - - - - - Description: - This class defines a dependent chamfer curve. A chamfer is a curve that creates a straight line corner between two parent curves. Methods are availalble to get/set the parent indices and ids, to get/set which ends of the curves are used for the chamfer, get/set the trim settings for each curve, and to get/set the length of the curve back from the selected end that represents the start of the chamfer. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index into the of the parent object. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Sets which end of the specified curve is used for the chamfer. - Parameters: - int pnum - - The parent number: 0 or 1. - - BOOL end - - TRUE to use the end of the curve; FALSE to use the beginning. - - - - - Returns which end of the specified curve is used for the chamfer. TRUE if the end of the curve is used; FALSE if the beginning is used. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - - - - Sets the length for the specified parent curve back from the end that defines the beginning of the chamfer, at the specified time. - Parameters: - TimeValue t - - The time at which to set the chamfer length. - - int pnum - - The parent curve number: 0 or 1. - - double length - - The chamfer length to set. - - - - - Returns the length of the chamfer at the specified time. - Parameters: - TimeValue t - - The time at which to return the chamfer length. - - int pnum - - The parent curve number: 0 or 1. - - - - - Determines if the specified curve is trimmed beyond the fillet. TRUE if the curve is trimmed; otherwise FALSE. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - - - - Sets if the specified curve is trimmed beyond the chamfer. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL trim - - TRUE to trim the curve beyond the chamfer; otherwise FALSE. - - - - - Returns the flip state for the specified curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - TRUE if flip is set; FALSE it not. - - - - - Sets the flip state for the specified curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL flip - - TRUE to flip; FALSE to not flip. - Operators: - - - - - Description: - This class represents a control vertex in a NURBS curve. Methods are available to get and set the point position, and get/set the weight. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & cv - - The control vertex to assign. - - - - - Equality operator. Compares if the coordinates and weight are the same. - Parameters: - & cv - - The control vertex to compare. - TRUE if the CVs are equal; otherwise FALSE. - - - - - Sets the position of the control vertex. - Parameters: - TimeValue t - - The time to set the position. - - pt - - Specifies the position to set. - - - - - Sets the position of the control vertex. - Parameters: - TimeValue t - - The time to set the position. - - float x, float y, float z - - Specifies the position to set. - - - - - Sets the position of the control vertex. - Parameters: - TimeValue t - - The time to set the position. - - double x, double y, double z - - Specifies the position to set. - - - - - Returns the position of the control vertex. - Parameters: - TimeValue t - - The time to get the position. - - - - - Retrieves the position of the control vertex. - Parameters: - TimeValue t - - The time to get the position. - - float& x - - The X coordinates is returned here. - - float& y - - The Y coordinates is returned here. - - float& z - - The Z coordinates is returned here. - - - - - Retrieves the position of the control vertex. - Parameters: - TimeValue t - - The time to get the position. - - double& x - - The X coordinates is returned here. - - double& y - - The Y coordinates is returned here. - - double& z - - The Z coordinates is returned here. - - - - - Sets the weight of the control vertex. - Parameters: - TimeValue t - - The time to set the weight. - - float wt - - Specifies the weight to set. This is a value greater than zero. Larger values cause the CV to have a greater effect, thus the curve or surface will try to pass closer to the CV. - - - - - Sets the weight of the control vertex. - Parameters: - TimeValue t - - The time to set the weight. - - double wt - - Specifies the weight to set. . This is a value greater than zero. Larger values cause the CV to have a greater effect, thus the curve or surface will try to pass closer to the CV. - - - - - Retrieves the weight of the control vertex. - Parameters: - TimeValue t - - The time to get the weight. - - float& wt - - The weight is returned here. - - - - - Returns the weight of the control vertex. - Parameters: - TimeValue t - - The time to get the weight. - - - - - Retrieves the weight of the control vertex. - Parameters: - TimeValue t - - The time to get the weight. - - double& wt - - The weight is returned here. - Operators: - - - - - Description: - This class describes the properties of a NURBS curve. This includes its number of trim points and its open/closed state. The Evaluate() method is used to compute points on the curve. - - All methods of this class are implemented by the system. - Data Members: - protected: - - int mMatID; - - This data member is available in release 3.0 and later only. - - The material ID for the curve. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns TRUE if the curve is closed; otherwise FALSE. - - - - - Returns the number of trim points in the curve. - - - - - Returns the 'i-th' trim point. - Parameters: - TimeValue t - - The time to retrieve the trim point. - - int i - - The zero based index of the trim point to return. - - - - - Retrieves the point along the curve at the specified point and the tangent at that point. - Parameters: - TimeValue t - - The time to evaluate the curve. - - double u - - Specifies the point along the curve to evaluate. This value must be between the uMin and uMax as returned from GetParameterRange(). - - & pt - - The point along the curve is returned here. - - & tangent - - The tangent at the specified point is returned here. - TRUE if the method was able to evaluate the curve; otherwise FALSE. - - - - - Retrieves the minimum and maximum valid values for u as passed to Evaluate(). - Parameters: - TimeValue t - - The time to get the parameter range of the curve. - - double& uMin - - The minimum value is returned here. - - double& uMax - - The maximum value is returned here. - - - - - Retrieves data about the at the specified time. - Parameters: - TimeValue t - - The time at which to get the NURBS information. - - int& degree - - The degree of the curve. - - int& numCVs - - The number of CVs. - - NURBSCVTab& cvs - - The table of CVs. Note: > NURBSCVTab; - - int& numKnots - - The number of knots. - - NURBSKnotTab knots - - A table of knots in U. Note: <double> NURBSKnotTab; - TRUE if the data was retrieved; otherwise FALSE. - - - - - Returns the material ID for the curve. - - - - - Description: - This class is used to create a dependent point that lies on a curve or relative to it. - - The point can either be on the curve or off the curve. If it is on the curve, the U Position is the only control of its location. The U Position specifies a location along the curve (based on the curve's local U axis). There are three ways to displace the point's location relative to the U position: - - Offset moves the point according to a relative (object space) X,Y,Z location. - - Normal moves the point along the direction of the curve's normal. (Negative values move it opposite to the normal.) - - U Position - - Tangent moves the point along the tangent of the U Position. - - All methods of this class are implemented by the system. - Data Members: - protected: - - NURBSId mParentId; - - The NURBSId of the parent curve. - - int mParentIndex; - - The index in the of the parent curve. - - NURBSConstType mCType; - - The type of constraint in use. - - mOffset; - - The offset amount. - - float mNormal; - - The distance along the normal. - - float mUTangent; - - The distance along the tangent. - - double mUParam; - - Specifies the point along the parent curve. - - BOOL mTrimCurve; - - The point that is constrained to the curve may be used to trim the curve. - - BOOL mFlipTrim; - - If TRUE the curve is trimmed from the point towards low parameter space. If FALSE the curve is trimmed from the point towards high parameter space. - - - - - Assignment operator. - Parameters: - & pt - - The point to assign. - - - - - Returns the parent index. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the point type. See NURBSConst Types. - - - - - Sets the offset value at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the offset value is set. - - pt - - The offset to set in object space. - - - - - Returns the offset value in object space at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the offset value is returned. - - - - - Sets the U Parameter for the point. - Parameters: - TimeValue t - - Specifies the time at which the value is set. - - double param - - The U parameter to set. - - - - - Returns the U parameter at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the value is returned. - - - - - Sets the normal distance at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the value is set. - - float dist - - The distance to set. - - - - - Returns the distance along the normal at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the value is returned. - - - - - the U tangent value at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the value is set. - - float dist - - The distance to set. - - - - - Returns the U tangent value at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the value is returned. - - - - - Returns TRUE if this point is used to trim the curve and FALSE if it is not. - - - - - Returns the state of the flip trim boolean. - - - - - Description: - This class is used to create a dependent point at the intersection of two curves. - - All methods of this class are implemented by the system. - Data Members: - protected: - - NURBSId mParentId[2]; - - The ids of the two parent curves. - - int mParentIndex[2]; - - The indicies of the two parent curves in the . - - BOOL mTrimCurve[2]; - - Indicates the point that is constrained to the curve may be used to trim the curve. - - BOOL mFlipTrim[2]; - - If TRUE the curve is trimmed from the point towards low parameter space. If FALSE the curve is trimmed from the point towards high parameter space. - - - - - Assignment operator. - Parameters: - &pt - - The intersection point to assign. - - - - - Returns the point in parameter space of the specified curve of the point of intersection. - Parameters: - int curveNum - - The parent curve number: 0 or 1. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index into the of the parent surface. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns TRUE if this point is used to trim the specified curve and FALSE if it is not. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - - - - Sets the trim curve boolean for the specified curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL trim - - TRUE to indicate this point is used to trim the curve; FALSE to indicate the curve is not trimmed beyond the point. - - - - - Returns the state of the flip trim boolean. - Parameters: - int pnum - - The parent curve number: 0 or 1. - TRUE indicates the specified curve is trimmed from the point towards low parameter space. FALSE indicates the curve is trimmed from the point towards high parameter space. - - - - - Sets the state of the flip trim boolean for the specified parent curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL flip - - TRUE to indicate the curve is trimmed from the point towards low parameter space. Use FALSE to indicate the curve is trimmed from the point towards high parameter space. - Operators: - - - - - Description: - This class provides access to the CV curve on surface parameters. These curves can be used for trimming the surface they lie on. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the specified parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the state of the trim surface toggle. - - - - - Returns the state of the trim flip toggle. - - - - - Description: - This class is used to create a dependent point at the intersection of a curve and a surface. - Data Members: - protected: - - NURBSId mParentId[2]; - - The NURBSIds of the parent surface and curve. Parent 0 should be the surface parent 1 should be the curve. - - int mParentIndex[2]; - - The indexes of the parent surface and curve. Parent 0 should be the surface parent 1 should be the curve. - - double mSeed; - - The seed location is a U position along the length of the parent curve. - - BOOL mTrimCurve; - - The trim curve flag. - - BOOL mFlipTrim; - - The trim flip flag. - - - - - Assignment operator. - Parameters: - &pt - - The point to assign. - - - - - Returns the seed value. - - - - - Establishes the curve or surface used by specifying its index in the . - Parameters: - int pnum - - Pass 0 for the surface; 1 for the curve. - - int index - - The index in the of the curve or surface. - - - - - Establishes the curve or surface used by specifying its NURBSId. - Parameters: - int pnum - - Pass 0 for the surface; 1 for the curve. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the parent curve or surface. - Parameters: - int pnum - - Pass 0 for the surface; 1 for the curve. - - - - - Returns the NURBSId of the parent curve or surface. - Parameters: - int pnum - - Pass 0 for the surface; 1 for the curve. - - - - - Returns the state of the trim curve flag. TRUE causes trimming; FALSE does not. - - - - - Returns the state of the trim flip flag. TRUE for flipped; FALSE for not flipped. - - - - - Description: - This class defines a NURBS CV Curve. CV Curves have control vertices. The position of the control vertices (CVs) controls the shape of the curve. Unlike spline vertices, CVs don't necessarily lie on the curve they define. The CVs define a control lattice which surrounds the NURBS curve. - - All methods of this class are implemented by the system. - Data Members: - protected: - - *mpCVs; - - of control vertices. - - double *mpKnots; - - of knots. - - BOOL mClosed; - - TRUE if the curve is closed; otherwise FALSE. - - int mOrder; - - The order of the curve. - - int mNumKnots; - - The number of knots. - - int mNumCVs; - - The number of control verticies. - - NURBSAutoParam mAutoParam; - - This data member is available in release 3.0 and later only. - - Controls automatic reparameterization. See NURBSAutoParam Types. - - - - - Assignment operator. - Parameters: - & curve - - The to assign. - - - - - Closes the curve. - - - - - Returns the order of the curve. - - - - - Returns the number of knots in the curve. - - - - - Retrieves the number of control vertices. - Parameters: - int& num - - The number is stored here. - - - - - Returns the number of control vertices. - - - - - Returns the knot value whose index is passed. - Parameters: - int index - - Specifies which knot value to return. - - - - - Sets the specified knot to the specified value. - Parameters: - int index - - The 0 based index of the knot to set. - - double value - - Specifies the value to set. - - - - - Returns a pointer to the specified control vertex of the curve. - Parameters: - int index - - The 0 based index of the control vertex to return. - - - - - Sets the specified control vertex to the CV passed. - Parameters: - int index - - The 0 based index of the control vertex to set. - - &cv - - The CV to set. - - - - - Sets the transformation matrix for the . This controls the relative position of the item within a . - Parameters: - TimeValue t - - The time at which to set the matrix. - - & xPack - - An instance of the XFormPacket class that describes the properties of the transformation. See Class . - - - - - Returns the transformation matrix of the at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the matrix. - - - - - Returns the current settings for automatic reparameterization. See NURBSAutoParam Types. - - - - - Sets the automatic reparameterization settings at the specified time. - Parameters: - TimeValue t - - The time to set them. - - NURBSAutoParam param - - The settings to establish. See NURBSAutoParam Types. - - - - - This method reparameterizes this CV sub-object. This can be used to provide a better relation between control point locations and the shape of the sub-object. - Parameters: - TimeValue t - - The time to reparameterize. - - NURBSParamaterization param - - The type of reparameterizing to perform. See NURBSMirrorAxis Types. - - - - - This method determines if the ends of the curve overlap even though the curve may not be closed (that is, the tangents match at the ends). - Parameters: - BOOL& overlap - - The result is returned here: TRUE if the ends overlap; otherwise FALSE. - - - - - By specifying a parameter point on the curve, this method adds a new control vertex to the curve. It moves all the other CVs but maintains the shape of the curve. Note that this causes the loss of any animation on the curve. - Parameters: - TimeValue t - - The time at which to refine the curve. If the curve is animated the u parameter below is time dependent. - - double u - - Specifies the distance along the curve to add the CV. See the base class method GetParameterRange() for the valid range of values for this parameter. - - - - - This method places a new CV along the current CV hull at the specified parameter point. This method leaves all the other CVs in place and changes the shape of the curve. This method preserves animation. - Parameters: - TimeValue t - - The time at which to refine the curve. If the curve is animated the u parameter below is time dependent. - - double u - - Specifies the distance along the curve to add the CV. See the base class method GetParameterRange() for the valid range of values for this parameter. - Operators: - - - - - Description: - This class defines a surface that uses control vertices (CVs) to describe its shape. The CVs define a control lattice which surrounds the surface. This class has methods to close the surface in U and V, set its order in U and V, set the number of knots and CVs in U and V, and get/set the knots and CVs in U and V. There is also a method to add additional CVs to the surface. The CV surface has a transformation matrix used to position the surface within a . - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The CV surface to assign. - - - - - Returns TRUE if the surface is 'rigid'; otherwise FALSE. - - - - - Sets the 'rigid' state of the surface. - Parameters: - BOOL isRigid - - TRUE for on; FALSE for off. - - - - - Returns the automatic parameterization setting. See NURBSAutoParam Types. - - - - - Sets the automatic parameterization setting at the specified time. - Parameters: - TimeValue t - - The time at which to set the parameterization. - - NURBSAutoParam param - - See NURBSAutoParam Types. - - - - - Sets the reparameterization type at the specified time. - Parameters: - TimeValue t - - The time at which to sets the reparameterization type. - - NURBSParamaterization param - - See nurbParameterizationTypes. - - - - - This method closes the surface in the U direction. The aligns the surface edge to edge in U and sets the tangents to match. - - - - - This method closes the surface in the V direction. The aligns the surface edge to edge in V and sets the tangents to match. - - - - - Returns the order of the surface in the U direction. - - - - - Returns the order of the surface in the V direction. - - - - - Returns the number of knots in the U direction. - - - - - Returns the number of knots in the V direction. - - - - - Sets the number of control vertices in both the U and V directions. Note that the CV data is not maintained. - Parameters: - int u - - Specifies the number of control vertices in the U direction. - - int v - - Specifies the number of control vertices in the V direction. - - - - - Returns the number of control vertices in the U direction. - - - - - Returns the number of control vertices in the V direction. - - - - - Returns the number of control vertices in both the U and V directions. - Parameters: - int &u - - The number of CVs in the U direction is returned here. - - int &v - - The number of CVs in the V direction is returned here. - - - - - Returns the specified knot value in the U direction. - Parameters: - int index - - The 0 based index of the knot value to return. - - - - - Returns the specified knot value in the V direction. - Parameters: - int index - - The 0 based index of the knot value to return. - - - - - Sets the specified knot in the U direction to the specified value. - Parameters: - int index - - The 0 based index of the knot value to set. - - double value - - The value to set. - - - - - Sets the specified knot in the U direction to the specified value. - Parameters: - int index - - The 0 based index of the knot value to set. - - double value - - The value to set. - - - - - Returns the specified control vertex of this surface. - Parameters: - int u - - The 0 based index in the U direction. - - int v - - The 0 based index in the V direction. - - - - - Sets the specified control vertex. - Parameters: - int u - - The 0 based index in the U direction. - - int v - - The 0 based index in the V direction. - - &cv - - The control vertex to set. - - - - - Sets the transformation matrix for the . This matrix controls the relative position of the surface within a . - Parameters: - TimeValue t - - The time at which to set the matrix. - - & xPack - - An instance of the XFormPacket class that describes the properties of the transformation (specifically if it's being moved, rotated, or scaled). See Class . - - - - - Returns the transformation matrix of the at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the matrix. - - - - - This method determines if the edges of the surface overlap in U and/or V even though the surface may not be closed (that is, the tangents match at the edges). - Parameters: - BOOL& uOverlap - - The U result is returned here: TRUE if the edges overlap in U; otherwise FALSE. - - BOOL& vOverlap - - The V result is returned here: TRUE if the edges overlap in V; otherwise FALSE. - - - - - This method adds a control vertex at the specified point on the surface without changing the shape of the surface. The other CV points will move to maintain the current shape. The point may be specified as a U value or a V value, or both. - - If you refine in U (U_V_Both = 0) you must specify v - - If you refine in V (U_V_Both = 1) you must specify u - - If you refine in U and V (U_V_Both = -1) you must specify u and v - Parameters: - TimeValue t - - The time at which to refine the surface. - - double u - - The position for the point in U space. - - double v - - The position for the point in V space. - - int U_V_Both - - This value must be 0, 1 or -1. - - If 0 the refinement is done in u (and v is specified). - - If 1 the refinement is done in v (and u is specified). - - If -1 the refinement is done in both u and v (and both u and v must be specified). - - - - - This method adds a new CV to the surface and changes its shape. The other CVs will not move as they do in Refine(). This method preserves any existing animation of the surface. - Parameters: - TimeValue t - - The time at which to refine the surface. - - double u - - The position for the point in U space. - - double v - - The position for the point in V space. - - int U_V_Both - - This value must be 0, 1 or -1. - - If 0 the refinement is done in u (and v is specified). - - If 1 the refinement is done in v (and u is specified). - - If -1 the refinement is done in both u and v (and both u and v must be specified). - Operators: - - - - - Description: - This class provides information about the display of the in the 3D viewports. An instance of this class is maintained by each . - Data Members: - BOOL mDisplayCurves; - - TRUE if curves are displayed; otherwise FALSE. - - BOOL mDisplaySurfaces; - - TRUE if surfaces are displayed; otherwise FALSE. - - BOOL mDisplayLattices; - - TRUE if lattices are displayed; otherwise FALSE. - - BOOL mDisplaySurfCVLattices; - - TRUE if surface CV lattices are displayed; otherwise FALSE. - - BOOL mDisplayCurveCVLattices; - - TRUE if curve CV lattices are displayed; otherwise FALSE. - - BOOL mDisplayDependents; - - TRUE if dependent sub-objects are displayed; otherwise FALSE. - - BOOL mDisplayTrimming; - - TRUE if surface trimming is displayed; otherwise FALSE. - - BOOL mDegradeOnMove; - - TRUE if the surface may degrade while transforming it; otherwise FALSE. - - - - - Assignment operator. - Parameters: - & disp - - The object to assign. - - - - - Description: - This class defines a dependent extrude surface. An extrude surface is extruded from a curve sub-object. It is similar to a surface created with the Extrude modifier. The advantage is that an extrude sub-object is part of the NURBS model, so you can use it to construct other curve and surface sub-objects. Methods are available to get/set the parent index and id, get/set the extrusion vector and get/set the extrusion distance. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Sets the extrusion axis at the specified time. - Parameters: - TimeValue t - - The time at which to set the axis system. - - & ray - - The extrusion axis. - - - - - Returns the extrusion axis at the specified time. - Parameters: - TimeValue t - - The time at which to get the axis. - - - - - Sets the length of the extrudion at the specified time. - Parameters: - TimeValue t - - The time at which to set the distance. - - double d - - The distance to set. - - - - - Returns the length of the extrudion at the specified time. - Parameters: - TimeValue t - - The time at which to return the distance. - - - - - Sets the start point at the specified time. - Parameters: - TimeValue t - - The time at which to set the start point. - - double startpoint - - The start point in the range 0.0 to 1.0. - - - - - Returns the start point at the specified time. - Parameters: - TimeValue t - - The time at which to get the start point. - Operators: - - - - - Description: - This class defines a dependent fillet curve. A fillet is a curve that creates a circular arc corner between two parent curves. Methods are available to get/set the parent indices and ids, get/set the trim state of the curves, get/set which ends of the curves are used, and get/set the radius of the fillet. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index into the of the parent curve. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Parameters: - int pnum - - The parent number: 0 or 1. - - BOOL end - - TRUE to use the end of the curve; FALSE to use the beginning. - - - - - Returns which end of the specified curve is used for the fillet. TRUE if the end of the curve is used; FALSE if the beginning is used. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - - - - Sets the radius for the fillet at the specified time. - Parameters: - TimeValue t - - The time at which to set the radius value. - - double radius - - The radius to set. - - - - - Returns the radius of the fillet at the specified time. - Parameters: - TimeValue t - - The time to return the fillet value. - - - - - Determines if the specified curve is trimmed beyond the fillet. TRUE if the curve is trimmed; otherwise FALSE. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - - - - Sets if the specified curve is trimmed beyond the fillet. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL trim - - TRUE to trim the curve beyond the fillet; otherwise FALSE. - - - - - Returns the flip state for the specified curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - TRUE if flip is set; FALSE it not. - - - - - Sets the flip state for the specified curve. - Parameters: - int pnum - - The parent curve number: 0 or 1. - - BOOL flip - - TRUE to flip; FALSE to not flip. - Operators: - - - - - Description: - This class provides access to the NURBS Fillet Surface. Methods are provided to get / set the parent surfaces, get / set the radius, and get / set the trim and trim flip settings. - protected: - - - - - Assignment operator. - Parameters: - & curve - - The surface to assign. - - - - - Sets the specified parent surface (by index) for the fillet. - Parameters: - int pnum - - The parent surface: 0 or 1. - - int index - - The index in the . - - - - - Sets the specified parent surface (by NURBSId) for the fillet. - Parameters: - int pnum - - The parent surface: 0 or 1. - - NURBSId id - - The ID of the surface. - - - - - Returns the index in the of the specified parent surface. - Parameters: - int pnum - - The parent surface: 0 or 1. - - - - - Returns the NURBSId of the specified parent surface. - Parameters: - int pnum - - The parent surface: 0 or 1. - - - - - Returns the UV location of the seed value on the specified surface. - Parameters: - int pnum - - The parent surface: 0 or 1. - - - - - Sets the UV location of the seed value on the specified surface. - Parameters: - int pnum - - The parent surface: 0 or 1. - - & seed - - The seed value to set. - - - - - Returns TRUE if the cubic setting is on; FALSE if off. When off, the radius is always linear. When on, the radius is treated as a cubic function, allowing it to change based on the parent surface's geometry. - - - - - Sets the cubic setting to on or off. - Parameters: - BOOL cubic - - TRUE for on; FALSE for off. - - - - - Returns the specified radius at the time passed. - Parameters: - TimeValue t - - The time at which to get the radius. - - int rnum - - Specifies which radius to get: 0 for start, 1 for end. - - - - - Sets the specified radius at the time passed. - Parameters: - TimeValue t - - The time at which to set the radius. - - int rnum - - Specifies which radius to set: 0 for start, 1 for end. - - float radius - - The radius to set. - - - - - Returns the trim surface setting for the specified parent surface. TRUE if on (trims the parent surface at the edge of the fillet); FALSE if off. - Parameters: - int pnum - - The parent surface: 0 or 1. - - - - - Sets the trim surface setting for the specified parent surface. - Parameters: - int pnum - - The parent surface: 0 or 1. - - BOOL trim - - TRUE for on (trims the parent surface at the edge of the fillet); FALSE for off. - - - - - Returns the state of the trim flip setting. When set this reverses the direction of the trim. - Parameters: - int pnum - - The parent surface: 0 or 1. - - - - - Sets the state of the trim flip setting. When set this reverses the direction of the trim. - Parameters: - int pnum - - The parent surface: 0 or 1. - - BOOL flip - - TRUE for on; FALSE for off. - - - - - Description: - used with a to fuse two CVs in a curve. This causes the CVs to reference one another so if you move one the other moves with it. - - All methods of this class are implemented by the system. - Data Members: - int mCurve1, mCurve2; - - The zero based indices of the curves to fuse. These may be the same value. Note that this is not the index in the of these items. Rather it is the index of CV curve in list of CV curves in the . For instance, if there were first two CV surfaces and then two CV curves in the , mCurve1 would be 0 and mCurve2 would be 1 since the CV surfaces don't count. - - int mCV1, mCV2; - - The indices of the CVs of curve1 and curve2 to fuse. - - - - - Description: - This class may be used with a to fuse two CVs in a surface. This causes the CVs to reference one another so if you move one the other moves with it. - - All methods of this class are implemented by the system. - Data Members: - int mSurf1, mSurf2; - - The zero based indices of the surfaces to fuse. These may be the same value. Note that this is not the index in the of these items. Rather it is the index of CV surface in list of CV surfaces in the . For instance, if there were first two CV curves and then two CV surfaces in the , mSurf1 would be 0 and mSurf2 would be 1 since the CV curves don't count. - - int mRow1, mCol1, mRow2, mCol2; - - The indices of the row and column CVs of surface 1 and surface 2 to fuse. - - - - - - Description: - This class is used to create an independent, free-standing point. There are methods to set the position of the point in various floating point formats and operators to compare points. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & pt - - The point to assign. - - - - - Equality operator. Compares if the X, Y and Z coordinates are equal. - Parameters: - & pt - - The point to compare. - TRUE if equal; otherwise FALSE. - - - - - Sets the position of the point at the specified time (as a ). - Parameters: - TimeValue t - - Specifies the time to set the position. - - pt - - The position to set. - - - - - Sets the position of the point at the specified time (as floats). - Parameters: - TimeValue t - - Specifies the time to set the position. - - float x - - The X position to set. - - float y - - The Y position to set. - - float z - - The Z position to set. - - - - - Sets the position of the point at the specified time (as doubles). - Parameters: - TimeValue t - - Specifies the time to set the position. - - double x - - The X position to set. - - double y - - The Y position to set. - - double z - - The Z position to set. - Operators: - - - - - Description: - This class defines a dependent iso curve. U and V iso curves are dependent curves created along lines of constant parameter value of a NURBS surface. Note the difference between "Iso Lines", which are a display artifact, and "IsoCurves" which are the dependent objects. There are methods available to get/set the parent surface index and id, get/set the direction of the iso curve, and get/set the parameter which determines the location on the surface the curve matches. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns TRUE if the iso curve is in the U direction; FALSE for the V direction. - - - - - Sets the parameter which determines where on the surface the iso curve is defined. - Parameters: - TimeValue t - - The time at which to evaluate the surface. - - double p - - The parameter defining the location on the surface. - - - - - Returns the parameter which determines where on the surface the iso curve is defined. - Parameters: - TimeValue t - - The time at which to evaluate the surface. - - - - - Returns the state of the trim flag. When set the surface is trimmed against the curve. When not set, the surface isn't trimmed - - - - - Returns the state of the trim flip flag. When set this trims the surface in the opposite direction - - - - - Returns the UV location of the seed value on the curve. - - - - - Description: - This class defines a dependent lathe surface. A lathe surface is generated from a curve sub-object. It is similar to a surface created with the Lathe modifier. The advantage is that a lathe sub-object is part of the NURBS model, so you can use it to construct other curve and surface sub-objects. Methods are available to get/set the parent index and id, get/set the axis and amount rotation of the lathe. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the specified parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - - - - - Sets the axis to use for the surface of revolution by specifying a time and a axis system. - Parameters: - TimeValue t - - The time at which the axis is set. - - & ray - - Specifies the axis for revolution. See Class . - - - - - Returns the axis system for the surface of revolution. - Parameters: - TimeValue t - - The time at which to return the axis. - - - - - Sets the amount of rotation for the surface. - Parameters: - TimeValue t - - The time at which to set the amount. - - double degrees - - The angle of the revolution in degrees. - - - - - Returns the angle of the revolution in degrees. - Parameters: - TimeValue t - - The time at which to return the angle. - - - - - Sets the start point at the specified time. - Parameters: - TimeValue t - - The time at which to set the start point. - - double startpoint - - The start point to set in the range 0.0 to 1.0. - - - - - Returns the start point at the specified time. - Parameters: - TimeValue t - - The time at which to get the start point. - Operators: - - - - - Description: - This class defines a dependent mirror curve. A mirror curve is similar to a mirror object that you create using the Mirror tool (on the 3ds Max toolbar) or the Mirror modifier. It is the original curve relfected about one or two axes. Methods are available to get/set the parent index and id, to get/set the reflection axis, and to get/set the offset distance. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - - - - - Returns the axis or axes of reflection for the curve. - - - - - This is an additional transformation applied to the axis specification. This corresponds to the gizmo they user may use interactively to alter the location of the mirror axis. This is exactly equivalent to setting the transform on the gizmo of a mirror modifier. - Parameters: - TimeValue t - - The time at which to set the transformation. - - & mat - - The transformation to set. - - - - - Returns the additional transformation applied to the mirror axis at the specified time. - Parameters: - TimeValue t - - The time at which to get the transformation matrix. - - - - - Sets the offset distance of the curve. - Parameters: - TimeValue t - - The time at which to set the distance. - - double d - - The distance to set. - - - - - Returns the offset distance of the curve. - Parameters: - TimeValue t - - The time at which to get the distance. - Operators: - - - - - Description: - This class defines a dependent mirror surface. A mirror surface is similar to a mirror object that you create using the Mirror tool (on the 3ds Max toolbar) or the Mirror modifier. It is the original surface relfected about one or two axes. Methods are available to get/set the indices of the parent surface in the and the parent Ids, to get/set the mirror axes, to get/set the mirror distance, and to set the transformation used to position the surface in the . - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the axis or axes of reflection for the surface. - - - - - This is an additional transformation applied to the axis specification. This corresponds to the gizmo the user may use interactively to alter the location of the mirror axis. This is exactly equivalent to setting the transform on the gizmo of a mirror modifier. - Parameters: - TimeValue t - - The time at which to set the transformation. - - & mat - - The transformation to set. - - - - - Returns the additional transformation applied to the mirror axis at the specified time. - Parameters: - TimeValue t - - The time at which to get the transformation matrix. - - - - - This is just like the offset parameter in the mirror modifier. It is an offset from the center of the local coordinate system for the mirror object that moves the mirror, in the direction specified by the mirror axis. - Parameters: - TimeValue t - - The time at which to set the offset. - - double d - - The offset distance. - - - - - Returns the offset distance of the mirror at the specified time. - Parameters: - TimeValue t - - The time at which to return the offset. - Operators: - - - - - Description: - This class provides access to the Multicurve Trim Surface which is a surface that is trimmed by multiple curves forming a loop. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the number of curves used for the trim loop. - - - - - Adds the specified curve (using a index) to the end of the list of curves comprising the trim loop. - Parameters: - int index - - The index into the of the curve to add. - The number of curves in the loop prior to appending. - - - - - Adds the specified curve (using a index) to the end of the list of curves comprising the trim loop. - Parameters: - NURBSId id - - The id to use. - The number of curves in the loop prior to appending. - - - - - Sets the specified curve in the trim loop to the curve specified by an index into the . - Parameters: - int pnum - - Zero based index of which curve to set. - - int index - - The index into the of the curve to use. - - - - - Sets the specified curve in the trim loop to the curve specified by a NURBSId. - Parameters: - int pnum - - Zero based index of which curve to set. - - NURBSId id - - The id of the curve to use. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - Zero based index of which curve to get. - - - - - Returns the NURBSId of the specified curve in the trim loop. - Parameters: - int pnum - - Zero based index of which curve to get. - - - - - Returns the index in the of the surface that is trimmed. - - - - - Returns the NURBSId of the surface that's trimmed. - - - - - Returns the state of the flip trim flag. This controls which side of the curve is trimmed from the surface. - - - - - Description: - This class provides access to the Multisided Blend surface. A Multisided Blend surface is a surface that "fills in" the edges defined by three or four other curve or surfaces. Unliked a regular, two-sided Blend surface, the curves or surfaces edges must form a closed loop - that is, they must completely surround the opening the Multisided Blend will cover. - - Note: For the blend to work, the curves that define the blend must form a loop (that is, sequence head to tail, and the ends must match). - protected: - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Sets the specified parent curve or surface (by index) as the speciifed edge for the surface. - Parameters: - int pnum - - The index of the parent curve or surface to set. - - int index - - The index in the of the curve or surface. - - - - - Sets the specified parent curve or surface (by NURBSId) as the speciifed edge for the surface. - Parameters: - int pnum - - The index of the parent curve or surface to set. - - NURBSId id - - The id of the curve or surface to set. - - - - - Returns the index in the of the specified curve or surface. - Parameters: - int pnum - - The index of the parent curve or surface to get. - - - - - Returns the NURBSId of the specified curve or surface. - Parameters: - int pnum - - The index of the parent curve or surface to get. - - - - - If using a surface for the blend surface edge, this method indicates which edge on the surface to use. - Parameters: - int pnum - - The index of the parent surface. - - int edge - - The edge to use for the blend. One of the following values: - - 0: The low U edge. - - 1: The high U edge. - - 2: The low V edge. - - 3: The high V edge. - - - - - Returns the edge used by the specified surface to create the blend. - Parameters: - int pnum - - The index of the parent surface. - The edge used for the blend. One of the following values: - - 0: The low U edge. - - 1: The high U edge. - - 2: The low V edge. - - 3: The high V edge. - - - - - Description: - This is the base class for many of the other classes in the NURBS API. It provides a common set of methods that each of them use. It has methods to get and set the name of the item, and methods to deal with error processing. To determine the type of object the derived class is use the method GetType(). - - All methods of this class are implemented by the system. - Data Members: - protected: - - MCHAR mName[NURBS_NAME_SIZE]; - - The name of the NURBS object. The maximum length of this name including the terminating NULL is specified using the following #define: NURBSType mType; - - The type of NURBS object this is. See NURBSObject TypesNURBSKind mKind; - - The kind of NURBS object this is. See NURBSObject KindsNURBSId mId; - - This is the ID of the NURBS object used to specify the parent object in many of the dependent point, curves and surface classes. This ID is not persistant across sessions and should not be saved to a file. A NURBSId is defined as follows: typedef unsigned long NURBSId; - - *mpObject; - - When an object is instantiated in the 3ds Max scene this pointer is filled in. For example, if you use the function CreateNURBSObject() and pass a , this data member is filled in to point to the actual editable NURBS object in 3ds Max that this is a part of. - - NURBSSet* mpNSet; - - When an object is instantiated in the 3ds Max scene this pointer is filled in. This points to the this object is a contained within. - - BOOL mSelected; - - TRUE if the object is selected; otherwise FALSE. - protected: - - - - - Assignment operator. - Parameters: - & pt - - The to assign. - - - - - Returns a pointer to the name of the item. - - - - - Returns the specific type of object this is. See NURBSObject Types - - - - - Returns the specific kind of object this is. See NURBSObject Kinds. - - - - - Returns the NURBSId of this . This ID is not persistant across sessions and should not be saved to a file. - - - - - Sets the pointer to the 3ds Max editable NURBS object maintained by this object. - Parameters: - *object - - The pointer to set. - - - - - Returns a pointer to the maintained by this class. - - - - - Returns a pointer to the maintained by this class. - - - - - Returns the index in the of this object or -1 if there isn't an associated . - - - - - Returns TRUE if the object is selected; otherwise FALSE. - - - - - Sets the object to selected or not. - Parameters: - BOOL set - - TRUE to select the object; FALSE to de-select it. - Operators: - - - - - Description: - This class defines a dependent offset curve. An offset curve is offset from the original, parent curve. It lies in the same plane as its parent, and is normal to the original. Methods are available to get/set the parent index and id and to get/set the distance from the parent curve. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the specified parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - - - - - Sets the distance of the offset curve from the original in 3ds Max units at the specified time. - Parameters: - TimeValue t - - The time to set the offset distance. - - double d - - The distance to set. - - - - - Returns the distance of the offset curve from the parent at the specified time. - Parameters: - TimeValue t - - The time to get the offset distance. - Operators: - - - - - Description: - This class defines a dependent offset surface. An Offset surface is offset a specified distance from the original along the parent surface's normals. Methods are available to get/set the parent index and parent Ids, and to get/set the offset distance of the surface. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the parent surface. - - - - - Returns the NURBSId of the parent surface. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Sets the offset distance of the surface at the specified time. - Parameters: - TimeValue t - - The time at which to set the offset a value. - - double d - - A distance of the offset in 3ds Max units. - - - - - Returns the distance of the offset at the specified time. - Parameters: - TimeValue t - - The time at which to return the offset a value. - Operators: - - - - - Description: - This class describes a point in 3 space using double precision X, Y and Z coordinates. Methods are available for getting the point coordinates a floats, doubles or a . - - All methods of this class are implemented by the system. - Data Members: - protected: - - double mX, mY, mZ; - - The X, Y and Z coordinates for the point. - - - - - Returns the point position as a . - - - - - Retrieves the point position using single precision. - Parameters: - float& x - - The X coordinate is returned here. - - float& y - - The Ycoordinate is returned here. - - float& z - - The Z coordinate is returned here. - - - - - Retrieves the point position using double precision. - Parameters: - double& x - - The X coordinate is returned here. - - double& y - - The Ycoordinate is returned here. - - double& z - - The Z coordinate is returned here. - - - - - Description: - This class is used to create a dependent point that lies at a point or relative to it. - - All methods of this class are implemented by the system. - Data Members: - protected: - - NURBSId mParentId; - - The id of the parent object. - - int mParentIndex; - - The index in the of the parent object. - - NURBSConstType mCType; - - The type of constraint in use. - - mOffset; - - The offset from the object that the point is. - - - - - Assignment operator. - Parameters: - & pt - - The construction point to assign. - - - - - Returnst the parent index. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the type of construction point this is. See NURBSConst Types. - - - - - Sets the offset value at the specified time. - Parameters: - TimeValue t - - Specifies the time at which the offset is set. - - pt - - The offset value to set. This value is specified in object coordinates. - - - - - Returns the offset value at the specified time in object coordinates. - Parameters: - TimeValue t - - The time to retrieve the offset. - Operators: - - - - - Description: - This class defines a curve that uses points to describe its shape. All the points lie on the curve itself. There are methods to get/set the number of points in the curve, get/set the points themselves, refine the curve (add points without changing its shape), and to get/set the transformation matrix used by the curve. This matrix is used to set the postion of the curve in the . - - All methods of this class are implemented by the system. - Data Members: - protected: - - *mpPts; - - of independent points. - - BOOL mClosed; - - TRUE if the curve is closed; otherwise FALSE. - - int mNumPts; - - The number of independent points. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Closes the point curve. - - - - - Returns the number of points in the curve. - - - - - Retrieves the number of points in the curve. - Parameters: - int &num - - The result is stored here. - - - - - Returns a pointer to the specified point. - Parameters: - int index - - The zero based index of the point to get. - - - - - Sets the specified point in the curve. - Parameters: - int index - - The zero based index of the point to set. - - &pt - - The point to set. - - - - - Sets the transformation matrix for the . This controls the relative position of the item within a . - Parameters: - TimeValue t - - The time at which to set the matrix. - - & xPack - - An instance of the XFormPacket class that describes the properties of the transformation. See Class . - - - - - Returns the transformation matrix that controls the relative position of the point curve in the . - Parameters: - TimeValue t - - The time at which to return the matrix. - - - - - This method adds a new point at the specified location on the curve without changing its shape. The point is specified as a distance in U parameter space. Note that calling this method causes all animation of the curve to be removed. - Parameters: - TimeValue t - - The time at which to refine the curve. The curve may be animated, and thus the underlying parameter space may be changing. So when the u value is specified it must relate to the curve at a specific time. - - double u - - The point at which to refine the curve. Developers should use the method NURBSCurve::GetParameterRange() to get the valid range of values that may be passed here. - Operators: - - - - - Description: - This class provides access to the point curve on surface parameters. These curves can be used for trimming the surface they lie on. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the parent surface. - - - - - Returns the NURBSId of the parent surface. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the state of the trim toggle. - - - - - Returns the state of the trim flip toggle. - - - - - Description: - This class defines a surface that uses points to describe its shape. This class has methods to close the surface in U and V, set the number of points in U and V, and get/set the points in U and V. There is also a method to add additional points to the surface. The point surface has a transformation matrix used to set the relative position of the surface in a . - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - This method closes the surface in the U direction. - - - - - This method closes the surface in the V direction. - - - - - Sets the number of points in the surface in the U and V directions. Any previously allocated points are not maintained when the new number is set. Note, if any of the u and v parameters are 1 or less, the method will return and do nothing. - - The number of points in U. Valid values are 2 and higher. - The number of points in V. Valid values are 2 and higher. - - - - Returns the number of points in the U direction. - - - - - Returns the number of points in the V direction. - - - - - Retrieves the number of points in both the U and V directions. - Parameters: - int &u - - The number in U is stored here. - - int &v - - The number in V is stored here. - - - - - Returns a pointer to the specified point in the surface. - Parameters: - int u - - The zero based index of the point in the U direction. - - int v - - The zero based index of the point in the V direction. - - - - - Sets the specified point in the surface to the point passed. - Parameters: - int u - - The zero based index of the point in the U direction. - - int v - - The zero based index of the point in the V direction. - - & pt - - The point to set. - - - - - Sets the transformation matrix for the . This controls the relative position of the surface within a . - Parameters: - TimeValue t - - The time at which to set the matrix. - - & xPack - - An instance of the XFormPacket class that describes the properties of the transformation. See Class . - - - - - Returns the transformation matrix of the at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the matrix. - - - - - This method adds a new point at the specified location on the surface without changing the shape of the surface. The location may be specified as a U value or a V value, or both. - - If you refine in U (U_V_Both = 0) you must specify v - - If you refine in V (U_V_Both = 1) you must specify u - - If you refine in U and V (U_V_Both = -1) you must specify u and v - Parameters: - TimeValue t - - The time at which to refine the surface. - - double u - - The location for the point in U space (range 0.0 to 1.0). - - double v - - The location for the point in V space (range 0.0 to 1.0). - - int U_V_Both - - This value must be 0, 1 or -1. - - If 0 the refinement is done in u (and v is specified). - - If 1 the refinement is done in v (and u is specified). - - If -1 the refinement is done in both u and v (and both u and v must be specified). - Operators: - - - - - Description: - This is the base class for procedurally defined curves. Note that this is not subclassed from . You must use the GenNURBSCVCurveProcedurally() function. - - The following typedef-ed functions are used by the GenNURBSCVCurveProcedurally() function. - - - - - Description: - This is the base class for a proceedurally defined surface. Note: This class is not subclassed from . You must use the GenNURBSCVSurfaceProcedurally() function. - - The following typedef-ed functions are used by the GenNURBSCVSurfaceProcedurally() function. - - - - - Description: - This class provides access to the Normal Proejcted Curve. A Normal Projected curve lies on a surface. It is based on an existing curve, which is projected onto the surface in the direction of the surface's normals. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Sets the surface or curve used by specifying its index into the . - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - int index - - The index in the of the surface or curve. - - - - - Sets the surface or curve used by specifying its NURBSId. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - NURBSId id - - The id of the surface or curve. - - - - - Returns the index in the of the surface or curve in use. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the NURBSId of the surface or curve in use. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the state of the trim flag. When set the surface is trimmed against the curve. When not set, the surface isn't trimmed - - - - - Returns the state of the trim flip flag. When set this trims the surface in the opposite direction - - - - - Returns the UV location of the seed value on the surface. - - - - - Description: - This class provides access to the Vector Projected Curve. A Vector Projected curve lies on a surface. This is almost the same as a Normal Projected curve, except that the projection from the existing curve to the surface is in the direction of a vector that you can control. Vector projected curves may be used for trimming. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - int index - - The index in the of the surface or curve. - - - - - Sets the surface or curve used by specifying its NURBSId. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - NURBSId id - - The id of the surface or curve. - - - - - Returns the index into the of surface or curve used. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the NURBSId of surface or curve used. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the state of the trim flag. When set the surface is trimmed against the curve. When not set, the surface isn't trimmed - - - - - Returns the state of the trim flip flag. When set this trims the surface in the opposite direction. - - - - - Returns the UV location of the seed value on the surface. - - - - - Sets the projection vector used at the time passed. - Parameters: - TimeValue t - - The time at which to set the projection vector. - - & pvec - - The vector to set. - - - - - Returns the projection vector used at the time passed. - Parameters: - TimeValue t - - The time at which to get the projection vector. - - - - - Description: - This class defines a dependent ruled surface. A ruled surface is generated from two curve sub-objects. It lets you use curves to design the two opposite borders of a surface. Methods are available to get/set the indices of the parent surface in the and the parent Ids and to set the surface normal matching state of the surfaces. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - int index - - The index in the of the specified parent object. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number: 0 or 1. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - Parameters: - int pnum - - The parent number: 0 or 1. - - - - - This allows one to control the matching of parent surface normals when creating the ruled surface. For example, normally when you create a ruled surface between two parent curves you don't want a 'bow tie' surface (one with the ends rotated 180 degrees so it crosses on itself in the middle). If you simply match the parent normals you'll get a 'bow tie' surface. To prevent this you use this method to set a state indicating that one or the other should be flipped before it's used. In this way, when the ruled surface is created, a 'bow tie' won't occur. - Parameters: - int pnum - - The number of the parent curve: 0 or 1. - - BOOL flip - - TRUE to match the parent surface normal; FALSE to not match it. - - - - - Returns the flip state of the specified parent curve. - Parameters: - int pnum - - The number of the parent curve: 0 or 1. - - - - - Sets the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to set the start point. - - int pnum - - The number of the parent curve: 0 or 1. - - double startpoint - - The start point in the range 0.0 to 1.0. - - - - - Returns the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to get the start point. - - int pnum - - The number of the parent curve: 0 or 1. - Operators: - - - - - Description: - This class contains a table of entities used to make up the set. Additionally it has two fuse tables: one for fuse curves and one for fuse surfaces. These are used to allow the CVs in the curves or surfaces to be 'stitched' together so if one curve or surface moves the other moves with it. This class also has information required to tessellate the objects to triangle meshes for use in the viewports and the production renderer. - - All methods of this class are implemented by the system. - Data Members: - protected: - - *mpVTess; - - This object describes the properties of a tesselation approximation to the mathematical surface for representation in the viewports. - - *mpRTess; - - This object describes the properties of a tesselation approximation to the mathematical surface for the production renderer. - - *mpRTessDisp; - - This object describes the tesselation properties for displacement mapping in the production renderer. - - *mpVTessCurve; - - This object describes the properties of a tesselation approximation to the mathematical curve for representation in the viewports. - - *mpRTessCurve; - - This object describes the properties of a tesselation approximation to the mathematical curve for the production renderer. - - float mTessMerge; - - Controls the tessellation of surface sub-objects whose edges are joined or very nearly joined. When input to a modifier - such as Select - requires a mesh, and when NURBS surfaces are tessellated for production rendering, by default 3ds Max adjusts the tessellation of adjoining surfaces to match each other, in terms of the number of faces along the edges. The Merge parameter controls how this is done. If Merge is zero, adjoining faces are unchanged. Increasing the value of Merge increases the distance 3ds Max uses to calculate how edges should match, guaranteeing no gaps between the surfaces when they are rendered. - - <NURBSObject*> mObjects; - - A table of pointers to the s in the set. - - *mpObject; - - The instantiated object in the scene associated with this . This is NULL if there isn't one. - - mDisplay; - - Controls the display of the object in the viewport.. - - > mSurfFuse; - - A table of objects used to allow surfaces in the set to relate to on another. - - > mCurveFuse; - - A table of objects used to allow curves in the set to relate to on another. - - - - - This removes the NURBS connection to a live NURBS object. One use of this is so you can call CreateNURBSObject() twice with the same . You call Clean() in between the calls. Another use is if you want to use the API to copy a NURBS object. You could call GetNURBSSet() followed by a Clea() followed by a CreateNURBSObject(). - - - - - Returns the number of objects in the set. - - - - - This method sets an object in the table of objects maintained by the set. If the index is to an existing object in the set this will replace that object. If it is a new index, all the objects which follow this one in the set are set to NULL and the one passed is set. - Parameters: - int index - - If the index is an existing object in the set this will replace the object. If it is a new index, all the objects which follow this one are set to NULL and the one passed is set. - - NURBSObject* obj - - Points to the object to add to the table. - specified pointer. If the value of index is greater than the number of items in the table, the table is resized and any non-initialized pointers are set to NULL. - Parameters: - int index - - The zero based index of the object to set. - - NURBSObject* obj - - Points to the object to set. - - - - - Adds the specified object pointer to the end of the table of object pointers. - - Note: This method is ONLY used for adding an object to a that is not yet in the scene. To add an object to an existing scene use the global function AddNURBSObjects(). - Parameters: - NURBSObject* obj - - The pointer to the object to append. - Returns the number of objects in the table prior to appending. - - - - - Removes the specified object pointer from the table. - Parameters: - int index - - The zero based index of the object to remove. - - - - - Deletes all the objects that are in the table. - - This method frees all the NURBSObjects in a . A developer using a must call this method to free all the memory when done. - - - - - Returns a pointer to the specified object in the table. - Parameters: - int index - - The zero based index of the object to return. - - - - - Returns a pointer to the specified object in the table. - Parameters: - NURBSId id - - The Id of the object to return. - - - - - Returns a pointer to the object for the production renderer for the specified tesselation operation. - Parameters: - NURBSTessType type=kNTessSurface - - The type of tesselation. See NURBSTess Types. - - - - - Returns a pointer to the object for the viewport renderer for the specified tesselation operation. - Parameters: - NURBSTessType type=kNTessSurface - - The type of tesselation. See NURBSTess Types. - - - - - Sets the object for the production renderer for the specified tesselation operation. - Parameters: - & tess - - The tesselation object. - - NURBSTessType type=kNTessSurface - - This parameter is available in release 3.0 and later only. - - The type of tesselation. See NURBSTess Types. - - - - - Sets the object for the viewport renderer for the specified tesselation operation. - Parameters: - & tess - - The tesselation object. - - NURBSTessType type=kNTessSurface - - This parameter is available in release 3.0 and later only. - - The type of tesselation. See NURBSTess Types. - - - - - Clears (deletes) the specified tesselation object used for viewport rendering. - Parameters: - NURBSTessType type=kNTessSurface - - The type of tesselation. See NURBSTess Types. - - - - - Clears (deletes) the specified tesselation object used for production rendering. - Parameters: - NURBSTessType type=kNTessSurface - - The type of tesselation. See NURBSTess Types. - - - - - Returns the tesselation merge value. - - - - - Returns a pointer to the instantiated object in the scene associated with this . This is NULL if there isn't one. - - - - - Returns the display settings for this . - - - - - Description: - This class describes the properties of a NURBS surface. This includes its material ID, texture/tiling options, renderable state, open/closed state, and normal inverted state. The Evaluate() method is used to compute points and tangents on the surface. - - All methods of this class are implemented by the system. - Data Members: - protected: - - BOOL mGenUVs; - - TRUE if the 'Generate Mapping Coordinates' checkbox is on; otherwise FALSE. - - BOOL mFlipNormals; - - TRUE if the surface normals are inverted; otherwise FALSE. - - BOOL mRenderable; - - TRUE if the surface may be rendered; otherwise FALSE. - - int mMatID; - - The material ID for the surface. - - BOOL mClosedInU, mClosedInV; - - The surface closed flags. - - mTextureChannelSet; - - This data member is available in release 3.0 and later only. - - This is the set of texture mapping channels used by this surface. - - BOOL mFlipNormals; - - TRUE if normals are flipped for the surface; otherwise FALSE. - - BOOL mRenderable; - - TRUE if the surface is renderable; otherwise FALSE. - - int mMatID; - - The zero based material ID for the surface. - - BOOL mClosedInU - - TRUE if the surface is closed in U; otherwise FALSE. - - BOOL mClosedInV; - - TRUE if the surface is closed in V; otherwise FALSE. - - *mpVTess; - - This data member is available in release 3.0 and later only. - - Points to the object for the viewport (optional). - - *mpRTess; - - This data member is available in release 3.0 and later only. - - Points to the object for the production renderer (optional). - - *mpRTessDisp; - - This data member is available in release 3.0 and later only. - - Points to the object for displacement mapping (optional). - - *mpVTessCurve; - - This data member is available in release 3.0 and later only. - - Points to the object for tesselating curves in the viewports(optional). - - *mpRTessCurve; - - This data member is available in release 3.0 and later only. - - Points to the object for tesselating curves in the production renderer (optional). - - - - - Assignment operator. - Parameters: - & curve - - The surface to assign. - - - - - Returns TRUE if the surface is renderable; otherwise FALSE. - - - - - Returns the state of the flip normals flag. - - - - - Returns TRUE if the generate UV mapping coordinates flag is set for the specified channel; otherwise FALSE. - Parameters: - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Sets the state of the generate UV mapping coordinates flag. - Parameters: - BOOL state - - TRUE for on; FALSE for off. - - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Returns the material ID. - - - - - Returns the specified texture coordinate. - Parameters: - TimeValue t - - The time to get the texture UVs. - - int i - - The zero based index of the coordinate to return. This value must be >=0 and < 4. - - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - the specified texture coordinate to the specified value. - Parameters: - TimeValue t - - The time to set the texture UVs. - - int i - - The zero based index of the texture coordinate to set. This value must be >= 0 and < 4. - - pt - - The texture coordinate value to set. - - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Retrieves the texture tiling and offset values for the surface. - Parameters: - TimeValue t - - The time to get the tile offset. - - float &ut - - The tiling value in the U direction. - - float &vt - - The tiling value in the V direction. - - float &uo - - The offset value in the U direction. - - float &vo - - The offset value in the V direction. - - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Sets the texture tiling and offset values for the surface. - Parameters: - TimeValue t - - The time to set the tile offset. - - float ut - - The tiling value in the U direction. - - float vt - - The tiling value in the V direction. - - float uo - - The offset value in the U direction. - - float vo - - The offset value in the V direction. - - int channel = 0 - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Returns a reference to the texture surface used by this surface for the specified channel. - Parameters: - int channel - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - - - - Sets the texture surface used by this surface for the specified channel. - Parameters: - int channel - - The channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - & texSurf - - The texture surface to set. - - - - - Returns the number of channels used by the surface. - - - - - Returns a channel number corresponding to the specified index into the . - Parameters: - int index - - The zero based index into the . - - - - - Returns TRUE if the surface is closed in the U direction; otherwise FALSE. - - - - - Returns TRUE if the surface is closed in the V direction; otherwise FALSE. - - - - - Retrieves the point on the surface, and the u and v derivatives based on the parameters u and v. - Parameters: - TimeValue t - - The time at which to evaluate the surface. - - double u - - The value at which to evaluate the surface in u. This value must be between the uMin and uMax as returned from GetParameterRange(). - - double v - - The value at which to evaluate the surface in v. This value must be between the vMin and vMax as returned from GetParameterRange(). - - & pt - - The point on the surface. - - & dPdU - - The derivative along u. - - & dPdV - - The derivative along v. - TRUE if the method was able to evaluate the surface; otherwise FALSE. - - - - - Retrieves the point on the surface, and the u and v derivatives and second derivatives based on the parameters u and v. - Parameters: - TimeValue t - - The time at which to evaluate the surface. - - double u - - The value at which to evaluate the surface in u. This value must be between the uMin and uMax as returned from GetParameterRange(). - - double v - - The value at which to evaluate the surface in v. This value must be between the vMin and vMax as returned from GetParameterRange(). - - & pt - - The point on the surface. - - & dPdU - - The derivative along u. - - & dPdV - - The derivative along v. - - & d2PdU2 - - The second derivative along u. - - & d2PdV2 - - The second derivative along v. - - & d2PdUdV - TRUE if the method was able to evaluate the surface; otherwise FALSE. - - - - - Retrieves the minimum and maximum valid values for u and v as passed to Evaluate(). - Parameters: - TimeValue t - - The time at which to get the parameter range. - - double& uMin - - The minimum value in u is returned here. - - double& uMax - - The maximum value in v is returned here. - - double& vMin - - The minimum value in u is returned here. - - double& vMax - - The maximum value in v is returned here. - - - - - Retrieves data about the at the specified time. - Parameters: - TimeValue t - - The time at which to get the NURBS information. - - int& degreeInU - - The degree of the surface in U. - - int& degreeInV - - The degree of the surface in V. - - int& numInU - - The number of CVs in U. - - int& numInV - - The number of CVs in V. - - NURBSCVTab& cvs - - The table of CVs. Note: > NURBSCVTab; - - int& numKnotsInU - - The number of knots in U. - - int& numKnotsInV - - The number of knots in V. - - NURBSKnotTab uKnots - - A table of knots in U. Note: <double> NURBSKnotTab; - - NURBSKnotTab vKnots - - A table of knots in V. - TRUE if the data was retrieved; otherwise FALSE. - - - - - This method retrieves the Chord Length Parameterization Texture Surface data. - Parameters: - TimeValue t - - The time at which to retrieve the data. - - int channel - - The texture channel. This is a number in the range 0 and 98 which correspond to 1 to 99 in the user interface. - - int& degreeInU - - The degree of the surface in U. - - int& degreeInV - - The degree in V. - - int& numInU - - The number of CVs in U. - - int& numInV - - The number of CVs in V. - - NURBSCVTab& cvs - - The table of CVs. Note: > NURBSCVTab; - - int& numKnotsInU - - The number of knots in U. - - int& numKnotsInV - - The number of knots in V. - - NURBSKnotTab uKnots - - A table of knots in U. Note: <double> NURBSKnotTab; - - NURBSKnotTab vKnots - - A table of knots in V. - TRUE if the data was retrieved; otherwise FALSE. - - - - - Returns the number of trim loops at the specified time. Each loop may be made up of several curves. - Parameters: - TimeValue t - - The time at which to return the number. - - - - - Returns the number of curves in the specified trim loop. - Parameters: - TimeValue t - - The time at which to return the number. - - int loop - - The zero based index of the trim loop. - - - - - Retrieves data about the specified 2D trim curve in use by the surface. - Parameters: - TimeValue t - - The time at which to retrieve the data. - - int loop - - The zero based index of the trim loop. - - int curve - - The zero based index of the trim curve within the loop. - - int& degree - - The degree of the curve is returned here. - - int& numCVs - - The number of CVs. - - NURBSCVTab& cvs - - The table of CVs. Note: > NURBSCVTab; - - int& numKnots - - The number of knots. - - NURBSKnotTab knots - - A table of knots. Note: <double> NURBSKnotTab; - TRUE if the data was retrieved; otherwise FALSE. - - - - - Retrieves data about the specified 2D trim curve in use by the surface. - Parameters: - TimeValue t - - The time at which to retrieve the data. - - int loop - - The zero based index of the trim loop. - - int curve - - The zero based index of the trim curve within the loop. - - int& degree - - The degree of the curve is returned here. - - int& numCVs - - The number of CVs. - - NURBSCVTab& cvs - - The table of CVs. Note: > NURBSCVTab; - - int& numKnots - - The number of knots. - - NURBSKnotTab knots - - A table of knots. Note: <double> NURBSKnotTab; - TRUE if the data was retrieved; otherwise FALSE. - - - - - Returns a pointer to the object used for production rendering of the specified type. - Parameters: - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - - - - - Returns a pointer to the object used for viewport rendering of the specified type. - Parameters: - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - - - - - Sets the object used for production rendering of the specified type. - Parameters: - & tess - - The object to set. - - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - - - - - Sets the object used for viewport rendering of the specified type. - Parameters: - & tess - - The object to set. - - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - - - - - Clears (deletes) the object used for viewport rendering of the specified type. - Parameters: - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - - - - - Clears (deletes) the object used for production rendering of the specified type. - Parameters: - NURBSTessType type=kNTessSurface - - The tesselation type. See NURBSTess Types. - Operators: - - - - - Description: - This class defines a dependent edge curve. There are methods available to get/set the parent surface index and id, and get/set the parameter which determines the location on the surface the curve matches. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign from. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene. - - - - - Returns the UV location of the seed value on the curve. - - - - - Description: - This provides access to the Surface Normal Curve. This is a curve created at a specified distance from a surface and normal to it. - - Note: The parent curve specified below must have one of the following types: surface-surface intersection, U Iso, V Iso, normal projected, vector projected, CV curve on surface, or point curve on surface. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the parent curve. - - - - - Returns the NURBSId of the parent curve. - - - - - the distance along the normal of the curve from the surface at the specified time. - Parameters: - TimeValue t - - The time at which to set the distance. - - double dist - - The distance along the normal from the surface to the curve. - - - - - Returns the distance along the normal from the surface to the curve. - Parameters: - TimeValue t - - The time at which to get the distance. - - - - - Description: - This class is used to create a dependent point on a surface or related to it. - - All methods of this class are implemented by the system. - Data Members: - protected: - - NURBSId mParentId; - - The NURBSId of the parent surface. - - int mParentIndex; - - The index in the of the parent surface. - - NURBSConstType mCType; - - The type of constraint used by the point. - - mOffset; - - The offset amount. - - float mNormal; - - The distance along the normal. - - float mUTangent; - - The positive tangent offset in U. At the location in parameter space of the constrained point is a tangent to the surface. This is the distance along the positive U tangent in parameter space. - - double mUParam; - - The point is constrained to exist on the parent surface. The surface itself is defined over a parameter range. The point is defined at a point in the parent surface parameter space. This is the location of the point in the parent surface parameter space in U. - - float mVTangent; - - This is the distance along the positive V tangent in parameter space. - - double mVParam; - - This is the location of the point in the parent surface parameter space in V. - - - - - Assignment operator. - Parameters: - & pt - - The point to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - - - - - Returns the type of constrained point this is. See NURBSConst Types - - - - - Sets the position of the point in the parent U parameter space. - Parameters: - TimeValue t - - The time to set the U parameter. - - double param - - The value to set. - - - - - Returns the position of the point in the parent U parameter space. - Parameters: - TimeValue t - - The time to get the U parameter. - - - - - Sets the position of the point in the parent V parameter space. - Parameters: - TimeValue t - - The time to set the U parameter. - - double param - - The value to set. - - - - - Returns the position of the point in the parent V parameter space. - Parameters: - TimeValue t - - The time to get the Vparameter. - - - - - Sets the offset of the point from the parent surface. - Parameters: - TimeValue t - - The time at which to set the offset. - - pt - - The offset to set. - - - - - Returns the offset of the point from the parent surface at the specified time. - Parameters: - TimeValue t - - The time at which to get the offset. - - - - - Sets the distance along the normal to the surface of the point at the specified time. - Parameters: - TimeValue t - - The time at which to set the distance. - - float dist - - The distance to set. - - - - - Returns the distance along the normal to the surface of the point at the specified time. - Parameters: - TimeValue t - - The time at which to get the distance. - - - - - Sets the distance along the U tangent of the point. - Parameters: - TimeValue t - - The time at which to set the distance. - - float dist - - The distance to set. - - - - - Returns the distance along the U tangent of the point. - Parameters: - TimeValue t - - The time at which to get the distance. - - - - - Sets the distance along the V tangent of the point. - Parameters: - TimeValue t - - The time at which to set the distance. - - float dist - - The distance to set. - - - - - Returns the distance along the V tangent of the point. - Parameters: - TimeValue t - - The time at which to get the distance. - Operators: - - - - - Description: - This class provides access to the Surface-Surface Intersection Curve. This is a curve that is defined by the intersection of two surfaces. You can use surface-surface intersection curves for trimming. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Sets the surface or curve by specifying its index into the . - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - int index - - The index into the of the object to set. - - - - - Sets the surface or curve by specifying its index into the . - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - NURBSId id - - The id of the object to set. - - - - - Returns the index into the of the curve or surface. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the NURBSId of the curve or surface. - Parameters: - int pnum - - Pass 0 for the surface and 1 for the curve. - - - - - Returns the state of the specified trim flag. When on, the surface is trimmed against the intersection curve. When off, the surface isn't trimmed. - Parameters: - int tnum - - Passing 0 trims the first parent surface, and passing 1 trims the second parent surface - - - - - Sets the state of the specified trim flag. When on, the surface is trimmed against the intersection curve. When off, the surface isn't trimmed. - Parameters: - int tnum - - Passing 0 trims the first parent surface, and passing 1 trims the second parent surface - - BOOL trim - - TRUE to trim; FALSE to not trim. - - - - - Returns the state of the trim flip flag. When on, the specified surface is trimmed in the opposite direction. - Parameters: - int tnum - - 0 for the first surface; 1 for the second surface. - - - - - Sets the state of the trim flip flag. When on, the specified surface is trimmed in the opposite direction. - Parameters: - int tnum - - 0 for the first surface; 1 for the second surface. - - BOOL flip - - TRUE to flip; FALSE not to flip. - - - - - Returns the UV location of the seed value on the first surface. If there is a choice of intersections, the intersection closest to the seed point is the one used to create the curve. - - - - - Description: - This class holds the data associated with a single texture channel. This includes the , texture vertices, channel number, tiling, offset, and rotation settings. The tiling, offset and angle values are applied after the texture surface is applied. This gives the user more control of the mapping. - Data Members: - private: - - int mChannel; - - The UV coordinates channel. This value can range from 0 to 98. A single surface can use up to 99 texture channels. - - BOOL mGenUVs; - - TRUE if the generate UV setting is on for this channel; otherwise FALSE. - - mTexUVs[4]; - - The texture vertices (UV coordinates). - - float mUTile; - - The U tiling. - - float mVTile; - - The V tiling. - - float mUOffset; - - The U offset. - - float mVOffset; - - The V offset. - - float mAngle; - - The rotation angle in radians. - - mTexSurface; - - The texture surface associated this channel. - private: - - - - - Description: - This class holds a table of pointers to all the data for a surface. There are methods to returns the table data by channel or by index and a method to add a new texture channel. - Data Members: - private: - - <NURBSTextureChannel*> mTextureChannels; - - A table of pointers to the texture channel data. - private: - - - - - Description: - This class holds a single texture vertex in a NURBS texture surface. Methods are available to get and set the point in various formats. - Data Members: - protected: - - double mX, mY; - - The position of the point. - - - - - Returns the position of the texture point at the specified time (as a ). - Parameters: - TimeValue t - - The time at which to get the position. - - - - - Retrieves the position of the texture point at the specified time (as floats). - Parameters: - TimeValue t - - The time at which to get the position. - - float& x - - The x position is returned here. - - float& y - - The y position is returned here. - - - - - Retrieves the position of the texture point at the specified time (as doubles). - Parameters: - TimeValue t - - The time at which to get the position. - - double& x - - The x position is returned here. - - double& y - - The y position is returned here. - - - - - Sets the position of the point at the specified time (using a ). - Parameters: - TimeValue t - - The time at which to set the position. - - pt - - The position to set. - - - - - Sets the position of the point at the specified time (using floats). - Parameters: - TimeValue t - - The time at which to set the position. - - float x - - The x coordinate to set. - - float y - - The y coordinate to set. - - - - - Sets the position of the point at the specified time (using doubles). - Parameters: - TimeValue t - - The time at which to set the position. - - double x - - The x coordinate to set. - - double y - - The y coordinate to set. - - - - - Description: - A NURBS texture surface is a surface associated with the surface sub-object. 3ds Max uses the texture surface to control how materials are mapped. In effect, changing the texture surface stretches or otherwise changes the UV coordinates for the surface, altering the mapping. - - This class provides access to the NURBS Texture Surface. This is a 2D (not 3D) surface that lives in the parameter space of the corresponding which controls the texture mapping used by the . - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the NURBS Texture Surface Type. See NURBSTextureSurface Types. - - - - - Returns the index in the of the surface that's mapped. - - - - - Returns the ID of the surface that's mapped. - - - - - Sets the number of points in U and V for the texture surface. - Parameters: - int u - - The number of points in U. - - int v - - The number of points in V. - - - - - Returns the number of points in U. - - - - - Returns the number of points in V. - - - - - Retrieves the number of points in U and V. - Parameters: - int &u - - The number of points in U is returned here. - - int &v - - The number of points in V is returned here. - - - - - Returns a pointer to the specified NURBS Texture Point. - Parameters: - int u - - Specifies the U point. - - int v - - Specifies the V point. - - - - - Sets the specified NURBS Texture Point. - Parameters: - int u - - Specifies the U point. - - int v - - Specifies the V point. - - & pnt - - The point to set. - - - - - Description: - This class defines a point on a curve used to trim a portion of the curve from the point towards one of the ends of the curve. The trim point is defined by a parameter and a direction. For instance, consider a CV curve that exists in the parameter space from 0.0 to 1.0. If there is a trim point in the middle of the curve the parameter for the point would be 0.5. If the portion that was being trimmed off was from 0.5 to 1.0 then the trim direction would be positive. - - All methods of this class are implemented by the system. - - - - - Returns the point in parameter space at which the trim point exists. - - - - - Returns the trim direction (positive, negative, or none) describing which portion of the curve is trimmed off. - - - - - Description: - This class defines a dependent U Loft surface. A U Loft surface interpolates a surface across multiple curve sub-objects. The curves become U-axis contours of the surface. Methods are available to get/set the number of curves used to make the loft, append curves to the list, get/set the parent ids, and get/set the flipped state for each of the curves. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the number of curves used by the surface. - - - - - Adds a curve to the end of the list of curves used to make the U loft surface. - Parameters: - int index - - The index of the curve to add in the . - - BOOL flip - - TRUE to flip the orientation of this curve's normal used to build the loft; otherwise FALSE. - The number of curves in the list prior to this one being added. - - - - - Adds a curve to the end of the list of curves used to make the U loft surface. - Parameters: - NURBSId id - - The NURBS id of the curve to add. - - BOOL flip - - TRUE to flip the orientation of this curve's normal used to build the loft; otherwise FALSE. - - - - - Sets the index in the of the specified parent object. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - int index - - The index into the of the parent surface. - - - - - Sets the NURBSId of the specified parent. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - NURBSId id - - The id to set. - - - - - Returns the index in the of the specified parent object. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Returns the NURBSId of the specified parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - - - - This method allows one to control the matching of parent normals when creating the U loft surface. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - BOOL flip - - TRUE to flip the orientation of the normal when building the surface at this curve; otherwise FALSE. - - - - - Returns the flip state of the specified parent normal. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Sets the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to set the start point. - - int pnum - - The parent number, 0, 1, 2, etc. - - double startpoint - - The start point in the range 0.0 to 1.0. - - - - - Returns the start point for the specified parent curve. Note: This is only applicable if the parent is a closed curve. - Parameters: - TimeValue t - - The time at which to get the start point. - - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Sets the curve tension for the specified parent curve. - Parameters: - TimeValue t - - The time at which to set the tension. - - int pnum - - The parent number, 0, 1, 2, etc. - - double tension - - The tension value to set. - - - - - Returns the tension setting of the specified parent curve at the specified time. - Parameters: - TimeValue t - - The time at which to get the tension. - - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Sets the curve use surface tangent setting. If the curve is a curve on surface, turning this on causes the U loft to use the tangency of the surface. This can help blend a loft smoothly onto a surface. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - BOOL useTangent - - TRUE to use the tangent; otherwise FALSE. - - - - - Returns TRUE if the curve use surface tangent setting is on; FALSE if off. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Sets the flip tangent setting for the specified parent curve. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - BOOL flipTangent - - TRUE to flip the tangent; otherwise FALSE. - - - - - Returns TRUE if the tangent is flipped for the specified parent curve; otherwise FALSE. - Parameters: - int pnum - - The parent number, 0, 1, 2, etc. - - - - - Returns TRUE if auto align is on; otherwise FALSE. - - - - - Returns TRUE if loft is closed; otherwise FALSE. - Operators: - - - - - Description: - This class provides access to the UV Loft Surface. This surface is similar to the U Loft surface, but has a set of curves in the V dimension as well as the U dimension. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the number of curves in the U dimension. - - - - - Appends the specified curve (by index) to the list of U curves. - Parameters: - int index - - The index in the of the curve to use. - - - - - Appends the specified curve (by NURBSId) to the list of U curves. - Parameters: - NURBSId id - - The NURBSId of the curve to use. - Returns the number of curves in the set prior to appending. - - - - - Sets the specified parent curve (by index) as the speciifed curve in the surface. - Parameters: - int pnum - - The index into the list of U curves of the parent curve to set. - - int index - - The index into the of the parent curve to set. - - - - - Sets the specified parent curve (by NURBSId) as the speciifed curve in the surface. - Parameters: - int pnum - - The index into the list of U curves of the parent curve to set. - - NURBSId id - - The NURBSId of the parent curve to set. - - - - - Returns the index into the of the specified parent curve. - Parameters: - int pnum - - The zero based index of the parent curve. - - - - - Returns the NURBSId of the specified parent curve. Note that a NURBSId won't be valid until the surface has been instantiated in the scene. - Parameters: - int pnum - - The zero based index of the parent curve. - - - - - Returns the number of curves in the V dimension. - - - - - Appends the specified curve (by index) to the list of V curves. - Parameters: - int index - - The index in the of the curve to use. - Returns the number of curves in the set prior to appending. - - - - - Appends the specified curve (by NURBSId) to the list of U curves. - Parameters: - NURBSId id - - The NURBSId of the curve to use. - Returns the number of curves in the set prior to appending. - - - - - Sets the specified parent curve (by index) as the speciifed curve in the surface. - Parameters: - int pnum - - The index into the list of V curves of the parent curve to set. - - int index - - The index into the of the parent curve to set. - - - - - Sets the specified parent curve (by NURBSId) as the speciifed curve in the surface. - Parameters: - int pnum - - The index into the list of V curves of the parent curve to set. - - NURBSId id - - The NURBSId of the parent curve to set. - - - - - Returns the index into the of the specified parent curve. - Parameters: - int pnum - - The zero based index of the parent curve. - - - - - Returns the NURBSId of the specified parent curve. Note that a NURBSId won't be valid until the surface has been instantiated in the scene. - Parameters: - int pnum - - The zero based index of the parent curve. - - - - - Description: - This class defines a dependent transform (xform) curve. A transform curve is a copy of the original curve with a different position, rotation, or scale. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & curve - - The curve to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent. Note that a NURBSId won't be valid until the object has been instantiated in the scene - - - - - Sets the transformation used to move/rotate/scale the curve from the original. - Parameters: - TimeValue t - - The time to set the transformation. - - & mat - - The transformation matrix to set. - - - - - Returns the transformation used to move/rotate/scale the curve from the original. - Parameters: - TimeValue t - - The time to get the transformation. - Operators: - - - - - Description: - This class defines a dependent transform (xform) surface. A transform surface is a copy of the original surface with a different position, rotation, or scale. Methods are available to get/set the indices of the parent surface in the and the parent Ids and to specify/retrieve the transformation used on the surface. - - All methods of this class are implemented by the system. - - - - - Assignment operator. - Parameters: - & surf - - The surface to assign. - - - - - Returns the index in the of the parent object. - - - - - Returns the NURBSId of the parent object. - - - - - Sets the transformation from the parent surface. - Parameters: - TimeValue t - - The time at which to set the transformation. - - & mat - - The transformation to set. - - - - - Returns the transformation from the parent surface. - Parameters: - TimeValue t - - The time at which the transformation is returned. - Operators: - - - - - The object class is the base class for all objects. An object is one of two things: A procedural object or a derived object. Derived objects are part of the system and may not be created by plug-ins. They are containers for modifiers. Procedural objects can be many different things such as cameras, lights, helper objects, geometric objects, etc. Methods of this class are responsible for things such as allowing the object to be deformed (changing its points), retrieving a deformed bounding box, converting the object between different types (to a mesh or patch for example), texture mapping the object (if appropriate) and interacting with the system regarding mapping. There are other methods involved in validity intervals for the object and its channels, and a method used to return the sub-object selection state of the object. - Method Groups: - See . - - - - - Indicates whether the object may be rendered. Some objects such as construction grids and helpers should not be rendered and can return zero. - Nonzero if the object may be rendered; otherwise 0. - - - - - This is the default name of the node when it is created. - - The default name of the node is stored here. - - - - This method determines if the object color is used for display. - TRUE if the object color is used for display; otherwise FALSE. - - - - - If an object wants to draw itself in the 3D viewports in its selected state in some custom manner this method should return nonzero. If this item returns nonzero, the BaseObject::Display() method should respect the selected state of the object when it draws itself. If this method returns zero the system will use its standard method of showing the object as selected. - Nonzero if the object will draw itself in the selected state; otherwise 0. If nonzero, the plug-in developer is responsible for displaying the object in the selected state as part of its Display() method. - - - - - This method is called to compute the intersection point and surface normal at this intersection point of the ray passed and the object. - Nonzero if a point of intersection was found; otherwise 0. - - The time to compute the intersection. - to intersect. See Class . - The point of intersection. - Surface normal at the point of intersection. - - - - Objects that don't support the IntersectRay() method (such as helper objects) can implement this method to provide a default vector for use with the normal align command in 3ds Max. - TRUE if this method is implemented to return the normal align vector; otherwise FALSE. - - The time to compute the normal align vector. - The point of intersection. - The normal at the point of intersection. - - - - Implemented by the System. This method locks the object as a whole. The object defaults to not modifiable. - - - - - Implemented by the System. This method unlocks the object as a whole. - - - - - Implemented by the System. Returns nonzero if the object is locked; otherwise 0. - - - - - This method is called to evaluate the object and return the result as an . When the system has a pointer to an object it doesn't know if it's a procedural object or a derived object. So it calls Eval() on it and gets back an . A derived object managed by the system may have to call Eval() on its input for example. A plug-in (like a procedural object) typically just returns itself. A plug-in that does not just return itself is the Morph (/MAXSDK/SAMPLES/OBJECTS/MORPHOBJ.CPP). This object uses a morph controller to compute a new object and fill in an which it returns. - The result of evaluating the object as an . - Sample Code: - Typically this method is implemented as follows: - - Specifies the time to evaluate the object. - - - - Implemented by the System. Locks the specified channels of the object. - - The channels to lock. - - - - Implemented by the System. Unlocks the specified channel(s) of the object. - - Specifies the channels to unlock. - - - - Implemented by the System. Returns the locked status of the channels. - The channels of the object that are locked. - - - - - Implemented by the System. Returns the locked status of the channels. - The channels of the object that are locked. - - Not used. - - - - This method determines if this object can have channels cached. Particle objects flow up the pipeline without making shallow copies of themselves and therefore cannot be cached. Objects other than particle system can just use the default implementation. - TRUE if the object can be cached; otherwise FALSE. - - - - - This is called by a node when the node's world space state has become invalid. Normally an object does not (and should not) be concerned with this, but in certain cases like particle systems an object is effectively a world space object an needs to be notified. - - - - - Returns TRUE if the object as a world space object; otherwise FALSE. World space objects (particles for example) can not be instanced because they exist in world space not object space. Objects other than particle system can just use the default implementation. - - - - - Implemented by the System. Copies the specified channels from the object passed. - - The source object. - Indicates the channels to copy. - - - - Indicates whether this object is deformable. A deformable object is simply an object with points that can be modified. Deformable objects must implement the generic deformable object methods (NumPoints(), GetPoint(i), SetPoint(i), Deform()). A deformable object is simply an object with points that can be modified. These points can be stored in any form the object wants. They are accessed through a virtual array interface with methods to get and set the 'i-th' point. If an object has tangents for instance, it would convert them to and from points as necessary. For example, a simple Bezier spline object that stored its control handles relative to the knot would convert them to be absolute when GetPoint() was called with 'i' specifying one of the control points. When the control point is later set, the object can convert it back to be relative to its knot. At this point it could also apply any constraints that it may have, such as maintaining a degree of continuity. The idea is that the entity calling GetPoint(i) and SetPoint(i) doesn't care what the point represents. It will simply apply some function to the point. - The Deformable object methods only need to be implemented if the object returns TRUE from this method. - Return nonzero if the object is deformable and implements the generic deformable object methods; otherwise 0. - - - - - The points of a deformable object are accessed through a virtual array interface. This method specifies the number of points in the object. The meaning of 'points' is defined by the object. A uses the vertices as the points for example. b> - The number of points in the object. - - - - - The points of a deformable object are accessed through a virtual array interface. This method returns the 'i-th' point of the object. - If your plug-in is a modifier and you want to operate on the selected points of the object you are modifying, you can't tell which points are selected unless you know the type of object. If it is a generic deformable object there is no way of knowing since the way the object handles selection is up to it. Therefore, if you want to operate on selected points of a generic deformable object, use a . - The 'i-th' point of the object. - - Specifies which point should be returned. - - - - The points of a deformable object are accessed through a virtual array interface. This method stores the 'i-th' point of the object. - - The index of the point to store. - The point to store. - - - - Returns TRUE if the 'i-th' point is selected; otherwise FALSE. - - The zero based index of the point to check. - - - - Returns a floating point weighted point selection if the object supports it. The default implementation just returns 1.0f if selected and 0.0f if not. - - The zero based index of the point to check. - - - - Returns TRUE if the object has weights for its points that can be set; otherwise FALSE. - - - - - Returns the weight of the specified point of the object. - - The point to return the weight of. - - - - Sets the weight of the specified point. - - The point whose weight to set. - The value to set. - - - - Retreives the number of faces and vertices of the polyginal mesh representation of this object. If this method returns FALSE then this functionality is not supported. Note: Plug-In developers should use the global function GetPolygonCount(Object*, int&, int&) to retrieve the number f vertices and faces in an arbitrary object. - TRUE if the method is fully implemented; otherwise FALSE. - - The time at which to compute the number of faces and vertices. - The number of faces is returned here. - The number of vertices is returned here. - - - - Informs the object that its points have been deformed, so it can invalidate its cache. A developer who uses the GetPoint() / SetPoint() approach to modifying an object will call PointsWereChanged() to invalidate the object's cache. For example, if a modifier calls SetPoint(), when it is finished it should call this method so the object can invalidate and/or update its bounding box and any other data it might cache. - - - - - This is the method used to deform the object with a deformer. The developer should loop through the object's points calling the defProc for each point (or each selected point if useSel is nonzero). The Deform() method is mostly a convenience. Modifiers can implement a '' callback object which is passed to the Deform() method. The object then iterates through its points calling their deformer's callback for each point. The only difference between using the Deform() method as opposed to iterating through the points is that the Deform() method should respect sub-object selection. For example, the 's implementation of Deform() iterates through its vertices, if the 's selection level is set to vertex then it only calls the 's callback for vertices that are selected. This way modifiers can be written that can be applied only to selection sets without any specific code to check selected points. The default implementation of this method just iterates through all points using GetPoint(i) and SetPoint(i). If an object supports sub-object selection sets then it should override this method. - Default Implementation: - Sample Code: - This code shows the implementation of this method. Note how it looks at the useSel parameter to only call the selected points if required. - - A pointer to an instance of the class. This is the callback object that actually performs the deformation. - A flag to indicate if the object should use the selected points only. If nonzero the selected points are used; otherwise all the points of the object are used. - - - - This method computes the bounding box in the objects local coordinates or the optional space defined by tm. Note: If you are looking for a precise bounding box, use this method and pass in the node's object TM (INode::GetObjectTM()) as the matrix. - - The time to compute the box. - A reference to a box the result is stored in. - This is an alternate coordinate system used to compute the box. If the tm is not NULL this matrix should be used in the computation of the result. - If TRUE, the bounding box of selected sub-elements should be computed; otherwise the entire object should be used. - - - - This method lets you know if the ApplyUVWMap() method is available for this object. This is used by things like the UVW mapping modifier, so that it can determine which objects can have their mapping modified. Returns nonzero if the object is mappable; otherwise zero. - - - - - Returns the maximum number of channels supported by this type of object. TriObjects for instance return MAX_MESHMAPS which is currently set to 100. - - - - - Returns the number of maps currently used by this object. This is at least 1+(highest channel in use). This is used so a plug-in that does something to all map channels doesn't always have to do it to every channel up to MAX_MESHMAPS but rather only to this value. - - - - - This method may be called to map the object with UVW mapping coordinates. If the object returns nonzero from IsMappable() then this method should be implemented. - - The mapping type. One of the following values: MAP_PLANAR MAP_CYLINDRICAL MAP_SPHERICAL MAP_BALL MAP_BOX - of tiles in the U direction. - of tiles in the V direction. - of tiles in the W direction. - If nonzero the U values are mirrored. - If nonzero the V values are mirrored. - If nonzero the W values are mirrored. - This is used with MAP_CYLINDRICAL. If nonzero, then any face normal that is pointing more vertically than horizontally will be mapped using planar coordinates. - This defines the mapping space. As each point is mapped, it is multiplied by this matrix, and then it is mapped. - This indicates which channel the mapping is applied to. See ~{Mapping Channels}~ . - - - - Indicates whether the object can be converted to the specified type. If the object returns nonzero to indicate it can be converted to the specified type, it must handle converting to and returning an object of that type from ConvertToType(). Note that all overrides of this method should either call _super::CanConvertToType or test to see if obtype == anyObjectClassID. If true, the method should return true. - Nonzero if the object can be converted to the specified type; otherwise 0. - - The of the type of object to convert to. See Class , Class IDs defined in . - - - - This method converts this object to the type specified and returns a pointer it. Note that if ConvertToType() returns a new object it should be a completely different object with no ties (pointers or references) to the original. Note that all overrides of this method should either call _super::ConvertToType or test to see if obtype == anyObjectClassID. If true, the object should return itself. - The following is an issue that developers of world space modifiers need to - be aware of if the world space modifier specifies anything but generic deformable objects as its input type. In other words, if a world space modifier, in its implementation of Modifier::InputType(), doesn't specifically return defObjectClassID then the following issue regarding the 3ds Max pipeline needs to be considered. Developers of other plug-ins that don't meet this condition don't need to be concerned with this issue. - World space modifiers that work on anything other than generic deformable - objects are responsible for transforming the points of the object they modify into world space using the TM. To understand why this is necessary, consider how 3ds Max applies the node transformation to the object flowing down the pipeline. - In the geometry pipeline architecture, the node in the scene has its - transformation applied to the object in the pipeline at the transition between the last object space modifier and the first world space modifier. The node transformation is what places the object in the scene - thus this is what puts the object in world space. The system does this by transforming the points of the object in the pipeline by the node transformation. This is only possible however for deformable objects. Deformable objects are those that support the Object::IsDeformable(), NumPoints(), GetPoint() and SetPoint() methods. These deformable objects can be deformed by the system using these methods, and thus the system can modify the points to put them in world space itself. - If a world space modifier does not specify that it works on deformable - objects, the system is unable to transform the points of the object into world space. What it does instead is apply the transformation to the TM. In this case, a world space modifier is responsible for transforming the points of the object into world space itself, and then setting the TM to the identity. There is an example of this in the sample code for the Bomb space warp. The Bomb operates on TriObjects and implements InputType() as { return ; }. Since it doesn't specifically return defObjectClassID, it is thus responsible for transforming the points of the object into world space itself. It does this in its implementation of ModifyObject() as follows: As the code above shows, the Bomb checks if the TM is non-NULL. If it is, the points of the object are still not in world space and thus must be transformed. It does this by looping through the points of the and multiplying each point by the TM. When it is done, it sets the TM to NULL to indicate the points are now in world space. This ensure that any later WSMs will not transform the points with this matrix again. - For the Bomb world space modifier this is not a problem since it specifies - in its implementation of ChannelsChanged() that it will operate on the geometry channel (GEOM_CHANNEL). Certain world space modifiers may not normally specify GEOM_CHANNEL in their implementation of ChannelsChanged(). Consider the camera mapping world space modifier. Its function is to apply mapping coordinates to the object it is applied to. Thus it would normally only specify TEXMAP_CHANNEL for ChannelsChanged(). However, since it operates directly on TriObjects, just like the Bomb, the system cannot transform the points into world space, and therefore the camera mapping modifier must do so in its implementation of ModifyObject(). But since it is actually altering the points of the object by putting them into world space it is altering the geometry channel. Therefore, it should really specify GEOM_CHANNEL | TEXMAP_CHANNEL in its implementation of ChannelsChanged(). If it didn't do this, but went ahead and modified the points of the object anyway, it would be transforming not copies of the points, but the original points stored back in an earlier cache or even the base object. - This is the issue developers need to be aware of. To state this in simple - terms then: Any world space modifier that needs to put the points of the object into world space (since it doesn't implement InputType() as defObjectClassID) needs to specify GEOM_CHANNEL in its implementation of ChannelsChanged(). - A pointer to an object of type obtype. - Default Implementation: - { return NULL; } - Sample Code: - The following code shows how a can be retrieved from a node. Note on the code that if you call ConvertToType() on an object and it returns a pointer other than itself, you are responsible for deleting that object. - - The time at which to convert. - The of the type of object to convert to. See Class , Class IDs defined in . - - - - This method allows objects to specify the class that is the best class to convert to when the user collapses the stack. The main base classes have default implementations. For example, specifies TriObjects as its preferred collapse type and shapes specify splines as their preferred collapse type - The of the preferred object type. See Class IDs defined in plugapi.h. - - - - - When the user clicks on the Edit button in the modify branch a list of 'Convert To:' types is presented. The use may click on one of these choices to collapse the object into one of these types (for instance, an Editable or an Editable NURBS object). This method returns a list of Class_IDs and descriptive strings that specify the allowable types of objects that this object may be collapsed into. Note: Most plug-ins call the base class method in in their implementation of this method. The base class implementation provided by checks if the object can convert to both an editable mesh and an editable spline. If it can, these are added to the allowable types. - Sample Code: - - The table of allowable Class_IDs. - The table of pointers to strings that correspond to the table of Class_IDs above. - - - - This method is called on the world space cache object when the stack gets collapsed, that lets the pipeline object decide, if it wants to return a different object than itself. The default implementation simply returns this. A e.g. can create and return an EditablePolyObject in this method, so that the collapsed object has a UI. I only implemented this method for , but this can potentially implemented that way for all pipeline objects, that currently pass up the editable version. It is important, that all places, that collapse the stack are calling this method after evaluating the stack. - It also is important, that the editable version implements this method to - simply return this, otherwise you'll get a non-editable object when you collapse an editable polyobject. - A pointer to the resulting object. - - - - - For objects that have sub selection levels, this method returns the current selection level of the object. For example, a has the following selection levels: object, vertex, face, edge. Other object types may have different selection levels. The only standard is that a value of 0 indicates object level. b> - The current selection level of the object. - - - - - Implemented by the System. - If the requested channels are locked, this method will replace their data - with a copy and unlock them, otherwise it leaves them alone. - - The channels to ready for modification. - - - - Retrieve the current validity interval for the nchan channel of the object. - Most procedural objects won't implement this method since they don't have individual channels. Developers wanting to get the validity interval for a procedural object should use Object::ObjectValidity() instead. - The validity interval of the specified channel. - - The time to retrieve the validity interval of the channel. - Specifies the channel to return the validity interval of. See . - - - - Sets the validity interval of the specified channel. - - Specifies the channel. See . - The validity interval for the channel. - - - - This method invalidates the intervals for the given channel mask. This just sets the validity intervals to empty (calling SetEmpty() on the interval). - - Specifies the channels to invalidate. - - - - This method returns the validity interval of the object as a whole at the specified time. - The validity interval of the object, including that queried from the base class. - - The time to compute the validity interval. - - - - This method must make a copy of its "shell" and then shallow copy (see below) only the specified channels. It must also copy the validity intervals of the copied channels, and invalidate the other intervals. - A pointer to the shallow copy of the object. - - The channels to copy. - - - - This method copies the specified channels from the fromOb to this and copies the validity intervals. A plug-in needs to copy the specified channels from the specified object fromOb to itself by just copying pointers (not actually copying the data). No new memory is typically allocated, this method is just copying the pointers. - - to copy the channels from. - Channels to copy. - - - - This method deletes the memory associated with the specified channels and set the intervals associated with the channels to invalid (empty). - - Specifies the channels to free. - - - - This method replaces the locked channels with newly allocated copies. It will only be called if the channel is locked. - - The channels to be allocate and copy. - - - - This method allows the object to enlarge its viewport rectangle, if it wants to. The system will call this method for all objects when calculating the viewport rectangle; the object can enlarge the rectangle if desired. This is used by the Editable Spline code to allow extra room for vertex serial numbers, which can extend outside the normal bounding rectangle. - Default Implementation: - {} - Sample Code: - - Points to the associated with the viewport. - The enlarged rectangle is returned here. - - - - When a modifier is applied to an object, it needs to include its own validity interval in the interval of the object. To do this, a modifier calls the UpdateValidity() method of an object. This method intersects interval v to the nchan channel validity of the object. - - The validity interval of the modifier is intersected with this channel of the object. See . - The interval to intersect. - - - - This method give the object the chance to reduce its caches. - - The time to discard any caches the object has. - - - - This is called to determine if this is a construction object or not. - Nonzero if the object is a construction object; otherwise 0. - - - - - This method returns the number of pipeline branches combined by the object. This is not the total number of branches, but rather the number that are active. For example in the boolean object, if the user does not have any operands selected, this methods would return zero. If they have one selected it would return one. - - This parameter must be supported by all compound objects. In case the selected parameter is true the object should only return the number of pipebranches, that are currently selected in the (this is the way it worked in R3 and before. In case this parameter is false, the object has to return the number of all branches, no matter if they are selected or not - - - - Retrieves sub-object branches from an object that supports branching. Certain objects combine a series of input objects (pipelines) into a single object. These objects act as a multiplexer allowing the user to decide which branch(s) they want to see the history for. It is up to the object how they want to let the user choose. For example the object may use sub-object selection to allow the user to pick a set of objects for which the common history will be displayed. When the history changes for any reason, the object should send a notification (REFMSG_BRANCHED_HISTORY_CHANGED) using NotifyDependents(). - The 'i-th' sub-object branch. - - The branch index. - This parameter must be supported by all compound objects. In case the selected parameter is true the object should only return the number of pipebranches, that are currently selected in the (this is the way it worked in R3 and before. In case this parameter is false, the object has to return the number of all branches, no matter if they are selected or not - - - - When an object has sub-object branches, it is likely that the sub-objects are transformed relative to the object. This method gives the object a chance to modify the node's transformation so that operations (like edit modifiers) will work correctly when editing the history of the sub object branch. An object can implement this method by returning a pointer to a new that is based on the node passed into this method. See Class . - A pointer to an . This can be the original passed in (the default implementation does this) or a new . - - The time to get the . - The original pointer. - The branch index. - This parameter must be supported by all compound objects. In case the selected parameter is true the object should only return the number of pipebranches, that are currently selected in the (this is the way it worked in R3 and before. In case this parameter is false, the object has to return the number of all branches, no matter if they are selected or not - - - - Returns the number of shapes contained inside this object. A shape container may return zero if it doesn't currently have any shapes. - The number of shapes. A return value of -1 indicates this is not a container. - - - - - This method returns the specified by the index passed at the time specified. See Class . - - The time to return the shape. - The index of the shape. - - - - Returns the matrix associated with the shape whose index is passed. This matrix contains the offset within the object used to align the shape viewport to the shape. - - The time to return the matrix. - The index of the shape whose matrix to return. - The matrix is returned here. - - - - This is used by the lofter. The lofter can have several shapes selected, and the bit array returned here will have a bit set for each selected shape. See Class . - - - - - This method is used for debugging only. The implements this method by making sure its face's vert indices are all valid. - TRUE if valid; otherwise FALSE. - - - - - It is called to return a pointer to the base object (an object that is not a derived object). This method is overridden by DerivedObjects to search down the pipeline for the base object. The default implementation just returns this. This function is still implemented by derived objects and WSM's to search down the pipeline. This allows you to just call it on a nodes ObjectRef without checking for type. - - - - - There are several methods used to access a parametric position on the surface of the object. If this method returns TRUE then Object::GetSurfacePoint() will be called to return a point on the surface that corresponds to the u and v parameters passed to it. If this method returns FALSE then it is assumed the object does not support returning a point on the surface based on parameteric values. For sample code see /MAXSDK/SAMPLES/OBJECTS/SPHERE.CPP. If the object has several parametric surfaces then a second version of GetSurfacePoint() with an integer which specifies which surface will be called. - - - - - Returns the number of parametric surfaces within the object. - - The time at which to check. - - - - This method needs to be implemented if Object::IsParamSurface() returns TRUE. This method is used to retrieve a point on the surface of the object based on two parameters of the surface, u and v. Note: This method assumes there is a single parametric surface. If there is more than 1 (NumSurfaces() returns > 1, use the GetSurface() method below which allows for multiple surfaces. - - The time to retrieve the point. - The parameter along the horizontal axis of the surface. - The parameter along the vertical axis of the surface. - This interval is updated based on the interval of the surface parameter. - - - - This method is used to retrieve a point on the specified surface of the object based on two parameters of the surface, u and v. - - The time to retrieve the point. - The zero based index of the surface. This number is >=0 and <. - The parameter along the horizontal axis of the surface. - The parameter along the vertical axis of the surface. - This interval is updated based on the interval of the surface parameter. - - - - This method allows the object to return flags that indicate whether the parametric surface is closed in the U and V dimensions. the appropriate closure variables to TRUE if the surface is closed in that direction, FALSE if it is not. A torus, for example, is closed in both directions. - - The time to check the surface. - The zero based index of the surface. This number is >=0 and <. - to TRUE if the surface is closed in U; otherwise to FALSE. - to TRUE if the surface is closed in V; otherwise to FALSE. - - - - This method allows an object to return extended Properties fields. It is called when the Properties dialog is being prepared. If you don't want to display any extended properties, simply return FALSE. To display extended property fields, place the field label in the appropriate label string and the display value in a formatted string. Two fields are supplied, each with a label and a data string; if only using one, make the second label field and data field blank (""). Return TRUE to indicate you have filled in the fields. The properties dialog will display your returned values. - TRUE if this method is implemented and the fields are filled in; otherwise FALSE. - - The time at which the strings are requested. - The string for the property 1 label. - The formatted data string to appear as property 1. - The string for the property 2 label. - The formatted data string to appear as property 2. - - - - This method adds an extension object into the pipeline. Implemented by the System. - - Points to the extension object to add. - The priority of the object. The methods (, PreChanChangedNotify() etc) of higher priority XTCObjects will be called before those of lower priority XTCObjects. - The branch identifier of the object. - - - - Returns the number of extension objects maintained by this . Implemented by the System. - - - - - Returns a pointer to the specified extension object. Implemented by the System. - - The zero based index of the extension object to return. - - - - Removes the extension object as indicated by the index. Implemented by the System. - - The zero based index of the extension object to remove. - - - - Sets the priority for the extension object whose index is passed. Implemented by the System. - - The zero based index of the extension object to remove. - The new priority to assign. - - - - Returns the integer priority number of the extension object whose index is passed. Implemented by the System. - - The zero based index of the extension object to check. - - - - Sets the branch ID of the extension object whose index is passed. Implemented by the System. - - The zero based index of the extension object whose branch ID is set. - The branch identifier to set. - - - - Returns the integer branch ID of the extension object whose index is passed. Implemented by the System. - - The zero based index of the extension object whose branch ID is to be returned. - - - - This method has to be called whenever the CompoundObject updates a branch (calling Eval() on it). *from is the object returned from Eval(os.obj). The branchID is an integer that specifies that branch. The extension channel will get a callback to XTCObject::RemoveXTCObjectOnMergeBranches() and XTCObject::MergeXTCObject(). By default it returns true to RemoveXTCObjectOnMergeBranches which means that the existing XTCObjects with that branchID will be deleted. The method MergeXTCObject simply copies the XTCObjects from the incoming branch into the compound object. Implemented by the System. - - The object to merge additional channels from. - The branch identifier to set. - - - - This method has to be called on the CompoundObject so it can delete the XTCObjects for the specified branch. The will again have the final decision if the gets really deleted or not in a callback to XTCObject::RemoveXTCObjectOnBranchDeleted() which will return true if the XTCOject should be removed. Implemented by the System. - - Specifies which brach of the compound object the extension objects are deleted from. - TRUE to reorder the channels, otherwise FALSE. - - - - This method copies all extension objects from the "from" object into the current object. In case deleteOld is false the objects will be appended. If it is true the old XTCObjects will be deleted. Implemented by the System. - - The source object which contains extension objects. - If true the original objects are deleted after the copy; if false they remain after the copy. - If true only a is performed; if false a complete copy of the objects is done. - - - - Implemented by the System. This method will delete all additional channels. - - - - - This method allows an object to choose whether or not it will display selection brackets in shaded viewports. The method will return FALSE if no selection brackets are displayed or TRUE if it does display selection brackets. - - - - - Should reduce any derived display data to save memory, since the node wont be drawn until the user undhides it. - - - This function should delete any derived data used to display the object such as gfx normals, direct mesh caches etc. - Tnis is called when the user hides the node or sets it as bounding box - - - - - This returns whether the Graphics Cache for this object needs to be rebuilt. - - - Parameters: - *gw the active graphics window - *ma the material aray assigned to the mesh - int numMat the number of materials in the material array - - - - - - This builds the graphics window cached mesh. - - - Parameters: - *gw the active graphics window - *ma the material aray assigned to the mesh - int numMat the number of materials in the material array - BOOL threaded whether when building the cache it can use additional threads. This is needed since the system may be creating many meshes at the same time - - - - - - This are called right before and after a modifier is applied to an object. This allows for certain types of opitimizations to happens since durinng modifier modification the object knows what channels are changing and can do optimizations to speed things up like invalidating specific display channels which it does not know about when say a baseobject is evaluated. - - - - - This virtual class is implemented by applications that want to supply a conversion method from one object type to another. A typical use would be to support conversion of a native 3ds Max type (such as ) to a plug-in's object type. There are a set of global functions that can be used with this class. These are documented at the bottom of the topic. One of these is called to register the with the system. Note that the registered object converters are called from the methods: Object::CanConvertToType and Object::ConvertToType. - - So for individual objects to support these, they'll need to add the line - - if (Object::CanConvertToType(obtype)) return 1; - - to the end of their CanConvertToType methods and - - if (Object::CanConvertToType(obtype)) - - return Object::ConvertToType(t, obtype); - - to the end of their ConvertToType methods. - - - - - - This method returns the Class ID of the object this converter converts from. - - - - - This method returns the Class ID of the object this converter converts to. - - - - - This method actually performs the conversion, creating and returning a new object with the class ID specified in ConvertsTo(). - - Points to the object to convert. - - - - Description: - 3D Studio DOS allowed developers to store APP_DATA with objects and nodes in the scene. When the 3DS DOS file is imported into 3ds Max, and no plug-in has registered to convert it, then it is just hung off the object (or in the case of KXP app data). - - A 3ds Max plug-in can register itself to read a particular APP_DATA chunk when a 3DS DOS file is loaded. If a chunk is encountered that matches a registered plug-in, that plug-in will be asked to create an instance of itself based on the contents of the APP_DATA chunk. The plug-in callback is given an opportunity to read the chunk and create an object other than a based on the contents of the chunk and the original object. - - A plug-in that wants to process app data registers a new class derived from this class by calling RegisterObjectAppDataReader(ObjectDataReaderCallback *cb); - - The system then maintains a list of these ObjectDataReaderCallbacks. - - - - - Returns the name that identifies the app data chunk. When the 3DS Import plug-in is loading objects, it will look for app data. For each app data chunk that the object has, it will go through the list of registered callbacks and call this method looking for a name match. When it does find a match it will call ReadData() on the callback that matched. - - - - - This method is called to read the app data and create an instance of an object based on the data and the original mesh object. For example, the 3D Surfer plug-in from 3DS DOS creates a patch object based on the app data parameters and returns a pointer to it. - Parameters: - *obj - - The original mesh object the app data was assigned to. If no callback was registered, this would be the object that would get created. - - void *data - - Points to the particular app data chunk handled by the registered callback. - - DWORD len - - The length of the app data chunk. - The created by the plug-in to hold the appdata. This would be the object created to take the place of the . For example, consider a 3DS object that had appdata embedded in it which represented the patch object from which the mesh was created (like 3D Surfer for example). This method would take that data and created a patch object so that the user could work with the object as a patch object in 3ds Max instead of a tri object. - - - - - The is the structure that flows up the geometry pipeline. It contains a matrix, a material index, some flags for channels, and a pointer to the object in the pipeline. This is what is passed down the pipeline, and ultimately used by the Node to Display, Hittest, render. - - - - - Pointer to the object in the pipeline. The validity interval of the object can be retrieved using obj->ObjectValidity() - - - - - Call this method to update the object state flags. - - The flags to set. The specified flags are ORed into the current state of the flags. - - - - Call this method to clear the specified object state flags. - - The flags to clear. - - - - Call this method to test the specified flags. - Nonzero if the specified flags are all set; otherwise 0. - - The flags to test. - - - - Copies the specified flag settings from the specified object state to this object state. - - The flags to copy. - The source object state. - - - - Assignment operator. The object pointer, flags, transformation matrix (and its validity interval), and material (and its validity interval) are copied from the specified object state. - - - - - Returns the validity interval of the object state's transformation matrix. - - - - - Returns the validity interval of the object state's material. - - - - - Returns the validity interval of the object state. If the object is not defined, this interval is NEVER. Otherwise it is the intersection of the tm validity interval, the mtl validity interval and the interval returned from obj->ObjectValidity(t). - The validity interval of the object state. - - Specifies the time to retrieve the validity interval. - - - - Returns nonzero if the object state's transformation matrix is the identity matrix; otherwise zero. - - - - - Sets the object state's transformation matrix to the specified and its validity interval to the interval passed. If the specified matrix is NULL, a new is allocated and is initialized to the identity matrix. - - Specifies the matrix to set. - Specifies the validity interval to set. - - - - Returns the object state's transformation matrix. - - - - - Sets the object state tm to the identity transformation matrix. - - - - - Applies the specified matrix to the object state tm. The object state tm is multiplied by the specified matrix. The specified interval is intersected with the object state tm validity interval. - - The matrix to apply. - The interval to intersect with the object state's tm validity interval. - - - - Copies the object state tm (and its validity interval) from the specified object state's tm. - - The object state whose tm is to be copied. - - - - Copies the object state material (and its validity interval) from the specified object state's material. - - The object state whose material is to be copied. - - - - Invalidates the specified channels of the object state's object. - - The channels of the object to invalidate. - If checkLock is TRUE and OBJ_CHANNELS is one of the specified channels, the object the object state points to is not deleted if it is locked; otherwise it is deleted. - - - - Deletes the object state's object. - Operators: - - If checkLock is TRUE, the object the object state points to is not deleted if it is locked; otherwise it is always deleted. - - - - Description: - providing a common interface to , , and objects. - All methods of this class are implemented by the system. - - The provides a common interface to three common classes of geometry objects, , and , and is helpful when writing reusable code that is not type-dependant. Specifically, the is intended for use in plug-ins, when a developer wants to avoid writing three versions of code for the three object types. Note that objects of other types, such as NURBS and Particle Systems, are not directly supported by the , although the wrapper can attempt to convert them to a supported type. - - The defines an abstracted concept of vertices, faces, and edges. Vertices are defined as points in space; for objects, these are the patch knots. Faces are defined as either triangles, polygons or patches, according to the object type. For objects, no access is provided to the flag values of the vertices. For objects, no access is provided to the patch handles; methods which set the position of a vertex will move the patch knot and attempt to maintain the position of the handles relative to the knot. - - ObjectWrappers do not have a class ID or a class descriptor, and are not part of the reference hierarchy. They can be instantiated like primitive types using new() and delete(). The Init() method assigns a specific object to the wrapper after the wrapper is created. - - Note that using ObjectWrappers may incur a small performance penalty, because every method of the class must branch into the appropriate type-specific method, and is therefore slower than calling type-specific methods directly. - - - - - For internal use only. - - - - - Assign an object to the . If the object is not a supported type (specified by the enable flags), it will be converted, and a copy of the converted object is held internally. - True if the operation succeeds, False otherwise. - - - The current slider time - - The object - - True to make a duplicate of the object, False otherwise - - Flags indicating which types should be supported. The object will be converted to the native type (and a copy maintained) unless it is one of these supported types. For objects, set the bit . For objects, set the bit . For objects, set the bit . - - Indicates which type to convert to, if the object is not already a supported type. For , pass . For , pass . For , pass . - - - - Release internal data, and reset to an empty state. If the underlying object was copied or converted to a different type by the Init() method, then the maintains a copy internally, consuming a significant amount of memory. Calling this method is important to free the internal copy. - - - - - Indicates whether the wrapper is currently empty - True if no object is assigned to the wrapper, False otherwise - - - - - Indicates the type of the underlying object - For , returns ObjectWrapper::triObject. For , returns ObjectWrapper::polyObject. For , returns ObjectWrapper::patchObject. - - - - - Returns the object pointer, or NULL if the underlying object is not type - - - - - Returns the object pointer, or NULL if the underlying object is not type - - - - - Returns the object pointer, or NULL if the underlying object is not type - - - - - Clear the validity mask for verts, faces, or edges. The validity mask applies when calling the methods Verts(), Faces() and Edges(). These methods maintain internal copies of data from the underlying object. Clearing the validity flags ensures that the next call to one of these methods will allocate a new, updated list instead of returning a stale list. The validity flag for a channel should be cleared whenever the channel is modifier. However, methods will mark the flags automatically, so it is not necessary to call this method unless the underlying object is being modified outside of the . - - - The validity flags to clear. To clear the vertex channel, pass . To clear the face channel, pass . To clear the edge channel, pass . - - - - Calls the method InvalidateGeomCache() on the underlying object - - - - - Returns the number of geometric vertices - - - - - Returns the number of geometric faces - - - - - Returns the number of geometry edges - - - - - Returns an array of the geometric vertices. Note that this method incurs a memory usage penalty because it allocates an internal cache. If this method is called when the vertex channel has been invalidated, it will update the cache, which incurs an additional performance penalty - - - - - Returns an array of the geometric faces. Note that this method incurs a memory usage penalty because it allocates an internal cache. If this method is called when the face channel has been invalidated, it will update the cache, which incurs an additional performance penalty. - - - - - Returns an array of the geometric edges. Note that this method incurs a memory usage penalty because it allocates an internal cache. If this method is called when the edge channel has been invalidated, it will update the cache, which incurs an additional performance penalty. - - - - - Returns an individual geometric vertex - - - The index of the vertex to retrieve - - - - Sets the position of a geometric vertex - - - The index of the vertex to set - - The position of the vertex - - - - Returns an individual geometric face - - - The index of the face to retrieve - - - - Sets the data for geometric face - - - The index of the face to set - - The data for the face - - - - Returns an individual geometric edge - - - The index of the edge to retrieve - - - - Returns the number of edges bordering a specified geometric face - - - The index of the face - - - - Returns the index number of an edge bordering a specified geometric face - - - The index of the face - - The index of the edge relative to the face - - - - For objects, this calls MNMesh::GetVertexSpace(). For other types, this calls MatrixFromNormal() on the vertex normal. - - - The index of the vertex - - The vertex space matrix - - - - Returns the geometric normal of a vertex - - - The index of the vertex - - - - Returns TRUE if the specified mapping channel is supported; otherwise FALSE. - - - The index of the map channel - - - - Sets whether the specified mapping channel is supported or not. - - - The index of the map channel - - TRUE to indicate the channel is supported; otherwise FALSE. - - - - Returns the number of texture or vertex color vertices for the specified mapping channel. - - - The index of the map channel - - - - Sets the number of texture or vertex color vertices for the specified mapping channel. - - - The index of the map channel - - The number of vertices to allocate. - - - - Returns a single texture or vertex color value for the specified mapping channel. - - - The index of the map channel - - The index of the texture vertex - - - - Sets a single texture or vertex color value for the specified mapping channel. - - - The index of the map channel - - The index of the texture vertex - - The value to set - - - - Returns an individual texture mapping face for the specified mapping channel - - - The index of the map channel - - The index of the texture face - - - - Sets an individual texture mapping face for the specified mapping channel - - - The index of the map channel - - The index of the texture face - - The data for the face - - - - Returns the zero based material ID for the specified face - - - The index of the face - - - - Sets the material ID for the specified face - - - The index of the face - - The zero based material ID - - - - Returns the smoothing group bits for the specified face - - - The index of the face - - - - Sets the smoothing group bits for the specified face - - - The index of the face - - The smoothing group bits - - - - Returns the current level of selection for the object. See the selection enum values above - - - - - Returns the bits representing the vertex selection status - - - - - Returns the bits representing the face selection status - - - - - Returns the bits representing the element selection status. For all currently supported types, this is identical to the face selection, because the underlying types do not natively support the element selection level. - - - - - Returns the bits representing the specified selection status - - - The selection level. See the selection enum values above - - - - Returns the bits representing the specified selection status - - - The selection level. See the selection enum values above - - The selection bits - - - - Converts the bits representing a face selection into bits representing an element selection, and expands the selection accordingly. If any face in an element is selected according the input bits, then all faces within that element will be toggled as selected in the output bits. This method does not change the selection on the object; the methods SetFaceSel() or SetElemSel() are needed to apply a selection after it is calculated - - - The output selection bits for the element level - - The input selection bits for the face level - - - - Grows the selection for the specified level. The perimeter of the selection is expanded by one sub object. The resulting selection is stored in the output bits; This method does not change the selection on the object - - - The selection level. See the selection enum values above - - The output selection bits - - - - Shrinks the selection for the specified level. The perimeter of the selection is reduced by one sub object. The resulting selection is stored in the output bits; This method does not change the selection on the object - - - The selection level. See the selection enum values above - - The output selection bits - - - - Returns the soft selection parameters - - - The selection parameters - - - - Sets the soft selection parameters. Note that UpdateSoftSel() may be needed to recalculate the soft selection weights. - - - The selection parameters - - - - Recalculates the soft selection weights. Use this after setting the soft selection parameters. - - - - - Returns the vertex soft selection weights. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current object and the soft selection parameters. - - - - - Returns the viewport display color corresponding to the given vertex soft selection weight. - - - The selection weight, ranging from 0 to 1 - - - - Performs a viewport hit testing operation against the object - - - The selection level. See the selection enum values above. - - The graphics window associated with the viewport the object is being hit tested in. - - The list of materials for the mesh - - This describes the properties of a region used for the hit testing. See Class . - - Flags specifying how the hit testing is performed. Accepted values are SUBHIT_IGNOREBACKFACING to specify the ignore backfacing mode, plus the following values defined in : SUBHIT_UNSELONLY, SUBHIT_ABORTONHIT, SUBHIT_SELSOLID, and SUBHIT_USEFACESEL - - The hit list object to hold the results of the hit test operation. See Class . - - The number of materials for the mesh. - - The object-to-world transform matrix for the object. This needed to calculate backface culling if the underlying object is type and the flag ObejctWrapper:: SUBHIT_IGNOREBACKFACING is specified return TRUE if any hits were found, FALSE otherwise - - - - Intersects a ray against the object, returning the face and barycentric coordinates of the hit point. - - - The ray to cast - - The distance travelled by the ray to the intersection point. - - The surface normal at the intersection point. - - The face index of the intersected face - - The barycentric coordinates of the hit point. For and object, there may be more than three coordinate values return Nonzero if an intersection was found, zero otherwise - - - - Renders the object using the specified graphics window and array of materials. - - - Points to the graphics window to render to. - - The list of materials to use to render the mesh. - - Specifies the rectangular region to render. If the mesh should be rendered to the entire viewport pass NULL - - One or more of the following flags defined in : COMP_TRANSFORM, COMP_IGN_RECT, COMP_LIGHTING, COMP_ALL or COMP_OBJSELECTED - - The number of materials for the mesh - - - - Converts the selection level enum values into the type-specific equivalents. For instance, an input of ObjectWrapper::SEL_VERT (integer value 1) would return MESH_VERTEX (integer value 2) if the underlying object was type . - - - - - Converts the hit level enum values into the type-specific equivalents. For instance, an input of ObjectWrapper::SEL_VERT (integer value 1) would return SUBHIT_VERTS (integer value 1<< 25) if the underlying object was type . - - - - - A light must be able to create one of these objects to give to the renderer. As the renderer is getting ready to render, it will ask for one of these from each of the lights. The Illuminate() method (inherited from ) is called by the renderer to illuminate a surface point. There is an for every instance of the light. The renderer will ask each light object to produce one of these ObjLightDescs. It will then set this data up in the node's render data (See Class ). For example in 3ds Max's volume light implementation of Atmospheric::Update() it goes through its node references to lights and calls GetRenderData(). It then casts this as an . This is how a atmosphere effect can get access to these descriptors at render time. - - - - - The light state structure. See Structure . - - - - - The pointer of the instance of the light that created the current object. - - - - - Indicates if the light's scale is uniform or not. TRUE if uniform, FALSE if not. This saves some steps in the renderer if the scale is uniform. - - - - - The position of the light in camera space. - - - - - This is effectively the light node's object TM. This matrix will transform points from light space to world space. - - - - - This matrix will transform points from world space to light space. This is the inverse of lightToWorld. - - - - - This matrix will transform points from light space to camera space. This is updated in UpdateViewDepParams() - - - - - This matrix will transform points from camera space to light space. This is updated in UpdateViewDepParams(). For example, the renderer would have points in camera space. To figure out if a point was in shadow it would transform the point from camera space to light space using this matrix. It could then look in the shadow buffer to see if the point was in shadow. - - - - - This is set by the renderer. It is used in RenderInstance::CastsShadowsFrom(). This is a number used by the renderer to identify the lights so it can quickly determine if a given light casts shadows from a given object. It is for use by the renderer. - - - - - Retrieves the light's exclusion list. - See Class . - - - - - This method is called once per render to update the light state for things that depend on the position of objects and lights in world space. A plug-in light could update any data it would need to here. The default implementation is shown below. - The value return should normally be 1. A returned value of 0 means an error has occured (such as out of memory) and the render will be halted. - Default Implementation: - - The time of the render. - See Class . - This pointer may be used to retireve information about the global rendering enviornment. - TRUE if shadows are turned on (in the render parameters, not the light parameters); otherwise FALSE. - This tells the Update procedure that the geometry of the objects that are shadowed by the light has changed (TRUE) or not (FALSE). If it is a shadow buffer, shadowGeomChanged == TRUE means it has to re-render the shadow buffer, shadowGeomChanged == FALSE means it can use the shadow buffer from the previous frame. - - - - This method is called to update the light state that depends on the global light level. - - The global light level. - - - - This method is called to update the light state that depends on the view matrix. This is used to cache certain computed quantities that are dependent on where you are looking from. In a given scene at a given time, the system may render from several viewpoints. This is because of things like reflection maps and mirrors that need to get rendered. This method is called for each of these different viewpoints. - - The world space to camera space transformation matrix. - - - - This function traverses a ray through the light volume. This method is implemented by plug-in lights. - Consider how the 3ds Max atmospheric effects like the volume lights use - this information. For each light the atmospheric effect is bound to, it calls the this method (TraverseVolume()) on the light. The volume light atmospheric effect passes a callback to this method (proc). The light then calls the Step() method of the callback for each partial segment of the ray. Given the illumination on the segment it computes the fog density over that segment. The density may be constant if noise is not turned on, or it may change if noise is turned on. Using the fog density and the illumination it computes the light reflected off the atmosphere for the segment. - - This is the passed into the Shade() method of the effect. The shade context passed in should only be used for state (like are shadows globally disabled). The position, normal, etc. serve no purpose. - Defines the world space ray that will be traversed. - The number of samples to sample along the ray. A reasonable range is from 25-100. This is more or less the suggested number of times the proc->Step() callback will be called. It is not precisely however because the system may take greater or fewer steps than specified as it needs to. - This is the end of the ray. This is the point at which the traversal will stop (ray.p+tStop*ray.dir). Note that the traversal can terminate earlier if the callback returns FALSE. - Specifies a percent of the light attenuation distances that should be used for lighting during the traversal. This is used so a light can have an attenuation set to a certain percent, and then have the volume light be attenuated at a different point. - This specifies the ending percent of the light attenuation distances that should be used for lighting during the traversal. - There are three ways the shadow maps can be sampled. If none of these flags are set, the shadow map is sampled directly (this is the fastest). One of the following values: TRAVERSE_LOWFILTSHADOWS This is a simple filtering where the system samples a point in the shadow map and then some of the neighboring points. This corresponds to 'Medium' in the Volume user interface (a value of 0 for flags is 'Low' just sampling the shadow map with no filtering at all). TRAVERSE_HIFILTSHADOWS This is a higher resolution sampling. This corresponds to 'High' in the Volume user interface. TRAVERSE_USESAMPLESIZE This produces the highest quality. This corresponds to 'Use Sample Range' in the Volume user interface. This is like a box filter, but also takes into consideration the position of the point within the pixel to do additional weighting. - A developer derives a class from and implements the Step() method. A pointer to it is passed here as the callback object. - - - - A class used to list the fonts currently open - - - - - The index in . - - - - - The style flags. - - - - - The handle we know the font by. - - - - - The number of users. - - - - - The loader for the font. - - - - - If a renderer or other plugin wants to determine if an object is using Pixar's OpenSubdiv to perform subdivision, it can use the GetInterface method to query the for the OSD_PARAMETER_INTERFACE interface. If the node contains an object that uses OpenSubdiv, it will return a pointer to this interface class, otherwise it will return NULL. - Once you have a valid pointer, you can use this class to retrieve the parameters for OpenSubdiv's subdivision operations for that node. - - - - - Get the tessellation level of this object. - For non-adaptive subdivision, this is the number of iterations. For adaptive subdivision, this is the secondary tessellation level. - - - The time at which to sample - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Get the OpenSubdiv Vertex Boundary parameter - The OpenSubdiv VertexBoundary type to be used; see above enums - - - - - Get the OpenSubdiv Varying Boundary parameter - The OpenSubdiv VaryingBoundary type to be used; see above enums - - - - - Get the OpenSubdiv Crease Mode parameter - The OpenSubdiv CreaseMode type to be used; see above enums - - - - - Get the OpenSubdiv Smooth Triangle parameter - true if OpenSubdiv is to smooth triangles in its processing - - - - - Get the OpenSubdiv Adaptive parameter. - - - true if OpenSubdiv is to use adaptive subdivision in its processing - - - - - Get the OpenSubdiv Adaptive Tessellation parameter - The maximum number of iterations for adaptive tessellation - - - The time at which to sample - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - Class This class contains data used to report usage analytics through theHold.Accept method and the ADP mechanism. Each of the data members value are included in the way point report. - - - - - Command name string. Likely to be localized. only when is used internally in Max. - - - - - Super class id of the object influenced by the command. The one created, modified or deleted. May be 0. - - - - - Class id of the object impacted by the command. The one created, modified or deleted. May be invalid. - - - - - Additional command details string that have been provided at construction by the user. Shall not be localized. Can be anything. May be empty. - - - - - returns number of bits set in the TrueBlock - - - - - Description: - This is the base class for the derivation of a new object snap plug-ins. - - Conceptually, the osnap class represents a "rule" for locating points in an object's local space. Typically, an instance of this class will only make sense for certain object types. It's the job of the ValidInput() method to filter out uninteresting nodes in the scene. When the scene is traversed, each object which passes the input test will be passed into the Snap() method. This method is the workhorse of object snap plug-ins and is responsible for computing, allocating and recording its hits. - - For convenience, an object snap plug-in may encompass multiple sub-rules. For example, the shape snap contains rules for computing both tangents and perpendicular points on splines. Therefore many of the methods have an index argument which identifies which sub-snap it applies to. - - For sample code see /MAXSDK/SAMPLES/SNAPS/SPHERE/SPHERE.CPP. - - - - - Returns the number of sub-snaps this plug-in provides. - Default Implementation: - {return 1;} - - - - - Returns the category string for this plug-in. If the plug-in fails to override this method, the snap will be added to the "standard" page of the UI. - Default Implementation: - {return NULL;} - - - - - Returns the for this plug-in. - Default Implementation: - ; } - - - - - Developers have the option of placing all their code in a single Snap() method or of breaking it up into multiple callbacks. Developers wishing to use callbacks should override this method to return TRUE. Note: if callbacks are used, the Snap() method is not called. - Default Implementation: - {return FALSE;} - - - - - Returns the number of callbacks used. - Default Implementation: - {return 0;} - - - - - This method is provided for future use so that snaps can evaluate the object at arbitrary points in the pipeline. Returns TRUE if the object associated with the node passed is supported; otherwise FALSE. The default implementation calls ValidInput() and fills the storage pointed to by os with the object state at the end of the geometry pipeline. This is the same object state returned by EvalWorldState. - Parameters: - *iNode - - The node whose object being checked. - - TimeValue t - - The time at which to check the object. - - *os - - This pointer should be updated to the of the object associated with the node by calling INode::EvalWorldState(). - Default Implementation: - Osnap::GetSupportedObject os) { - - *os = inode->EvalWorldState(t); - - assert(os); - - ; - - unsigned long supertype = os->obj->SuperClassID(); - - return ValidInput(supertype,thistype)?TRUE:FALSE; - - } - - - - - Returns a pointer to the snap's name to be displayed in the user interface. - Parameters: - int index - - The index of the sub-snap whose name is returned. - - - - - Reserved for future use. - Parameters: - int index - - The index of the sub-snap whose name is returned. - Default Implementation: - {return NULL;} - - - - - This method is used to check if the object whose super class ID and class ID are passed is valid input for this object snap plug-in to snap to. - Parameters: - SClass_ID scid - - The Super Class ID to check. - - cid - - The Class ID to check. - Returns TRUE if the object is OK to snap to; otherwise FALSE. - Sample Code: - boolean SphereSnap::ValidInput(SClass_ID scid, Class_ID cid){ - - boolean c_ok = FALSE, sc_ok = FALSE; - - sc_ok |= (scid == GEOMOBJECT_CLASS_ID)? TRUE : FALSE; - - )? TRUE : FALSE; - - return sc_ok && c_ok; - - } - - - - - This method should return a pointer to a (typically static) . These markers define the identifying markers which get displayed in the viewports. - Parameters: - int index - - The subsnap whose marker the system requires. - A pointer to an . If this method returns NULL, a default marker will be displayed. - - - - - Returns a value to indicate the type of highlighting to be done for this snap. Typically, some part of the objects geometry is illuminated. In some cases it is desirable to illuminate the objects bounding box and occasionally to draw a world space crosshair. The default implementations should normally be used. - One or more of the following values: - - HILITE_NORMAL - - This is the default and indicates that some part of the objects geometry will be highlighted. The description of this geometry is recorded in the hitmesh member of the class . - - HILITE_BOX - - This is return value indicates that the objects bounding box should be drawn as the result of a hit on this object. - - HILITE_CROSSHAIR - - Reserved for grid snapping. This return value indicates that a world space crosshair should be drawn through the hitpoint. - Default Implementation: - {return HILITE_NORMAL;} - - - - - This method is reserved for future use. - Default Implementation: - {return TRUE;} - - - - - This method is reserved for future use. - Default Implementation: - {} - - - - - Returns a handle to a bitmap that contains the icons to be displayed for this snap. If there are N subsnaps, this bitmap should contain N icons. The size of an individual icon is 16x15 or 16x16. - - - - - Returns a handle to a bitmap that contains the masks for the UI icons for this snap plug-in. - - - - - This is the workhorse of a snap plug-in. This method should compute and record hits on the given object. - Parameters: - Object* pobj - - A pointer to an object which passed the valid input test. Note that if this method is called, you can make certain assumption about the class of the object and do appropriate casting as needed. - - *p - - The cursor position. - - TimeValue t - - The time at which to check. - Default Implementation: - {} - - - - - Developers may override this method to do additional hit testing on each object as an additional rejection criteria. The default implementation returns TRUE and consequently filters nothing. Note that if this method returns FALSE for a given object, the snap method will never be called for it. - - Note: Nodes are always trivially rejected if the cursor position does not fall within the screen space bounding box of the node. - Parameters: - Object* pobj - - A pointer to the object returned by GetSupportedObject. - - *p - - The cursor position. - - TimeValue t - - The time at which to hittest. - Returns TRUE if the object is being hit and should be considered for snapping. - Default Implementation: - {return TRUE;} - - - - - Returns the specified callback to be used for snapping. - Parameters: - int sub - - The sub-snap index. - Note the following typedef - a SnapCallback is simply a pointer to a function passed two arguments: - - *p) ; - Default Implementation: - { return NULL;} - - - - - This method is no longer used. - - - - - Returns the reference to the snap's icon name - Parameters: - int index - - The index of the sub-snap whose icon name is returned. - - - - - Description: - This class encapsulates the data required to record a snapped point. Typically a plug-in creates instances of this class and records them with the OsnapManager. The manager is responsible for freeing the memory associated with recorded hits. All the methods of this class are implemented by the system. If a snap plugin needs to record additional data for its hits, it should derive from this class and provide a clone method which copies this additional data and calls the base classes clone method. - - - - - Assignment operator. - Parameters: - & h - - The to assign. - - - - - Returns a pointer to a new instance of the class and initializes it with this instance. Developers deriving from this class should overide this method. - - - - - This method is not currently used. - - - - - Implemented by the system. - - This method determines the damage rectangle for this hit. - Parameters: - TimeValue t - - The time at which to compute the rectangle. - - *vpt - - The viewport in which to compute the rectangle. - - Rect *rect - - Points to storage for the computed result. - - int marksize - - The size of the icon. - - - - - Returns the hit location in object space. - - - - - Returns the hit location in world space. - - - - - Returns the hit location in screen space. IPoint3.z is the depth in screen space. - - - - - Returns the sub-snap index which made this hit. - - - - - Returns a pointer to the node which got hit. - - - - - Implemented by the System. - - This method updates the internal data to reflect a change in time. For example, if a hit is recorded on the endpoint of a particular edge of a mesh, the node moving would invalidate the hit data and a call to this method would be required before using its data. - Parameters: - TimeValue t - - The time at which to reevaluate it. - The updated point in world space. - - - - - Description: - This class is used for drawing markers in the viewports. The marker is drawn as a polyline. The class maintains a cache of the points for the polyline. There are constructors used to initialize the cache and a display() method to draw the marker in the specified viewport. - - The class must implement the GetMarkers() method which typically returns pointers to these static instances. - - - - - Assignment operator. - Parameters: - & om - - The to assign. - - - - - Description: - This class extends/decorates class with a few useful methods. Snap plugins should continue to derive from class . Code that wishes to work with these plugins can use them directly or create and work with instances of this class - - - - - Returns true if the snap identified by the index parameter is active - - - - - Turns On the snap identified by the index parameter - - - - - Turns Off the snap identified by the index parameter - - - - - If a feature needs to determine and/or set the OpenSubdiv modifier's parameters, it can use the GetInterface method to query the for the OSD_MODIFIER_INTERFACE interface. If the is an OpenSubdiv modifier, it will return a pointer to this interface class, otherwise it will return NULL. - Once you have a valid pointer, you can use this class to retrieve and set the parameters for the OpenSubdiv modifier - - - - - the OpenSubdiv Vertex Boundary parameter - - - The OpenSubdiv VertexBoundary type to be used; see enums in - - - - the OpenSubdiv Varying Boundary parameter - - - The OpenSubdiv VaryingBoundary type to be used; see enums in - - - - the OpenSubdiv Crease Mode parameter - - - The OpenSubdiv CreaseMode type to be used; see enums in - - - - the OpenSubdiv Smooth Triangle parameter - - - true if OpenSubdiv is to smooth triangles in its processing - - - - the OpenSubdiv Adaptive parameter - - - true if OpenSubdiv is to use adaptive subdivision in its processing - - - - the operation mode. - - - The operation mode (see enums above) - - - - the uniform tessellation level of this object for the renderer. - - - The time at which to set - - The number of iterations - - - - the general uniform tessellation level of this object. - - - The time at which to set - - The number of iterations - - - - the OpenSubdiv Adaptive Tessellation level parameter - - - The time at which to set - - The maximum number of iterations for adaptive tessellation - - - - This is a base class developers creating object space modifiers may derives their plug-ins from. It simply provides a default implementation of SuperClassID(). - - - - - - Description: - This is a post load call back for fixing up parameter block2s. This callback handles conversion of pre-ParamBlock2 versions of an object to a ParamBlock2 version. NOTE: this thing deletes itself when it's done. - Data Members: - All data members are public. - - ParamVersionDesc* versions; - - This is an array of ParamVersionDesc2s. - - int count; - - This is the number in the array specified above. - - ParamBlockDesc2* curdesc; - - This is a pointer to the current version of the description. - - ReferenceTarget* targ; - - This is a pointer to a reference target. This is usually the this pointer of the object. - - int pbRefNum; - - This is the reference index of the parameter block. - - - - - Description: - The parameter block descriptor describes each parameter in a parameter block. { - - - - ParamType type; - - *user; - - BOOL animatable; - - }; - Data Members: - ParamType type - - The parameter type. See ParamType and ParamType2. - - *user - - This value is not used - it must always be passed as NULL. - - BOOL animatable - - This is a flag indicating if the parameter may be animated or not. Pass TRUE if the value may be animated and FALSE if it is constant. - - - - - Description: - In the Parameter Block2 scheme there is one object per entire Parameter Block2. - - This class is used when adding a paramblock descriptor for each parameter block2. This is usually done in the form of a static instance of this class. The constructor takes a number of fixed, block-related arguments and then a varargs-based variable list of arguments that define the block and its parameters. - - All methods of this class are implemented by the System. - Data Members: - ParamDef* paramdefs; - - of parameter definitions. - - ClassDesc2* cd; - - This is the class descriptor of the class which owns this parameter block descriptor. - - MCHAR* int_name; - - This is the internal name of this parameter descriptor. This name is not localized. Internal names are meant to be parsable as identifiers. As such they should begin with an alpha character, have only alphanumerics, and have no spaces, punctuations, etc. The convention for multi-word names is to use studly-caps, eg, paintRadius. - - int local_name; - - This is the string table resource ID for the localized (sub-anim) name. - - BlockID ID; - - The permanent parameter block ID. - - USHORT count; - - The number of parameters in block. - - ULONG version; - - This is the parameter block version. - - BYTE flags; - - One or more of the following 11 values (see the constructor argument flags below for details): (New in Max8) Note: The following data members are optional and used by the auto-construct code: - - int ref_no; - - The reference number for the auto-constructed parameter block. - - int dlg_template; - - The rollout dialog template resource. - - int title; - - table resource ID of the rollout title. - - int test_flags; - - The ClassDesc2::Begin/EndEditParams() test flags. See the flag_mask parameter description below for details. - - int rollup_flags; - - This is used to control rollup creation. See the rollup_flags parameter description below for details. - - ParamMap2UserDlgProc* dlgProc; - - Points to the parameter map user dialog proc (if used). - - MSPluginClass* pc; - - If this belongs to a scripted plug-in this points to the scripted class (or NULL otherwise). SeeMAXScript SDK. - - Value* rollout; - - If this belongs to a scripted plug-in this points to rollout name. See MAXScript SDK. - - IParamBlock2* class_params; - - Pointer to class parameter block if the CLASS_PARAM flag is specified for the block. See the flags descriptions below for details. - - - - - This method is used for building descriptors incrementally. It adds a parameter to an existing descriptor. - - Note that you must not modify a descriptor with this function once it has been used to construct a ParamBlock2 (for instance in object creation); there is no version control in place and crashes or unpredictable results can occur. - Parameters: - ParamID id, ... - - This function takes a single parameter definition in exactly the same varargs format as the constructor. See the Constructors section. - - - - - This method is used for modifying a descriptors incrementally. It overrides an existing parameter definition of same ID passed. Note: You must not modify a descriptor with this method once it has been used to construct a ParamBlock2. - Parameters: - ParamID id, ... - - This function takes a single parameter definition in exactly the same varargs format as the constructor. See the Constructors section. - - - - - Deletes the specified parameter from the descriptor. - Parameters: - ParamID id - - The permanent ID of the parameter to delete. - - - - - Deletes the specified parameter from the descriptor. - Parameters: - int index - - The index of the parameter to delete. - - - - - Deletes all parameters from the descriptor. - - - - - This method is used for modifying a descriptor incrementally. It alters a parameter definition optional information tag of an existing descriptor. Note: You must not modify a descriptor with this method once it has been used to construct a ParamBlock2. - Parameters: - ParamID id - - The permanent ID of the parameter. - - int option_tag, ... - - This method takes a single tagged option in the same varargs format as the tagged parameter options in the constructor. See the <optional_tagged_param_specs> section in the constructor's documentation. - - - - - Modifies the list of controls enabled by a certain control This method allows to modify the list of controls that are enabled/disabled by a given control that represents a boolean parameter. Any existent list of dependent controls are replaced. - - - pID The identifier of the control to be modified. The id must designate a control in this parameter block descriptor. - dependentPIDs Identifiers that depend on the control specified by pID. - The parameters must be part of the same parameter block descriptor as the parameter that controls them (pID). - True if the control was modified successfully, false otherwise - A parameter descriptor should not be modified after a parameter block has been created based on it. - - - - - This method is used for modifying a descriptor incrementally. It allows for specifying the content of certain controls such as list and combo boxes by supplying a list of string resource ids. This method alters a parameter definition optional information tag of an existing descriptor. Note: You must not modify a descriptor with this method once it has been used to construct a ParamBlock2. - - - - - The permanent ID of the parameter to be modified - - Resource ids of the strings that represent the user visible values for this parameters - - Optional list of integer values to be associated with the corresponding item in the stringItems parameter. If this parameter is not specified, the items in stringItems will be associated with their zero based index. - - - - This method sets the pointer maintained by this class. You can only call this method once on a descriptor and then only if it has been constructed initially with a NULL cd. See the notes in the constructor. - Parameters: - ClassDesc2* pCD - - Points to the to set. - - - - - Returns the number of parameters in the block. - - - - - Returns the version of the parameter block. - - - - - Returns the index into the parameter definition array of the parameter whose ID passed. - Parameters: - ParamID id - - The permanent parameter ID. - - - - - Finds the parameter with the matching internal name (ParamDef::int_name), and returns its index. Returns -1 is the parameter is not found. - The name comparison is case-insensitive. - - The internal name of the parameter to find (see ) - - - - Returns the permanent parameter ID of the parameter whose index is passed. - Parameters: - int i - - The zero based index of the parameter in the paramdefs array. - - - - - This method is used for accessing a parameter's structure. - Parameters: - ParamID id - - The permanent ID of the parameter. - - - - - Returns the parameter definition for the parameter with the given index. - A pointer to the parameter definition for the given index, or null if the index is invalid. - - Index of the parameter to be fetched. - - - - This method is used with static class parameter blocks only. - - Sets the floating point value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - float v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the integer value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - int v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the \ \ value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - & v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - & v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the string value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - MCHAR* v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the Mtl* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - Mtl*v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the Texmap* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - Texmap* v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the PBBitmap* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - PBBitmap* v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the INode* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - INode* v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the ReferenceTarget* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - ReferenceTarget*v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Sets the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to set the value. - - & v - - The value to set. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to set. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the floating point value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - float& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the integer value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - int& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the \ \ value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - & v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - & v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the string value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - MCHAR*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the Mtl* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - Mtl*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the Texmap* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - Texmap*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the PBBitmap* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - PBBitmap*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the INode* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - INode*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the ReferenceTarget* value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - ReferenceTarget*& v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Retrieves the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t - - The time at which to get the value. - - & v - - The value to retrieve is returned here. - - &ivalid - - This is the validity interval which is updated by the validity of the retrieved parameter. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - TRUE on success; otherwise FALSE. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The value of the parameter. - - - - - This method is used with static class parameter blocks only. - - Retrieves the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The \ \ value of the parameter - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The integer value of the parameter. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The floating point value of the parameter. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The TimeValue value of the parameter. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - The TimeValue value of the parameter. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - A pointer to the object. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - A pointer to the . - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - A pointer to the object. - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - A pointer to the . - - - - - This method is used with static class parameter blocks only. - - Returns the value of the specified parameter at the specified time. - Parameters: - ParamID id - - The permanent ID of the parameter. - - TimeValue t=0 - - The time at which to get the value. - - int tabIndex=0 - - If the parameter is a <> this is the zero based index into the table of the value to get. - A pointer to the . - - - - - Returns a string resource from plug-in module's resource. - Parameters: - StringResID id - - The permanent ID of the parameter. - - - - - This method invalidates any current parameter map2 user interface currently open for this descriptor. - - - - - This method invalidates the control whose parameter ID is specified. - Parameters: - ParamID id - - The permanent ID of the parameter. - - int tabIndex=-1 - - If the parameter is a <> this is the zero based index of parameter whose associated control is to be redrawn. - - - - - This overload of SetUserDlgProc() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to set the user dialog proc for. See original function for the rest of the description. - - - - - This method allows for special handling for a set of controls. The developer provides a dialog proc object to process the message from the controls. This method is used to tell the parameter map that the developer defined method should be called. The given proc will be called after default processing is done. Note that if the proc is non-NULL when the ParamMap is deleted its DeleteThis() method will be called. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of SetUserDlgProc() with default map ID of 0. - Parameters: - ParamMap2UserDlgProc* proc=NULL - - A pointer to the user dialog proc object to process the control. - - - - - Returns the user dialog proc for the parameter map associated with this descriptor. - Parameters: - MapID map_id - - Specifies the ID of the map/rollout to get the user dialog proc for. - - - - - This method allows dynamic setting of the P_OWNERS_REF reference number for given Reference Target parameter. - Parameters: - ParamID id - - The permanent ID for the parameter. - - int refno - - The reference number to set. - - - - - This method returns the P_OWNERS_REF reference number for given Reference Target parameter. - Parameters: - ParamID id - - The permanent ID for the parameter. - - - - - Sets the sub-texture number for the specified texmap parameter. You can use this to dynamically change a parameter's sub object number. - Parameters: - ParamID id - - The parameter ID for the texmap. - - int texno - - The sub-texture number to set. - - - - - Sets the sub-material number for the specified texmap parameter. You can use this to dynamically change a parameter's sub object number. - Parameters: - ParamID id - - The parameter ID for the material. - - int mtlno - - The sub-material number to set. - - - - - Returns the sub-texture number for the specified parameter. - Parameters: - ParamID id - - The ID of the parameter. - - - - - Returns the sub-material number for the specified parameter. - Parameters: - ParamID id - - The ID of the parameter. - - - - - This method allows dynamic setting of the TYPE_OPEN/SAVEFILEBUTTON p_init_file field. - Parameters: - ParamID id - - The permanent ID for the parameter. - - MCHAR* s - - The string to set. - - - - - This method returns the TYPE_OPEN/SAVEFILEBUTTON p_init_file field. - Parameters: - ParamID id - - The permanent ID for the parameter. - - - - - Adds an interface to the descriptor's interfaces list. - - - The interface can later be obtained from the list using GetInterface() - - The interface to add - - - - Removes an interface from the descriptor's interfaces list. - - - - The interface to remove - - - - Allows a custom filter list to be supplied to the File dialog routines. - - - - The parameter that defines a file dialog - A string containing a correctly formatted filter list. This buffer is maintained by the calling code - - - - Description: - The parameter block descriptor describes each parameter in a parameter block. This version has an ID used to identify each parameter. - - { - - - - ParamType type; - - *user; - - BOOL animatable; - - DWORD id; - - }; - Data Members: - ParamType type - - The parameter type. See ParamType and ParamType2. - - *user - - This value is not currently used - it must always be passed as NULL. - - BOOL animatable - - This is a flag indicating if the parameter may be animated or not. Pass TRUE if the value may be animated and FALSE if it is constant. - - DWORD id - - This is an ID used to identify this parameter. This provides a solution to the problem of backwards compatibility. If you alter the parameter structure of your plug-in in the future (by adding or deleting parameters for example) previously saved 3ds Max files will be incompatible. You can however use a mechanism which uses these IDs to convert older versions to the current version. See the Advanced Topics section on ~{ Parameter Maps }~ for more detail on how this is done. ParamID pb2_id - - This is an ID used to identify this parameter in a . There are 2 special values for this member: -1 - This parameter is not used in the -2 - Use the 'id' member value as the id. Otherwise, the value specifies the parameter id that corresponds to this parameter. This member is used by function CopyParamBlock2ToParamBlock, ProcessPB2ToPB1SaveToPrevious, and when copying parameters between and instances - - - - - This is a handy post load call back for fixing up parameter blocks. This will look up the version of the loaded callback and fix it up so it matches the current version. NOTE: this deletes itself when its done. See ~{ Parameter Maps }~ for more details. - - - - - - - Safe method for getting the targ member variable. This performs extra checks to ensure that pointer targ is still valid and hasn't been deleted. - Returns targ if the pointer is still valid, otherwise NULL. - - - - - Gets the refNum Reference on the member targ. - - - - - Description: - Any parameter that can be controlled by a controller has a dimension. This dimension can be considered a unit of measure. It describes its type and its order of magnitude. When a controller needs to display the parameter values (for example in the function curve editor) it converts the value using its parameter dimension Convert() function. It can also convert back using the Unconvert() function. - - Some parameters are stored over one range of values and displayed in another. For example parameter that use stdAngleDim store their parameters in radians but display them in degrees. By using stdAngleDim the value is converted to the proper format for display. Some parameter dimensions do not perform any conversion, for example stdWorldDim. - - There are several default parameter dims implemented. Listed with each one is the type, convert functions and range of values usually stored (these are not enforced in any way). - - If the type of parameter for your plug-in does not fit within any of the dimensions listed here you may simply use defaultDim. This performs no conversions and has no range. - - *defaultDim; - - Convert() is original value. - - UnConvert() is original value. - - Range: None. - - *stdWorldDim; - - The DimType is DIM_WORLD - - Convert() return original value. - - UnConvert() returns original value. - - *stdAngleDim; - - The DimType is DIM_ANGLE. - - Convert() is RadToDeg() - - UnConvert() is DegToRad() - - *stdColorDim; - - The DimType is DIM_COLOR - - Convert() return original value. - - UnConvert() returns original value. - - Range: 0-1 - - *stdColor255Dim; - - The DimType is DIM_COLOR255 - - Convert() is value * 255.0f - - UnConvert() is value / 255.0f - - Range: 0-255 - - *stdPercentDim; - - The DimType is DIM_PERCENT - - Convert() is value * 100.0f - - UnConvert() is value / 100.0f - - Range: 0-100 - - *stdNormalizedDim; - - The DimType is DIM_NORMALIZED - - Convert() is original value. - - UnConvert() is original value. - - Range: 0-1 - - *stdSegmentsDim; - - The DimType is DIM_SEGMENTS - - Convert() is original value. - - UnConvert() is original value. - - *stdTimeDim; - - The DimType is DIM_TIME - - Convert() is value/GetTicksPerFrame() - - UnConvert()is value*GetTicksPerFrame() (see the section ~{ Time Functions }~ for details). - If the DimType is custom then the methods below must be implemented. Note: This class is derived from which provides methods DimensionType(), Convert() and Unconvert(). - - - - - Returns the dimension scale. - - - - - Sets the dimension scale. - - - - - Returns the name of the dimension. - - - - - Description: - This class (along with ) describes the dimension of a parameter. This dimension can be considered a unit of measure. It describes the parameter's type and order of magnitude. - - The dimension type and possibly the dimension scale (if the type is custom) are used to determine a scale factor for the parameter. When a controller is drawing a function curve, it only needs to use the Convert() function - the scale factor is rolled into the single 'vzoom' parameter passed to Animatable::PaintFCurves(). So, for a controller to plot a value 'val' at time t it would do the following: - - TimeToScreen(t,tzoom,tscroll); - - int y = ValueToScreen(dim->Convert(val),rect.h()-1,vzoom,vscroll); - - - - - Returns the dimension type of the parameter. See Dimension Types - - - - - When a controller needs to display the parameter values (for example in the function curve editor) it converts the value using this method. - The converted value. - - The value to convert. - - - - This method is used to un-convert from a displayed value to the actual value - The un-converted value. - - The value to un-convert. - - - - Converts integer values based on the parameter dimensions. In order to ensure that integers larger than 2 ^ 24 - 1 are converted properly, use this method instead of ParamDimensionBase::Convert(float value) - - - This method converts the integer parameter value to a float value and calls Convert on that float value. If the return value from that call is unchanged, the original integer value is returned, otherwise the returned float value cast to an integer is returned. This is to handle the case where a large integer value (>2^24 - 1) that cannot be represented as a float value is passed. This would result in a value change even though the Convert implementation itself did not change the value. - The converted value. - - The value to convert. - - - - Unconverts integer values based on the parameter dimensions. In order to ensure that integers larger than 2 ^ 24 - 1 are converted properly, use this method instead of ParamDimensionBase::UnConvert(float value) - - - This method converts the integer parameter value to a float value and calls UnConvert on that float value. If the return value from that call is unchanged, the original integer value is returned, otherwise the returned float value cast to an integer is returned. This is to handle the case where a large integer value (>2^24 - 1) that cannot be represented as a float value is passed. This would result in a value change even though the UnConvert implementation itself did not change the value. - The converted value. - - The value to convert. - - - - Description: - Every sub-class defines a to manage its part of the material editor. - - - - - Returns the unique of the plug-in this dialog manages. See Class . - - - - - This method returns the current material or texture being edited. - - - - - This method is called when the current time has changed. This gives the developer an opportunity to update any user interface data that may need adjusting due to the change in time. - Parameters: - TimeValue t - - The new current time. - - - - - This method should stuff values into all the parameter dialog's controls, edit fields etc. In fact this method is now only called after doing a "Reset". It is also useful inside the material/map when a NotifyRefChanged() is processed it may need to be called. - - - - - This method is called when the dialog box becomes active or inactive. Currently this is used when working with color swatch custom controls. swatches need to know when the dialog box becomes active or inactive because they change their method of drawing themselves. When the dialog is active, color swatches are drawn in pure color (this requires a color register in the palette). When the dialog becomes inactive the color swatches are drawn using dithered painting. This is needed because there are only 8 available color registers. - - A method of the color swatch control is called to indicate if it is in an active or inactive dialog. See the sample code below. Also see Class . - Parameters: - BOOL onOff - - TRUE if the dialog is active; otherwise FALSE. - Sample Code: - - - - - This method needs to be implemented if the plug-in texmap is using a . It should return the index of the sub-texmap corresponding to the window whose handle is passed. If the handle is not valid return -1. - Parameters: - HWND hwnd - - The window handle to check. - Default Implementation: - { return -1;} - Sample Code: - - - - - This method needs to be implemented if the plug-in material is using a . It should return the index of the sub-map corresponding to the window whose handle is passed. If the handle is not valid return -1. - Parameters: - HWND hwnd - - The window handle to check. - Default Implementation: - { return -1;} - - - - - Description: - If there are controls which require custom handling you can create an object from this class and set it as the parameter map's user callback (usually using SetUserDialogProc()). - - - - - This gets called if the DlgProc is registered with a parameter map associated with one of the IAutoXXXParamDlg instances and that dialog has SetThing() called on it. This provides a simple way for the user dialog proc to track changes to the underlying object in the parameter map. - Parameters: - *m - - The item that was set. - Default Implementation: - {} - - - - - This is a variant of Update() method in used to supply more context, including the pmap itself and its validity interval. Changes you make to the validity internal passed in affect the validity interval of the whole parammap. - Parameters: - TimeValue t - - The time at which the update is taking place. - - & valid - - The validity interval of the parameter map. - - *pmap - - The parameter map the user dialog proc is associated with. - - - - - Use this overload when validity interval is irrelevant. - - - - - Description: - This class is used with parameter maps. If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback (usually using SetUserDialogProc()). - - - - - This is the dialog proc that will be called to process the control messages. This proc will be called after the default processing is complete. - Parameters: - TimeValue t - - This is the current time. - - *map - - This is a pointer to the parameter map. - - HWND hWnd - - This is the handle to the dialog. - - UINT msg - - This is the message that should be processed by the dialog proc. - - WPARAM wParam - - This is a parameter that holds message specific information. - - LPARAM lParam - - This is a parameter that holds message specific information. - This is essentially the equivalent of a normal Windows dialog proc, so it should return whatever value a normal dialog proc returns for the message. An exception is that the value REDRAW_VIEWS may be returned to cause the viewports to be redrawn. - - - - - This method is available in release 2.0 and later only. - - This method is called whenever the dialog is being updated. If the parameter map is invalidated, 3ds Max will update the user interface. When it does, this method is called so a developer may do anything they need to on each update. - Parameters: - TimeValue t - - The time at which the update is taking place. - Default Implementation: - {} - - - - - - - Description: - The class is used in conjunction with the parameter maps mechanism. It is used for creating descriptors that define the properties of a user interface control such as its type (spinner, radio button, check box, etc.), which resource ID it refers to, and which index into the virtual array of parameters it uses. See the Advanced Topics section on ~{ Parameter Maps }~ for an overview of how these descriptors are used. - - - - - Description: - This structure describes a version of the parameter block. - Data Members: - *desc; - - This is an array of parameter block descriptors. - - int count; - - This is the number of items in the array. - - DWORD version; - - This is the version number. - - - - - constructors/destructor/assigning - - - - - Test for equality. - - - - - set standard read/write and custom channels methods. If a custom particle channel is indeed a standard particle channel then it's stored as a flag - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - See PFExport void SetReadChannels() - - - - - get channels methods - - - - - has channels methods. Returns true if the channel is present - - - - - returns true if all readChannels are present - - - - - returns true if all writeChannels are present - - - - - This is the base class for creating particle system plug-ins. Many particle systems may be derived from class instead of this class. See Class for more details. Note: This class is derived from and still has GEOMOBJECT_CLASS_ID as its super class. To determine if an object is a , call: Animatable::GetInterface() with the ID I_PARTICLEOBJ or use the macro: GetParticleInterface(anim) where anim is the object in question. This will return a ParticleObject* or NULL. See Class . Note: See the method Animatable::GetProperty() for details on choosing the method used to evaluate the particle system during motion blur rendering. - - - - - This method is called to add the force field object passed to the list of force field objects operating on this particle system. - Sample Code: - - Points to an instance of a object. - - - - This method is called to add the collision object passed to the list of collision objects operating on this particle system. - If a particle does not support this method it should return FALSE; otherwise return TRUE. - Sample Code: - - Points to an instance of a collision object. - - - - Returns the position of the specified particle in world space at the time passed. The Particle Age texture map and the Particle Motion Blur texture map use this method. - When a texture map calls these methods, the particle index i is passed to the texmap in the data member ShadeContext::mtlNum. The particle systems encode the index of the particle associated with the face of the particle mesh being shaded into the mtlNum. For instance, once the particle system generates a mesh to be rendered, every face of the mesh corresponds to a particle. This isn't a one-to-one correspondance because there are more faces than particles (if the particles are represented as tetrahedrons there are four faces per particle). When a texture map or material that is shading a mesh generated by a particle system wants to know which particle the face is associated with it gets this info out of the ShadeContext::mtlNum. For example, here is a fragment of the code from the Particle Age texture map where it evaluates the color of the point being shaded: - - The time to return the particle position. - The index of the particle. - - - - Returns the velocity of the specified particle at the time passed (in 3ds Max units per tick). This is specified as a vector. The Particle Age texture map and the Particle Motion Blur texture map use this method. - - The time to return the particle velocity. - The index of the particle. - - - - Returns the world space size of the specified particle in at the time passed. The Particle Age texture map and the Particle Motion Blur texture map use this method. - - The time to return the particle size. - The index of the particle. - - - - Returns a value indicating where the particle geometry (mesh) lies in relation to the particle position. This is used by Particle Motion Blur for example. It gets the point in world space of the point it is shading, the size of the particle from ParticleSize(), and the position of the mesh from ParticleCenter(). Given this information, it can know where the point is, and it makes the head and the tail more transparent. - One of the following: PARTCENTER_HEAD The particle geometry lies behind the particle position. PARTCENTER_CENTER The particle geometry is centered around particle position. PARTCENTER_TAIL The particle geometry lies in front of the particle position. - - The time to return the particle center. - The index of the particle. - - - - Returns the age of the specified particle - the length of time it has been 'alive'. The Particle Age texture map and the Particle Motion Blur texture map use this method. - - Specifies the time to compute the particle age. - The index of the particle. - - - - Returns the life of the particle - the length of time the particle will be 'alive'. The Particle Age texture map and the Particle Motion Blur texture map use this method. - - Specifies the time to compute the particle life span. - The index of the particle. - - - - If a particle system has a fixed number of particles of fixed topology, then it can return TRUE for this method, and the renderer will then compute the image motion blur velocities based on the vertex motions, giving motion blur for rotating particles etc. If the particle system is topology-varying it should return FALSE. - - - - - Description: - This class describes a particle system. Methods are available to display, hit test, and compute the bounding box of the particle system. Other methods allocate and free the particles and allow custom particle drawing procedures to be used. - Data Members: - > points; - - The location of each particle. - - > vels; - - The velocity of each particle (optional). - - <TimeValue> ages; - - The age of each particle (optional). - - float size; - - The world space radius of a particle. - - - - - Implemented by the System. - - Draws the particle system into the . - Parameters: - *gw - - The graphics window into which to particle system is to be drawn. - - MarkerType type=POINT_MRKR - - One of the following values: - - See the MarkerType enum. - - - - - Implemented by the System. - - This method hit tests the particle system and returns TRUE if the particle system was hit. - Parameters: - *gw - - The graphics window to hit test in. - - *hr - - Pointer to an instance of describing the hit test region. - - int abortOnHit=FALSE - - If TRUE the hit testing should be aborted upon the first successful hit; otherwise hit testing should continue through all particles. - - MarkerType type=POINT_MRKR - - The type of particle marker being used. One of the following values: - - See the MarkerType enum. - TRUE if a particle is hit; otherwise FALSE. - - - - - Implemented by the System. - - Returns the 3D bounding box of the particles. - Parameters: - *tm=NULL - - If not NULL, this is the optional space to compute the bounding box in. - - - - - Implemented by the System. - - Sets all the counts to 0. This will be the points, and if used, the velocities and ages. - - - - - Implemented by the System. - - Sets the size of the particle system. This is to at least set the number of points in the particle system. The flags indicate if optional parameters velocities and ages should be allocated as well. - Parameters: - int c - - The size for each allocated table. - - DWORD flags - - One or more of the following values: - - PARTICLE_VELS - Velocities should be allocated. - - PARTICLE_AGES - Particles ages should be allocated. - - - - - Implemented by the System. - - Returns the number of points in the particle system. - - - - - Implemented by the System. - - Returns the 'i-th' point of the particle system. - - - - - Implemented by the System. - - Determines if particle i is alive (has not expired). - Parameters: - int i - - The index of the particle to check. - TRUE if the 'i-th' particle is alive; otherwise FALSE. - - - - - Implemented by the System. - - Establishes a custom draw callback object. This allows the particles to be displayed in any manner desired (not just using the standard point markers). See Class . - Parameters: - *d - - The custom draw callback object. - Operators: - - - - - Description: - A is made up of a series of objects derived from this class. This is similar to the way faces relate to a mesh. All methods of this class are implemented by the system. - Data Members: - int type; - - The patch type. One of the following values: - - PATCH_UNDEF - - . - - PATCH_TRI - - Triangular patch. - - PATCH_QUAD - - Quadrilateral patch. - - int v[4]; - - A patch can have three or four vertices based on the type. The corner vertices on a patch are referred to as a, b, c, (and if it's a quad patch d). These are ordered a, b, c, d going counter-clockwise around the patch. - - int vec[8]; - - A patch can have six or eight vector points. The vectors are referred to as follows: ab is the vector coming out of vertex a towards b. ba is the one coming out of b towards a. bc is the vector coming out of b towards c. cb is the one coming out of c towards b, and so on. - - int interior[4]; - - A patch can have three or four interior vertices. - - aux[9]; - - This is used internally for triangular patches only (degree 4 control points). - - int edge[4]; - - Pointers into the edge list. There can be three or four depending on the patch type. - - DWORD smGroup; - - The smoothing group. This defaults to 1. All patches are smoothed in a . - - DWORD flags; - - - - - - - This method is used by the constructors internally. Developers should not call this method. - - - - - The vertices are copied from the array passed. Based on the patch type either three or four vertices are copied. - Parameters: - int *vrt - - The vertices are set to these values. These values are indices into the v array. - - - - - Sets the vertices for Tri to those passed. - Parameters: - int a, int b, int c - - The vertices to set. v[0]=a; v[1]=b; v[2]=c;These values are indices into the v array. - - - - - Sets the vertices for a Quad to those passed. - Parameters: - int a, int b, int c, int d - - The vertices to set. v[0]=a; v[1]=b; v[2]=c; v[3] = d; These values are indices into the v array. - - - - - Sets the vectors for a Tri to those passed. - Parameters: - int ab, int ba, int bc, int cb, int ca, int ac; - - The vectors to set. vec[0]=ab; vec[1]=ba; vec[2]=bc; - - vec[3]=cb; vec[4]=ca; vec[5]=ac;These values are indices into the vec array. - - - - - Sets the vectors for a Quad patch to those passed. - Parameters: - int ab, int ba, int bc, int cb, - - int cd, int dc, int da, int ad; - - The vectors to set. vec[0]=ab; vec[1]=ba; vec[2]=bc; vec[3]=cb; - - vec[4]=cd; vec[5]=dc; vec[6]=da, vec[7]=ad; These values are indices into the vec array. - - - - - Sets the interior vertex values for a Tri . - Parameters: - The interior values to set: interior[0]=a; interior[1]=b; interior[2]=c; These values are indices into the interior array. - - - - - Sets the interior vertex values for a Tri . - Parameters: - int a, int b, int c, int d - - The interior values to set: interior[0]=a; interior[1]=b; interior[2]=c; interior[3]=d; These values are indices into the interior array. - - - - - Returns the vertex specified by the index. - Parameters: - int index - - The vertex to retrieve. This value may be 0, 1, 2 (or 3 if it's a quad patch). - - - - - Returns a pointer to the vertex array. - - - - - Triangle patch interpolator. This method returns a point on the surface of the patch based on the specified u, v and w values. The u, v, w values are barycentric coordinates. u+v+w = 1.0. If u is 1, and v and w are 0, the point is at the first vertex. If u is 0, v is 1, and w is 0, then the point is at the second vertex. If u and v are 0 and w is 1 then the point is at the third vertex. Varying positions between these values represent different positions on the patch. - Parameters: - *pMesh - - Points to the to interpolate. - - float centerU, float centerV, float centerW - - The barycentric coordinates. - A point on the surface of the patch. - - - - - Quadrilateral patch interpolator. This method returns a point on the surface of the patch based on the specified u and v values. - Parameters: - *pMesh - - Points to the to interpolate. - - float fU - - The fU value in the range 0.0 to 1.0. This defines the distance along one axis of the patch. - - float fV - - The fV value in the range 0.0 to 1.0. This defines the distance along the other axis of the patch. - A point on the surface of the patch. - - - - - This method is used internally. It compute the degree-4 alias control points. - - - - - Whenever you are done working on a , this method should be called. If the interior vertices of the patch are automatic it will update them to correctly match the changes to the other vectors. This computes interior vertices considering this patch only. - Parameters: - PatchMesh* pMesh - - Points to the to compute the interior vertices of. - - - - - Sets the type of the patch to either Tri or Quad and optionally resets the arrays. - Parameters: - int iType - - The patch type. One of the following values: - - PATCH_TRI - Triangular - - PATCH_QUAD - Quadrilateral - - BOOL init = FALSE - - If TRUE the arrays are reset to undefined; otherwise they are left unchanged. Normally this is set to FALSE. - - - - - Assignment operator. - Parameters: - & from - - The patch to copy from. - - - - - Sets the flag controlling if interior vertices are computed automatically. - Parameters: - BOOL sw = TRUE - - TRUE to set; FALSE to clear. - - - - - Returns TRUE if the PATCH_AUTO flag is set; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Sets the hidden state of the patch. - Parameters: - BOOL sw = TRUE - - TRUE to hide; FALSE to unhide. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if the patch is hidden; otherwise FALSE. - - - - - This may be called to dump the patch mesh structure via DebugPrint(). See ~{ Troubleshooting }~. - Operators: - - - - - Description: - This class is used to apply the data to a . It will modify the mesh as required to add the cap. Simply fill in the vertices, vectors and patches bordering the cap, then call the method. All methods of this class are implemented by the system. - - - - - The number of polygons. - - - - - A pointer to the . - - - - - access operator. - - - - - This method is used to modify the mesh based on the , the flipped state, the smoothing group and an orientation matrix. - Parameters: - &mesh - - The to modify. - - &capInfo - - The describing the cap. See Class . - - BOOL flip - - A switch to indicate if the cap should be oriented normally or flipped. The is used for both the front and back side of a cap. Either the front or the back will have to be flipped. This switch is used to indicate if a particular one is flipped. - - DWORD smooth - - The smoothing group for all the faces in the cap. - - *tm=NULL - - The orientation matrix. A grid cap generates new vertices inside the shape that make up the grid. In the case of a SurfRev for example, the end cap might be rotated, or scaled in some manner. A matrix is required so the capper knows how to orient the vertices into the correct location. This matrix is ignored for non-grid capping. - - int mtlID=-1 - - Specifies the material ID of the patches that make up the cap. The default for this value is -1, which causes the capper to use material ID 0 for non-flipped caps and ID 1 for flipped caps. Note that these ID values are zero-based, while the UI display is 1-based. - Nonzero if the mesh was modified; otherwise zero. - Operators: - - - - - This is the information class for patch capping. All methods of this class are implemented by the system. Developers must only declare an instance of this class and then call MakeCap on the shape. - - - - - This is used internally. - - - - - This is used internally. - - - - - This is used internally. - - - - - This is used internally. - - - - - This is used internally. - - - - - Assignment operator used internally. - - - - - This method is used internally. - - - - - This method is used internally. - - - - - Description: - A support class for the . All methods of this class are implemented by the system. - - - - - The number of vertices. - - - - - The number of vectors. - - - - - List of verts in patch mesh corresponding to verts in the spline (1 per vert) - - - - - List of vecs in patch mesh corresponding to vecs in the spline (1 per vector) - - - - - This method is used internally. - - - - - This establishes the corresponding mesh vertex for a vertex in the . This should be called for each vertex in the . - Parameters: - int index - - The index into the shape. - - int vertex - - The corresponding index into the mesh. - - - - - This establishes the corresponding mesh vertex for a vector in the . This should be called for each vertex in the . - Parameters: - int index - - The index into the shape. - - int vector - - The corresponding index into the patch. - - - - - cap vectors. When a patch cap is generated, new interior vectors will be generated within the patch, and patch edges within the cap will have new vectors. edges along the edges of the originating bezier shape will use existing vectors. This class provides information on which is which. All methods of this class are implemented by the system. - - - - - Capping types supported. See Shape Capping Types. - - - - - Polygon number for ORIGINAL. - - - - - Index for ORIGINAL or into newVecs table. - - - - - Compares this class instance to another one - - - - - cap vertices. These can be original vertices from the or new free vertices in the center of the . All methods of this class are implemented by the system. - - - - - Capping types supported. See Shape Capping Types. - - - - - The polygon number (ORIGINAL or EDGE) - - - - - The index of the vertex (ORIGINAL) or the segment for the EDGE vertex. - - - - - Compares this class instance to another one - - - - - Description: - This class describes a patch edge using the vertices at the edge ends, and the indices of the patches sharing the edge. All methods of this class are implemented by the system. - Data Members: - int v1; - - Index of the first vertex. - - int vec12; - - Vector from v1 to v2. - - int vec21; - - Vector from v2 to v1. - - int v2; - - Index of second vertex. - - IntTab patches; - - Index of the patches using this edge. If the edge is only used by one patch, patches[1] will be less than zero. Note: Previous to R4.0 two separate integer variables (patch1 and patch2) were used. - - int aux1; - - This is used to track topology changes during editing (Edit ). - - int aux2; - - This is used to track topology changes during editing (). - - - - - This is used internally to save the data to the .MAX file. - - - - - This is used internally to load the data from the .MAX file. - - - - - Description: - This is a storage class for hit records so the system can know which patch was hit. When this data is logged with the system, the memory is owned and freed by the System. - - - - - The associated with this hit record. - - - - - The index of the sub-object component. For example, if vertices's were being hit tested, this would be the index into the vertex table. - - - - - Types for patch vertex hits. - - - - - Description: - A patch mesh can be made up of any number of patches. Each of these patches can be three or four sided. Each edge of a patch can only be used by either one patch (which makes it an open edge) or two patches (which makes it a transitional edge between the two). - - All methods of this class are implemented by the system. - Topology: - int numVerts; - - The number of vertices. - - int numVecs; - - The number of vectors. - - int numPatches; - - The number of patches. - - int numEdges; - - The number of edges. - - *patches; - - The list of patches. - - *vecs; - - The list of PatchVecs. - - *edges; - - The list of PatchEdges. - - > hooks; - - This data member is available in release 3.0 and later only. - - This table is used internally - Geometry: - *verts; - - The list of PatchVerts. - Texture Coordinate Assignment: - <int> numTVerts; - - This data member is available in release 3.0 and later only. - - A table containing the number of texture vertices for each channel. - - *> tVerts; - - This data member is available in release 3.0 and later only. - - A table containing pointers to the texture vertices for each channel. - - Previous to R4.0 this was a <UVVert *>. - - *> tvPatches; - - This data member is available in release 3.0 and later only. - - A table containing pointers to the texture vertex patches for each channel. - Material Assignment: - DWORD mtlIndex; - - The object level material. - Selection: - vertSel; - - The selected vertices. - - edgeSel; - - The selected edges. - - patchSel; - - The selected patches. - - int bezVecVert; - - This is used internally. - - DWORD dispFlags; - - The display attribute flags. See Patch FlagsDWORD selLevel; - - The current selection level. One of the following values: - - PATCH_OBJECT - level. - - PATCH_VERTEX - Vertex level. - - PATCH_PATCH - level. - - PATCH_EDGE - level. - - int cacheSteps; - - This data member is available in release 3.0 and later only. - - The meshSteps used for the cache. - - BOOL cacheAdaptive; - - This data member is available in release 3.0 and later only. - - The adaptive switch used for the mesh cache. - - > extrudeDeltas; - - This data member is available in release 3.0 and later only. - - This data member is for internal use only. - - > extrudeData; - - This data member is available in release 3.0 and later only. - - This data member is for internal use only. - - bevelEdges; - - This data member is available in release 3.0 and later only. - - This data member is for internal use only. - - <float> edgeDistances; - - This data member is available in release 3.0 and later only. - - This data member is for internal use only. - - - - - Sets the number of vertices in the patch mesh. - Parameters: - int ct - - The new number of vertices. - - BOOL keep = FALSE - - If TRUE any old vertices are copied to the new array; otherwise they are freed. - TRUE if the number of vertices was allocated; otherwise FALSE. - - - - - Returns the number of vertices in the patch mesh. - - - - - Sets the 'i-th' vertex. - Parameters: - int i - - The index of the vertex to set. - - &xyz - - The vertex location. - - - - - Sets the 'i-th' vertex. - Parameters: - int i - - The index of the vertex to set. - - float x, float y, float z - - The vertex location. - - - - - Returns the 'i-th' vertex. - Parameters: - int i - - The index of the vertex to retrieve. - - - - - Returns the address of the 'i-th' vertex. - Parameters: - int i - - The index of the vertex. - - - - - Sets the number of vectors. - Parameters: - int ct - - The new vector count. - - BOOL keep = FALSE - - If TRUE any previous vectors are copied; otherwise they are freed. - TRUE if the number was allocated and set; otherwise FALSE. - - - - - Returns the number of vectors. - - - - - Sets the 'i-th' vector. - Parameters: - int i - - The index of the vector to set. - - &xyz - - The vector to set. - - - - - Sets the 'i-th' vector. - Parameters: - int i - - The index of the vector to set. - - float x, float y, float z - - The vector values to set. - - - - - Returns the 'i-th' vector. - Parameters: - int i - - The index of the vector to retrieve. - - - - - Returns the address of the 'i-th' vector. - Parameters: - int i - - The index of the vector. - - - - - Sets the number of patches. - Parameters: - int ct - - The new patch count. - - BOOL keep = FALSE - - If TRUE any previous patches are copied; otherwise they are freed. - TRUE if the number was allocated and set; otherwise FALSE. - - - - - Returns the number of patches. - - - - - Sets the number of edges. - Parameters: - int ct - - The new edge count. - - BOOL keep = FALSE - - If TRUE any previous edges are copied; otherwise they are freed. - TRUE if the number was allocated and set; otherwise FALSE. - - - - - Returns the number of edges. - - - - - This method is not currently used. - - - - - This method is not currently used. - - - - - This method is available in release 2.0 and later only. - - Sets the number of mapping vertices in the original TV map or vertex color channel. - Parameters: - int mp - - Specifies the channel. If 0, the number of vertices in the original mapping channel (map channel 1) is set. If nonzero, the number of vertices in the vertex color channel (map channel 0) is set. - - int ct - - The number of map vertices desired. - - BOOL keep=FALSE - - If TRUE, any existing mapping verts are copied over into the new array. - TRUE on success; otherwise FALSE. - - - - - Sets the number of mapping verts in the original mapping channel (channel 1). - Parameters: - int ct - - The number of map vertices desired. - - BOOL keep = FALSE - - If TRUE, any existing mapping verts are copied over into the new array. - TRUE if successful, FALSE if unsuccessful. - - - - - This method is available in release 2.0 and later only. - - Returns the number of mapping verts in the original map or vertex colors. - Parameters: - int mp - - If 0, the number of vertices in the original mapping channel (map channel 1) is returned. If nonzero, the number of vertices in the vertex color channel (map channel 0) is returned. - - - - - Returns the number of mapping vertices in the original mapping channel (channel 1). - - - - - This method is available in release 3.0 and later only. - - Sets the number of mapping verts in the specified mapping channel. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int ct - - The number of mapping verts desired. - - BOOL keep=FALSE - - If TRUE any old vertices are copied to the new array; otherwise they are freed. - TRUE if the number of vertices was allocated; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Returns the number of mapping verts in the specified mapping channel. - Parameters: - int mp - - In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - - - - This method is available in release 4.0 and later only. - - Returns a pointer to the list of PatchTVerts for the specified channel of this patch. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - - - - This method is available in release 2.0 and later only. - - Sets the 'i-th' map vertex of the specified channel. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the map vertex to set. - - const UVVert &xyz - - The value to set. - - - - - Sets the 'i-th' map vertex. - Parameters: - int i - - The index of the map vertex to set. - - const UVVert &xyz - - The value to set. - - - - - This method is available in release 2.0 and later only. - - Sets the 'i-th' map vertex of the specified channel. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the map vertex to set. - - float x, float y, float z - - The values to set. - - - - - Sets the 'i-th' map vertex. - Parameters: - int i - - The index of the map vertex to set. - - float x, float y, float z - - The values to set. - - - - - This method is available in release 3.0 and later only. - - Sets the 'i-th' map patch. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the map vertex to set. - - &tvp - - The map patch to set. - - - - - This method is available in release 3.0 and later only. - - Sets the specified map patch. - Parameters: - int i - - The zero based index of the texture patch to set. - - &tvp - - The map patch to set. - - - - - This method is available in release 2.0 and later only. - - Previous to R4, this method returned an UVVert&. - - Returns the 'i-th' map vertex of the specified channel. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the map vertex to retrieve. - - - - - Previous to R4, this method returned an UVVert&. - - Returns the 'i-th' map vertex. - Parameters: - int i - - The index of the map vertex to retrieve. - - - - - This method is available in release 2.0 and later only. - - Previous to R4, this method returned an UVVert*. - - Returns a pointer to the 'i-th' map vertex of the specified channel. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the texture vertex. - - - - - Previous to R4, this method returned an UVVert*. - - Returns a pointer to the 'i-th' map vertex. - Parameters: - int i - - The index of the map vertex. - - - - - This method is available in release 2.0 and later only. - - Sets the number of map patches in the original TV or vertex color channels. (Note that setNumMapPatches() is called from setNumPatches(), so this doesn't need to be called separately once a map channel is active.) - - Note: - - If the map patches are NULL and keep = TRUE they stay NULL. - - If the map patches are NULL and keep = FALSE they are allocated, and map verts also init themselves from the main vert array. - - If the map patches are non-NULL and ct = 0 they are set to NULL (and freed) - Parameters: - int channel - - If 0, the number of map patches in the original map channel are set. If nonzero, the number of map patches in the vertex color channel is set. - - int ct - - The number of map patches desired - should match the number of patches. - - BOOL keep=FALSE - - The keep flag. See above. - - int oldCt=0 - - The old number of patches. This is important for determining how much to copy over when keep is TRUE. - TRUE if storage has been allocated and the number is set; otherwise FALSE. - - - - - Sets the number of map patches in the original TV channel. (Note that setNumMapPatches() is called from setNumPatches(), so this doesn't need to be called separately once a map channel is active.) - - Note: - - If the map patches are NULL and keep = TRUE they stay NULL. - - If the map patches are NULL and keep = FALSE they are allocated, and map verts also init themselves from the main vert array. - - If the map patches are non-NULL and ct = 0 they are set to NULL (and freed) - Parameters: - int ct - - The number of map patches desired - should match the number of patches. - - BOOL keep=FALSE - - If TRUE, existing map patches are copied into the new map patch array. oldCt should specify how many patches were around previously. - - int oldCt=0 - - The old number of patches. This is important for determining how much to copy over when keep is TRUE. - TRUE if storage has been allocated and the number is set; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Sets the number of map patches in the specified map channel. (Note that this is called from setNumPatches(), so it doesn't need to be called separately once a map channel is active.) - - Note: - - If the map patches are NULL and keep = TRUE they stay NULL. - - If the map patches are NULL and keep = FALSE they are allocated, and map verts also init themselves from the main vert array. - - If the map patches are non-NULL and ct = 0 they are set to NULL (and freed). - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int ct - - The number of map patches desired - should match the number of patches. - - BOOL keep=FALSE - - If TRUE, existing map patches are copied into the new map patch array. oldCt should specify how many patches were around previously. - - int oldCt=0 - - The old number of patches. This is important for determining how much to copy over when keep is TRUE. - TRUE if storage has been allocated and the number is set; otherwise FALSE. - - - - - This method is available in release 2.0 and later only. - - Returns the 'i-th' texture patch structure of the specified channel. - Parameters: - int channel - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The index of the . - - - - - This method is available in release 2.0 and later only. - - Returns the 'i-th' texture patch from map channel 1. - Parameters: - int i - - The index of the . - - - - - This method is available in release 3.0 and later only. - - Sets the specified mapping vertex in the channel passed. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the vert to set. - - const UVVert &xyz - - The vert to set. - - - - - This method is available in release 3.0 and later only. - - Sets the specified mapping vertex in the channel passed. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the vert to set. - - float x - - The x coordinate of the vert to set. - - float y - - The y coordinate of the vert to set. - - float z - - The z coordinate of the vert to set. - - - - - This method is available in release 3.0 and later only. - - Sets the specified mapping patch in the channel passed. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the to set. - - &tvp - - The map patch to set. - - - - - This method is available in release 3.0 and later only. - - Previous to R4, this method returned an UVVert&. - - Returns a reference to the specified mapping vert from the specified channel. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the vert to get. - - - - - This method is available in release 3.0 and later only. - - Previous to R4, this method returned an UVVert*. - - Returns a pointer to the specified mapping vert from the specified channel. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the vert to get. - - - - - This method is available in release 3.0 and later only. - - Returns a reference to the specified map patch from the specified channel. - Parameters: - int mp - - The mapping channel. In this method, 0 is the vertex color channel, and channels 1 through MAX_MESHMAPS-1 are the map channels. - - int i - - The zero based index of the map patch to get. - - - - - Renders a patch mesh using the specified graphics window and array of materials. - Parameters: - *gw - - Points to the graphics window to render to. - - *ma - - The list of materials to use to render the patch. - - RECT *rp - - Specifies the rectangular region to render. If the patch mesh should be rendered to the entire viewport pass NULL. - - int compFlags - - One or more of the following flags: - - COMP_TRANSFORM - - Forces recalculation of the model to screen transformation; otherwise attempt to use the cache. - - COMP_IGN_RECT - - Forces all polygons to be rendered; otherwise only those intersecting the box will be rendered. - - COMP_LIGHTING - - Forces re-lighting of all vertices (as when a light moves); otherwise only re-light moved vertices - - COMP_ALL - - All of the above flags. - - COMP_OBJSELECTED - - If this bit is set then the node being displayed by this mesh is selected. Certain display flags only activate when this bit is set. - - COMP_OBJFROZEN - - If this bit is set then the node being displayed by this mesh is frozen. - - int numMat=1 - - The number of materials supported. - - - - - Checks the given hr to see if it intersects the patch mesh object. - Parameters: - *gw - - Points to the graphics window to check. - - *ma - - The list of materials for the patch mesh. - - *hr - - This describes the properties of a region used for the hit testing. See Class . - - int abortOnHit = FALSE - - If nonzero, the hit testing is complete after any hit; otherwise all hits are checked. - - int numMat=1 - - The number of materials supported. - TRUE if the item was hit; otherwise FALSE. - - - - - Checks to see if there is a snap point near the given mouse point. - Parameters: - *gw - - The graphics window in which to check. - - *snap - - This structure describes the snap settings used, and the results of the snap test. See Structure . - - *p - - The mouse point to check. - - &tm - - The object transformation matrix. This is the transformation to place the object into the world coordinate system. - - - - - This method may be called to perform sub-object hit testing of the patch mesh. - Parameters: - *gw - - The graphics window associated with the viewport the patch mesh is being hit tested in. - - *ma - - The list of materials for the patch mesh. - - *hr - - This describes the properties of a region used for the hit testing. See Class . - - DWORD vflags - - Flags for sub object hit testing. One or more of the following values: - - SUBHIT_PATCH_SELONLY - - Selected only. - - SUBHIT_PATCH_UNSELONLY - - Unselected only. - - SUBHIT_PATCH_ABORTONHIT - - Abort hit testing on the first hit found. - - SUBHIT_PATCH_SELSOLID - - This treats selected items as solid and unselected items as not solid. Treating an item as solid means the patch will be hit if the mouse is anywhere inside the patch region and not just over a visible edge. - - SUBHIT_PATCH_VERTS - - Hit test vertices. - - SUBHIT_PATCH_VECS - - Hit test vectors. - - SUBHIT_PATCH_PATCHES - - Hit test patches. - - SUBHIT_PATCH_EDGES - - Hit test edges. - - & hitList - - See Class . - - int numMat=1 - - The number of materials for the mesh. - TRUE if the item was hit; otherwise FALSE. - - - - - This method is available in release 4.0 and later only. - - This method will render a 'gizmo' version of the and is used primarily by Editable and Edit to facilitate the Show End Result feature. - Parameters: - *gw - - The graphics window associated with the viewport the patch mesh gizmo should be shown in. - - - - - Computes the bounding box of the patch mesh. The bounding box is stored with the patch mesh object, use getBoundingBox() to retrieve it. - - - - - Retrieves the bounding box of the patch mesh object. - Parameters: - *tm=NULL - - The optional TM allows the box to be calculated in any space. - - - - - This method should be called when the changes. It invalidates the caches of the patch mesh. - - - - - Frees everything from the patch mesh. - - - - - This method is used internally in data flow evaluation. - - - - - This method is used internally in data flow evaluation. - - - - - This method is used internally in data flow evaluation. - - - - - This method is used internally in data flow evaluation. - - - - - Sets the state of the specified display flags. - - - The flags to set. See . - - - - Returns the state of the specified display flags. - - - The flags to get. See . - - - - Clears the specified display flags. - - - The flags to clear. See . - - - - Returns the bits representing the vertex selection status. See the Data Members above. See Class . - - - - - Returns the bits representing the edge selection status. See the Data Members above. See Class . - - - - - Returns the bits representing the patch selection status. See the Data Members above. See Class . - - - - - Constructs a vertex selection list based on the current selection level. For example if the selection level is at object level all the bits are set. If the selection level is at vertex level only the selected vertex bits are set. See Class . - - - - - Create a quadrilateral patch given a patch index and a list of all the vertices, vectors, interiors, and a smoothing group. - Parameters: - int index - The index of the patch to create (0>= index < numPatches). - - int va - The first vertex. - - int vab - Vector ab. - - int vba - Vector ba. - - int vb - The second vertex. - - int vbc - Vector bc. - - int vcb - Vector cb. - - int vc - The third vertex. - - int vcd - Vector cd. - - int vdc - Vector dc. - - int vd - The fourth vertex. - - int vda - Vector da. - - int vad - Vector ad. - - int i1 - Interior 1. - - int i2 - Interior 2. - - int i3 - Interior 3. - - int i4 - Interior 4. - - DWORD sm - The smoothing group. - TRUE if the patch was created; otherwise FALSE. - - - - - Create a triangular patch given a patch index and a list of all the vertices, vectors, interiors, and a smoothing group. - Parameters: - int index - The index of the patch to create (0>= index < numPatches). - - int va - The first vertex. - - int vab - Vector ab. - - int vba - Vector ba. - - int vb - The second vertex. - - int vbc - Vector bc. - - int vcb - Vector cb. - - int vc - The third vertex. - - int vca - Vector ca. - - int vac - Vector ac. - - int i1 - Interior 1. - - int i2 - Interior 2. - - int i3 - Interior 3. - - DWORD sm - The smoothing group. - TRUE if the patch was created; otherwise FALSE. - - - - - Returns the number of mesh steps. - - - - - This method is available in release 3.0 and later only. - - Returns the Surface Render Steps setting. - - - - - This method is available in release 3.0 and later only. - - Returns the 'Show Interior ' setting; TRUE if on; FALSE if off. - - - - - This is currently not used. Reserved for future use. - - - - - This method is available in release 2.0 and later only. - - Returns the tessellation approximation object used for rendering in the viewports. - - - - - This method is available in release 2.0 and later only. - - Returns the tessellation approximation object used for production rendering. - - - - - This method is available in release 3.0 and later only. - - Returns the tessellation approximation object used for display in the viewports. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if normals are used from the viewport tessellator; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if normals are used from the production renderer tessellator; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if the viewport mesh is welded after tessellation; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if the production renderer mesh is welded after tessellation; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - the number of texture maps used by this . - Parameters: - int ct - - The number to use. This is a value between 2 and MAX_MESHMAPS-1. - - BOOL keep=TRUE - - TRUE to keep the old mapping information after the resize; FALSE to discard it. - - - - - This method is available in release 3.0 and later only. - - Returns the number of mapping channels in use. - - - - - This method is available in release 4.0 and later only. - - This method will allocate mapping channels as needed. If the map channel is already present, no action is taken. Otherwise, the additional channels are created. - Parameters: - int chan - - Specifies which channel. See ~{Mapping Channels}~. If zero (special vertex color channel) and init is TRUE, all vertex colors are initialized to white (1,1,1). - - BOOL init=TRUE - - If TRUE, the channel is initialized to match the 's structure. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if the specified mapping channel is supported; otherwise FALSE. - Parameters: - int mp - - Specifies which channel. See ~{Mapping Channels}~. - - - - - This method is available in release 3.0 and later only. - - Returns the maximum number of possible mapping channels. - - - - - This method may be called to map this with UVW mapping coordinates. - Parameters: - int type - - The mapping type. One of the following values: - - MAP_PLANAR - - MAP_CYLINDRICAL - - MAP_SPHERICAL - - MAP_BALL - - MAP_BOX - - float utile - - of tiles in the U direction. - - float vtile - - of tiles in the V direction. - - float wtile - - of tiles in the W direction. - - int uflip - - If nonzero the U values are mirrored. - - int vflip - - If nonzero the V values are mirrored. - - int wflip - - If nonzero the W values are mirrored. - - int cap - - This is used with MAP_CYLINDRICAL. If nonzero, then any patch normal that is pointing more vertically than horizontally will be mapped using planar coordinates. - - &tm - - This defines the mapping space. As each point is mapped, it is multiplied by this matrix, and then it is mapped. - - int channel=1 - - This parameter is available in release 2.0 and later only. - - This indicates which channel the mapping is applied to - channel==1 corresponds to the original texture channel. Note that this is a change from what it meant before release 3.0. Previously channel 1 referred to the color per vertex channel (and this parameter defaulted to 0). - - - - - This method tags the points in the patch components to record our topology (this stores identifying values in the various aux2 fields in the ). This information can be used after topology-changing operations to remap information tied to vertices, edges and patches. - Returns TRUE if tagged successfully; otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - Transforms the vertices and vectors of the patch mesh, re- computes the interior bezier points for each patch in the mesh and invalidates the geometry cache. - Parameters: - &tm - - The matrix to transform with. - - - - - This method is available in release 3.0 and later only. - - This method is used internally. - - - - - This method is available in release 3.0 and later only. - - This is a method which may be used to delete sets of verts or patches. - Parameters: - &delVerts - - A bit array with bits set for verts to delete. - - &delPatches - - A bit array with bits set for patches set to delete. - - - - - This method is available in release 3.0 and later only. - - Subdivides the selected edge or patch. - Parameters: - int type - - One of the following values: - - SUBDIV_EDGES - - Subdivides an edge. - - SUBDIV_PATCHES - - Subdivides an entire patch - - BOOL propagate - - TRUE to propagate; FALSE to not propagate. - - - - - This method is available in release 3.0 and later only. - - Add a patch of the desired type to each selected edge that doesn't have two patches attached. - Parameters: - int type - - One of the following values: - - PATCH_TRI - - PATCH_QUAD - - - - - This method is available in release 3.0 and later only. - - This method is obsolete and should not be used. - - - - - This method is available in release 3.0 and later only. - - This method is obsolete and should not be used. - - - - - This method is available in release 3.0 and later only. - - This method is obsolete and should not be used. - - - - - This method is available in release 3.0 and later only. - - This method is obsolete and should not be used. - - - - - This method is available in release 3.0 and later only. - - This method is used internally. - - - - - This method is available in release 4.0 and later only. - - This method changes the mapping of a patch or all selected patches to linear. - Parameters: - int index - - The index of the patch for which to change the mapping to linear. A value < 0 indicates all selected patches are to be changed to linear mapping. - - - - - This method is available in release 4.0 and later only. - - This method changes the mapping of a patch or all selected patches to curved. - Parameters: - int index - - The index of the patch for which to change the mapping to curved. A value < 0 indicates all selected patches are to be changed to curved mapping. - - - - - This method is available in release 4.0 and later only. - - This method will check if one or all selected patches have linear mapping applied. - Parameters: - int index - - The index of the patch for which to check if mapping is linear. A value < 0 indicates all selected patches are checked for linear mapping. - TRUE if the specified patch or selected patches have linear mapping applied, otherwise FALSE. - - - - - This method is available in release 4.0 and later only. - - This method will check if one or all selected patches have curved mapping applied. - Parameters: - int index - - The index of the patch for which to check if mapping is curved. A value < 0 indicates all selected patches are checked for curved mapping. - TRUE if the specified patch or selected patches have curved mapping applied, otherwise FALSE. - - - - - This method is available in release 3.0 and later only. - - This method will allow you to obtain the average normal of all selected patches or edges. - Parameters: - int type - - This option is available in release 4.0 and later only. - - Specifies if the average normal return is based on all selected patches, using PATCH_PATCH, or all selected edges using PATCH_EDGE. - - - - - This method is available in release 3.0 and later only. - - This method is used internally. - - - - - This method is used internally. - - - - - This method is available in release 4.0 and later only. - - This method flips the normal of the specified patch. This is done by reordering the vertices. If the has textures assigned to it then the texture patches are processed as well. - Parameters: - int index - - The index of the patch for which you want to flip the normal. - - - - - This method is available in release 4.0 and later only. - - This method makes sure the patches in the operation set are all facing the same direction. This is determined by the vertex order around the edges of the patch. - Parameters: - BOOL useSel - - If this parameter is set to TRUE, the operation set is the set of selected patches as indicated by the patchSel. If this parameter is set to FALSE, all patches are processed. - - - - - This method is available in release 3.0 and later only. - - This method is used internally. - - - - - This method is available in release 3.0 and later only. - - This method is used internally. - - - - - This method is available in release 4.0 and later only. - - This method will produce the mesh version of the . - Parameters: - & msh - - The mesh in which the resulting mesh should be stored. - - DWORD convertFlags - - The flags modifying the mesh process. - - PATCH_CONVERT_KEEPSEL - - This flag indicates that the subobject vertex and patch selections in the should be converted to subobject vertex and face selections in the mesh. - - PATCH_CONVERT_USESOFTSEL - - This flag indicates that soft selections should be used in the mesh to interpolate between selected and nonselected vertices. (Soft Selections cannot be based on edge or patch selection in the , only vertex selection.) - - - - - This method is available in release 4.0 and later only. - - This method provides direct access to the vertex weights array and is included to match a similar function in the class. - A pointer to the vertex weights array. - Default Implementation: - { return mpVertexWeights; } - - - - - This method is available in release 4.0 and later only. - - This method allocates a vertex weights array, if none is currently allocated. This method is included to match a similar function in the class. - - - - - Initializes the data members to default values. - - - - - Assignment operator from another . - - - - - Assignment operator. This operator will do the conversion from a to a . Note that this can get very slow if there are a lot of faces in the mesh. When the system does the conversion is must do a fair amount of work with its interior connection lists. It builds a data base of what is connected to what and makes sure that the doesn't have any places where an edge is used by more than two patches. Also, for every face in the mesh it generates a triangular patch. Therefore use this method with some caution as it can create some very complex objects. - - - - - This method is available in release 3.0 and later only. - - The following is similar to operator=, but just takes the major components, not the display flags, selection level, etc. - Parameters: - &fromPatchMesh - - The patch mesh to copy from. - - - - - This is an important method to call after putting together a . This method does the work to figure out how the is connected together, one patch to another. It determines which edges are used by which patches and so on. - Parameters: - int patch - - This option is available in release 4.0 and later only. - - This optional parameter allows you to only update adjacency information for a single new patch. If the plugin code is adding new patches and not removing any others then you can call this method with the new patch index and the various adjacency information in vertices, vectors, and edges will be built. If you call this method for the entire object (no parameter or patch < 0) it will destroy all adjacency information and rebuild it from scratch. - TRUE if the patch mesh is valid, FALSE if it is not. - - - - - This method computes the interior bezier points for each patch in the mesh. This method should be called after any modifications have been made to alter the (for example changes to point positions). If there are any automatic patches this will compute the interior vectors. - - - - - This method may be called to apply the coplanar constraints to the patch mesh. The constraints may optionally only apply to selected vertices. There is a flag that may be set for a patch vertex (PVERT_COPLANAR). For example, you can set this flag to make a vertex coplanar with its vectors. If this is done, then when this method is called, the patch code will then go through the and find the average plane that is used by the vertex and all the vectors associated with it. It will then constrain all the vectors to lie in this plane (by rotating them so that they lie on the plane). In this way there will be a consistent transition between the patches sharing the vertex. - Parameters: - BOOL selOnly = FALSE - - If TRUE the constraints are only applied to the selected vertices; otherwise all vertices. - - - - - This method is available in release 4.0 and later only. - - This method will weld any edges which are selected and have the same endpoints. - TRUE if any welding took place, otherwise FALSE. - - - - - This method is available in release 4.0 and later only. - - This method will copy the patches specified by the , or by the patch selection set if the patches pointer is NULL. This method is used by Editable and Edit to facilitate the shift-copy operations. - Parameters: - *patches - - The array containing the series of selected patches. - - - - - This method is available in release 3.0 and later only. - - This method will create all the necessary geometry for an extrusion operation. - Parameters: - int type - - This option is available in release 4.0 and later only. - - Specifies the extrusion type, either PATCH_PATCH or PATCH_EDGE. If the extrusion type is set to PATCH_EDGE, then the edgeClone parameter will tell the function to clone the selected edges prior to creating the extrusion geometry. - - BOOL edgeClone - - This option is available in release 4.0 and later only. - - The edge clone flag. If set to TRUE the function will clone the selected edges prior to creating the extrusion geometry. - - - - - This method may be called to dump the patch mesh structure via DebugPrint(). See ~{ Troubleshooting }~. - - - - - This method is available in release 3.0 and later only. - - Calculates the intersection of the specified ray with this patch mesh object. This method calls the method of the same name on the cache. - Parameters: - & ray - - Specifies the origin and direction of the ray to intersect with the patch mesh. See Class . - - float& at - - The computed point of intersection on the surface of the patch mesh. - - & norm - - The face normal at the point of intersection (at). - Nonzero if the ray intersected the mesh object; otherwise 0. Note that this method ignores backfaces when computing the result. - - - - - This method is available in release 4.0 and later only. - - This method will perform automatic smoothing on the patch mesh. The smoothing angle is determined for each patch by computing the normals at each corner of the patch (using the corner vertex and the two edge vectors connected to that vertex), then averaging the normals of the two corners of each edge to arrive at a normal for that edge. These normals are used to determine whether adjacent patches are within the auto-smooth threshold angle. - Parameters: - float angle - - The minimum angle between surface normals for smoothing to be applied, in radians. - - BOOL useSel - - If this parameter is set to TRUE then only the selected patches are smoothed. - - BOOL preventIndirectSmoothing - - TRUE to turn on; FALSE to leave it off. This matches the option in the Smooth UI - use this to prevent smoothing 'leaks" when using this method. If you use this method, and portions of the patch mesh that should not be smoothed become smoothed, then try this option to see if it will correct the problem. Note that the problem it corrects is rare, and that checking this slows the automatic smoothing process. - - - - - This method is available in release 4.0 and later only. - - This method examines the selected edges and will return TRUE if all selected edges are used by only one single patch. If the method returns FALSE, there are no edges selected or any of the selected edges are used by more than one single patch. - - - - - This method is available in release 4.0 and later only. - - This method will return a that defines the group of patches defining an element that contains the patch indicated by the specified index. A element is any set of patches sharing common vertices. - Parameters: - int index - - The patch index for which to return the element. - - - - - Description: - This class provides a storage and access mechanism for a named patch selection clipboard. - Data Members: - MSTR name; - - The name of the clipboard. - - <BitArray*> sets; - - This table is a - - - - - Description: - This class is the base class for the creation of objects. This class stores an instance of a that holds all the Patches that make up this patch object. This class also maintains a cache. All methods of this class are implemented by the system. - Data Members: - patch; - - The patch mesh for this patch object. - - mesh; - - The cache. - - BOOL meshValid; - - Indicates if the mesh cache is valid. - - BOOL showMesh; - - Indicates if the mesh is shown in the viewports - - vselSet; - - This data member is available in release 3.0 and later only. - - Vertex level named selection sets. - - eselSet; - - This data member is available in release 3.0 and later only. - - level named selection sets. - - pselSet; - - This data member is available in release 3.0 and later only. - - level named selection sets. - - int patchSelSubType; - - This data member is available in release 4.0 and later only. - - The sub-object selection level, defined by; - - PO_PATCH - - sub-object level. When SetSubobjectLevel(PO_PATCH) is called, both the selection - - level and patchSelSubType are set to PO_PATCH. - - PO_ELEMENT - - Element sub-object level. When SetSubobjectLevel(PO_ELEMENT) is called, the selection level is set to PO_PATCH and patchSelSubType is set to PO_ELEMENT. - - - - - This method is available in release 4.0 and later only. - - This method sets or clears the status of the Show End Result flag. - Parameters: - DWORD fl - - The flag you wish to set or clear. Currently the only flag defined is the Show End Result flag EP_DISP_RESULT. - - BOOL val - - Specifies if the given flag should be set or cleared. - - - - - This method is available in release 4.0 and later only. - - This method clears the status of the Show End Result flag. - Parameters: - DWORD fl - - The flag you wish to set or clear. Currently the only flag defined is the Show End Result flag EP_DISP_RESULT. - - - - - This method is available in release 4.0 and later only. - - This methods allows you to obtain the status of the Show End Result flag. - Parameters: - DWORD fl - - The flag you wish to set or clear. Currently the only flag defined is the Show End Result flag EP_DISP_RESULT. - - - - - This method is available in release 2.0 and later only. - - This should be implemented by classes derived from whose patches change over time. - Parameters: - TimeValue t - - The time to update the patch mesh. - Default Implementation: - {} - - - - - This method checks to see if the mesh cache is up to date, and if not, it generates it. - Parameters: - TimeValue t - - This parameter is available in release 2.0 and later only. - - The mesh cache should be generated to reflect this time. - - - - - Returns TRUE if the patch lattice is displayed; otherwise FALSE. - - - - - Returns TRUE if the patch vertices are shown; otherwise FALSE. - - - - - Returns the number of mesh steps (viewport). - - - - - This method is available in release 3.0 and later only. - - Returns the Surface Render Steps setting. - - - - - This method is available in release 3.0 and later only. - - Returns the 'Show Interior ' setting; TRUE if on; FALSE if off. - - - - - Returns the state of the adaptive switch. TRUE is on; FALSE is off. - - - - - Returns the tesselation approximation object used for rendering in the viewports. - - - - - Returns the tesselation approximation object used for production rendering. - - - - - Returns the tesselation approximation object used for display in the viewports. - - - - - Returns TRUE if normals are used from the viewport tesselator; otherwise FALSE. - - - - - Returns TRUE if normals are used from the production renderer tesselator; otherwise FALSE. - - - - - Returns TRUE if the viewport mesh is welded after tesselation; otherwise FALSE. - - - - - Returns TRUE if the production renderer mesh is welded after tesselation; otherwise FALSE. - - - - - Invalidates the mesh cache. - - - - - This method is available in release 4.0 and later only. - - This method goes hand-in-hand with GetSubobjectLevel(), except that this method returns the type of geometry that is actually being acted upon. - The sub-object type, either PO_PATCH or PO_ELEMENT. - - - - - This method is available in release 3.0 and later only. - - This method will delete the selected patches, exactly like the DeleteMesh modifier does. - Parameters: - BOOL interactive - - This parameter is available in release 4.0 and later only. - - If this parameter is set to TRUE it will cause the method to display the appropriate prompts, create an undo object, and notifies the dependents. - - - - - This method is available in release 4.0 and later only. - - In vertex mode, this method examines selected vertices, and if any of the vertices that are part of the selection set are used by more than one patch, those vertices (and any attached vectors) are duplicated into separate geometry for each patch using it. - - In edge mode, this method examines the selected edges and any vectors on the selected edges that are used by more than one patch are duplicated into separate geometry for each patch using them. Any vertices used by more than one selected edge are duplicated as well for patches on opposite sides of the edge. - - Note: If the vertices and vectors involved have controllers attached, they are removed by this operation. - Parameters: - BOOL interactive - - If this parameter is set to TRUE it will cause the method to display the appropriate prompts, create an undo object, and notifies the dependents. - - - - - This method is available in release 4.0 and later only. - - This method will perform the edge weld function on the patch object. Note that this does not take into account any threshold but welds edges only if they use the same two vertices as endpoints. When two or more edges are welded, the locations of the edge vectors are averaged to create the new edge. - - - - - When called with the Animate state active and on a nonzero TimeValue, this method will prepare the controllers for the geometry that is being created. The program can then fill in the animated vertex values later. - Parameters: - TimeValue t - - This parameter is available in release 4.0 and later only. - - The time at which to prepare and execute the extrude operation. - - - - - This method flips the normals of a specified patch or all selected patches. This method will save undo information and displays a prompt if patchIndex < 0 while there are no patches selected. - Parameters: - int patchIndex - - The index of the patch for which to flip the normal. If this parameter is < 0, the normals of all selected patches will be flipped (if there are any selected). - - Any vertices set to PVERT_COPLANAR that lie on the boundary between flipped and unflipped patches will have their type set to PVERT_CORNER. This is because attempting to compute normals of neighboring patches with opposite normals in order to get a proper plane often results in invalid normals being generated. Making the vertex a corner type prevents the problem. Any vertices not on the boundary between flipped and unflipped patches are left as is. - - - - - This method is available in release 4.0 and later only. - - This method examines the selected patch set and attempts to make them all face the same direction. Preferred direction is arbitrary; the first selected patch encountered in each contiguous group determines the direction all patches in that group will attain. - - Any vertices set to PVERT_COPLANAR that lie on the boundary between flipped and unflipped patches will have their type set to PVERT_CORNER. This is because attempting to compute normals of neighboring patches with opposite normals in order to get a proper plane often results in invalid normals being generated. Making the vertex a corner type prevents the problem. Any vertices not on the boundary between flipped and unflipped patches are left as is. - - - - - When called with the Animate state active and on a nonzero TimeValue, this method will prepare the controllers for the geometry that is being created. The program can then fill in the animated vertex values later. - Parameters: - TimeValue t - - This parameter is available in release 4.0 and later only. - - The time at which to prepare and execute the bevel operation. - - - - - This method is available in release 4.0 and later only. - - This method returns the common color for all selected vertices. If no vertices are selected then white (1,1,1) will be returned, however, if multiple vertices with different colors are selected, then black (0,0,0) will be returned. - Parameters: - int mp=0 - - The map channel. - - bool *differs=NULL - - This parameter is returned to indicate if there were any differences. - - - - - - - This method is available in release 4.0 and later only. - - This method will set all selected vertices to the specified color. - Parameters: - clr - - The color you wish to apply to all the selected vertices. - - int mp=0 - - The map channel. - - - - - This method is available in release 4.0 and later only. - - This method will select all vertices which fall into a specified color range. - Parameters: - VertColor clr - - The starting color of the vertices you wish to select by color. - - int deltaR - - The difference range for the red color component. - - int deltaG - - The difference range for the green color component. - - int deltaB - - The difference range for the blue color component. - - BOOL add - - This flag adds vertices to the selection that fall into the color range. - - BOOL sub - - This flag subtracts vertices from the selection that fall into the color range. - - int mp=0 - - The map channel. - - - - - This method is available in release 4.0 and later only. - - This method returns the common color for all selected patches. If no patches are selected then white (1,1,1) will be returned, however, if different vertex colors are present in the selected patches, then black (0,0,0) will be returned. - Parameters: - int mp=0 - - The map channel. - - bool *differs=NULL - - This parameter is returned to indicate if there were any differences. - - - - - - - This method is available in release 4.0 and later only. - - This method will set all selected patches to the specified color. - Parameters: - clr - - The color you wish to apply to all the selected patches. - - int mp=0 - - The map channel. - - - - - This method is available in release 4.0 and later only. - - This method will change the mapping type of the selected patches to linear or curved. - Parameters: - BOOL linear - - If TRUE the mapping type will be changed to linear. FALSE will change the mapping type to curved. - - - - - This method is available in release 4.0 and later only. - - This method examines the patch mesh and selects any edges used by only one single patch. - - - - - This method is available in release 4.0 and later only. - - This method will create a bezier spline shape from the selected edges of the patch mesh. Each edge will become a separate spline in the output shape. The user will be prompted to enter a name for the new editable spline object that will be created. - - - - - Description: - This class represents a single hit record for sub-patch level hit testing. All methods of this class are implemented by the system. - Data Members: - DWORD dist; - - The distance of the hit. If the user is in wireframe mode, this is the distance in pixels to the item that was hit. If the user is in shaded mode, this is the Z depth distance. Smaller numbers indicate a closer hit. - - *patch; - - The associated with this sub-patch hit. - - int index; - - The index of the sub-object component. For example, if vertices were being hit tested, this would be the index into the vertex table. - - int type; - - The type of the hit. One of the following values: - - PATCH_HIT_PATCH - - PATCH_HIT_EDGE - - PATCH_HIT_VERTEX - - PATCH_HIT_VECTOR - - PATCH_HIT_INTERIOR - - - - - Returns the next sub hit record. - - - - - Description: - This class stores the texture vertex information associated with a patch and provides methods to access this. All methods of this class are implemented by the system. - Data Members: - UVVert p; - - The texture vertex location. - - int aux1; - - Used to track topology changes during editing (Edit ). - - - - - Assignment operator. - Parameters: - UVVert& from - - The texture vertex to copy from. - - - - - Description: - This class represents a patch vector. This can be either an interior vector or an edge vector. All methods of this class are implemented by the system. - Data Members: - p; - - The vertex location. - - int vert; - - The vertex which owns this vector. - - IntTab patches; - - These are the patches that share this vector. If the edge is open there will only be one patch. In this case patches[0] will be used and patches[1] will be -1. Note: As of R4.0 the previous array of [2] has been replaced with the IntTab because vectors can now be used by more than two patches. - - DWORD flags; - - The patch vector flag: - - PVEC_INTERIOR - - This indicates the vector is an interior vector. These are the three vectors inside a tri patch or the four inside a quad patch. - - int aux1; - - This data member is available in release 3.0 and later only. - - Used to track topology changes during editing (Edit ). - - int aux2; - - This data member is available in release 3.0 and later only. - - Used to track topology changes during editing (). - - - - - Resets the data members. The vertex owner is set to undefined. The patches using the vector is set to undefined. - - - - - Adds the specified patch to this vector table. - Parameters: - int index - - The index in the class patches table (patches) of the patch to add. - Returns TRUE if the patch was added; otherwise FALSE. - - - - - Assignment operator. - Parameters: - & from - - The patch vector to copy from. - - - - - This method is available in release 3.0 and later only. - - Transforms the vertex location p by the specified matrix. - Parameters: - &tm - - The matrix to transform the vertex. - - - - - This is used internally to save the data to the .MAX file. - - - - - This is used internally to load the data from the .MAX file. - Operators: - - - - - Description: - This class stores the information associated with a patch vertex and provides methods to access the data associated with this vertex. All methods of this class are implemented by the system. - Data Members: - p; - - The vertex location. - - IntTab vectors; - - The list of vectors attached to this vertex. There can be any number of vectors attached to a vertex. For example consider the north pole of a sphere made from a set of triangular patches. If there were 16 patches meeting at this point there would be 16 vectors. The table contains the indices of these vectors. This is set up automatically when a developer calls buildLinkages(). - - Note: <int> IntTab; - - Note that the methods below allow a developer to manipulate the tables of this class. Developers must be careful when doing so as it is easy to corrupt the patch data structures. It may be easier for developers to manipulate the patches, delete vertices, etc., by manipulating them in the and then call buildLinkages() again. The methods below do work however and may be used. - - IntTab patches; - - The list of patches using this vertex. - - IntTab edges; - - This data member is available in release 4.0 and later only. - - The list of edges using this vertex. This table will be set up automatically when a developer calls buildLinkages(). - - DWORD flags; - - The patch vertex flags - - PVERT_COPLANAR - - This constrains things such that this vertex and all the vectors that are attached to it are coplanar. If this is set, and you call ApplyConstraints(), the system will adjust the vectors to the average plane that they are in and then constrain them to it. - - PVERT_CORNER - - The vertex is a corner. - - PVERT_HIDDEN - - The vertex is hidden. - - int aux1; - - Used to track topo changes during editing (Edit ). - - int aux2; - - Used to track topology changes during editing (). - - - - - Assignment operator. - Parameters: - & from - - The patch vertex to copy from. - - - - - This method deletes the elements from the vectors table and patches table. - - - - - Returns the index in this classes vectors table of the vector whose index is passed. If not found, -1 is returned. - Parameters: - int index - - The index in the class vectors table (vecs) of the vector to find. - - - - - Adds the specified vector to this vector table. - Parameters: - int index - - The index in the class vectors table (vecs) of the vector to add. - - - - - Deletes the specified vector from this vector table. - Parameters: - int index - - The index in the class vectors table (vecs) of the vector to delete. - - - - - Returns the index in this classes patches table of the patch whose index is passed. If not found, -1 is returned. - Parameters: - int index - - The index in the class patches table (patches) of the patch to find. - - - - - Adds the specified patch to this vector table. - Parameters: - int index - - The index in the class patches table (patches) of the patch to add. - - - - - Deletes the patch specified by the index. - Parameters: - int index - - The index in the class patches table (patches) of the patch to delete. - - - - - Returns the index in this classes edges table of the patch whose index is passed. If not found, -1 is returned. - Parameters: - int index - - The index in the class edges table (edges) of the edge to find. - - - - - Adds the specified edge to this vector table. - Parameters: - int index - - The index in the class edges table (edges) of the edge to add. - - - - - Deletes the edge specified by the index. - Parameters: - int index - - The index in the class edges table (edges) of the edge to delete. - - - - - This method is available in release 3.0 and later only. - - Transform the vertex by the specified matrix. - Parameters: - &tm - - The matrix which transforms the point. - - - - - This method is available in release 3.0 and later only. - - Sets the hidden state of the vertex. - Parameters: - BOOL sw = TRUE - - TRUE to set to hidden; FALSE for visible. - - - - - This method is available in release 3.0 and later only. - - Returns TRUE if the vertex is hidden; otherwise FALSE. - - - - - This method is used internally to save the class data to disk storage. - - - - - This method is used internally to load the class data from disk storage. - Operators: - - - - - A class specific to path configuration files. - - - Used by the DragAndDropManager to help determine the type of operation that should be performed given a specific drop operation. - - - - - This class is used for per -'something' floating-point information. For example, it is used with Meshes to keep track of such per-vertex information as weighted (Affect Region or Soft) selections and vertex weights. It is used in to store per-edge data (edge weights). Currently there's only one "type" of data supported, floating point values, but this may be extended in the future. arrays in Meshes and MNMeshes cannot be reserved for plug-ins at this time; 3ds Max maintains the list in MESH.H of the reserved vertex data channels, and in MNMESH.H for the data channels. The methods of this class are deliberately made to look like <> methods. All methods of this class are implemented by the system. - - - - - The number of elements of per-vertex data. - - - - - The type of data held by this class. See Data Types for Mesh Vertices . - - - - - The number of elements currently allocated in the data array. - - - - - Points to the actual data. - - - - - Allocates and returns a pointer to an array of floats of the specified size. - - The number of floats to allocate. - - - - Deletes the specified array of floats. - - Pointer to the array of floats to free. - - - - Returns the number of bytes used by the base data type for the vertex data. This is only implemented for a type of VDATA_TYPE_FLOAT in which case it returns sizeof(float). Other cases simply return 0. - - - - - Returns the address of the specified element in the array passed. - - The array whose at-th element address is returned. - The zero based index of the element. - - - - Returns the address of the specified element in the data array. - - The zero based index of the element. - - - - Copies the specified number of elements between the two data arrays. - - Points to the destination data array. - Points to the source data array. - The number of elements to copy. - - - - Copies the specified number of elements between the two specified locations in the data array. - - The zero based index into the data array of the destination. - The zero based index into the data array of the source. - The number of elements to copy. - - - - Computes the weighted sum of the arguments passed. This is effectively c = a*prop1 + b*prop2. This is used, for example, in splitting an edge, where we would want to interpolate the vertex weight values from the edge's endpoints to create the weight for the new vertex. - - A pointer to the location in which the result should be stored. - A pointer to the first value to be summed. - The weight given to the first value. - A pointer to the second value. - The weight given to the second value. - - - - Computes the weighted sum of the arguments passed. This is similar to the method above except to, fr1, and fr2 are indices of the values in the array. That is, PerData::WeightedSum (c, a, prop1, b, prop2), where a, b, and c are ints between 0 and PerData::dnum-1, is equivalent to the call PerData::WeightedSum (PerData::Addr(c), PerData::Addr(a), prop1, PerData::Addr(b), prop2). - - The index in the array of the location in which the result should be stored. - The index of the first value to be summed in the array. - The weight given to the first value. - The index of the second value to be summed in the array. - The weight given to the second value. - - - - Sets the number of elements allocated in the data array. - - The number of elements to allocate. - If TRUE previous values are kept (copied to the new storage); otherwise they are discarded. Defaults to TRUE. - - - - Sets the number of elements allocated in the data array and sets the dnum member to num. - - The number of elements to allocate. - If TRUE previous values are kept (copied to the new storage); otherwise they are discarded. Defaults to FALSE. - - - - Reduces the size of the data array to contain dnum elements. - - - - - Returns the number of elements used (dnum) - - - - - Clears (deletes) any allocated data and sets the count and type to 0. - - - - - Removes any element whose corresponding element in the is not set. - - Specifies which elements to delete. Data elelemts corresponding to bits that are on remain; for bits that are off the elements are deleted. - - - - Deletes the specified number of elements from the specified location in the data array. - - The location to delete elements. - The number of elements to delete. - - - - Inserts the specified number of data elements into the specified location in the data array. - - The zero based index of the location for the insert. - The number of elements to insert. - The data to insert. - - - - Appends the specified elements to the data array. - - The number of elements to append. - The data to append. - - - - Inserts the specified number of elements into the data array at the given location. - - The zero based index of the location to insert the data. - The number of elements to insert. - The data to insert. - - - - Appends the specified number of elements to the data array. - - The number of elements to append. - The data to append. - - - - Swaps the contents of this object and the specified one. - - The object to swap with. - - - - Assignment operator. - - The VertexData source. - - - - Description: - This class is used to filter Animatables during a hit test. See the methods Interface::PickAnimatable(). and PickAnimatableCallback::GetAnimatableFilter(). - - - - - This method should return TRUE if the passed is an acceptable hit and FALSE otherwise. This is used in the case a PickAnimatable was started. - Parameters: - *animatable - - The animatable to test. - Return TRUE if this is an acceptable hit, FALSE otherwise. - - - - - Description: - This allows added filtering of Classes that the user will be able to choose from in Interface13::DoPickClassDlg() below. If an instance is passed to DoPickClassDlg(), it is called for each candidate Class found that matches the passed SClass_ID. If IsValidClassDesc() returns true, the Class will be added to the dialog's list for the user to choose from. - - - - - Filters classes to display in the UI. - - - This method should return true if the class passed is acceptable to list, false otherwise. - Return true if this is an acceptable class, false otherwise. - - The candidate class - - - - Derive your command mode class from this one if you wish to implement your own pick command mode and want to hook it into the select by name mechanism. - - - - - Description: - This class is the callback object passed to Interface::SetPickMode(). - - - - - This method is called whenever the pick mode needs to hit test. - Parameters: - *ip - - An interface pointer available to call functions defined by 3ds Max. - - HWND hWnd - - The window handle. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. - - m - - Point to check in screen coordinates. - - int flags - - Scene and Node Hit Testing Flags. - Return TRUE if something was hit; otherwise FALSE. - Sample Code: - Interface::PickNode method - - // to perform the hit test. - - - - - - - This method is called when the user picks something. - Parameters: - *ip - - An interface pointer available to call functions defined by 3ds Max. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. The vpt should have the result of the hit test in it. - Return TRUE to end the pick mode; FALSE to stay in the pick mode. Note that returning TRUE will set the command mode to MOVE. When a plug-in is in the create branch, setting the command mode to move ends the creation process. - - - - - This method gets called when a node or controller is picked from Trackview or Schematic view The track will not be selected in Trackview if the this function returns FALSE. Override this function if you wish to support and receive nodes or controllers picked from Trackview. - Parameters: - Animatable* anim - - A pointer to the animatable object. - TRUE if the Pick Mode callback accepts the animatable object, otherwise FALSE. - Default Implementation: - The default implementation will test if anim is an , and if so, will set it as the closest in a view and pass it on to Pick - - - - - This method is called when the user right-clicks or presses ESC. - Parameters: - *ip - - An interface pointer available to call functions defined by 3ds Max. - - *vpt - - An interface pointer that may be used to call methods associated with the viewports. The vpt should have the result of the hit test in it. - TRUE to end the pick mode, FALSE to continue picking. - Default Implementation: - { return FALSE; } - - - - - Called when the mode is entered. The developer may provide any pre-processing here. - Parameters: - *ip - - An interface pointer available to call functions defined by 3ds Max. - - - - - Called when the mode is exited. The developer may provide any post-processing here. - Parameters: - *ip - - An interface pointer available to call functions defined by 3ds Max. - - - - - Called to get the default cursor to use. - The handle of the default cursor. - Default Implementation: - {return NULL;} - - - - - Called to get the hit test cursor to use. - The handle of the hit test cursor. - Default Implementation: - {return NULL;} - - - - - This method is called if the user hits the H key while in your pick mode. You can provide a filter to filter the name list. See Class . - A pointer to an instance of . - Default Implementation: - {return NULL;} - - - - - This method is called when the PickAnimatable mode is started. See PickModeCallback::PickAnimatable method. You can provide a filter to filter the . The filter can be used differently depending on the context to identify Animatables that can be picked or not. See Class . - A pointer to an instance of . - Default Implementation: - {return NULL;} - - - - - Implement this method to return TRUE to allow the user to pick more than one thing. In that case the Pick() method may be called more than once. - TRUE to allow multiple picks; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - Description: - This class is used to filter nodes during a hit test. See the methods Interface::PickNode(). and PickModeCallback::GetFilter(). - - - - - This method should return TRUE if the node passed is an acceptable hit and FALSE otherwise. - Parameters: - *node - - The node to test. - Return TRUE if this is an acceptable hit, FALSE otherwise. - - - - - Description: - This is the callback object passed to IMtlParams::SetPickMode(). It gets set so the user can pick objects in the scene. Its methods allow for filtering the picks, changing cursors over valid hits, and allowing multiple picks. - - All methods of this class are virtual. - - - - - This method is called when the user picks something. - Parameters: - *node - - This is the node that was selected. - Return TRUE to end the pick mode; FALSE to ignore the pick and to continue to allow the user to pick. - - - - - This method is called to allow the callback to filter hits. It should return TRUE if this is an acceptable hit; FALSE otherwise. - Parameters: - *node - - This is the node that was selected. - - - - - This method is called when the pick mode has been entered. The developer may provide any pre-processing here. - Default Implementation: - {} - - - - - This method is called when the pick mode has been exited. The developer may provide any post-processing here. - Default Implementation: - {} - - - - - This method is called to get the default (non-hit) cursor to use. - The handle of the non-pickable object cursor or NULL if the default cursor should be used. - Default Implementation: - {return NULL;} - - - - - This method is called to get the pickable object cursor to use. - The handle of the pickable object cursor or NULL if the default cursor should be used. - Default Implementation: - {return NULL;} - - - - - This method determines if multiple objects can be picked. Returning TRUE allows the user to pick more than one thing. In this case the Pick() method may be called more than once. - Default Implementation: - {return FALSE;} - - - - - Description: - These templated classes allow you to set up a buffer for pixels that will automatically deallocate the buffer when they goes out of scope. All methods of this class are implemented by the system. - - Note the following typedefs set up for the standard pixel storage formats. - - <UBYTE> PixelBuf8; - - <USHORT> PixelBuf16; - - > PixelBuf24; - - > PixelBuf32; - - > PixelBuf48; - - > PixelBuf64; - - - - - Returns the address of the pixel buffer. - - - - - operator. This allows access to the pixel buffer using the [ ] operator. - Parameters: - int i - - The index to access. - - - - - Fills the specified portion of the pixel buffer with the specified color. - Parameters: - int start - - The start location for the fill. - - int count - - The number of pixels to fill. - - T color - - The color to use as the fill. - Nonzero if filled; otherwise 0. - Operators: - - - - - Description: - The manipulator system exports a helper plane class. This is very useful when writing OnMouseMove() methods. It is normally used to intersect a view ray with some plane that is used by the manipulator. - Data Members: - msXYPlane; - - This constant defines the XY plane. - - msXZPlane; - - This constant defines the XZ plane. - - msYZPlane; - - This constant defines the YZ plane. - - - - - This method will intersect the plane with a ray. - Parameters: - & ray - - The ray you wish to test for intersection. - - Points3& intersectionPoint - - The resulting intersection point, if the ray intersected the plane. - TRUE if the ray intersects, otherwise FALSE. - - - - - This method returns the normal of the plane. - - - - - This method returns the point that the plane passes through. - - - - - This method returns the plane equation constant. - - - - - This method can be used to test which plane (either this or plane) is most orthogonal with the given view ray, returning that plane. This can be useful in determining which plane to project a view ray onto, if more than one is applicable. - Parameters: - & viewDir - - The given view ray. - - & plane - - The plane to test. - - - - - Description: - This class describes a 2D point using float x and y coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, normalize and compute the dot product of two Point2s. All methods are implemented by the system. - Data Members: - float x,y; - - The x and y components of the point. - - Origin; - - This is equivalent to (0.0f, 0.0f); - - XAxis; - - This is equivalent to (1.0f, 0.0f); - - YAxis; - - This is equivalent to (0.0f, 1.0f); - Constructors - - - - - Allows access to x, y using the subscript operator. - A value for i of 0 will return x, 1 will return y. - - - - - Unary -. Negates both x and y. - - - - - Unary +. Returns the point unaltered. - - - - - The 'Length' squared of the point. This is v.x*v.x+v.y*v.y. - - - - - Returns the length of the point. This is sqrt(v.x*v.x+v.y*v.y); - - - - - Returns the component with the maximum abs value. 0=x, 1=y. - - - - - Returns the component with the minimum abs value. 0=x, 1=y. - - - - - This method returns a normalized version of this . This method is more accurate than *this/Length() (internal computations are done in double precision). - - - - - Member-wise, in-place addition of this vector (x+a.x, y+a.y) - - - - - Member-wise, in-place subtraction of this vector (x-a.x, y-a.y) - - - - - Member-wise, in-place multiplication of this vector: (x*a.x, y*a.y) - - - - - Member-wise, in-place division of this vector: (x/a.x, y/a.y) - - - - - Adds floating point value to this . - - - - - Subtracts floating point value from this . - - - - - Multiplies this by a floating point value. - - - - - Divides this by a floating point value. - - - - - Sets the x and y coordinate and returns a reference to this . - - - - - Member-wise subtraction of two vectors: (x-a.x, y-a.y) - - - - - Member-wise addition of two vectors: (x+a.x, y+a.y) - - - - - Member-wise multiplication of two vectors: (x*a.x, y*a.y) - - - - - Member-wise division of two vectors: (x/a.x, y/a.y) - - - - - Returns the dot product of two 's. - - - - - Returns the dot product of two 's. - - - - - Equality operator. Compares two 's. - - - - - Returns true if the absolute difference between point components is less or equal to the given epsilon for each component - - - - - This method is used to unify (or normalize) this (in place) and return the result. Internal computations are done in double precision. - - - - - This method is used to unify (or normalize) this (in place) and return the previous length. Internal computations are done in double precision. - - - - - Description: - This class describes a 3D point using float x, y and z coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, and element by element multiply and divide two points. - - This class is also frequently used to simply store three floating point values that may not represent a point. For example, a color value where x=red, y=green, and z=blue. For color, the range of values is 0.0 to 1.0, where 0 is 0 and 1.0 is 255. All methods are implemented by the system. - - Note: In 3ds Max, all vectors are assumed to be row vectors. Under this assumption, multiplication of a vector with a matrix can be written either way (Matrix*Vector or Vector*Matrix), for ease of use, and the result is the same - the (row) vector transformed by the matrix. - Data Members: - float x, y, z; - - The x, y and z components of the point. - - Origin; - - This data member is available in release 3.0 and later only. - - This is equivalent to (0.0f, 0.0f, 0.0f); - - XAxis; - - This data member is available in release 3.0 and later only. - - This is equivalent to (1.0f, 0.0f, 0.0f); - - YAxis; - - This data member is available in release 3.0 and later only. - - This is equivalent to (0.0f, 1.0f, 0.0f); - - ZAxis; - - This data member is available in release 3.0 and later only. - - This is equivalent to (0.0f, 0.0f, 1.0f); - - - - - Copy Assignement Operator. x, y, and z are initialized to the specified . - - - - - Allows access to x, y and z using the subscript operator. - An value for i of 0 will return x, 1 will return y, 2 will return z. - - - - - Unary - operator. Negates x, y and z. - - - - - Unary +. Returns the . - - - - - The 'Length' squared of this point. This is v.x*v.x+v.y*v.y+v.z*v.z. - - - - - Returns the 'Length' of this point (vector). - - - - - Returns the 'Length' of this point (vector) using float square root. - - - - - Returns the component with the maximum abs value. 0=x, 1=y, 2=z. - - - - - Returns the component with the minimum abs value. 0=x, 1=y, 2=z. - - - - - Normalizes point using float precision - - - - - Normalizes point using double precision - - - - - Subtracts a from this . - - - - - Adds a to this . - - - - - Element-by-element multiplication of two Point3s - - - - - Member-wise, in-place division of this vector. - - - - - Adds floating point value to this . - - - - - Subtracts floating point value from this . - - - - - Multiplies this by a floating point value. - - - - - Divides this by a floating point value. - - - - - Equality operator. Test for equality between two 's. - Nonzero if the 's are equal; otherwise 0. - - - - - Returns true if the absolute difference between point components is less or equal to the given epsilon for each component - - - - - Subtracts a from a . - - - - - Adds a to a . - - - - - Divides a by a element by element. - - - - - Multiplies a by a element by element. - - (x*x, y*y, z*z). - - - - - The dot product of two 's (vectors). - - - - - The cross product of two 's (vectors). - The cross product of two 's. - - - - - Converts this into a using the X and Y components. Useful for passing a where a is expected. - - - - - Description: - This class describes a point using float x, y, z and w coordinates. Methods are provided to add and subtract points, multiply and divide by scalars, and element by element multiply and divide two points. - Data Members: - float x, y, z, w; - - The x, y, z and w components of the point. - - Origin; - - This is equivalent to (0.0f, 0.0f, 0.0f, 0.0f); - - XAxis; - - This is equivalent to (1.0f, 0.0f, 0.0f, 0.0f); - - YAxis; - - This is equivalent to (0.0f,1.0f, 0.0f, 0.0f); - - ZAxis; - - This is equivalent to (0.0f, 0.0f,1.0f, 0.0f); - - WAxis; - - This is equivalent to (0.0f, 0.0f, 0.0f,1.0f); - - - - - Allows access to x, y, z and w using the subscript operator. - An value for i of 0 will return x, 1 will return y, 2 will return z and 3 will return w. - - - - - Unary - operator. Negates x, y, z and w. - - - - - Unary +. Returns the . - - - - - Subtracts a from this . - A that is the difference between two Point4s. - - - - - Adds a to this . - A that is the sum of two Point4s. - - - - - Element-by-element multiplication of two Point4s: - - (x*x, y*y, z*z, w*w). - A element-by-element multiplied by another . - - - - - Element-by-element division of two Point4s: - - (x/x, y/y, z/z, w/w). - A element-by-element divided by another . - - - - - Adds floating point value to this . - A + a float. - - - - - Subtracts a floating point value from this . - A - a float. - - - - - Multiplies this by a floating point value. - A multiplied by a float. - - - - - Divides this by a floating point value. - A divided by a float. - - - - - Sets the x, y, z and w coordinate to the values passed and returns a reference to this . - Parameters: - float X - - The new x value. - - float Y - - The new y value. - - float Z - - The new z value. - - float W - - The new w value. - A reference to this . - - - - - Equality operator. Test for equality between two 's. - Nonzero if the 's are equal; otherwise 0. - - - - - Compares this and the specified one to see if the x, y, z and w values are within plus or minus the specified tolerance. - Parameters: - & p - - The point to compare. - - float epsilon = 1E-6f - - The tolerance to use in the comparison. - true if the absolute difference between point components is less or equal to the given epsilon for each component. - Operators: - - - - - Subtracts a from a . - A that is the difference between two Point4s. - - - - - Adds a to a . - A that is the sum of two Point4s. - - - - - Divides a by a element by element. - A resulting from dividing a by a element by element. - - - - - Multiplies a by a element by element. - - (x*x, y*y, z*z, w*w). - A resulting from the multiplication of a and a . - - - - - Description: - This is the base class for Controller Containers. Methods are available to get and set the sub-controllers, get/set the number of sub-controllers, and add sub-controllers. - - - - - the number of sub-controllers. - Parameters: - int num - - The number of sub-controllers. - - BOOL keep=FALSE - - If the number if sub-controllers is reallocated this indicates if the previously allocated ones are kept. TRUE to keep; FALSE to discard them. - Default Implementation: - {} - - - - - Return the number of sub-controllers. - Default Implementation: - { return NULL; } - - - - - Delete all the sub-controllers that are set to TRUE in the . - Parameters: - set - - This has bits set for the sub-controllers to be deleted. It should be GetNumSubControllers() in size. - Default Implementation: - {} - - - - - Adds the specified sub-controller. - Parameters: - Control* ctrl - - Points to the controller to add. - Nonzero if implemented; otherwise zero. - Default Implementation: - { return 0; } - - - - - Return a pointer to the i-th sub-controller. - Parameters: - int i - - The zero based index of the - Default Implementation: - { return NULL; } - - - - - the I-th sub-controller. - Parameters: - int i - - The zero based index of the sub-controller to set. - - Control* ctrl - - Points to the control to set. - Default Implementation: - {} - - - - - Traits information for all point classes - - - - - Describes a single polygon in a using linear segments. All methods of this class are implemented by the system. - - - - - Marks the polyline as closed by setting the POLYLINE_CLOSED flag to one. - - - - - Tells if the polyline is closed or not. - true if polyline is closed, false if it is not. - - - - - Marks the polyline as open by resetting the POLYLINE_CLOSED flag to zero - - - - - Tells if the polyline is open or not. - true if polyline is open, false if it is not. - - - - - Sets the POLYLINE_NO_SELF_INT flag. - - - - - Returns true if the POLYLINE_NO_SELF_INT flag is set, false if it is not. - - - - - Returns TRUE if the specified point is surrounded (contained within) this . This method should only be called on closed PolyLines. - - The point to check if it is inside the polyline or not. - - - - Returns the length of the calling object. - - - - - Returns true if the polyline is clockwise in the XY plane (ignoring the Z dimension), false otherwise. If the calling object self intersects, the result is meaningless. - - - - - Returns TRUE if the polyline intersects itself in the XY plane (ignoring the Z dimension), false otherwise. - - TRUE to find all self intersections, FALSE to find only the first self intersection. Defaults to FALSE. - Pointer to an class. Defaults to nullptr. If a non-null callback is supplied, the callback will be called for each intersection with the 'p' argument indicating the intersection point; 'piece1' and 'piece2' will indicate the indices of the two segments in the which intersect. - - - - Returns the number of vertices (points) in the polyline. - - - - - Returns the number of segments (edges between vertices) of the polyline. - - - - - Computes the bounding box of the polyline. The result is stored in the bdgBox data member. - - - - - Ensures that the calling object has flushed out any cached data it may have had. This resets the bounding box size and sets the cache validity to false. This should be called when any points have been changed in the polyline. - - - - - Returns the bound box of the polyline. The optional TM allows the box to be calculated in any space. - - The points of the polyline are multiplied by this matrix before the box computation. Defaults to NULL. - - - - This renders the polyline to the display. - - Points to the graphics window to render to. - The list of materials to use to render the polyline. See Class , Class - methods. - The number of materials for the polyline. - if this is set material is used to determine what colors to render the polyline. Otherwise the standard sel/subsel colors are used - this is the segment sel bitarray used to draw the selected segments - = TRUE if this is set the start/endsegments will be used around the polyline draw. If you are drawing several polylines in a row it is faster to set this to false and use start/endsegments around the entire draw instead of each individual polyline - - - - Transforms the points of the polyline by the specified matrix. - - The matrix used to transform the points. - - - - Returns a point interpolated on a segment between two points. - The interpolated point. - - The index of the segment to interpolate. - A value in the range of 0.0 to 1.0. 0 is the first point and 1 is the second point. - - - - Returns a point interpolated on the entire curve. This method returns a point but does not tell on which segment the point falls. - The interpolated point. - - A value in the range of 0.0 to 1.0 for the entire curve. - The parameter type for interpolation. The default value, POLYSHP_INTERP_SIMPLE, is based on segments (rather than the entire curve). See - - - - Returns a tangent vector interpolated on a segment between two points. - The tangent vector. - - The index of the segment. - A value in the range of 0.0 to 1.0. 0 is the first point and 1 is the second point. - - - - Returns a tangent vector interpolated on the entire curve. - The tangent vector. - - A value in the range of 0.0 to 1.0 for the entire curve. - The parameter type for interpolation. The default value, POLYSHP_INTERP_SIMPLE, is based on segments (rather than the entire curve). See - - - - The number of points in the polyline. - - - - - Pointer to the actual points in the polyline. - - - - - See PolyLine Flags. - - - - - The bounding box of the polyline. - - - - - The length of the polyline. - - - - - Cached lengths for each point. - - - - - Cached percentages for each point. - - - - - Indicates if the cache is valid. - - - - - Initializes the . The array of points (pts) is freed, the number of points is set to 0, and the cache validity is set to FALSE. - - - - - Sets the number of points in the polyline. - true if the number of points was set, false otherwise. - - The number to set. - If set to true, any existing points are copied to the new array. If not, they are freed. Defaults to true. - - - - Appends the specified point to the polyline. This adds the point to the end of the points list. - - The point to appended. - - - - Inserts the specified point at the location passed. - - The "pts" array index indicating where to insert the point. - The point to insert. - - - - Deletes the specified point. - - The "pts" array index indicating which point to delete. - - - - Reverses the order of the points in the polyline. - - Defaults to false. This should normally be passed as TRUE. If TRUE, and the polyline is closed, this method will make sure that vertex zero is the same on the reversed version as on the non-reversed version. Otherwise if passed as FALSE the last vertex becomes the first vertex, and the first vertex becomes the last. This is an important distinction for the lofter because it always wants vertex zero to be in the same place. - - - - Assignment operator. - - - - - Assignment operator. This generates a polyline from the spline. - - - - - access operator. Returns the specified point in the pts array. - - - - - Called to dump the polyline structure via DebugPrint(). See ~{ Troubleshooting }~. - - This title string is displayed using a before the rest of the data. - - - - Tells if the line segment defined between the two input points intersects this object or not. - true if the line segment defined between points p1 and p2 intersects this , false otherwise. - - The endpoints of the line to check. - TRUE to find all intersections. FALSE to find only the first intersection. Defaults to FALSE. - A pointer to an class. Defaults to nullptr. If a non-null callback is supplied, the callback will be called for each intersection with the 'p' argument indicating the intersection point; 'piece1' will indicate the index of the segment on this involved in the intersection and 'piece2' will be -1. - - - - Tells if the input intersects this or not. - true if the input line intersects this , false otherwise. - - The input to check. - TRUE to find all intersections. FALSE to find only the first intersection. - A pointer to an class. Defaults to nullptr. If a non-null callback is supplied, the callback will be called for each intersection with the 'p' argument indicating the intersection point; 'piece1' will indicate the index of the segment in 'line' which intersects and 'piece2' will indicate the index of the segment in this which intersects 'line'. - - - - Returns the material ID for the specified segment. - - The zero based index of the segment. - - - - Lets the developer transfer the content of a line object to another object without suffering from any copy penalties. This is useful to transfer polylines to a new array, for instance. - - PolLine object to swap with. - - - - This is a callback used to draw a series of lines. A developer would implement a class derived from this one that has a pointer within it. This is the base class used by and . Below is the code from showing how this is used: class :public { - - *gw; - - - - { gw = NULL; } - - { gw = g; } - - int proc(Point3 *p, int n) - - { gw->polyline(n, p, NULL, NULL, 0, NULL); return 0; } - - void SetLineColor(float r, float g, float b) - - {gw->setColor(LINE_COLOR,r,g,b);} - - }; - - Typically a developer would not have to use this class, but would rather use Class , and Class . - - - - - - Draws a polyline between the specified points. - - of vertices of the polyline. - of vertices in the polyline. - - - - Sets the color used to draw the polyline. - - Red component in the range 0.0 to 1.0 - Green component in the range 0.0 to 1.0 - Blue component in the range 0.0 to 1.0 - - - - Description: - 3ds Max 4 introduces a new type of pipeline object, the polygon-based mesh object, or for short. This object is based on the which has been present in the SDK for some time and used for 3ds Max effects like MeshSmooth, , and Connect. - - PolyObjects are more restricted than TriObjects in that they only support "manifold topology". That is to say, you can't create "rat's nest" meshes out of polygon meshes. Each edge in a polygon mesh can be referenced only once on each "side", with a well defined "outside" and "inside" direction for every element of polygons. In TriObjects, you could create a mesh with 5 vertices and 3 faces: (0,1,2), (0,1,3), and (0,1,4). This would be illegal in PolyObjects because the edge (0,1) is referenced in the (0->1) direction by three different faces. (0,1,2), (1,0,3) would be a legal pair of faces, however, because the (0,1) edge is referenced only once in each direction. This implies also that the two faces have consistent normals - there's a well-defined inside and outside at the edge. It's impossible to have neighboring faces have inconsistent normals in a , which is why the FlipNormals method in Editable Poly only works on entire elements. - - PolyObjects have a complete edge list present virtually all the time. They also have full topological links - the edges reference the vertices and faces they use, the faces reference the vertices and edges, and the vertices also reference the edges and faces. This is somewhat wasteful of memory, but it makes it very easy to navigate the mesh and do complex algorithms like subdivision or Booleans. (Of course this also means there's more to keep track of in these operations.) - - objects flowing up the pipeline should be freely convertible between TriObjects and PolyObjects. Virtually all data should be preserved in converting back and forth between these types. Exceptions include edge data, such as crease values, which are lost upon conversion to TriObjects (since TriObjects have no edge lists). - - Virtually all the public methods of are based on the equivalent methods in . class provides implementations of all the required methods of , , , , , and . All methods of this class are implemented by the system. - - - Data Members: - mm; - - See class for information about manipulating the mesh. - - - - - This does error finding and repairing on the mesh if the mesh topology has changed since the last call. - Parameters: - *inode - - The node in the scene. - - - - - Accessor for the mm data member. - - - - - Sets displacement subdivision parameters to match one of the standard displacement approximation presets. - Parameters: - int preset - - Should be 0 for low, 1 for medium, or 2 for high. - bool notifyDependents (default true) - If true, sends REF_CHANGE message to dependents as expected. Option allows you to turn this off under special circumstances, e.g. on object creation/copy. - - - - - Indicates whether displacement subdivision is currently disabled. - - - - - Accesses most of the displacement parameters. See class for details. - - - - - Indicates whether displacement subdivision splitting is on. - - - - - Indicates whether displacement subdivision is on. - - - - - Accessor method for the displacement subdivision parameters that can be quicker to use than SetDisplacementParameters() and GetDisplacementParameters(). - - - - - - - Represents a single point of a . All methods of this class are implemented by the system. - - - - - The location of the point. - - - - - See Predefined PolyPt Flags. - - - - - See Predefined PolyPt flags2. - - - - - Auxiliary data attached to this point (usually mesh vertex number for capping) - - - - - Gets the material ID on a per-segment basis within the spline or polyline. - - - - - A multi-polygon shape class. This class is used in the caching of bezier shapes. This is used for doing a one time interpolation of a bezier shape into a form that is the same shape but doesn't require any further interpolation. In this way the system can do the complex calculations once, store the shape into this representation, and not have to go through the cubic spline calculations to figure out where the points are in the future. This class maintains an array of PolyLines. As an example, this is used in the Extrude modifier. First, it generates a from the bezier shape it is extruding. Next, this is used to generate the mesh. - - - - - selected vertices - - - - - selected segments - - - - - selected polygons - - - - - Builds a bounding box surrounding every line in the lines list. The bounding box is returned through the bdgBox data member. - - - - - Invalidates the cache of each line in the . The bounding box is set to empty. This method also invalidates the capping caches. - - This parameter is not used. - - - - Invalidates the morph, and grid cap caches. - - - - - Returns the bounding box of the PolyLines in this . The optional TM allows the box to be calculated in any space. - - The points of the PolyLines in this are transformed by this matrix prior to the bounding box computations. optional TM allows the box to be calculated in any space. - - - - Computes the bounding box of this . - - The time at which to evaluate the bounding box. - The result is stored here. - The points of each in this are deformed using this matrix. - If set to true, the box is computed about the selected vertices only. All points will be used for this otherwise. - - - - Transforms the vertices of each in this by the specified matrix. - - The transformation matrix. - - - - This method may be called to fill in the passed with the appropriate capping information. See ~{ Patches and Faces }~ for more details on capping. This method is used for meshes. The method below is used for patches. - Nonzero if the cap info was set up successfully. Zero otherwise. - - This should be passed as the current time. You may retrieve this using (See Class ). - This information is filled in by this method. (See Class ). - The cap type. See . - - - - This method may be called to fill in the passed with the appropriate capping information. This method is used for patches. Note that it is generally not recommended to try to create patch caps from PolyShapes. The patch cap uses bezier information, so it is much better to use a to make a patch cap. It is very inefficient to do this with a . - Nonzero if the cap info was set up successfully. Zero otherwise - - This should be passed as the current time. You may retrieve this using (See Class ). - This information is filled in by this method. (See Class ). - - - - This may be called to display information about the to the debug window via DebugPrint(). See ~{ Troubleshooting }~. - - A string to be display before the data is displayed. - - - - This methods looks at the shape organization, and puts together a shape hierarchy. This provides information on how the shapes are nested. For example on a donut object with two circles, this method determines which circle is inside the other one. - The result is store here. - - This parameter is not used. - If non-NULL the result is store here (in addition to being returned). (See Class ). - - - - This is a very important call to make. Whenever you have changed the , for example after you are done adding polygons to the shape or have changed the number of points in a shape, you should call this method. This method updates a set of embedded selection set data within the shape. This selection set data tells what polygons are selected, what segments are selected, and what control points are selected. This resets the sizes of the selection bit arrays for this shape. - - - - - Constructs a vertex selection list based on the current selection level of the specified poly. For example if the selection level is at object level all the bits are set. If the selection level is at vertex level only the selected vertex bits are set. See Class . - - The poly whose selection level is constructed. - - - - The number of lines in the polyshape. - - - - - The array of lines. - - - - - Currently not used. - - - - - Stores the bounding box surrounding each in the shape. - - - - - The selection level. One of the following values: Selection Level Flags - - - - - Display Attribute Flags. - - - - - The morph cap information. - - - - - Determines if the morph cap is valid. - - - - - The grid cap information. - - - - - Determines if the grid cap is valid. - - - - - The patch cap information. - - - - - Determines if the patch cap is valid. - - - - - Hierarchy cache. - - - - - Determines if the hierarchy cache is valid. - - - - - For Internal use only. Initializes member variables. This function is a special version used by the constructors and should not be called by plug-in developers. If you need to clear out a use NewShape(). - - - - - This deletes all the lines from the and clears the shape out. Use this method instead of Init() function. - - - - - Sets the number of polygons used by the poly shape. - true if the number of lines were set, false otherwise. - - The number of lines. - If set to true, any old lines are copied to the new storage. They are freed otherwise. Defaults to true. - - - - Creates a new and appends it to the end of the list of lines maintained by this . - The address of the newly added line. - - - - - Appends the specified to the end of the lines list. - - The to be appended to the caller object. - - - - Inserts the specified at the input location - - The index into the lines list specifying where to insert the . - The to be inserted. - - - - Deletes the specified from the lines list. - - The index into the lines list specifying which line to delete. - - - - Assignment operator. - - - - - Assignment operator. Note that this operator does not offer as much control as calling the method on the itself named MakePolyShape(). That version allows you to specify the number of steps and an optimize parameter. These options are not available on this simple assignment operator. - - - - - Reverses the whose index is passed. - - The spline to reverse. - This should normally be passed as "true". If set to true, and the polyline is closed, this method will make sure that vertex zero is the same on the reversed version as on the non-reversed version. Otherwise, if set to false, the last vertex becomes the first vertex, and the first vertex becomes the last. This is an important distinction for the lofter because it always wants vertex zero to be in the same place. - - - - Reverses the splines of this shape if the corresponding bit in reverse is set. The has one bit for each polyline. - - If the bit is set the spline is reversed; otherwise it is left alone. - This should normally be passed as TRUE. If set to true, and the polyline is closed, this method will make sure that vertex zero is the same on the reversed version as on the non-reversed version. Otherwise, if set to false, the last vertex becomes the first vertex, and the first vertex becomes the last. This is an important distinction for the lofter because it always wants vertex zero to be in the same place. - - - - Returns the material ID for the specified segment of the specified poly. - - The zero based index of the poly. - The zero based index of the segment. - - - - Deletes multiple lines at once. This is faster than deleting one by one using Delete(), because the internal bookkeeping only needs to be done once. Lines are deleted in reverse order, from highest index to lowest index. If the array of indices is not properly sorted (in ascending order), or if the indices are not unique, the results will be undefined: the wrong lines may be deleted, or more likely 'false' will be returned, leaving you with a in an undefined state. - true if the delete operations succeeded, false if any of the indices are invalid. - - Point to an array of indices to delete. Indices should be unique, and sorted in ascending order. - of entries in the indices array. - - - - Append multiple lines at once. This is faster than appending one by one using Append(), because the internal bookkeeping only needs to be done once. - - of lines to append. - of entries in the lines array. - Should be used instead of operator = ? Using Swap() is faster, and should be used if you are just going to discard the contents of the lines array. - - - - Description: - This is the callback object used by ILoad::RegisterPostLoadCallback(). The proc() method will be called when everything has been loaded and all the references are in place. It is assumed that if the callback needs to be deleted, the proc() method will do it. - - - - - This method will be called when loading is complete. - - This class provides methods to load data from disk. - - - - This method determines the order that the various registered callbacks execute. Lower priorities are run first - allowable values {0..10}: 0 is reserved for & . This method is overridden, for example, by the ParmBlock2 PostLoadCallbacks to return 0 so it can execute before the others. - The allowable return values are 0 to 10, with 5 being the default. 0 is reserved for and .. - Default Implementation: - { return 5; } - Custom Attributes are added to their owner objects in a Priority 6 . Custom Attributes and object MetaData should be expected only in PostLoadCallbacks with a Priority of 7 or lower. Custom Attributes added in PostLoadCallbacks with a higher Priority may be replaced by the Priority 6 . - PostLoadCallbacks that could cause a node evaluation should have a Priority of 7 or lower, as in the evaluation attempts to access a Custom Attribute may occur, for example in a scripted controller. If the is just doing something like data collection, it should have a Priority of 10. - PostLoadCallbacks with a priority less than 0 will be treated as 0, greater than 10 will be treated as 10. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - The command to execute. - Optional argument 1 (defined uniquely for each ). - Optional argument 2. - Optional argument 3. - - - - Description: - The data members of this class are used to specify the options for creating a preview of the active viewport. A pointer to an instance of this class is passed into the method: - - )=0; - - - - - Specifies the output file or device. 0=default AVI codec, 1=user picks file, 2=user picks device. - - - - - Specifies the percentage (0-100) of current rendering output resolution. - - - - - The start frame limit. - - - - - The end frame limit. - - - - - Specifies how many frames are skipped between rendered frames. The is similar to the 'Every Nth Frame' parameter in the user interface. - - - - - The frames per second setting. - - - - - If TRUE is displayed in the viewports; otherwise it is not shown. - - - - - If TRUE shapes are displayed in the preview; otherwise they are not shown. - - - - - If TRUE lights are displayed in the preview; otherwise they are not shown. - - - - - If TRUE cameras are displayed in the preview; otherwise they are not shown. - - - - - If TRUE helper objects are displayed in the preview; otherwise they are not shown. - - - - - If TRUE space warp helper objects are displayed in the preview; otherwise they are not shown. - - - - - If TRUE particle objects are displayed in the preview; otherwise they are not shown. - - - - - If TRUE bone objects are displayed in the preview; otherwise they are not shown. - - - - - If TRUE the grid lines are displayed in the preview; otherwise they are not shown. - - - - - If TRUE the safe frames are displayed in the preview; otherwise they are not shown. - - - - - If TRUE frame numbers are shown in the preview; otherwise they are not shown. - - - - - If TRUE the background image is displayed; otherwise it is not used. - - - - - Specifies the rendering level used: 0=smooth/hi, 1=smooth, 2=facet/hi, 3=facet, 4=flat, 5=hidden line 6=lit wire, 7=wire, 8=box. - - - - - If TRUE multipass camera effects are displayed in the preview; otherwise they are not shown. - - - - - If TRUE cam/view name is shown in the preview; otherwise it is not shown. - - - - - If TRUE the preview file is played automatically when done; otherwise it is not played automatically. - - - - - Specifies the viewport preset used: 0=highquality, 1=standard, 2=performance, 3=dxmode, 4=userdefined. - - - - - Specifies the viewport visual style used: 0=defaultshading, 2=facets, 3=flatcolor, 4=hiddenline, 5=wireframe, 6=boundingbox, 7=ink, 8=colorink, 9=acrylic, 10=tech, 11=graphite, 12=colorpencil, 13=pastel, 14=clay, 15=modelassist. - - - - - If TRUE viewport edged faces mode is used; otherwise it is not used. - - - - - If TRUE viewport textures are shown in the preview; otherwise they are not shown. - - - - - Property Enumeration. - - - allows to define a callback for use with EnumerateProperties. It will be called for every parameter stored in the system - - - - - The call back function. - - - This is called for every property in the system, providing a way of stopping the enumeration if needed - TRUE to stop the enumeration - - The actual property found - - - - Description: - This template class represents a variable length array of pointers which can be stored and manipulated. - - - - - Assignment operator. - Default Implementation: - <T>&)PtrVector::operator=(v); } - - - - - This method allows you to append data to the array. - Parameters: - T *ptr - - A pointer to the data. - - int extra = 10 - - The amount of extra space you wish to allocate. - Default Implementation: - { PtrVector::append(ptr,extra); } - - - - - This method allows you to insert data into the array at the specified location. - Parameters: - T* ptr - - A pointer to the data to add. - - int at - - The index in the array you wish to insert at. - - int extra = 10 - - The extra space you wish to reserve. - Default Implementation: - { PtrVector::insertAt(ptr,at,extra); } - - - - - class - Description: - This class represents a variable length array of pointers which can be stored and manipulated. - Data Members: - protected: - - int size; - - The size of the array. - - int nused; - - The number of elements used. - - void** data; - - The variable length data. - protected: - - - - - This method allows you set the capacity of the array. - Parameters: - int i - - The capacity to set. - - - - - This method allows you to set the length and capacity if necessary. - Parameters: - int i - - The length to set. - - - - - This method allows you to delete the entire ptr array, but not the objects. - - - - - This method will shrink the array to its used capacity. - Default Implementation: - { reshape(nused); } - - - - - This method returns the length of the array. - Default Implementation: - { return nused; } - - - - - This method returns the capacity of the array. - Default Implementation: - { return size; } - - - - - Description: - Any parameter in a block can have an accessor callback object that has its Get() or Set() method called whenever the parameter is accessed. This may be used to provide access to dynamically-computed virtual parameters and sometimes to allow parameter-specific processing by the class as the parameter in the block is modified (such as keeping object data members up-to-date). - - The Get() and Set() methods are called at all times when a parameter is accessed, including parameters that are animated. The Get() method is called after the controller is accessed, so the current controller value is seen and can be optionally overridden in the Get() method. Note that the controller is accessed whenever the 3ds Max time is changed (such as a frame slider move) and so the Get() method will be called each frame as this happens. - - A pointer to an instance of this class is a data member of the structure. - - - - - This method is called when IParamBlock2::GetValue is called on parameter 'id', and the parameter value is v. This method is called after the controller is accessed, so the current controller value is seen and can be optionally overridden in this method. Note that the controller is accessed whenever the 3ds Max time is changed (such as a slider move) and so this method will be called each frame as this happens. - Default Implementation: - {} Notes: The content of 'v' is the value from the parameter, and can be changed by this Get method. If the parameter type is such that the parameter value is a data value held by a pointer (v.p, v.p4, v.m, v.p2) that pointer is guaranteed to be non-null, and the Get method must not set it to null. Either the existing data value must be updated in-place (pointer unchanged), or the existing data value must be deleted (typically using PB2Value::Free) and a new pointer assigned. The will free this pointer when it is done using the data. If the parameter type is TYPE_STRING or TYPE_FILENAME, v.s contains a pointer to a copy of the string, and owns this copy. v.s may be null. The string can be modified in place, or can be replaced with a new string using the 's ReplaceString method. The will free this pointer when it is done using the data. If the parameter type is TYPE_BITMAP, v.bm contains a pointer to a , and owns this pointer. v.bm may be null. The can be modified in place, or the existing must be deleted (typically using PB2Value::Free) and a new pointer assigned (typically by cloning a . The will free this pointer when it is done using the data. - - - The value being accessed. - - Points to the owner of the parameter block. - - The permanent ID of the parameter. - - If the parameter is a <> this is the zero based index of the parameter in the table. - - The current time the get is taking place. - - The validity interval to update. The intersection of the provided "valid" interval with the interval for the provided TimeValue and returned as the updated interval value. - - - - This method is called when IParamBlock2::SetValue is called on parameter 'id', and the parameter value being set is v. This is called just before calling SetValue() on the parameter's controller, so it can take note of the value going in and change it if desired. - Parameters: - & v - - The value being set. - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. - - TimeValue t - - The current time the set is taking place. - Default Implementation: - {} Notes: The content of 'v' is the value being set on the parameter, and can be changed by this method. If you get the value of the parameter from the parameter block from within the method, whether the value returned will be the existing value or the new value varies by parameter type and whether the parameter is animatable. For parameter types that correspond to data types such as float, integer, and point3, the method is called before the parameter block parameter is set unless the parameter block parameter is already animated or setting the value would cause it to be animated. If the parameter block parameter would remain constant after the set, the method is called after the parameter block parameter is set. If the parameter type is such that the parameter value is a data value held by a pointer (v.p, v.p4, v.m, v.p2) that pointer is guaranteed to be non-null, and the method must not set it to null. Either the existing data value must be updated in-place (pointer unchanged), or the existing data value must be deleted (typically using PB2Value::Free) and a new pointer assigned. The will free this pointer when it is done using the data. If the parameter type is TYPE_STRING or TYPE_FILENAME, v.s contains a pointer to a copy of the string, and owns this copy. v.s may be null. The string can be modified in place, or can be replaced with a new string using the 's ReplaceString method. The will free this pointer when it is done using the data. If the parameter type is TYPE_BITMAP, v.bm contains a pointer to a , and owns this pointer. v.bm may be null. The can be modified in place, or the existing must be deleted (typically using PB2Value::Free) and a new pointer assigned (typically by cloning a . The will free this pointer when it is done using the data. - - - - - This method is called when IParamBlock2::SetValue is called on parameter 'id', and the parameter value being set is v. This is called before setting the parameter's value or calling SetValue() on the parameter's controller, so it can take note of the value going in and change it if desired. - Parameters: - & v - - The value being set. - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. - - TimeValue t - - The current time the set is taking place. - Default Implementation: - {} Notes: The content of 'v' is the value being set, and can be changed by the PreSet method. If you get the value of the parameter from the parameter block from within the PreSet method, the value returned will be the existing value. If the parameter type is such that the parameter value is a data value held by a pointer (v.p, v.p4, v.m, v.p2) that pointer is guaranteed to be non-null, and the PreSet method must not set it to null. Either the existing data value must be updated in-place (pointer unchanged), or the existing data value must be deleted (typically using PB2Value::Free) and a new pointer assigned. The will free this pointer when it is done using the data. If the parameter type is TYPE_STRING or TYPE_FILENAME, v.s contains a pointer to a copy of the string, and owns this copy. v.s may be null. The string can be modified in place, or can be replaced with a new string using the 's ReplaceString method. The will free this pointer when it is done using the data. If the parameter type is TYPE_BITMAP, v.bm contains a pointer to a , and owns this pointer. v.bm may be null. The can be modified in place, or the existing must be deleted (typically using PB2Value::Free) and a new pointer assigned (typically by cloning a . The will free this pointer when it is done using the data. - - - - - This method is called when IParamBlock2::SetValue is called on parameter 'id', and the parameter value being set is v. This is called after setting the parameter's value or calling SetValue() on the parameter's controller. - Parameters: - & v - - The value that was set. - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. - - TimeValue t - - The current time the set is taking place. - Default Implementation: - {} Notes: The content of 'v' is the value that was set, and cannot be changed by the PostSet method. If you get the value of the parameter from the parameter block from within the PostSet method, the value returned will be the new value. If the parameter type is such that the parameter value is a data value held by a pointer (v.p, v.p4, v.m, v.p2) that pointer is guaranteed to be non-null. - - - - - Checks to see if a keyframe exists for the given parameter at the given time. Returns TRUE if a keyframe exists at the specified time; otherwise FALSE. For parameters not directly hosted in the parameter block that are internally animatable, this provides a keyframe query callback so that any ParamMap2 spinners associated with these 'virtual' parameters can show keyframe status for the underlying parameter. In these cases, developers should implement this method for the parameter usually asking the underlying parameter for its keyframe state. - Parameters: - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - TimeValue t - - The current time. - Default Implementation: - { return FALSE; } - - - - - This allows a plug-in to provide a dynamically-created local name for a parameter or <> parameter entry. If you specify the P_COMPUTED_NAME parameter flag, you also need to supply a p_accessorPBAccessor instance pointer that has this method implemented. - Parameters: - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. bool localized - - If true, then the name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - Default Implementation: - { return _M(""); } - - - - - This method is called when a <> parameter has a change made to its table structure. - Parameters: - tab_changes changeCode - - Describes the change that has just occurred to the <> parameter. One of the following enumerations: - - enum tab_changes { tab_insert, tab_append, tab_delete, tab_ref_deleted, tab_setcount, tab_sort }; - - >* tab - - Points to the actual <> in the pblock parameter. - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - The start index of the change (for tab_insert, tab_append, tab_delete, tab_ref_deleted) - - int count - - The number of elements changed (for tab_insert, tab_append, tab_delete). - - - - - Description: - This is a Bitmap/BitmapInfo wrapper class. It is used by ParamBlock2s to store bitmap information. The class has two public data members that hold the and the itself. - Data Members: - bi; - - Stores the for the bitmap. - - *bm; - - Points to the itself. - - - - - Implemented by the System - - The is used to Load the bitmap as specified by the . - - - - - Implemented by the System - - Makes a copy of the bitmap and returns a pointer to it. - - - - - This method is called when the specified owner objects sets the value v. This is called just before calling SetValue() on the parameters controller, so it can take note of the value going in and change it if desired. NOTE: This is ONLY called when the is being performed as part of a RescaleParam operation, such as happens when RescaleWorldUnits() is called. NOTE: This method is NOT called when the parameter in question is animated, as the system rescales the controller separately. - Parameters: - & v - - The value being set (already scaled). - - float scaleFactor - - The scale factor that was used to compute the new value (above). - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. - - TimeValue t - - The current time the set is taking place. - Default Implementation: - {} - - - - - Description: - A pointer to an instance of this class is a data member of struct and is also used by the p_validator tag in a constructor. Any parameter can have a custom validator. This is used by the scripter and node pick button filter for example. If you want to validate a parameter block 2 value create an instance of this class and implement the Validate() method. - - - - - Returns TRUE if the given if valid; otherwise FALSE. - Parameters: - & v - - The value to check. - - - - - A variant of Validate() method to PBValidate which supplies more context than the original Validate(), effectively giving the same context information as the & Get() methods in a . - Parameters: - & v - - The value to check. - - ReferenceMaker* owner - - Points to the owner of the parameter block. - - ParamID id - - The permanent ID of the parameter. - - int tabIndex - - If the parameter is a <> this is the zero based index of the parameter in the table. - - - - - This class is used to identify the particle group and action list the hit particle belongs to. Instances of this are logged to the system, and therefore are owned and the memory is freed by the System. - - - - - Description: - This is used internally by the / Map Browser which supports the display of small and large icon images for material and texture maps. This class is the postage stamp image object. - - The width in bytes of the image pixel array is given by the following macro, where w is pixel width. - - ByteWidth(w) (((w*3+3)/4)*4) - - - - - Returns the width of the image in pixels. - - - - - Returns the height of the image in pixels. - - - - - Retrieves the image bytes of the postage stamp. - Parameters: - UBYTE *img - - This is an array of RGB triplets. - - - - - This method is used to load the postage stamp image. - - - - - This method is used to save the postage stamp image. - - - - - Description: - quantizer, for doing true-color to paletted conversion. All methods of this class are implemented by the system. Create a object by calling: - - *BMMNewQuantizer(); - - Be sure to call Quantizer::DeleteThis() when done. - - - - - This method allocates the histogram used in doing the conversion. - Nonzero if the histogram was allocated; otherwise zero. - - - - - This method uses the histogram and computes the palette. - Parameters: - *pal - - Storage for the palette to compute. - - int palsize - - The size of the palette. - - *forceCol - - If there is a color that you want to make sure is available in the palette, you may pass it here. This is used for the background color of an image for example. If this is not NULL the quantizer will make up a palette and make sure that this color is in it. For backgrounds, this looks much nicer because the background won't be dithered when shown using the palette. - Nonzero if the palette was computed; otherwise zero. - - - - - Adds the specified colors to the histogram so they are taken into account in the palette computations. - Parameters: - *image - - The pixels to include. - - int npix - - The number of pixels above. - - - - - Adds the specified colors to the histogram so they are taken into account in the palette computations. - Parameters: - *image - - The pixels to include. - - int npix - - The number of pixels above. - - - - - Adds the specified colors to the histogram so they are taken into account in the palette computations. - Parameters: - *image - - The pixels to include. - - int npix - - The number of pixels above. - - - - - Description: - This class provides a compact representation for orientation in three space and provides methods to perform Quaternion algebra. - - Quaternions provide an alternative representation for orientation in three-space. To reduce computing, you can substitute quaternion multiplication for rotation-matrix composition. - - A quaternion is made up of four terms: a real scalar part which specifies the amount of rotation and an imaginary vector part which defines the axis of rotation. If the quaternion is normalized, the scalar term equals the cosine of half the angle of rotation, the vector term is the axis of rotation, and the magnitude of the vector term equals the sine of half the angle of rotation. - - Interpolation between two key frame orientations is much easier using quaternions and produces smooth and natural motion. Unlike Euler angles, no numerical integration is necessary; quaternions provide an analytic result (no approximations). - - The rotation convention in the 3ds Max API is the left-hand-rule. Note that this is different from the right-hand-rule used in the 3ds Max user interface. - - For additional information see: Quaternion operations: - - From "Quaternion Calculus and Fast Animation", - - by Ken Shoemake, in notes for SIGGRAPH 1987 Course # 10, - - "Computer Animation: 3-D Motion Specification and Control". - - All methods of this class are implemented by the system. - Data Members: - float x,y,z,w; - - The x, y, z values make up the vector portion. w is the angle of rotation about the vector (see remarks above for details). - - - - - access operator. Valid i values: 0=x, 1=y, 2=z, 3=w. - - - - - Unary negation. Returns (-x,-y,-z,-w). - - - - - Unary +. Returns the unaltered. - - Assignment operators - - - - - Returns the inverse of this quaternion (1/q). - - - - - Returns the conjugate of a quaternion. - - - - - Returns the natural logarithm of a UNIT quaternion. - - - - - Returns the exponentiate quaternion (where q.w==0). - Operators: - - - - - This operator is the same as the /= operator. - - - - - This operator is the same as the *= operator.. - - - - - Multiplies this quaternion by a quaternion. - - - - - Multiplies this quaternion by a floating point value. - - - - - Divides this quaternion by a floating point value. - - - - - Modifies q so it is on same side of hypersphere as qto. - - - - - Returns nonzero if the quaternions are equal; otherwise 0. - - - - - Sets this quaternion to the identity quaternion (x=y=z=0.0; w=1.0). - - - - - Returns nonzero if the quaternion is the identity; otherwise 0. - - - - - Normalizes this quaternion, dividing each term by a scale factor such that the resulting sum or the squares of all parts equals unity. - - - - - Converts the quaternion to a 3x3 rotation matrix. The quaternion need not be unit magnitude. - Parameters: - &mat - - The matrix. - - BOOL b=FALSE - - This parameter is available in release 4.0 and later only. - - When this argument is set to false (or omitted), each function performs as it did before version 4.0. When the boolean is TRUE, the matrix is made with its terms transposed. When this transposition is specified, EulerToQuat() and QuatToEuler() are consistent with one another. (In 3ds Max 3, they have opposite handedness). - - - - - This operator is the same as the / operator. - - - - - This operator is the same as the * operator. - - - - - Returns the product of two quaternions. - - - - - Returns the ratio of two quaternions: This creates a result quaternion r = p/q, such that q*r = p. (Order of multiplication is important) - - - - - Description: - This class is only available in release 5 or later. - - The class provides the interfaces for creating Advanced Lighting plug-ins in 3ds Max. plug-ins are controlled through the Advanced Lighting dialog from the render menu. - - A behaves as a light in the scene. An implementation of must also provide an implementation of , to be returned from RadiosityEffect::CreateLightDesc(). This is then used by the renderer to apply the radiosity light during a render. - - The architecture is designed to support scene based lighting solvers (which use a pre-calculated solution), as well as image based solvers (which calculate their solution at render time). The method RunProcess() and its relatives, StopProcess(), AbortProcess(), and WaitForCompletion() are called by the system to request processing of a scene based solution. Image based solvers only need stub implementations of these methods. - - A can use a to control the viewport display of scene geometry. In particular, it is possible for a lighting solution to be displayed interactively in the viewport if the provides geometry with appropriate vertex illumination. - - A may want to reference objects in the scene to detect events which invalidate its lighting solution. A problem arises that the can become inundated with reference messages, so to address this problem the should ignore any message where the PART_EXCLUDE_RADIOSITY flag is set in the PartID of the message. Any message where ((partID|PART_EXCLUDE_RADIOSITY)!=0) is an event that the system deems should not invalidate the radiosity, for example, when texture display in viewport is turned on or off. - - See also IsInterestedInChannels() in Class . - - All methods of this class are virtual. - - - - - - - Enables or disables the radiosity effect. - - - Corresponds to the Active checkbox in the Advanced Lighting dialog. Although a TimeValue parameter is passed to this method, the active state of the plug-in is not animatable. Plug-ins should call the default implementation of SetActive(), optionally adding their own code. - - - Specifies whether the plug-in is active or inactive - - Specifies the current scene time when the method is called. - - - - Merges this radiosity solution into the current solution. - - - This method is called for the currently selected radiosity plugin, when merging objects from a file that also has a radiosity plugin. The default behaviour does not merge the solutions. - IO_OK if the merge succeeded. - - - The file loader used to merge this radiosity solution - - Identifies the class of the radiosity plugin being loaded. - - - - Returns whether the given light should render it's illumination in the production render. - - - If the return value is true, the light is disabled while rendering. - - This is used to allow the radiosity plug-in to override lights in the scene with light from it's own solution. - Return true if the light should be enabled while rendering; or false if it should be disabled - - - The of the light. - - Indicates whether the solution will be re-calculated (ie, there is a glowing object that will create the solution). - - - - Create light objects that the renderer can use to get the radiosity contribution. - - - NumLightDesc returns the number of objects the radiosity plugin needs for rendering. CreateLightDesc creates all of the objects, and stores their addresses in buffer. Buffer must be large enough to hold all of the addresses. - The number of objects the RadisoityEffect will return from CreateLightDesc() - - - - - Creates light objects that the renderer can use to get the 's contribution. - - - CreateLightDesc() creates a number of objects indicated by NumLightDesc(), and stores their addresses in the buffer. Caller is responsible for ensuring that the buffer is large enough. - - Note: the caller will delete the objects when the render is completed, so this method should dynamically allocate the instances, rather than providing static instances. - - - The buffer into which the pointers should be stored. - - - - Called by the system to start the radiosity processing. - - - This should start the process from the beginning, or where it stopped previously, if applicable. The method should launch a separate thread and return immediately; the system will call WaitForCompletion() to wait for the thread to complete. - - This is specific to solvers which use a pre-calculated solution. Other solvers need only a stub implementation. - - - Specifies the scene time when the method is called. - - This can be used to retrieve information about the global rendering environment. - - Specifies whether the lighting solution is being calculated for interactive rendering. Note that the default renderer does not support interactive rendering with Advanced Lighting, but other plug-in renderers might potentially do so, in which case the should attempt to generate a fast, lower quality solution for interactive display. - - - - Stop the lighting calculation. - - - If possible, the should attempt to reach an intermediate solution, so that calculation can be continued later. However, this may take awhile, and If allowAbort is true, the is expected to prompt the user with a dialog, asking if they wish to abort. - - - If true, the RadisoityEffect is expected to prompt the user with a dialog so they may abort the process of stopping the calculation and saving an intermediate solution - - - - Abort the lighting calculation. - - - The should to abort immediately, without saving an intermediate solution. - - - - - Wait for radiosity process to complete. - - - This is called by the system when waiting for the lighting calculation to finish. This method should not return to the caller until the calculation is complete, or when the timeout (in milliseconds) expires. The can be used to display the progress of the calculation to the user, and to check if the cancel button is pressed. - - - Use this to display a progress bar for the user, or to detect when the user hits the cancel button. - - An amount of time (measured in milliseconds) that the system is willing to wait. The method should measure its own running time and return to the caller when the timeout expires. - - - - Called right before RunProcess. - - - Indicates whether the plug-in wants the renderer to build camera-space vertices. - True if the wants the renderer to calculate camera-space vertices, false otherwise. - - - Specifies the current scene time when the method is called. - - This can be used to retrieve information about the global rendering environment. - - Specifies whether the lighting solution is being calculated for interactive rendering. Note that the default renderer does not support interactive rendering with Advanced Lighting, but other plug-in renderers might potentially do so, in which case the should attempt to generate a fast, lower quality solution for interactive display. - - True if the user has selected "Conserve Memory" in the Render Dialog, under the "MAX Default Scanline A-Buffer" rollout, or if the render is occurring in the material editor. - - - - Description: - This class is only available in release 5 or later. - - This class provides access to the Advanced Lighting dialog. It allows you to open and close the dialog, and get or set the currently active Advanced Lighting plug-in. This class is a function-published static interface; you can use GetCOREInterface() to obtain an instance of the class, as follows: - - r = static_cast<IRadiosityInterface*>(GetCOREInterface(RADIOSITY_INTERFACE)) - - This interface is also accessible via MAXScript as "<b>SceneRadiosity</b>". - - All methods of this class are implemented by the system. - - - - - - - Displays the Advanced Lighting dialog, unless it is already displayed. - - - - - Hides the Advanced Lighting dialog, if it is currently displayed. - - - - - Minimizes the Advanced Lighting dialog if it is open. - - - - - Get the radiosity in the scene. - - - Returns a pointer to the currently active Advanced Lighting plug-in () if any. - - - - - Description: - This class defines a Pseudo-random number generator that precisely matches the behavior of the MSVCRT 6.0 random routines. That is to say, for equivalent calls to srand() and Random::srand(), both rand() and Random::rand() will produce the same results. - - The benefit, however, in having this class is that each instantiation is independent, permitting several uncoupled random number generators to be present in the system at once. Moreover, each instantiation is automatically "pre-seeded", making calls to Random::srand unnecessary in most uses. Even arrays of items will operate independently. - - In addition to providing the analogues to the "stdlib" functions, this class also provides two useful member functions which can be used to get a random number bounded in either a float or int interval. - - Note: To use this class be sure to link to MAXUTIL.LIB. - Sample Code: - Note in all "get" cases that contain limits they are specified (max, min). Also be aware that the min value can be attained, but the max cannot. That is to say min <= value < max. - Data Members: - static const int s_rand_max; - - This is akin to the Windows API global RAND_MAX. The constant RAND_MAX is the maximum value that can be returned by the rand function. RAND_MAX is defined as the value 0x7fff. - - - - - This method is akin to the global srand() function. From the Windows API documentation: - - The srand function sets the starting point for generating a series of pseudorandom integers. - Parameters: - unsigned int seed = 1 - - To reinitialize the generator, use 1 as the seed argument. Any other value for seed sets the generator to a random starting point. rand retrieves the pseudorandom numbers that are generated. Calling rand before any call to srand generates the same sequence as calling srand with seed passed as 1. - - - - - This method is akin to the global rand() function. From the Windows API documentation: - - The rand function returns a pseudorandom integer in the range 0 to RAND_MAX. Use the srand function to seed the pseudorandom-number generator before calling rand. - - - - - Returns a random number in the half-open interval [min, max) such that r=get(max, min) := min <= r < max. Note that max is the first arg, and min is the second, permitting one to select, for example, an int in [0,5) = [0,4] with "get(5)". With no arguments, Random::get() is equivalent to Random::rand(). - Parameters: - int max_exclusive = s_rand_max+1 - - The maximum value. - - int min_inclusive = 0 - - The minimum value. - - - - - Returns a random number in the half-open interval [min, max) such that r=get(max, min) := min <= r < max. Note that max is the first arg, and min is the second, permitting one to select, for example, a float in [0.0, 5.0) with "getf(5)". With no arguments, Random::getf() returns a float in [0.0, 1.0). - Parameters: - float max_exclusive = 1.0f - - The maximum value. - - float min_inclusive = 0.0f - - The minimum value. - - - - - class - Description: - This class has interfaces for srand() and rand() methods of VC++ and other functions for random number generation. The srand() and rand() methods from stdlib.h have two main problems: - - a) It's not satisfactorily random. The rand() function returns a pseudorandom integer in the range 0 to 0x7fff=32767. If we need a lot of random numbers using rand() (i.e. for generating 100,000 particles), we run out of continuity of random numbers. Generated random numbers becomes too discrete. - - b) The rand() method is global function, not class object. Hence it is shared between all modules of your plug-in. Changes in one module may change randomness pattern in other independent module. To solve this contradiction, rand methods have to be implemented as a class object. - - The does exactly that. It has much more random numbers: RAND_MAX = 0xFFFFFFFF = 4,294,967,295. Also, using instances of the class, it's much easier to create separate threads of random numbers for a specific module. - - - Data Members: - static const DWORD32 RAND_MAX - - This definition is used to override the VC++ rand methods. - - - - - This method sets the starting point for generating a series of pseudorandom integers. To reinitialize the generator, use 1 as the seed argument. Any other value for seed sets the generator to a random starting point. rand() retrieves the pseudorandom numbers that are generated. Calling rand() before any call to this method generates the same sequence as calling it with seed passed as 1. - Parameters: - DWORD32 seed - - The starting seed. - - - - - This method returns a pseudorandom integer in the range 0 to RAND_MAX - - - - - This method returns the random number sign, either -1 or 1. - - - - - This method return a random number between 0.0f and 1.0f. - - - - - This method return a random number between -1.0f and 1.0f. - - - - - This method return a random number between -0.5f and 0.5f. - - - - - This method return a random number between 0 and maxnum. - - - - - This method returns TRUE if the random number generator has been explicitly initialized by the srand() method. - - - - - Description: - This class describes a vector in space using an origin point p, and a unit direction vector dir. - Data Members: - p; - - Point of origin. - - dir; - - Unit direction vector. - - - - - is only used for opening text file in read-only mode. It's equivalent to use when opening files in "rt" mode. But is very slow when reading files. So we optimize the original codes in and create this new class which is thousand times faster for reading text files than . - Invoke any non-read-only methods in will result in a runtime exception. Such methods include putch(),puts(),printf(). - - - - - Open a new text file. - The instance itself if max is able to open the file or undefined if it fails. - - The file name. - The encoding to use if if can not be determined from the file contents, If -1, a default encoding based on the file language setting in Preference /Files (exposed through ) will be used. - - - - The commong mix-in interface for setting realWorldMapSize properties on objects and modifiers. - - - Details follow here. This class is used with multiple inheritence from a class which exports a "real-world map size" toggle. The class must implement two abstract methods for setting and getting this value. The class must implement the following method: BaseInterface* GetInterface(Interface_ID id) { if (id == RWS_INTERFACE) return this; else return FPMixinInterface::GetInterface(id); } The client class must add this interface the first time ClassDesc::Create() is called on the class's class descriptor. See maxsdk/samples/objects/boxobj.cpp for an example of the use of this class. - - - - - Gets the state of the real-world map size toggle - the current state of the toggle - - - - - Class for creating undo record for any class with a "Real-World Map Size" property. - This is a template class where the template parameter T is the type which supports the real-world map size property. This class must have a method called SetUsePhysicalScaleUVs(BOOL state). - - - - - Description: - This is the callback used with Interface::RegisterRedrawViewsCallback(). - - - - - This method will be called after all the viewports have completed drawing. - Parameters: - *ip - - A pointer for calling functions available in 3ds Max. - - - - - A scene entity that owns other scene entities and listens to messages from them. - - - A reference link is similar to the relationship that exists between an observer and its subjects in an observer design patters, except that reference links also mean ownership, unless otherwise specified. - Note that copying instances would not correctly establish reference hierarchy relationships between this destination object and the references held by the source object. Therefore copying of ReferenceMakers is prohibited. 3ds Max does not control the lifetime of ReferenceMakers but it does that of ReferenceTargets, therefore only cloning of ReferenceTargets is supported. For more information, see ReferenceTarget::Clone(). - Note that RefMakerHandle is a typename for pointers to an object of type . - See the section on ~{ Reference System }~ for an overview of the 3ds Max reference architecture. - - - - - Deletes an instance of this class. - - - Deletes all references to and from this object, sends REFMSG_TARGET_DELETED messages, and deletes the object. If the undo system is engaged (holding) it ensures that the operation is undo/redo-able. Note that this method should only be called by plugins when they need to delete plugin objects via pointers or in case the plugin to be deleted does not allow the system to automatically delete it. See ReferenceTarget::MaybeAutoDelete() and ReferenceTarget::AutoDelete() for more information. - - - - - Used when cloning reference makers. - - - This routine is used when cloning reference makers, to delete old reference and make a new one. In max r9, additional checks have have been added to ReplaceReference. If parameter which is < 0, REF_FAIL will be immediately returned. If parameter which is >= NumRefs, an attempt will be made to set the reference, and then another check will is made to see if which is >= NumRefs, and if so REF_FAIL is returned. There are 2 additional tests that can be enabled in order to ensure that plugins set up their references correctly. Both are executed at run-time when a plugin calls ReplaceReference: - - - - - - - Deletes all references from this . - - - Implemented by the System. - This is always REF_SUCCEED indicating the references were deleted. - - - - - Deletes all refs to this RefMaker/RefTarget. - - - Implemented by the System. This method deletes all the references to this reference maker/reference target. This also sends the REFMSG_TARGET_DELETED message to all dependents. - This is REF_SUCCEED if the references were deleted; otherwise it is REF_FAIL. - - - - - Deletes all references both to and from this item. - - - Implemented by the System. Deletes all references both to and from this item. - This is REF_SUCCEED if the references were deleted; otherwise it is REF_FAIL. - - - - - Deletes the specified reference. - - - Implemented by the System. This method deletes the reference whose virtual array index is passed. The other reference indices are not affected, i.e. the number of references is not reduced nor are they reordered in any way. Note the system calls SetReference(i, NULL) to set that reference to NULL. Also, if this is the last reference to the item, the item itself is deleted by calling its DeleteThis() method. - This is REF_SUCCEED if the reference was deleted; otherwise it is REF_FAIL. - - - The virtual array index of the reference to delete. - - - - Tells whether this reference can be transfered. - - - A can choose not to let ReferenceTarget::TransferReferences() affect it. Note that plugins probably should not use this. It is used by certain system objects that have references. - Default to return TRUE - - - Currently not used. - - - - Stores a as its 'i-th' reference`. - - - The plugin implements this method to store the reference handle passed to it as its 'i-th' reference. In its implementation of this method, the plugin should simply assign the reference handle passed in as a parameter to the member variable that holds the 'i-th' reference. Other reference handling methods such as ReferenceMaker::DeleteReference(), or ReferenceMaker::ReplaceReference() should not be called from within this method. The plugin itself or other plugins should not call this method directly. The system will call this method when a new reference is created or an existing one is replaced by calling ReferenceMaker::ReplaceReference(). - - - The index of the reference to store. Valid values are from 0 to -1. - - The reference handle to store. - - - - Returns the total number of references this can hold. - - - The plugin implements this method to indicate the total number of of references it can make. This includes all references whether they are NULL (inactive) or non-NULL (active) at the time when this method is called. A plugin can hold a variable number of references, thus the return value of this method is not to be cached and reused by client code. - The total number of references this plugin can hold. The default implementation is return 0. - - - - - Returns the 'i-th' reference. - - - The plugin implements this method to return its 'i-th' reference. The plug-in simply keeps track of its references using an integer index for each one. This method is normally called by the system. - The reference handle of the 'i-th' reference. Note that different calls to this method with the same 'i' value can result in different reference handles being retrieved, as the plugin changes the scene objects it references as its 'i-th' reference. - - - The index of the reference to retrieve. Valid values are from 0 to -1. - - - - Access the of this . - - - The is used to specify and enumerate the save reference hierarchy for the . If a plugin needed to specify a save reference hierarchy different than its normal reference hierarchy, it would implement SpecifySaveReferences() and specify the save reference hierarchy through the in that implementation. - the for the . - - - - - Called for saving data. - - - Called by the system to allow the plugin to save its data. - The default implementation is return IO_OK. - - - This pointer may be used to call methods to write data to disk. See the section on ~{ Loading and Saving Plug-in Data }~ for an overview of the load/save process. - - - - Called for loading data. - - - Called by the system to allow the plug-in to load its data. See the section on ~{ Loading and Saving Plug-in Data }~ for an overview of the load - save process. - The default implementation is return IO_OK. - - - This interface pointer may be used to call methods to read data from disk. - - - - Used to load old files with references. - - - Implement this if you have added or deleted references and are loading an old file that needs to have its references remapped. - This method is used when you have modified a to add or delete references, and are loading old files. It gets called during the reference mapping process, after the Load() method is called. You determine what version is loading in the Load(), and store the version in a variable which you can look at in RemapRefOnLoad() to determine how to remap references. The default implementation of this method just returns the same value it is passed, so you don't need to implement it unless you have added or deleted references from your class. This method makes it a lot easier to load old files when the reference topology has changed. - The output index of the reference. - - - The input index of the reference. - - - - Rescale size of all world units in object and its reference hierarchy. - - - Must call: or before calling this on an object, unless being called from a RescaleWorldUnits implementation. The instance is not required, but improves performance by reducing notification messages. Note that Interface::RescaleWorldUnits performs these actions. This method may be implemented to rescale the size of all world units in an object and its reference hierarchy. In the implementation, developers must call: before performing any scaling. This prevents multiple rescales of the same object. The default implementation calls RescaleWorldUnits on each of its references, and on its custom attribute container if it exists. - - - The scale factor. - - - - Send a notification all classes that reference this class. - - - Since a cannot have dependents, ReferenceMaker::NotifyDependents() is implemented to simply return REF_SUCCEED. - - - - - The default save enumeration. - - - This method is used internally. - - - - - Used to specify reference slot remapping during scene file save. - - - Plugins that want to add, remove, or change the references held by the as stored to the scene file implement this method. The method implementation would modify the stored reference hierarchy through the specified . Plugins that implement this method must call SpecifySaveReferences() on their parent class after they have finished performing operations on the . The modifies the save hierarchy in the order that operations are performed on it, so operations on higher-indexed reference target slots should occur before operations on lower-indexed reference target slots. Otherwise, the indexing on the higher-indexed reference target slots may point at an incorrect slot. For example, if the plugin currently had slots 1,2,3 and then inserted slot 4 at position 3 and then removed slot 2, the plugin would end up with slots 1,4,3. If the order of the operations was reversed, the plugin would end up with slots 1,3,4. The level implementation finalizes the preparation of the to support the scene file save reference slot remapping. - true if no errors processing any add, remove, or change operations registered with the . An error will occur if the reference slot index specified for an operation is invalid after performing any previously registered operations. - - The for the object - - - - Begins an enumeration that searches back in the dependency network. - - - Implemented by the System. See the documentation for for more details. When called on instances that derive from , the call is passed along to the ReferenceTarget::DoEnumDependents method. Otherwise this method returns 0. - Return 1 to stop the enumeration and 0 to continue. The default implementation for is return 0; - - - The callback object called for each dependent. - - - - Method to perform an enumeration on a . - - - Implemented by the System. See the documentation for for more details. - Return 1 to stop the enumeration and 0 to continue. - - - The callback object called for each dependent. - - - - This method provides a general purpose reference enumerator. - - - This method provides a general purpose reference enumerator that calls RefEnumProc::proc() on each element in a reference hierarchy. This function walks down the reference hierarchy, recursively calling RefEnumProc::proc() on the references held by a reference, This function ensures that RefEnumProc::proc() is called only once on each reference. Processing each reference only once improves efficiency, and prevents potential infinite recursive loops when processing indirect references. To enumerate the up the reference hierarchy, see ReferenceTarget::DoEnumDependents. - Returns false if the enumeration was terminated because the 's proc returned REF_ENUM_HALT, true otherwise - - - The callback object whose proc() method is called for each element. - - Added in 3ds 6 SDK. Defaults to true. With includeCustAttribs set to true, will be called for the custom attributes applied to the reference maker. - - Added in 3ds 9 SDK. Defaults to true. With includeIndirectRefs set to true, will be called for the indirect references held by the reference maker. - - Added in 3ds 9 SDK. Defaults to true. With includeNonPersistentRefs set to false, will not be called on direct references from the reference maker unless IsRealDependency or ShouldPersistWeakRef returns true for that reference; and the proc method will not be called on indirect references from the reference maker unless ShouldPersistIndirectRef returns true for that indirect reference. - - Added in 3ds 9 SDK. Defaults to true. With preventDuplicatesViaFlag set to true, processing of a duplicate reference is detected by requesting and clearing a flag bit on all animatables, and then testing/setting the flag bit prior to calling the proc on each reference maker. When set to false, a list of reference makers visited is maintained. If you expect to enumerate only a small number of references, this argument should be set to false. Note however that you do not know what references are held by the references you may enumerate into, so in most cases this argument should be true. - - - - Get the index of the . - - - Implemented by the System. This method returns the virtual array index of the reference target passed. - The virtual array index of the reference target to find. If the reference target is not found, -1 is returned. - - - The reference target to find the index of. - - - - Tells whether it is a . - - - This function differentiates things sub classed from from subclasses of . The implementation of this method (in ) returns FALSE and its implementation in returns TRUE. This can be useful when tracing back up the reference hierarchy, to know when you run into something that was sub classed directly off of , and hence to stop the traversal at that point. - Default of FALSE. - - - - - Returns whether this is a "real" (strong) dependency or not. - - - Used Internally. When a reference target's last "real" (strong) reference is deleted the target is deleted. Any leftover "non-real" (weak) reference makers will receive a REFMSG_TARGET_DELETED notification. This method returns TRUE if the reference dependency is "real" (strong). Otherwise it returns FALSE. Certain references are not considered "real" (strong) dependencies. For instance, internally there are certain reference makers such as the object that handles editing key information in the motion branch. This object implements this method to return FALSE because it is not a "real" strong) reference dependency. It's just needed while the editing is taking place. Plugin developers don't need to concern themselves with this method because it is used internally. - TRUE if the reference dependency is "real". Otherwise it returns FALSE. Default implementation is TRUE. - - - A pointer to the reference target. - - - - Specifies whether a weak reference is to be persisted on a partial load or save. - - - This method specifies the partial load/save behavior of a weak reference. This method will only be called if IsRealDependency returns FALSE. If this method returns true, and this ref maker is loaded/saved, the weak reference will be forced to be loaded/saved. If false, the reference will not be forced to be loaded/saved, but will be hooked back up if it is loaded. - The default implementation is to return FALSE. Otherwise, it is possible that on a partial load that this reference maker would hold the only reference to the target. If something else temporarily referenced the target, then the target will be deleted when that reference is dropped. From the user's perspective, this is a randomly occurring event. - Typical cases where an implementation of this method would return TRUE is when post load callbacks are used to check and process the references, checking for things like owner-less parameter blocks. - Whether to force the load/save of the weak reference if this reference maker is saved. - - - The weak reference. - - - - Receives and responds to messages. - - - A plugin which makes references must implement a method to receive and respond to messages broadcast by its dependents. This is done by implementing NotifyRefChanged(). The plugin developer usually implements this method as a switch statement where each case is one of the messages the plugin needs to respond to. The Method StdNotifyRefChanged calls this, which can change the partID to new value. If it doesn't depend on the particular message& partID, it should return REF_DONTCARE. - The return value from this method is of type RefResult. This is usually REF_SUCCEED indicating the message was processed. Sometimes, the return value may be REF_STOP. This return value is used to stop the message from being propagated to the dependents of the item. - - - This is the interval of time over which the message is active. Currently, all plug-ins will receive FOREVER for this interval, with the exception of REFMSG_FLAGDEPENDENTS notifications. In that case, changeInt.Start() is the timepoint to perform the dependency test. - - This is the handle of the reference target the message was sent by. The reference maker uses this handle to know specifically which reference target sent the message. - - This contains information specific to the message passed in. Some messages don't use the partID at all. See the section List of Reference Messages for more information about the meaning of the partID for some common messages. - - The message parameters passed into this method is the specific message which needs to be handled. - - If called through , the value of 'propagate' passed to it. Used if calling from within . - - - - Used to specify and enumerate the save reference hierarchy, if different from the normal reference hierarchy. - - - A can add, remove, or replace the contents of its "reference slots" in the context of scene files saves. The primary use of this ability is to support Save To Previous, particularly when converting a plugin from ParamBlock to ParamBlock2. When performing a Save to Previous, instead of storing the ParamBlock2 instance, the plugin needs to store a ParamBlock instance. At the beginning of a scene file save, the virtual ReferenceMaker::SpecifySaveReferences() method is called. If a plugin needs to store an alternative reference hierarchy, the plugin would specify the changes from the normal reference hierarchy using the supplied . See ReferenceMaker::SpecifySaveReferences for an example implementation. - If an Add or Replace reference slot operation is performed, and a non-NULL is supplied, the will hold a reference to the . This reference will be dropped at the end of the scene file save. - The Add/Remove/Replace reference slot operation calls register actions with the , and these actions are processed in the ReferenceMaker::SpecifySaveReferences() implementation. Invalid reference slot indices will not be detected until the ReferenceMaker::SpecifySaveReferences() implementation is executed, and will result in return value of false from that implementation. - If a plugin needs to access the save reference hierarchy, it would do so through the . The most common case of this would be in a SaveEnum(). For example: - If the is used to enumerate the save reference hierarchy before it has been prepared by a call to ReferenceMaker::SpecifySaveReferences(), the normal reference hierarchy will be exposed. That is, ReferenceSaveManager::NumRefs() will be routed to ReferenceMaker::NumRefs(), ReferenceSaveManager::GetReference() will be routed to ReferenceMaker::GetReference(), etc. - This interface is implemented by 3ds Max. Plug-ins do not need to implement it. - - - - - Returns the number of direct references in the save reference hierarchy. - - - The number of direct references in the save reference hierarchy is based on the number of references held by the and the Add/Remove reference slot operations. If no Add/Remove reference slot operations were performed, or if the save reference hierarchy has not been prepared, the value returned is the result from ReferenceMaker::NumRefs(). - Returns the number of direct references in the save reference hierarchy. - - - - - Returns the i'th direct reference in the save reference hierarchy. - - - Returns the i'th direct reference in the save reference hierarchy. If no Add/Remove/Replace reference slot operations was performed on the slot, or if the save reference hierarchy has not been prepared, the value returned is the result from ReferenceMaker::GetReference using the appropriate index value. The index value may be different than 'i' if Add/Remove reference slot operations were performed. - Returns the i'th direct reference in the save reference hierarchy. - - Which direct reference in the save reference hierarchy to return - If true, a NULL value will be returned if the reference does not pass the persistence tests. A reference is persistent if or returns true for the reference, or if the reference was specified using AddReferenceSlot or ReplaceReferenceSlot. Note that even if a reference is not persistent for a given , it may be persistent on another , and thus would be saved to the scene file. The behavior of the 3ds scene file load is that if the is loaded, it is set as a reference to all ReferenceMakers that held a reference to it, regardless of whether it was considered persistent on that ReferenceMakers or not. In most cases, and particularly in SaveEnum and EnumAuxFiles implementations, usePersistenceTests would be true - you only want to enumerate references that are guaranteed to be saved. If for some reason you want to look at all references, including those not guaranteed to be saved, then usePersistenceTests would be false. You can perform additional tests on the references using IsRealDependency and ShouldPersistWeakReference to see whether the reference would be persistent. - - - - Returns whether this is a "real" (strong) dependency or not. - - - Returns true if the reference is considered a strong dependency. If the reference was specified by a Add/Replace operation, it is considered a strong dependency. Otherwise, the call is passed to ReferenceMaker::IsRealDependency, and its value is returned. - true if the reference dependency is "real". Otherwise it returns false. - - A pointer to the reference target. - - - - Returns whether a weak reference is to be persisted on a partial load or save. - - - Returns true if the reference should be persisted if it is not a strong dependency. The call is passed to ReferenceMaker::ShouldPersistWeakRef, and its value is returned. - Whether to force the load/save of the weak reference if this reference maker is saved. - - A pointer to the reference target. - - - - Returns the number of indirect references in the save reference hierarchy. - - - The number of indirect references in the save reference hierarchy is based on the number of indirect references held by the and the Add/Remove indirect reference slot operations. If no Add/Remove indirect reference slot operations were performed, or if the save reference hierarchy has not been prepared, the value returned is the result from IIndirectReferenceMaker::NumIndirectRefs(). - Returns the number of direct references in the save reference hierarchy. - - - - - Returns the i'th indirect reference in the save reference hierarchy. - - - Returns the i'th indirect reference in the save reference hierarchy. If no Add/Remove/Replace indirect reference slot operations was performed on the slot, or if the save reference hierarchy has not been prepared, the value returned is the result from IIndirectReferenceMaker::GetIndirectReference using the appropriate index value. The index value may be different than 'i' if Add/Remove indirect reference slot operations were performed. - Returns the i'th indirect reference in the save reference hierarchy. - - Which indirect reference in the save reference hierarchy to return - If true, a NULL value will be returned if the reference does not pass the persistence tests. A reference is persistent if returns true for the reference, or if the reference was specified using AddIndirectReferenceSlot or RemoveIndirectReferenceSlot. Note that even if a reference is not persistent for a given , it may be persistent on another , and thus would be saved to the scene file. The behavior of the 3ds scene file load is that if the is loaded, it is set as a reference to all ReferenceMakers that held a reference to it, regardless of whether it was considered persistent on that ReferenceMakers or not. In most cases, and particularly in SaveEnum and EnumAuxFiles implementations, usePersistenceTests would be true - you only want to enumerate references that are guaranteed to be saved. If for some reason you want to look at all references, including those not guaranteed to be saved, then usePersistenceTests would be false. You can perform additional tests on the references using ShouldPersistIndirectReference to see whether the reference would be persistent. - - - - Returns whether the indirect reference is to be persisted on a partial load or save. - - - Returns true if the indirect reference is to be persisted on a partial load or save. If the indirect reference was specified by a Add/Replace operation, it should be persisted and the method will return true. Otherwise, the call is passed to IIndirectReferenceMaker::ShouldPersistIndirectRef, and it's value is returned. - Whether to force the load/save of the indirect reference if this reference maker is saved. - - - A pointer to the reference target. - - - - Adds a reference slot to the save reference hierarchy. - - - Inserts a reference slot at the specified index value. A GetReference call on that slot will return the specified . The will hold a reference to the specified until the end of the save operation. - - The index to insert a reference slot at. - The reference to store in the reference slot. - - - - Replaces the contents of a reference slot in the save reference hierarchy. - - - Specifies the value to return for a GetReference call on that slot. The will hold a reference to the specified until the end of the save operation. - - The index of the reference slot. - The reference to store in the reference slot. - - - - Removes a reference slot from the save reference hierarchy. - - - Deletes a reference slot at the specified index value. - - The index of the reference slot to delete - - - - Adds an indirect reference slot to the save reference hierarchy. - - - Inserts an indirect reference slot at the specified index value. A GetIndirectReference call on that slot will return the specified . The will hold a reference to the specified until the end of the save operation. - - The index to insert a indirect reference slot at. - The reference to store in the indirect reference slot. - - - - Replaces the contents of an indirect reference slot in the save reference hierarchy. - - - Specifies the value to return for a GetIndirectReference call on that slot. The will hold a reference to the specified until the end of the save operation. - - The index of the indirect reference slot. - The reference to store in the indirect reference slot. - - - - Removes an indirect reference slot from the save reference hierarchy. - - - Deletes an indirect reference slot at the specified index value. - - The index of the indirect reference slot to delete - - - - Returns whether a replacement was specified. - - - Returns true if SetReplacementReferenceTarget() was called. - - - - - Returns the that is to be saved instead of the represented by this instance of the . - - - This method should not be called unless ReplacementReferenceTargetSpecified() returns true since this method will return NULL if SetReplacementReferenceTarget has not been called. - Returns the replacement . - - - - - Detect whether SpecifySaveReferences() was called on the . - - - Before the save reference hierarchy can be accessed, SpecifySaveReferences() needs to be called on the to prepare the save reference hierarchy. - Returns true if SpecifySaveReferences() was called on the . - - - - - Clears the save reference hierarchy. - - - Clears the save reference hierarchy, dropping references to any ReferenceTargets specified by Add/Replace direct/indirect reference slot operations. - - - - - A scene entity that is being owned and listened to by other scene entities. - - - is the base class for scene entities that allow to be referenced by instances of class . Most plugins are derived from this class. - This class exposes methods for sending notification messages to its dependent objects, enumerating their dependents, etc. - Note that RefTargetHandle is a typename for pointers to an object of type . - - - - - Deletes the object when it has no more real dependents. - - - This function is called by 3ds Max in order to delete a plugin object when its last real dependent has been deleted. It also allows derived classes to control the lifetime of their instances. The default implementation of this method will drop the references this object makes to other objects, and if the undo system is engaged (holding) it will ensure that the deletion is undo/redo-able. Override this method only if you don't want instances of your plugin to be automatically deleted when the last reference to them is deleted. Most subclasses of class will not need to override this method. Plugins should call ReferenceTarget::MaybeAutoDelete() or ReferenceMaker::DeleteMe() to delete instances of plugin objects. For more information on how 3ds Max deletes reference targets, see ReferenceTarget::MaybeAutoDelete() - Default implementation always returns REF_SUCCEED. Overwrites should also always return REF_SUCCEED. - Classes that overwrite this method to prevent deletion of their instances, should be deleted by calling ReferenceMaker::DeleteMe() on them. - - - - - Deletes the object when it has no more real dependents. - - - The system calls this method to check if it can delete objects that had a reference to them deleted (dropped). If there are no more real dependents on this object, this function will ask the object to auto-delete itself. See ReferenceTarget::AutoDelete() for more information on this. Note that "weak" references will not prevent the deletion of the object. Plugins should also call this method when they need to delete plugin instances. See ReferenceTarget::AutoDelete() for more information on deleting plugin instances. - REF_SUCCEED if this object was deleted successfully, or REF_FAIL if the object has outstanding real dependents to it and as a result it cannot be deleted. - Objects can prevent their own deletion by overwriting ReferenceTarget::AutoDelete(). Examples of objects that may want to do this are singletons such as class . - - - - - Tests for a cyclical reference. - - - Implemented by the System. This method may be called to test for cyclical references. - REF_SUCCEED if a cyclic reference would be created; otherwise REF_FAIL. - - - This interval is reserved for future use. Currently any plugin should specify FOREVER for this interval. - - The reference maker performing the loop test. - - - - Checks if a has references. - - - Implemented by the System. - Returns 1 if the reference target has items that reference it, otherwise 0. - - - - - Checks if this has Real (Strong) Dependents. - - - This function goes through it's list of dependents or ReferenceMakers and queries the results of their IsRealDependency Functions. - TRUE if any one of them are, FALSE otherwise. - - - - - Starts Dependency Test. - - - To see if this reference target depends on something: - - - - - Ends Dependency Test. - - - To see if this reference target depends on something: - - - - - Called after a reference is made to a target. - - - This is called after a reference is made to this. If the target (this) needs to know that a reference to made to it, the target (this) can override this function. - This method is not called when performing an undo of removing a reference to a reference target, or redoing of setting a reference. - - - The creating the reference. - - - - Called after a reference is made to a target because of undo or redo. - - - Called when reference is added because of an undo or a redo. Otherwise it is similar to RefAdded. - - - The creating the reference. - - - - Called after a reference to this is deleted. - - - This is called after deleting a reference to a reference target. - Prior to 3ds Max 2024, this method was called from ReferenceTarget::MaybeAutoDelete only when the target was not deleted when the reference to it was dropped. Starting in 3ds Max 2024, this method is called from ReferenceMaker::DeleteReference whenever a reference is dropped. - This method is not called when performing an undo of setting a reference to a reference target, or redoing removing a reference - - - The removing its reference. - - - - Called after a reference to this is deleted because of undo or redo. - - - Called when reference is removed because of an undo or a redo. Otherwise it is similar to RefDeleted. - - - The removing its reference. - - - - Transfers all the references from oldTarget to this. - - - Implemented by the System. This method is used to transfer all the references from oldTarget to this reference target. - Always returns REF_SUCCEED. - - - The previous reference target. - - If this is TRUE the previous reference target is deleted. - - - - This method is used by 3ds Max to clone an object. - - - This method should not be directly called by plug-ins. Instead, either RemapDir::CloneRef() or CloneRefHierachy() should be used to perform cloning. These methods ensure that the mapping from the original object to the clone is added to the used for cloning, which may be used during backpatch operations - See the remarks in method BaseClone() below. - A pointer to the cloned item. - - - A instance used for remapping references during a Clone. - - - - This method copies base class data from an object to its clone. - - - This method is available in release 4.0 and later only. Virtual method. - All plugins that implement a Clone() method have to call this BaseClone() method from that Clone() method with the old and the new object as parameters. The ordering in regards to when this method is called is unimportant, however this method must, of course, be called after the cloned object is created. This method allows base classes to copy their data into a new object created by the clone operation. As described in the Clone method, the Clone method should just create a new instance and then call the BaseClone method. The BaseClone method should then clones any references and sets any other necessary data. This allows classes that derive from this class to clone cleanly. See the Clone method documentation for a code example. All overrides of BaseClone() must call the base class implementation. The base class implementation copies the objects into the newly created object. - - - Points to the old object to clone. - - Points to the new object created. - - This class is used for remapping references during a Clone. - - - - This sends the REFMSG_FLAGDEPENDENTS message up the pipeline. - - - This sends the REFMSG_FLAGDEPENDENTS message up the pipeline. There are two reasons to flag dependents: - - - - - This method is called to flag dependents into the FG. - - - This method is called to flag dependents into the FG. (Note that the above method is obsolete) The default implementation just sends out the notification REFMSG_FLAGDEPENDENTS with PART_PUT_IN_FG as the partID. In particular, a driven controller could override this method and call its driver's version of this method - - - - - Sends messages to ReferenceTargets. - - - This method is available in release 4.0 and later only. Used by a to send 'reverse' notification messages to its ReferenceTargets, or to this . - - - The message sent to the reference target. - - The sending the message. - - - - A callback class for ReferenceMaker::EnumRefHierarchy. - - - This is the callback object for ReferenceMaker::EnumRefHierarchy. This class's proc() method is called for each element in the reference hierarchy. When enumerating indirect references, it is possible to enter an infinite recursive loop unless references are not processed more than once. The system prevents processing duplicates by either maintaining a list of all references processed, or by clearing a flag bit on all references and then testing/setting the flag bit as references are processed. In the ReferenceMaker::EnumRefHierarchy method, this object's BeginEnumeration method is called before starting an enumeration, and EndEnumeration at the end. These methods increment and decrement an internal counter. When the counter is decremented to 0, the list of visited references is cleared. This ensures that the list of visited references is maintained during recursive calls to EnumRefHierarchy, but cleared when the outer most call is exited. In some cases however, it is desirable to maintain the list of visited references across calls to EnumRefHierarchy. In these cases, call this object's BeginEnumeration method prior to the calls to EnumRefHierarchy, and EndEnumeration when done. For example: - - - - - This method is called once for each element in the reference hierarchy. - - - This method is called once for each element in the reference hierarchy. The return value specifies whether continue processing the references, indirect references, and custom attributes of the refmaker; whether to skip processing of those and continue to the next element, or whether to terminate enumeration. Typically the return value will be REF_ENUM_CONTINUE. - One of the following values: - - - A pointer to the reference maker to this item. - - - - This method sets and checks whether a was visited. - - - Implemented by system. This method is used to check whether a was previously visited by this callback object, and registers it as having been visited if not. This method is used to ensure we call the proc only once on each . - Returns true of the rmaker was previously visited, false if not. - - - A pointer to the reference maker - - - - This method prepares the instance for enumeration. - - - Implemented by system. This method is used to initialize the instance for tracking the reference makers that have been visited. Normally, you do not need to call this method as ReferenceMaker::EnumRefHierarchy calls this method prior to enumerating the specified reference maker. In some cases though, you may want to have instance track the reference makers visited over multiple calls to EnumRefHierarchy. For example, you may want to call RefEnumProc::proc() on each node in a selection set, tracking the reference makers that have been visited across the entire selection set. Note that each call this method must be paired with a call to EndEnumeration. - - - Defaults to true. With preventDuplicatesViaFlag set to true, processing of a duplicate reference is detected by requesting and clearing a flag bit on all animatables, and then testing/setting the flag bit prior to calling the proc on each reference maker. When set to false, a list of reference makers visited is maintained. If you expect to enumerate only a small number of references, this argument should be set to false. Note however that you do not know what references are held by the references you may enumerate into, so in most cases this argument should be true. Note that the setting specified here overrides the preventDuplicatesViaFlag argument setting in the EnumRefHierarchy call. - - - - This method finalizes the instance after enumeration. - - - Implemented by system. This method is used to finalize the instance after enumeration, freeing any memory or max system resources used to track the reference makers that have been visited. This method should only, and must be, called if you called the BeginEnumeration method. - - - - - Manages a variable number of references. Note, Do not use this class as this is used by the internal system only. This class will be removed in future versions of the SDK. Note: the template type must be class (or derived from it). - - - - - Restore class for class Note, Do not use this class as this is used by the internal system only. This class will be removed in future versions of the SDK. The template type must be class (or derived from it). This handles undo and redo special in the class. This is because the system needs to save the object that it is storing along with the reference. This overrides DeleteReference to add a special undo record to the undo stack. - - - - - Note, Do not use this class as this is used by the internal system only. This class will be removed in future versions of the SDK. - - - - - Defines a class for monitoring a . - - - Defines a class for monitoring a by holding a weak reference to it (IsRealDependency returns false) and passing NotifyRefChanged messages to the owner of the class instance. The owner would create an instance of this class passing itself as the owner and the to watch as the target. The owner must derive from , and would typically derive from . If the owner derives from , during scene load IIndirectReferenceMaker::SetIndirectReference is called to set the indirect reference. Thus, you wouldn't normally call this class's Save or Load methods from the owner if it derives from . - - - - - Get the object being watched. - - - The object instance being watched. - - - - - For remapping references during a Clone. - - - - - - - Returns a pointer to an item's clone if it was cloned or NULL otherwise. - - - A pointer to the clone of the item, NULL if not cloned - - - This is the item to see if cloned. - - - - This method is used to back patch the pointer for cloned items. - - - If oldTarg has already been cloned, then the RefTargetHandle variable pointed to by patchThis is set to the pointer of the clone. If oldTarg has not been cloned, a back patch procedure is registered that is run after all cloning is completed but before the PostPatchProcs are run. The back patch procedure checks to see if oldTarg has been cloned, and if so the the RefTargetHandle variable pointed to by patchThis is set to the pointer of the clone. If oldTarg has not been cloned, the RefTargetHandle variable pointed to by patchThis is set to oldTarg. Because there may be a delayed write to the RefTargetHandle variable, this variable should not be a stack variable. Note that this method is primarily used when an object being cloned holds a raw pointer to a (i.e., it does not hold a reference to the ). In general, this is not safe due to the potential for a dangling pointer when that is deleted. It is better to use a or a SingleWeakRefMaker member variable to hold the pointer as it will hold a reference to the and properly NULL the pointer when/if the is deleted. - - - The RefTargetHandle variable to be set. - - The original target. - - - - Adds a Procedure that is called after cloning and back patching. - - - This method is used for adding a whose procedure method is called after the reference hierarchy has been cloned and any back patching has occurred. These will be called in the order that they are registered. The procs are called from the RemapDirImp::Backpatch(). More information can be found at the RefTargMonitorRefMaker::Proc method. See NodeMonitor::Clone for an example. - - - Points to the callback object. - - If true, the callback object is deleted when the is deleted. - - - - Registers a mapping of original object to clone. - - - - - Runs back patch procedures and PostPatchProcs. - - - - - Used internally. - - - - - Used internally. - - - - - Used internally. - - - - - This is the base class for any renderer plugin. - - - The main entry points for this class are methods Open(), Render(), and Close(). Any render operation works as follows: - - - - - Returns true if and only the renderer supports the stop functionality, in which case the Stop button will be displayed in the render progress dialog, and StopRendering() may be called. - This method may only be called from the main thread. - - - - - Called to instruct the renderer to stop rendering. The renderer is expected to stop rendering at its earliest convenience. If, for example, the renderer is in the process of rendering an iteration, it may finish rendering this iteration (or not), as it wishes - so long as it outputs a valid rendered image representing the progress rendered so far. - - - - - Requests that the renderer pauses itself, at which point it should stop rendering and free CPU resources until a resume is requested. - - - - - Requests that the renderer resumes rendering, following a call to PauseRendering(). - - - - - Returns true if the renderer has the given requirement, or returns false otherwise. - - - - - Returns whether this renderer plugin is compatible with any render elements whatsoever. ! This affects whether the render elements tab is displayed at all. - - - - - Returns whether this renderer plugin is compatible with the given render element. - - The render element for which to verify compatibility. - - - - This method returns a pointer to an , the interface used to perform interactive rendering (aka Active Shade). Ownership of the interface remains with the , i.e. the is responsible for freeing this interface, if necessary, in its destructor. Consequently, every call to this method should return the same pointer value - there is a one-to-one association between classes IInteractiveRenderer and . - Should return null if interactive rendering is not supported by the renderer. - - - - - Platform information concerning the renderer. - - - It could be information of OS, CPU, GPU, etc. If the string is longer than 32-character, it will be trunked on Render Message Window. - - The returned string containing the platform info. - - - - Called once and only once per render operation; used to initialize the renderer before rendering a sequence of frames. - - - This gives a chance to the renderer to build any data structures which it will need in the rendering phase. If this call returns 0, then the caller is not required to call Close(), so Open() should do any necessary cleanup before returning 0. - Nonzero for success, zero for failure. - - - The root node of the scene to render. Note: If you are rendering in the Materials Editor, you'll instead get a pointer to the that is in the sample slot - not the root node of the scene. - - The view node. This may be a camera, a light, or NULL. - - parameters for rendering orthographic or user viewports. This is used if vnode is NULL. - - This class contains a set of common renderer parameters. - - The owner window for messages. - - An array of default lights if there are no user created lights in the scene. - - of lights in defaultLights array. - - A callback used to allow the renderer to update the progress dialog. - - - - Called to render a single frame. - - - This may be called zero or more times, in between calls to Open() and Close(), to render a sequence of frames, at a series of time values which are not necessarily sequential. - Nonzero for success, zero for failure. - - - The time at which this frame is to be rendered. - - The bitmap to which the image is to be rendered. - - A set of frame dependent parameters. - - The owner window handle. - - A callback used to allow the renderer to update the progress dialog. - - This parameter allows one to specify a different view transformation on each render call. For example, one may render a given scene at a given time from many different viewpoints, without calling Render::Open() for each one. - - - - Called once and only once per render operation; used to free any resources allocated by Open() or Render(). - - - This method needs to be called whenever Open() was called and returned a non-zero value. The renderer should free any allocated resources, returning in a state identical to the one before Open() was called. - - - The owner window handle. - - A callback used to allow the renderer to update the progress dialog. - - - - This method is called to apply the render effects at the specified time value. - - - It should be called between the Open() and Close() methods. - - This can be used during a multi-pass rendering, in order to apply the render effects to the final, blended bitmap. - Parameters: - Returns true if the effects were successfully applied; otherwise false. - - - The time to apply the render effects. - - Points to the bitmap. - - Passing true indicates that 's display should be refreshed by the renderer; false indicates it should not be. - - - - This method is called to create and return a pointer to an instance of the class. - - - The renderer can add rollup page(s) to the renderer configuration dialog using the interface passed into this method. - A pointer to an instance of the class. This class will be deleted using RendParamDlg::DeleteThis(). - - - An interface that provides methods for use in displaying parameters, for example this class has methods for adding rollup pages. - - If TRUE then the rollup page should just display the parameters so the user has them for reference while rendering, they should not be editable. - - - - This method simply sets all the parameters to their default values. - - - - - Renderers which support texture baking should override this method to return true. - - - It is checked when the Render to Texture dialog is opened; if the current renderer does not support texture baking, then a warning message is displayed and the user will not be able to press the Render button in the dialog. - By default this will return false - - - - - A renderer should override this method to return true if it supports any custom preset categories beyond the standard categories. - - - By default this will returns false - - - - - Return a number indicating the current version of the renderer's custom preset. - - - The number can be arbitrary - By default this will return -1 - - - - - Return true if the renderer can load presets of the indicated version. - - - By default this will return false. - - The version to test compatibility against - - - - Returns the UI name of a supported custom category. - - - If the ID is a supported custom category, return the name of the category to be displayed in the UI. Otherwise return NULL - - - The custom preset index to return the name of. catIndex will be a number between RENDER_PRESETS_CUSTOM_CATEGORY_INDEX_BEGIN and RENDER_PRESETS_CATEGORY_COUNT. - - - - Returns the index of a supported custom category. - - - If the input is the name of a custom category supported by the renderer, return the ID number of the category. Otherwise returns 0 - - - The name of a custom category - - - - called before a render preset is saved. - - - For each custom category supported use root->AddSaveTarget() passing the object with the parameters for that category if the corresponding bit is set in the saveCategories, The object will be saved along with the preset. - Example Implementation: - - An instance of an class to be used to save any custom presets specified - Species the custom preset categories to be saved - - - - called after a preset is saved. - - - No specific action is required from the renderer at this time. - - - - - called before a preset is loaded. - - - For each custom category supported, if the corresponding bit is not set in the loadCategories, use root->Store() passing the object with the parameters for that category. The object will be preserved, so the renderer can refer to it after the preset is loaded. - - An instance of an class to be used to store any custom presets specified - Lists the custom preset categories to be loaded. Any categories not being loaded should be stored on root. - - - - called after a preset is loaded. - - - For each custom category supported... - - If the bit is set in the loadCategories: use root->GetSaveTarget() to retrieve the loaded object, and update the renderer's active parameters to match this object - - If the bit is not set in the loadCategories: use root->Retrieve() to retrieve the object that was stored during pre-load. Update the renderer's active parameters to match this object. This is important in case a certain category was held in the file and loaded, but the user did not choose to load that category. In this case the renderer must restore its parameters to their former value. - - An instance of an class to be used to retrieve any custom presets stored pre-load. - Lists the custom preset categories that have been loaded. - - - - Description: - This class has a single virtual method to delete the class. For example, when objects are deleted this is the method to do so. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - Parameters: - int cmd - - The command to execute. - - ULONG arg1=0 - - Optional argument 1 (defined uniquely for each cmd). - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - - - - Description: - A pointer to an instance of this class is a data member of the ( *globContext;). This can be used by materials, texmaps, etc. to retrieve information about the global rendering environment. This is information such as the renderer in use, the project type for rendering, the output device width and height, several matrices for transforming between camera and world coordinates, the environment map, the atmospheric effects, the current time, field rendering information, and motion blur information. - - Note that raytracing (and all shading calculations in the default renderer) take place in camera space. - - When a ray intersects on the face edge it can happen that no intersection is returned. One way to handle this situation is to perturb the ray minimally so it will point in a slightly different direction. This presumes that you are fairly sure that the no intersection is probably not what you're looking for. IntersectRay() is linear in the number of faces so NUM_ATTEMPTS should be kept small. - - - Data Members: - *renderer; - - A pointer to the active renderer. - - int projType; - - Returns the type of projection used during rendering. One of the following values: - - PROJ_PERSPECTIVE - - PROJ_PARALLEL - - int devWidth; - - The width in pixels of the output device. - - int devHeight; - - The height in pixels of the output device. - - float xscale; - - The X scale factor for mapping from world space to screen space. - - float yscale; - - The Y scale factor for mapping from world space to screen space. - - float xc; - - The X center point used in mapping from world space to screen space. - - float yc; - - The Y center point used in mapping from world space to screen space. - - BOOL antialias; - - TRUE if antialiasing is enabled; otherwise FALSE. - - camToWorld; - - This matrix may be used to transform coordinates from camera space to world space. - - worldToCam; - - This matrix may be used to transform coordinates from world space to camera space. - - float nearRange; - - The near range setting of the camera. - - float farRange; - - The far range setting of the camera. - - float devAspect; - - The pixel aspect ratio of a device pixel. This is the height / width. - - float frameDur; - - This defines the duration of one frame in floating point units. This is used, for example, by video post rendering where the user can stretch time. A video post frame might be 1/2 a frame long for instance. - - *envMap; - - The environment map (which may be NULL). - - globalLightLevel; - - This parameter is available in release 3.0 and later only. - - This is the global light level. - - *atmos; - - The atmosphere effects (which may be NULL). - - ToneOperator* pToneOp; - - This data member is available in release 4.0 and later only. - - The tone operator, may be NULL - - TimeValue time; - - The current time. - - BOOL wireMode; - - This parameter is available in release 3.0 and later only. - - TRUE if rendering in wire frame mode; otherwise FALSE. - - float wire_thick; - - This parameter is available in release 3.0 and later only. - - The global wire thickness. - - BOOL force2Side; - - TRUE if force two-sided rendering enabled; otherwise FALSE. - - BOOL inMtlEdit; - - TRUE if the rendering is being done in the materials editor; otherwise FALSE. - - BOOL fieldRender; - - TRUE if field rendering is being done; otherwise FALSE. - - BOOL first_field; - - TRUE if this is the first field; FALSE if it's the second. - - BOOL field_order; - - Determines which field is first. 0 if the even first; 1 if odd first. - - BOOL objMotBlur; - - This is used for handling object motion blur in ray-trace maps and materials. TRUE if object motion blur is enabled; FALSE if it's disabled. - - int nBlurFrames; - - This is used for handling object motion blur in ray-trace maps and materials. The number of object motion blur time slices. See Class . - - - - - Returns a pointer to the Render Element Manager. See Class . - - - - - Returns the number of render elements. - - - - - Returns a pointer to the specified render element (or NULL if not found). - Parameters: - int n - - The zero based index of the render element. - - - - - Computes the screen space coordinates of the point passed in world coordinates. This is implemented as: - Parameters: - p - - The point to map to screen space. - - - - - Returns a pointer to the current anti-aliasing filter from the renderer. See Class . - - - - - Returns the filter size of the current anti-aliasing filter. - - - - - Returns the number of RenderInstances. - - - - - Returns a pointer to the 'i-th' . - Parameters: - int i - - Specifies which to return (0 through NumRenderInstances()-1). - - - - - This method evaluates the global environment map using the specified ray as a point of view, and returns the resulting color. - Parameters: - &sc - - The shade context. - - &r - - Defines the direction of view of the environment. See Class . - - BOOL applyAtmos - - TRUE if atmospheric effects should be considered; otherwise FALSE. - Default Implementation: - (0.0f,0.0f,0.0f,1.0f); } - - - - - This method takes the specified ray and intersects it with the single inst. - Parameters: - *inst - - The render instance to intersect. The may be retrieved via & m = *(inst->mesh); - - & ray - - Defines the direction to check. This is the point to look from, and a normal vector specifying the direction to look. See Class . - - &isct - - The information about the first opaque object hit by the ray is returned here. See Structure . - - &xpList - - The list of transparent objects that are intersected on the way to the opaque one are returned here. See Class . - - BOOL findExit - - TRUE to compute the exit point; FALSE to not compute it. Once a ray has been intersected with a transparent object and you want to find out where the refracted ray leaves the object, this parameter may be set to TRUE. This allows the ray to look at the inside faces of the object and compute the intersection point at exit. - - - - - This method takes the specified ray and intersects it with the entire 3ds Max scene. - Parameters: - &ray - - Defines the direction to check. This is the point to look from, and a normal vector specifying the direction to look. See Class . - - int skipID - - This specifies an ID (from RenderInstance::nodeID) that is skipped in the intersection computations. This is used to prevent self intersection. - - &hit - - The information about the first opaque object hit by the ray is returned here. See Structure . - - &xplist - - The list of transparent objects that are intersected on the way to the opaque one are returned here. See Class . - - int blurFrame = NO_MOTBLUR - - NO_MOTBLUR is used for non-motion blurred objects. If this is not equal to NO_MOTBLUR, it should be in the range 0 to nBlurFrames-1. In that case, this method will only consider blur objects corresponding to that blur sub-frame. - - When object motion blur is turned on, for each object, several objects are generated. Each of these objects is given a number. This corresponds to the value RenderInstance::objMotBlurFrame. - - This method will always intersect objects that aren't motion blurred. However, if this is set to a number other than NO_MOTBLUR, then when it comes to a motion blurred object, it will only look at the sub-object corresponding to the specified slice in time. - - This may be used to do a kind of dither where for each of the sub-samples, this number is randomly selected. In this way the different motion blur slices will basically blur together and give a motion blurred ray trace result. - - - - - Returns a pointer to a class which describes the properties of a view being rendered.. See Class . - - - - - This method is used internally. - Default Implementation: - { return NULL; }; - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - Default Implementation: - { return 0; } - - - - - Description: - This class provides information about the rendering environment. All methods of this class are implemented by the system. - Data Members: - ProjectionType projType; - - The projection type: One of the following values: - - ProjPerspective - - ProjParallel - - float kx,ky; - - 3D to 2D projection scale factor. - - float xc,yc; - - The screen origin. - - BOOL fieldRender; - - Indicates if the image is field rendered. - - BOOL fieldOdd; - - If TRUE, the first field is Odd lines. - - TimeValue renderTime[2]; - - Render time for the 2 fields, if field rendering. If not, use renderTime[0]. - - worldToCam[2]; - - The world to camera transformation matrix; worldToCam[0] is for field 0, worldToCam[1] is for field 1. Use worldToCam[0] if not field rendering. - - camToWorld[2]; - - The camera to world transformation matrix; camToWorld[0] is for field 0, camToWorld[1] is for field 1. Use camToWorld[0] if not field rendering. - - Rect region; - - This data member is available in release 4.0 and later only. - - This rectangle holds the sub-region in the image that was rendered if the last render was a region render. If it was not a region render then the rectangle is empty. - - - - - Maps the specified world point to a screen point. - Parameters: - p - - The world point. - - int field=0 - - The field order. This specifies which camToWorld matrix is used in the conversion. - The 2D screen point. - - - - - Maps the specified point in camera space to screen space and returns it. - Parameters: - p - - The point to convert. - - - - - Returns the viewing ray through the screen point, in camera space. - Parameters: - p - - The screen point. - - - - - Returns the viewing ray through the specified screen point, in world space. - Parameters: - p - - The screen space point. - - int field=0 - - The field order - specifies which camToWorld matrix is used in the conversion. - - - - - This class provides information about a single node being rendered. This includes information such as the mesh of the object, its material, unique node ID, object space bounding extents, number of lights affecting it, material requirements, and normals and vertex coordinates in various spaces (object and camera). - Data Members: - ULONG flags; - - The flags that describe the properties of this instance. See Render Instance Flags . - - *mtl; - - This is the material from the node. - - float wireSize; - - The wireframe size. - - *mesh; - - The mesh to be rendered. This is the result of GeomObject::GetRenderMesh(). - - float vis; - - visibility (between 0.0 and 1.0). This is the value the visibility track evaluates to at a particular time. - - int nodeID; - - A unique ID associated with the node. It's unique within the scene during a render. - - int objMotBlurFrame; - - This will be equal to NO_MOTBLUR for all non-blurred objects. For blurred objects, it takes on the values (0..nBlurFrames-1) for the successive blur-instances. - - int objBlurID; - - The purpose of this is to differentiate blur-instances generated from different nodes. All the blur-instances for an object-motion-blurred object will have the same objBlurID. This is as distinct from nodeID, which is different for every instance. This makes it possible to easily avoid intersecting a ray with all blur-instances for an object. If RenderGlobalContext::IntersectWorld() is being used, then passing in the objBlurID for the parameter skipID will have this effect. - - The basic technique is this: When reflecting or refracting rays, and object motion blur is enabled, choose sub-frame times randomly for the different rays (effectively giving a coarse stochastic sampling of time). - - objToWorld; - - This matrix can be used to transform object coordinates to world coordinates. - - objToCam; - - This matrix can be used to transform object coordinates to camera coordinates. - - normalObjToCam; - - This matrix can be used for transforming surface normals from object space to camera space. - - camToObj; - - This matrix can be used to transform camera coordinates to object coordinates. - - obBox; - - The object space extents of the object being rendered. - - center; - - The object bounding sphere center (in camera coordinates) - - float radsq; - - The square of the bounding sphere's radius. - - - - - - Sets the specified flag(s) to the state passed. - Parameters: - ULONG f - - The flags to set. See Render Instance Flags . - - BOOL b - - The state to set; TRUE for on; FALSE for off. - - - - - Sets the specified flag(s) to on. - Parameters: - ULONG f - - The flags to set. See Render Instance Flags . - - - - - Clears the specified flag(s). - Parameters: - ULONG f - - The flags to set to zero. See Render Instance Flags . - - - - - Returns TRUE if the specified flag(s) are set; otherwise FALSE. - Parameters: - ULONG f - - The flags to set to zero. See Render Instance Flags - - - - - Returns a pointer to the next in in the list. A pointer to the first element in the list may to retrieved from RenderGlobalContext::InstanceList(). - - - - - Returns the validity interval of the mesh of this render instance. - - - - - Returns the number of lights affecting the node. - - - - - Returns a pointer to the for the 'i-th' light affecting the node. - Parameters: - int n - - Specifies which light. - - - - - Returns TRUE if this particular instance will cast shadows from the particular light based on the light's Exclusion/Inclusion list; FALSE if it won't cast shadows. - Parameters: - & lt - - Describes the light. See Class . - - - - - Returns the pointer for the instance. - - - - - Returns a pointer to the evaluated object for the instance. You can use this to get more information about the type of object being rendered. For instance you could look at the and recognize it as a sphere, a box, a torus, etc. - - - - - Returns the material requirements of the material assigned to the node. See Material Requirements Flags. - Parameters: - int mtlNum - - Specifies the number of the sub-material whose requirements should be returned. A value of -1 may be passed to return a value generated by looping over all the sub-materials and ORing together the requirements. - - int faceNum - - This is the integer face number for objects which support material per face (if flag INST_MTL_BYFACE is set). See Class . - - - - - Returns the geometric normal of the specified face in object space. - Parameters: - int faceNum - - Zero based index of the face whose normal is returned. - - - - - Returns the vertex normal of the specified face in camera coordinates. - Parameters: - int faceNum - - Zero based index of the face in the mesh. - - int vertNum - - Zero based index of the vertex in the face. - - - - - Returns the three vertex normals of the specified face in camera coordinates. - Parameters: - int faceNum - - Zero based index of the face in the mesh. - - n[3] - - The normals are returned here. - - - - - Returns the coordinate for the specified vertex in camera coordinates - Parameters: - int vertnum - - The zero based index of the vertex in the mesh. - - - - - Returns the vertices of the specified face in object coordinates. - Parameters: - int fnum - - Zero based index of the face in the mesh. - - obp[3] - - The three vertices of the face in object coordinates. - - - - - Returns the vertices of the specified face in camera (view) coordinates. - Parameters: - int fnum - - Zero based index of the face in the mesh. - - cp[3] - - The three vertices of the face in camera coordinates. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - Default Implementation: - { return 0; } - - - - - Objects can provide a material as a function of face number via the interface provided by Class . This method will return RenderInstance::mtl if flag INST_MTL_BYFACE is not set. If INST_MTL_BYFACE is set it will return the proper by-face material. See Render Instance Flags . - Parameters: - int faceNum - - The zero based index of the face in the mesh. - - Objects can provide a material as a function of face number via the interface (chkmtlapi.h). - - - - - An instance of this class is passed into the MtlBase::BuildMaps() method. This is used for the Mirror and Automatic Cubic maps. These maps callback to methods of this class to perform a rendering from a particular view. Sample code using these methods is available in /MAXSDK/SAMPLES/MATERIALS/MIRROR.CPP and ACUBIC.CPP. All methods of this class are implemented by the system. - - - - - - Returns the pointer of the node being rendered. This pointer allows a developer to access the properties of the node. See Class . - - - - - Returns the node ID for the item being rendered or -1 if not set. This ID is assigned when the scene is being rendered - each node is simply given an ID: 0, 1, 2, 3, etc. The NodeRenderID() is simply a number automatically assigned to every node being rendered so that they can be differentiated in texture maps such as the Auto-cubic, which needs to store a cubic map for each node it is applied to. - - - - - Retrieves the current view dependent parameters. - Parameters: - &vp - - The instance to update. - - - - - Retrieves the sub-render parameters. - Parameters: - &srp - - The instance to update. - - - - - Returns the current sub material index or -1 if at node material level. - - - - - Computes the plane containing the current material or sub material. This is used by the Flat Mirror material. - Parameters: - float pl[4] - - The plane containing the current material or sub material. The four float values in pl[4] represent the plane equation. If you call the four values A,B,C and D, then the plane equation of the plane is Ax + By + cZ + D = 0. - - - - - This method computes the rectangle in screen space of the specified material. This uses the viewTM, but assumes the remaining view params (devWidth, devHeight, devAspect, fov) are the same as the main render. This method is specific to the Flat Mirror material. - Parameters: - Rect &sbox - - The resulting 2D box. - - Matrix3* viewTM=NULL - - The view matrix. - - int mtlIndex=-1 - - The material index, or -1 if a node level material. - - - - - This method computes the bounding box in camera space of the object associated with the reflection or refraction map being built in a call to a map's BuildMaps() method. - - - - - This method computes the bounding box in object space of the object associated with the reflection or refraction map being built in a call to a map's BuildMaps() method. - - - - - This method returns the object to world transformation. - - - - - Returns a pointer to a class that describes properties of the rendering environment. - - - - - Renders the scene and stores in the result into bm. - Parameters: - *bm - - The to render the result to. The properties of this bitmap define the properties of the render (such as the width and height). - - &vp - - The . - - &srp - - The . - - *clipPlanes=NULL - - This is a pointer to an array of Point4s, each of which represents a clip plane. If it is non-null, the renderer will clip all objects against these planes in addition to the normal left/right/top/bottom clipping. This is used by the Mirror material to clip away stuff that is behind the mirror. If not needed this may default to NULL. - - int nClipPlanes=0 - - The number of clipping planes above. A maximum of 6 is possible. - Nonzero on success; otherwise zero. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - This class is passed into the method ObjLightDesc::Update(). The methods of this class are implemented by the 3ds Max scanline renderer. Developer creating other renderer plug-ins may choose to implement the methods of this class if they wish to use the same architecture. Developers who wish to take advantage of the 3ds Max volumetric light effects should implement the methods of this class. The volumetric lights are set up to work with this mechanism. - - - - - This method is used to update the progress bar and check the keyboard and mouse for user cancellation. A plug-in renderer should override this method by calling the RendProgressCallback::Progress() method on the passed in to the Renderer::Render() method. - Parameters: - Nonzero to continue; zero if the user has canceled. - - This is the number completed so far. - This is the total number of things to complete. - - - - This is a multiplier that scales the brightness of all scene lights. - - - it doesn't affect the ambient light level. It is included in so the lights can use it to multiply times the light's color. - - - - - This class has a set of data members, and these parameters are passed to the renderer when the renderer is opened. All methods of this class are implemented by the system. - Data Members: - RendType rendType; - - The type of rendering to perform. - - BOOL isNetRender; - - Determines if this is a render on a network node. - - BOOL fieldRender; - - If TRUE the image will be field rendered; otherwise frame rendered. - - int fieldOrder; - - The field order used. One of the following values: - - 0 specifies even. - - 1 specifies odd. - - TimeValue frameDur; - - This is used, for example, by video post. In video post you can stretch time. A video post frame might be 1/2 frame long for example. This data member defines the duration of one frame in TimeValue units. - - BOOL colorCheck; - - Determines if the color is ranged checked. - - int vidCorrectMethod; - - Video correction method. One of the following values: - - 0 specifies FLAG (with black). - - 1 specifies SCALE_LUMA (scale luminance). - - 2 specifies SCALE_SAT (scale saturation). - - int ntscPAL; - - Determines if the color is range checked using NTSC or PAL standards. One of the following values: - - 0 specifies NTSC. - - 1 specifies PAL. - - BOOL superBlack; - - If TRUE Super Black is used. - - int sbThresh; - - Specifies the Super Black threshold. - - BOOL rendHidden; - - If TRUE hidden objects are rendered. - - BOOL force2Side; - - If TRUE two sided materials are used for all items in the scene. - - BOOL inMtlEdit; - - If TRUE the rendering is taking place in the material editor. - - float mtlEditTile; - - If rendering is taking place in the material editor, scale tiling. - - BOOL mtlEditAA; - - If TRUE antialiasing should be done in the material editor. - - BOOL multiThread; - - This is used internally. - - BOOL useEnvironAlpha; - - If TRUE one should use alpha from the environment map. - - BOOL dontAntialiasBG; - - If the low-order bit is set don't antialias against the background (this is often used for 'sprites' in video games). For 3ds Max 1.1 and 1.2 (in 2.0 and later see scanBandHeight below), this parameter may also be used to access the height of the abuffer in scan lines. This may be obtained using the following syntax: BOOL useDisplacement; - - The apply displacement mapping setting. - - bool useRadiosity; - - Indicates if radiosity should be included in rendering. - - bool computeRadiosity; - - Indicates if radiosity should be computed before rendering. - - *envMap; - - The environment map. This may be NULL. - - *atmos; - - The atmosphere effects. This may be NULL. To the renderer it looks like there is only one atmosphere. You can use this atmosphere and it will go ahead and call all the individual atmospheric effects for you. - - *effect; - - The post-processing effects. This may be NULL if there aren't any. - - RadiosityEffect* pRadiosity; - - Points to the radiosity effect. - - ToneOperator* pToneOp; - - Points to the tone operator if present. This may be NULL - - MCHAR biFileName[MAX_PATH]; - - The bitmap output file name. - - TimeValue firstFrame; - - This is the first frame that will be rendered. This lets Open() know the first frame that will be rendered, so it will not have to evaluate at frame 0 when building. - - int scanBandHeight; - - This is the height of a scan band (for the default 3ds Max scanline renderer). - - ULONG extraFlags; - - RENDER_HIDE_FROZEN - - Instruct the renderer to hide frozen objects - - int width; - - The image height. - - int height; - - The image width. - - BOOL filterBG; - - The filter background. - - - - - - Returns a pointer to the render element manager interface. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - An instance of this class is created by Renderer::CreateParamDlg(). Since this dialog is modeless and non-interactive, as the user changes parameters in the dialog, the renderer does not need to update its state. When the user is through, they may choose 'OK' or 'Cancel' from the dialog. If the user selects OK then the AcceptParams() method will be called. If the user selects Cancel, then the RejectParams() method is called. - - - - - If the user selects OK from the dialog, this method will be called, at which time the renderer can read the parameters out of the UI and modify its state. - - - - - If this method is called, typically the renderer will not have to do anything since it has not yet modified its state, but if for some reason it has, it should restore its state. - Default Implementation: - {} - - - - - An instance of this class is passed to IRendParams::SetPickMode(). This is a callback that gets called as the user tries to pick objects in the scene. - - - - - Called when the user picks something. - Parameters: - *node - - The node that was selected. - TRUE to end the pick mode; FALSE to continue. - - - - - Return TRUE if this is an acceptable hit; otherwise FALSE. - Parameters: - *node - - The node that was selected. - - - - - This method is called as the mode is entered. - Default Implementation: - {} - - - - - This method is called when the mode is exited. - Default Implementation: - {} - - - - - Returns the handle of the default cursor. This is the cursor to use when the user is not over a pickable object. - Default Implementation: - {return NULL;} - - - - - Returns the handle of the hit cursor. This is the cursor to use when the user IS over a pickable object. - Default Implementation: - {return NULL;} - - - - - Implement this method to return TRUE to allow the user to pick more than one thing. In that case the Pick() method may be called more than once. - TRUE to allow multiple picks; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - This class is a callback passed in to the renderer. The system passes this callback to the renderer, and the renderer will use these methods whenever it is doing something that is going to take some time. For instance when transforming objects it can update the progress bar. This is also passed in to the shadow buffer code so the shadow buffer can show its progress. All methods of this class are implemented by the system. They are called by a plug-in renderer. - - - - - - Allows the plug-in to set the string displayed in renderer dialog. - Parameters: - const MCHAR *title - - The string to display. Multiple title strings can be provided by separating them with newline (' - ') characters. The progress callback is then responsible for displaying these strings correctly, e.g. by alternating them every few seconds. - - - - - Allows the plug-in to update the renderer progress display. - Parameters: - int done - - The number of items completed so far. - - int total - - The total number of items to process. For undeterminate (infinite render,...) progress, passing -1 as the total will trigger the marquee mode of the progress bar. - RENDPROG_CONTINUE - - Continue to process. - - RENDPROG_ABORT - - Stop processing. - - - - - Sets the field number display. - Parameters: - int which - - FIELD_FIRST - - FIELD_SECOND - - FIELD_NONE - - - - - The plug-in renderer should call this on every frame, passing in values for the various parameters. These are displayed in the rendering in progress dialog. - Parameters: - int nlights - - The total number of lights. - - int nrayTraced - - The number of lights using raytraced shadows. - - int nshadowed - - The number of lights using shadows. - - int nobj - - The total number of objects. - - int nfaces - - The total number of faces. - - - - - Sets the current rendering process step. This is used by the logging to give a global picture of the rendering process progress, not just of the current task. Let's say your rendering process is two steps (Translation and rendering) You would call this function at the beginning of the translation with (1,2) as parameters. Then use the Progress function as usual. Calling SetStep(2,2) at the beginning of the rendering task. This enable 3ds Max to know the total progress of the rendering task. - Parameters: - int current - - One based current step number. Passing zero or a negative value here will make the application skip the progress logging. int total - - One based total step count. Passing zero, negative value or a value lower than current will make the application skip the progress logging - - - - - Description: - This callback object may be used to handle custom bitmaps and tooltips for the display buttons of a curve control. There are also methods which get called to handle the situations when a curve is reset or a new curve is created. - - All methods of this class are virtual. - - - - - This method is called to set the image list. - - This callback is used to update the HIMAGELIST to handle custom bitmaps on the display buttons. The image list has to have 2*NumCurves 16x15 or 16x16 bitmaps. The format for the first set of images is for Out&In Enabled. The second set is for Out&In Disabled (which are not yet used). - Parameters: - HIMAGELIST &hCTools - - A reference to the image list to set. An HIMAGELIST is a Win32 data type that is a handle to an image list. - - *pCCtl - - This pointer can be used to determine which calls the callback, in case the plugin uses many CurveControls and want to set different bitmaps for different CurveControls. - If the image list was assigned the callback should return TRUE. If it returns FALSE, the default bitmaps will be used. - Default Implementation: - {return FALSE;} - - - - - This callback allows the developer to assign custom ToolTips to the display buttons. One simply has to assing a string to the ToolTip parameter for the specified button number. - Parameters: - int iButton - - The zero based index of the button whose tool tip text to retrieve. - - MSTR &ToolTip - - The string for the tool tip text. - - *pCCtl - - This pointer can be used to determine which calls the callback, in case the plugin uses many CurveControls and want to set different Tooltips for different CurveControls. - TRUE if the method is implemented to use custom tooltips; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - This methods gets called when the user preses the Reset button (cross symbol) in the user interface (if the control is using the upper toolbar). - Parameters: - int curvenum - - The zero based index of the curve. - - *pCCtl - - Points to the interface for the custom curve control. - Default Implementation: - {} - - - - - This method gets called after the curve control creates a new curve. The developer can set the default values here for the new curve. This call will be a result of a call to SetNumCurves(i) where the new size is bigger than the old size. - Parameters: - int curvenum - - The zero based index of the curve. - - *pCCtl - - Points to the interface for the custom curve control. - Default Implementation: - {} - - - - - Description: - This class is the restore object used in the undo / redo system of 3ds Max. - - - - - The developer implements this method to restore the state of the database to as it was when theHold.Put() was called with this restore object. - - Regardless of the value of the isUndo parameter, the method must restore the state of the scene to the one it was in when theHold.Put() was called with this restore object. - - RestoreObj::Restore and RestoreObj::Redo may be called several times in a row: these methods must protect against any problems that may arise because of this, such as trying to undo multiple times in a row what has been undone already. - - Nonzero if is being called in response to the Undo command; otherwise zero. If is nonzero, the developer needs to save whatever data they need to allow the user to redo the operation. - - - - This method is called when the user selects the Redo command. The developer should restore the database to the state prior to the last Undo command. - - - - - Returns the size of the restore object in bytes. This size does not need to be exact but should be close. This is used to make sure all the accumulated restore objects do not grow beyond a manageable size. - Default Implementation: - { return 1; } - The size of the restore object in bytes. - - - - - This method is called when theHold.Accept() or theHold.Cancel() is called. This means the restore object is no longer held, it was either tossed out or sent to the undo system. The developer may then call ClearAFlag(A_HELD) to indicate the restore object is no longer being held. - - - - - This method is used internally to 3ds Max in debugging only. It is used to display a symbolic name for the restore object. - The name of the restore object. - Default Implementation: - { return MSTR(_M("---")); } - - - - - This method is used to specify whether putting this restore object to the hold system should mark the scene dirty in terms of requiring a scene file save. - Whether to make the scene dirty in terms of requiring a scene file save. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - Default Implementation: - {return -1;} - - - - - This class is only available in release 5 or later. - This class is to hold different representations of the rotation. In particular, it holds rotation value as represented by Euler angles or quaternion. Different types of rotation controllers may use different representations. To avoid losing information due to converting from one representation to another, we can use to hold the result. - - For example, the Skin pose feature reads rotation of a node from the rotation controller and stores the result in (c.f. maxsdk/include/iSkinPose.h). - - It is guaranteed that rv keeps the original representation of the controller. - - Being asked of Euler angles, will return 3 float numbers in the format of . There must be an association between numbers and axes. - - There are two classes of Euler angle types. In one class, the rotation axes are not repeated (non-repetitive). They are enum's from kXYZ to kZYX. In the other class, one of the rotation axes is repeated (repetitive). They are enum's from kXYX to kZXZ. For convenience, enum kReptd is used to denote the starting one: kRept == kXYX. - - For non-repetitive Euler angles, there are two well-defined methods to associate three ordered angles, to three axes. - - First, we can associate angles with x-, y-, and z-, axes, respectively. The first angle, for example, is always associated with the x-axis, no matter where it appears in the Euler order. Suppose - - a(0.1, 0.2, 0.3) - - then a.x (==0.1), a.y(==0.2), a.z (==0.3), are the angles of the x-axis, y-axis, and z-axis, respectively, no matter whether the order (type) of the Euler angles is kXYZ or kZXY. - - Let's call this way of association by axis (name). - - Second, we can associate them by position: the first angle, from left, is always associated with the first axis in the Euler angle order. For examples, the first angle is applied to the x-axis for kXYZ and kXZY, but to the y-axis for kYXZ and kYZX, etc. Suppose a is a , a, a, a, are the angles of the z-axis, x-axis, and y-axis, respectively, for Euler type kZXY. - - Let's call this way of association by order. - - For repetitive Euler type, the association by axis is ambiguous because one axis may appear twice in the Euler axes. In this case, "by order" is well defined. - - This class uses the association of by axis for non-repetitive types and by order for repetitive type. Suppose, - - a = rv.Euler(RotationValue::kZXZ) // repetitive Euler type - - Then, a[0] and a[2] are both applied to the Z axis, but a[0] corresponds to the first z-axis from left, a[2] corresponds to the second z-axis (third axis) from left, and a[1] corresponds to the x-axis. - - - - - - - an object of to an Euler angle representation. Angles are assumed in radians. To set to Euler angles of x, y, z, of order XYZ, do, for example: - - a; - - a.Set(Point3(x, y, z), RotationValue::kXYZ); - - - - - - - an object of to a quaternion representation. - - - - - - - Used to get the rotation in specific representation. Suppose rv is a , to get it in terms of Euler angles of order XYZ: - - rv.Euler(); - - in order ZXY: - - rv.Euler(RotationValue::kZXY); - - or, to get it in quaternion: - - )rv; - - to get it in matrix form: - - )rv - - - - - Given a matrix, m, we can apply the rotation, rv, of from left side (PreApplyTo) - - )rv) * m - - - - - Given a matrix, m, we can apply the rotation, rv, of from right side (PoseApplyTo) - - )rv) - - - - - To apply a rotation, aa, as represented as to a , rv, from the right side, - - rv.PostRotate(aa) - - The internal representation of rv after applying to it will not be change. Mathematically, - - )rv) * MatrixOf(aa) - - If rv is in Euler angles, this method will try to keep the Euler angles from jumping at the borders of (+/-)180 degrees. - - - - - Used to get the internal representation and returns the representation type. If it is a Euler angle type, the first three numbers of the returned from GetNative() are to be interpreted as Euler angles. - - - - - Used to get the internal representation and returns the actual float numbers. - - - - - Adds the specified value to the value of the normal. - - The normal value to add to the existing value. - - - - Converts the normal to a unit vector. - - - - - Returns the normal. - - - - - ORs the specified smoothing group value to the existing value. - - The smoothing group bits to set. - - - - Returns the smoothing group value. - - - - - Returns the material index. - - - - - Returns the RGB value. - - - - - The flags contain the clip flags, the number of normals at the vertex, and the number of normals that have already been rendered. These are used internally. For example, the clipping flags are used to see if the can be either trivially accepted or rejected when rendering. - - - - - The rendered vertex position - - - - - If used, a single will be stored here. - - - - - In some cases, there may be two or more RNormals per vertex. If this is the case, these 'extra' RNormals are allocated and the pointer to the memory is stored here. If these are used, then data member rn is not used (rn is copied into ern[0]). - - - - - Description: - This is the base class for the creation of plug-ins which work with the Standard material. These appear in the Super Sampling rollout in the dropdown. They have an Enable checkbox and a Quality spinner for their user interface. An optional modal dialog may also be presented. - - A is a plug-in that determines where inside a single pixel the shading and texture samples are computed. For some Samplers this pattern is the same for each pixel, for others a different pattern is chosen for each pixel. After determining the sample locations, the sampler calls back to the renderer to compute the shading values. It then averages the resulting shading values and returns its estimate of the final color. - - Some Samplers are adaptive. This means that the decides on-the-fly how many samples to take to achieve its goal. There are many subtleties to adaptive Samplers and many ways to define the adaptive mechanism. The adaptive mechanism used by the R3 Samplers is very simple: take 4 samples, look for the maximum change in any of the color channels, if it's greater than the threshold, then sample the entire pixel according to the given quality. Threshold is an optional parameter that may, but need not be used by adaptive Samplers. - - The transfer of control from 3ds Max to the plug-in is as follows: A is responsible for the sampling loop. It samples until it is done and computes the sum of its samples upon completion. Once the 's DoSample() method is called 3ds Max no longer has control. This is how adaptive samplers are handled. The DoSample() routine will determine how often and where it samples, then it calls the provided SamplingCallback::SampleAtOffset() method to have 3ds Max compute the shading value. - Plug-In Information: - Class Defined In SAMPLER.H - - Super Class ID SAMPLER_CLASS_ID - - Standard File Extension DLH - - Extra Include File Needed None - - - - - This is the method where the plug-in does its sampling loop. Upon completion it returns the color and transparency back to 3ds Max in c and t. - - A sampler samples a range of 0.0 to 1.0. For a pixel sampler this range gets mapped to a single pixel. The sampler doesn't need to be concerned with this however. It just works within the 0.0 to 1.0 space determining where to put the samples. Essentially, this method generates a set of points and calls SamplingCallback::SampleAtOffset() for each one. Then it sums up the results of the values returned from SampleAtOffset(), divides by the number of samples, and stores the results in c and t. - Parameters: - ShadeOutput* pOut - - This is the output of the sampling. - - SamplingCallback* cb - - This is the callback provided by 3ds Max which the sampler uses to actually do the sampling. - - ShadeContext* sc - - The Shade Context which provides information about the pixel being sampled. - - MASK mask=NULL - - The 64 bit pixel mask. This mask coresponds to the 8x8 sub-pixel area grid. The actual geometry covers only some portion of these bits. This is essentially an 8x8 raster for the inside of the pixel where bits are set over the polygon being rendered and bits are off for areas not over the polygon. Developers typically only want to sample where the geometry is and thus when the bits are on. If not the results are very poor visually. - - Note: Most polygons are quite small in a typically complex scene being rendered. In other words, most polygons that need to get sampled will only have a small number of these mask bits on since the polygons are very small relative to the pixel. For instance, edge on polygons may project down to only a few bits within the pixel. Consequently it is quite possible that there may be zero samples, i.e. no geometry in the mask. Developers need to check for this zero samples condition. If this is the case then a method of called SurfacePtScreen() is used. This method returns a point which is guaranteed to be on the fragment no matter how small it is. This point can then be used for at least a single sample. - Sample Code: - The following is a brief analysis of the DoSamples() method from the Uniform of 3ds Max. This sampler sub-divides the sample area into a grid and samples the pixel at the center point of each grid unit. - - This code is from the file /MAXSDK/SAMPLES/RENDER/SAMPLERS/STDSAMPLERS.CPP. - - The complete code is shown below and then a code fragment analysis follows: - - The above code is broken into smaller fragments to look at below: - - Here the sampler is just getting the number of sides in the sampling grid. This is computed based on the Quality spinner in the user interface. In this sampler this results in a number between 2 and 6 (developers can look at the UniformSampler::GetSideSamples() method to see this). Thus the resulting sampling grid is 2x2 or 3x3, up to 6x6. Then the number of samples is computed by multiplying the number of sides times itself. - - Next the side size inverse is computed to know how big the step size is. This is the amount to step along each time. - - The sample scale is how large is the piece that's being sampled. For example, if the grid is 2x2 then each sample is scaled by 1/2 - - Next the number of samples, and the color and transparency are initialized to zero: - - Then the sampling loop begins. Here the positions of individual sampling points are computed. Each point is then checked to see if it corresponds to a point in the mask (is over a polygon). (The sampleInMask function is defined in /MAXSDK/SAMPLES/RENDER/SAMPLERS/SAMPLERUTIL.CPP). If it is a point that's over a polygon then SampleAtOffset() is called. What SampleAtOffset() does is turn the passed 2D sample into a 3D sample and fills out a with a color and transparency. These returned values are summed up over the sampling loop ((*pOut) += sampOut;). - - At the end of the sampling loop a check is done to see if there were zero samples. This is the case if the geometry is very small relative to the pixel. There are two approaches that one might take when there are zero samples. One is to simply return black. A strict 'jitter-type' sampler might do this since, in fact, no samples were hit. This will result in artifacts to the image however. A better approach is to use the method SurfacePtScreen() to return a point which is guaranteed to be at the center of the fragment. Then this point is passed to SampleAtOffset() so a single sample which is on the fragment is used. - - If a single sample point was used, DoSamples() is finished. The reults are in pOut as returned from SampleAtOffset(). - - If a number of samples was taken, the shade info is scaled by the inverse of the number of samples (nSamples) to get the final colors. - - - - - - - This methods returns the integer number of samples given the current quality setting. If doing adaptive sampling (where the number of samples may vary) return the maximum number of samples possible. - - - - - Returns the sampling quality in the range of 0.0 to 1.0. Quality means how many samples are taken to compute the shade in a pixel. Higher quality is of course achieved by more samples. Quality 0.0 means "minimal", Quality 1.0 means "best", and Quality 0.5 means "good, the default ". Some samplers do not have adjustable quality (like 3ds Max 2.5 Star), in which case the quality spinner is disabled and this method is ignored. - - - - - This method returns 0 on "unchangeable", otherwise the number of quality levels. - - - - - Returns TRUE if sampling is enabled; otherwise FALSE. - - - - - Returns a comment string for the which appears in the Materials Editor user inteface. - - - - - This method determines which of the various optional parameters are displayed. Zero or more of the following values (which may be added together): - - IS_ADAPTIVE - Samples is adaptive in some way. - - ADAPTIVE_CHECK_BOX - Enable the Adaptive check box. - - ADAPTIVE_THRESHOLD - Enable the adaptive Threshold spinner. - - SUPER_SAMPLE_TEX_CHECK_BOX - Enable the texture Super Sampling check box. - - ADVANCED_DLG_BUTTON - Enable the Advanced button. This allows an additional popup dialog to be presented to the user. See the method ExecuteParamDialog(). - - OPTIONAL_PARAM_0 - Enable optional spinner 0. See the methods GetOptionalParamName(), GetOptionalParamMax(), etc. - - OPTIONAL_PARAM_1 - Enable optional spinner 1. - - The following option is simply a set of these: - - R3_ADAPTIVE = (IS_ADAPTIVE+ADAPTIVE_CHECK_BOX+ADAPTIVE_THRESHOLD) - Default Implementation: - { return 0; } - - - - - Returns TRUE if Super Sampling is on; otherwise FALSE. See SetTextureSuperSampleOn() above. - Default Implementation: - { return FALSE; } - - - - - This method is called on the to reflect the change in the 'Adaptive' checkbox state. - Parameters: - BOOL on - - TRUE for on; FALSE for off. - Default Implementation: - {} - - - - - Returns TRUE if Adaptive is on (cheched in the user interface); otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - Returns the adaptive threshold setting. - Default Implementation: - { return 0.0f; } - - - - - Samplers plug-ins support two optional parameter which may be used by the plug-in for its own needs. This methods returns the number of parameters it supports. Note that the max value is 2. - Default Implementation: - { return 0; } - - - - - Returns the name of the specified parameter. - Parameters: - long nParam - - The zero based index of the optional parameter: 0 for the first one, 1 for the second. - Default Implementation: - { return _M(""); } - - - - - Returns the maximum value of the specified optional parameter. - Parameters: - long nParam - - The zero based index of the optional parameter: 0 for the first one, 1 for the second. - Default Implementation: - { return 1.0f; } - - - - - Returns the value of the specified optional parameter. - Parameters: - long nParam - - The zero based index of the optional parameter: 0 for the first one, 1 for the second. - Default Implementation: - { return 0.0f; } - - - - - Sets the value of the specified optional parameter. - Parameters: - long nParam - - The zero based index of the optional parameter: 0 for the first one, 1 for the second. - - float val - - The value to set. - Default Implementation: - {} - - - - - This method is called to put up a modal dialog which allows editing of the extended parameters. The rest of the operation of 3ds Max should be disalbed by this modal dialog (which is why you should use GetMAXHWnd()). This method is called when the Advanced button is pressed (which is enabled by using the ADVANCED_DLG_BUTTON flag returned from SupportsStdParams(). - Parameters: - HWND hWndParent - - The parent window handle. Use Interface::GetMAXHWnd(). - - StdMat2* mtl - - Points to the owning Standard material. - Default Implementation: - {} - - - - - Description: - This is the callback object for the DoSamples() method of class . The SampleAtOffset() method is the one that actually computes the shading value for the . - - - - - This is the method that integrates the sampler into the renderer. The plug-in calls this method to actually perform a sample at the specified 2D point. This method computes the output color and transparency. - Parameters: - ShadeOutput* pOut - - The output of the sampling - - & sample - - The 2D sample point. - - float sampleScale - - The scale of the sample. This parameter is the way a sampler tells the shader to use the whole pixel (sampleScale=1) size for texture samples or some fraction. This scale is an edge scale not an area scale, so if you want samples 1/4 pixel large the sampleScale should be 1/2. - TRUE if the sample was processed; FALSE if the clipped sample was ignored. - - - - - A callback class for saving dependents. - - - Instances of this class are passed to ReferenceMaker::SaveEum. Typically, terminate is called passing in the instance, and if terminate returns FALSE SaveEnum is called on 's custom attribute container, its direct references, and its indirect references. Finally, proc is called passing in the instance. If terminate returns TRUE, SaveEnum typically immediately returns. - - - - - This is the method allows processing the passed . - - - Any processing needing to be performed on the passed RefenceMaker after enumerating the references held by the would be done in this method. - - - A pointer to the reference maker - - - - This is the method specifies whether to continue processing the passed . - - - This method specifies whether to continue processing the passed . Typically the method would check to see if the has already been processed and return TRUE if it has. Any processing needing to be performed before enumerating the references held by the would be done in this method. - FALSE if to continue enumerating the references held by the and call proc on the , TRUE to terminate processing of the . - - - A pointer to the reference maker - - - - Description: - A describes an arbitrary non-uniform scaling in an arbitrary axis system. The s gives the scaling along the x, y, and z axes, and the quaternion q defines the axis system in which scaling is to be applied. All methods are implemented by the system. - Data Members: - s; - - Scale components. - - q; - - The axis system of application. - - - - - Adds a to this . - - - - - Multiplies this by a float. This updates the scale components. - - - - - access operator. This allows the scale components to be accessed using the array operator. - Parameters: - int el - - Specifies the element to access: 0=x, 1=y, 2=z. - - - - - - - Equality operator. Test for equality between two 's. - Nonzero if the 's are equal; otherwise 0. - - - - - Description: - This is a base class for creating file export plug-ins. The plug-in implements methods of this class to describe the properties of the export plug-in and a method that handles the actual export process. - - - - - Returns the number of file name extensions supported by the plug-in. - - - - - Returns the 'i-th' file name extension (i.e. "3DS"). - Parameters: - int i - - The index of the file name extension to return. - - - - - Returns a long ASCII description of the file type being exported (i.e. "Autodesk 3D Studio File"). - - - - - Returns a short ASCII description of the file type being exported (i.e. "3DStudio"). - - - - - Returns the ASCII Author name. - - - - - Returns the ASCII Copyright message for the plug-in. - - - - - Returns the first message string that is displayed. - - - - - Returns the second message string that is displayed. - - - - - Returns the version number of the export plug-in. The format is the version number * 100 (i.e. v3.01 = 301). - - - - - This method is called to have the plug-in display its "About..." box. - Parameters: - HWND hWnd - - The parent window handle for the dialog. - - - - - This method is called for the plug-in to perform its file export. - Parameters: - const MCHAR *name - - The export file name. - - *ei - - A pointer the plug-in may use to call methods to enumerate the scene. - - *i - - An interface pointer the plug-in may use to call methods of 3ds Max. - - BOOL suppressPrompts=FALSE - - This parameter is available in release 2.0 and later only. - - When TRUE, the plug-in must not display any dialogs requiring user input. It is up to the plug-in as to how to handle error conditions or situations requiring user input. This is an option set up for the 3ds Max API in order for plug-in developers to create batch export plugins which operate unattended. See Interface::ExportToFile(). - - DWORD options=0 - - This parameter is available in release 3.0 and later only. - - In order to support export of selected objects (as well as future enhancements), this method now has this additional parameter. The only currently defined option is: - - SCENE_EXPORT_SELECTED - - When this bit is set the export module should only export the selected nodes. - One of the following three values should be returned: - - - - - This method is called by 3ds Max to determine if one or more export options are supported by a plug-in for a given extension. It should return TRUE if all option bits set are supported for this extension; otherwise FALSE. - - Note that the method has a default implementation defined in order to provide easy backward compatibility. It returns FALSE, indicating that no options are supported. - Parameters: - int ext - - This parameter indicates which extension the options are being queried for, based on the number of extensions returned by the SceneExport::ExtCount() method. This index is zero based. - - DWORD options - - This parameter specifies which options are being queried, and may have more than one option specified. At present, the only export option is SCENE_EXPORT_SELECTED, but this may change in the future. If more than one option is specified in this field, the plugin should only return TRUE if all of the options are supported. If one or more of the options are not supported, the plugin should return FALSE. - Default Implementation: - {return FALSE;} - - - - - Description: - This class represents the scene file (*.max) and is available through the built-in type instance sceneFileDropType. - - - - - Description: - This is a base class for creating file import plug-ins. The plug-in implements methods of this class to describe the properties of the import plug-in and a method that handles the actual import process. - - - - - Returns the number of file name extensions supported by the plug-in. - - - - - Returns the 'i-th' file name extension (i.e. "3DS"). - Parameters: - int i - - The index of the file name extension to return. - - - - - Returns a long ASCII description of the file type being imported (i.e. "Autodesk 3D Studio File"). - - - - - Returns a short ASCII description of the file type being imported (i.e. "3DStudio"). - - - - - Returns the ASCII Author name. - - - - - Returns the ASCII Copyright message for the plug-in. - - - - - Returns the first message string that is displayed. - - - - - Returns the second message string that is displayed. - - - - - Returns the version number of the import plug-in. The format is the version number * 100 (i.e. v3.01 = 301). - - - - - This method is called to have the plug-in display its "About..." box. - Parameters: - HWND hWnd - - The parent window handle for the dialog. - - - - - This method actually performs the file import. - Parameters: - const MCHAR *name - - The file name chosen by the user to import. - - *ii - - An import interface pointer that may be used to create objects and nodes in the scene. - - *i - - Pass the 3ds Max interface pointer here. - - BOOL suppressPrompts=FALSE - - This parameter is available in release 2.0 and later only. - - When TRUE, the plug-in must not display any dialogs requiring user input. It is up to the plug-in as to how to handle error conditions or situations requiring user input. This is an option set up for the 3ds Max API in order for plug-in developers to create batch import plugins which operate unattended. See Interface::ImportFromFile(). - One of the following three values should be returned: - - - - - This method is used to control the zoom extents done after the import is accomplished. It returns a value that indicates if the plug-in should override the user preference setting. - - Also see the method Interface::GetImportZoomExtents() which returns the state of the system zoom extents flag. - One of the following values: - - ZOOMEXT_NOT_IMPLEMENTED - - Indicates to use the preference setting. - - ZOOMEXT_YES - - Indicates to do a zoom extents after import regardless of the preference setting. - - ZOOMEXT_NO - - Indicates to not do a zoom extents regardless of the preference setting. - Default Implementation: - { return ZOOMEXT_NOT_IMPLEMENTED; } - - - - - Class that uses the RAII idiom to push/pop the error traceback disable state. This ensures that the error traceback disable state is properly popped in the event of an exception. - - - - - Class that uses the RAII idiom to create a maxscript visible stack frame. This ensures a stack frame is allocated in the constructor and properly deallocated in the destructor. This ensures resources are properly cleaned up in the event of an exception. Also note, that this will optionally allocate thread local storage for the calling thread. This is done because using any of the core maxscript classes requires access to maxscript's thread local storage. If this is not done, the application could crash. - - - - - Class that uses the RAII idiom to push/pop setting a structured error handler. This ensures that the structured error handler is properly restored in the event of an exception. An instance is created as a member of instances. The structured error handler is called when a structured error is thrown (such as an access violation). It captures information on the error, captures the c++ call stack, stores this information in an , and throws the . - - - - - Class that uses the RAII idiom to push/pop a . This ensures that the is properly popped in the event of an exception. - - - - - Class that uses the RAII idiom to push/pop the thread local current_controller. This ensures that the thread local current_controller is always properly restored, even in the event of an exception. - - - - - Class that uses the RAII idiom to push/pop the plugin stored in thread local current_plugin. This ensures that the current_plugin thread local is properly popped in the event of an exception. - - - - - Class that uses the RAII idiom to push/pop the struct stored in thread local current_struct. This ensures that the current_struct thread local is properly popped in the event of an exception. - - - - - Class that uses the RAII idiom to save and restore the current frame data. This ensures that the current frame data is properly restored in the event of an exception. An instance should be created at the top of a try expression, and as the expresion is exited, either normally or via an exception, the current frame data is automatically restored. - - - - - Class that uses the RAII idiom to allocate and deallocate value temp arrays. This ensures that the current frame data is always properly deallocated, even in the event of an exception. - - - - - return false to default handling - - - - - Description: - This class represents the script file (*.ms, *.mse, *.mcr) and is available through the built-in type instance scriptFileDropType. - - - - - Exception thrown when attempting to execute MAXScript commands that are disallowed by ISceneScriptSecurityManager. - - - - - By default, SelectChildren(ViewExp*) will be called when double click message is triggered. If this function returns true, system will handle OverrideDoubleClickProc(ViewExp*, int) instead. - true if double click is handled. - - - - - Override double click handle function - - pointer to - These flags describe the state of the mouse buttons. See . - - - - Description: - This is a call-back class for the selection filter drop down in the tab panel. This allows plug-ins to add additional filters to this list. - - - - - Returns the name of the filter that will appear in the drop down list in the tab panel. - - - - - This is the method that does the filtering of the node. It returns TRUE if the node may be selected; FALSE if it is not selectable. - Parameters: - SClass_ID sid - - The Super Class ID of the node. - - cid - - The Class ID of the node. - - *node - - Points to the node to check. - - - - - Called when the callback is registered via Interface::RegisterSelectFilterCallback. - - - - - Called when the callback is unregistered via Interface::UnRegisterSelectFilterCallback. Note that the instance can safely be deleted in this method. - - - - - Description: - The Morph communicates with the Morph Controller through this class. A pointer to one of these is passed to MorphControl::SetValue() as the val parameter. All methods of this class are implemented by the system. - Data Members: - tm; - - The relative transformation matrix from the Morph to the Target. - - *obj; - - The target object. - - MSTR name; - - The name it creates. - - BOOL forceCreate; - - If TRUE then make sure the key is created even if it is at frame 0. - - - - - Description: - This class is used to allow a transform () controller to know that it is being specifically moved, rotated, or scaled. - - When SetValue() is called on a controller, the val pointer is passed in for a certain data type. For a transform () controller SetValue() passes in a pointer to an instance of this. This provides higher level information to the transform controller than what is provided by passing a matrix. For example, if rotation is taking place, the XFORM_ROTATE command would be used. In this way the PRS transform controller would not make position or scale keys since it knows only rotation is taking place. Typically one of the different constructors is used depending on the command needed. All methods of this class are implemented by the system. - Data Members: - SetXFormCommand command; - - The command. The transform controller takes the val pointer and casts it to an instance of this class and looks at this data member to see which operation is being performed. - - One of the following values: - - XFORM_MOVE - - The move command. An incremental move is being applied to the matrix. - - XFORM_ROTATE - - The rotate command. An incremental rotation is being applied to the matrix. - - XFORM_SCALE - - The scale command. An incremental scaling is being applied to the matrix. - - XFORM_SET - - To just set the matrix without telling the controller any other higher level information this command may be used. This just sets the value of the matrix (it is not incremental). Any time a node modifies a controller, it will set the method to get CTRL_RELATIVE, and the packet command is set to XFORM_SET. - - tmParent; - - The parent matrix. - - tmAxis; - - This usually represents the coordinate system one is moving, rotating, or scaling in. However, if the command is XFORM_SET, then tmAxis is the actual matrix being set. - - p; - - If the command is XFORM_MOVE or XFORM_SCALE, then this contains the amount of the move or scale. - - q; - - If the command is XFORM_ROTATE then this contains the amount of the rotation. - - aa; - - If the command is XFORM_ROTATE this will also contain the amount of the rotation. This form can represent multiple revolutions however (as opposed to q). - - BOOL localOrigin; - - Indicates the local axis is being used. If TRUE it is; otherwise it is not. If the rotation or scaling is occurring about the pivot point this is TRUE. - - - - - - Used by developers to create plug-ins. The methods of this class must be implemented to provide data to the 3ds Max interactive renderer. This will let that renderer to properly reflect the look of the shader in the viewports. The methods associated with the actual illumination code are from the base class . There are various Get and methods defined in this class. Plug-in developers provide implementations for the 'Get' methods which are used by the interactive renderer. The implementations of the '' methods are used when switching between shaders types in the Materials Editor. This is used to transfer the corresponding colors between the old and the new one. Note that some shaders may not have the exact parameters as called for in the methods. In those case an approximate value may be returned from the 'Get' methods. For example, the Strauss doesn't have an Ambient channel. In that case the Diffuse color is taken and divided by 2 and returned as the Ambient color. This gives the interactive renderer something to work with that might not be exact but is somewhat representative. - - - - - - Copies the standard shader parameters from pFrom to this object. Note that plug-ins typically disable the macro recorder during this operation as the Get and methods are called. See the sample code for examples. - - The pointer to the source parameters. - - - - Returns the Diffuse/Specular lock' - true if the Diffuse/Specular lock is on, false otherwise. - - - - - Returns the Ambient/Diffuse lock. - true if the Ambient/Diffuse lock is on, false otherwise. - - - - - Returns the Ambient/Diffuse Texture lock. - true if the Ambient/Diffuse Texture lock is on, false otherwise. - - - - - Sets the Self Illumination parameter to the specified value at the time passed as TimeValue. - - The value to set. - The time to set the value. - - - - Sets the Self Illumination On/Off state. - - true for on, false for off. - - - - Sets the Self Illumination at the specified time. - - The color for the self illumination to set to. - The time to set the color. - - - - Sets the Ambient at the specified time. - - The color for the ambient to set to. - The time to set the color. - - - - Sets the Diffuse at the specified time. - - The color for the diffuse color to set to. - The time to set the color. - - - - Sets the Specular at the specified time. - - The color to set to. - The time to set the color. - - - - Sets the Glossiness parameter to the specified value at the time passed. - - The value to set to. - The time to set the value. - - - - Sets the Specular Level parameter to the specified value at the time passed. - - The value to set. - The time to set the value. - - - - Sets the Soften Specular Highlights Level to the specified value at the time passed. - - The value to set. - The time to set the value. - - - - Returns the The Self Illumination setting. parameters to this method are not applicable and may safely be ignored. - true if the Self Illumination setting is on (checked), false otherwise. - - - - - Returns the Ambient . The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Diffuse . The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Specular . The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Self Illumination . The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Self Illumination Amount. The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Glossiness Level. The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Specular Level. The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Soften Level as a float. The parameters to this method are not applicable and may safely be ignored. - - - - - Returns the Self Illumination setting. - true if the Self Illumination setting is on (checked), false if it is off - - - - - Returns the Ambient at the specified time. - - The time at which to return the color. - - - - Returns the Diffuse at the specified time. - - The time at which to return the color. - - - - Returns the Specular at the specified time. - - The time at which to return the color. - - - - Returns the Glossiness value at the specified time. - - The time at which to return the value. - - - - Returns the Specular Level at the specified time. - - The time at which to return the value. - - - - Returns the Soften Specular Highlights setting at the specified time. - - The time at which to return the value. - - - - Returns the Self Illumination Amount at the specified time. - - The time at which to return the value. - - - - Returns the Self Illumination at the specified time. - - The time at which to return the color. - - - - Evaluates the hightlight curve that appears in the user interface. This gets called from the DrawHilite() function which is available to developers in /MAXSDK/SAMPLES/MATERIALS/SHADER/SHADERUTIL.CPP - The output value on the curve. A value of 1.0 represents the top of the curve as it appears in the UI. Values greater than 1.0 are okay and simply appear off the top of the graph. - - The input value. - - - - This is the highlight curve function for the two highlight curves which intersect and appear in the UI, for instance in the Anistropic shader. - The output value of the curve. - - The x input value. - The y input value. - This is used by multi-layer shaders to indicate which layer to draw. The draw highlight curve routines use this when redrawing the graph. - - - - A shader parameter dialog class. An instance of is returned by a shader when it is asked by 3ds Max to display its rollup page. - - - - - Sets the current Standard material and its shader (which are being edited) to those which are passed as inputs. - - The pointer to the standard material to be set as the current standard material. - The pointer to the shader to be set as the current shader. - - - - Returns a pointer to the current . - - - - - The dialog procedure for the user interface controls of the . - In response to a WM_INITDIALOG message: Zero if the dialog box procedure calls the SetFocus() function to set the focus to one of the controls in the dialog, Non-zero Otherwise. If non-zero, the system sets the focus to the first control in the dialog that can be given the focus. - In response to any message other than WM_INITDIALOG: Nonzero if the procedure processes the message, zero otherwise. - - The window handle of the rollup page. - The message to process. - The first dialog parameter. - The second dialog parameter. - - - - Loads the user interface controls with their current values. - - Not currently used. - - - - Returns the window handle of the rollup panel. - - - - - Updates the opacity parameter of the plug-in in the user interface. - - - - - Updates the map buttons in the user interface. For example it can put a " " or "m" or "M" on the button face based on the state of the map. - - - - - Description: - This class is passed to materials and texture maps. It contains all the information necessary for shading the surface at a pixel. - - Normally, the is provided by the 3ds Max renderer. However developers that need to create their own for use in passing to the texture and material evaluation functions can do so by deriving a class from and providing implementations of the virtual methods. Some sample code is available demonstrating how this is done in /MAXSDK/SAMPLES/OBJECTS/LIGHT.CPP (see the code for class SCLight : public ). The default implementations of these methods are shown for developers that need to create their own . - - Note that raytracing (and all shading calculations in the default renderer) takes place in camera space. - - For additional information on the methods DP(), Curve(), DUVW() and DPdUVW() see . - - All methods are implemented by the system unless noted otherwise. - Data Members: - BOOL doMaps - - Indicates if texture maps should be applied. - - BOOL filterMaps; - - Indicates if textures should be filtered. - - BOOL shadow - - Indicates if shadows should be applied. - - BOOL backFace; - - Indicates if we are on the back side of a 2-sided face. - - int mtlNum - - The material number of the face being shaded. This is the sub-material number for multi-materials. - - ambientLight - - This is the color of the ambient light. - - int nLights; - - This is the number of lights being used in a render, which is the number of active lights in the scene, or if there are none, 2 for the default lights. For example, this is used in the Standard material in a loop like this: - - int rayLevel; - - This data member is available in release 2.0 and later only. - - This is used to limit the number of reflections for raytracing. For instance, if you're rendering a hall of mirrors, and the ray is reflecting back and forth, you don't want the raytracing to go forever. Every time Texmap::EvalColor() gets called again on a ray you create a new and bump up the rayLevel one. This allows you to test this value and see if it has reached the limit of how deep to go (if it reaches a maximum level, you can return black for example). - - Note that it is conceivable that more than one raytrace material can be in effect at a time (from different developers). In such a case, where one surface might have one raytracer and another surface a different one, and a ray was bouncing back and forth between them, each needs to be aware of the other. This is why this value is here - the two texmaps each modify and check it. - - int xshadeID; - - This data member is available in release 2.0 and later only. - - This is currently not used. - - *globContext; - - This data member is available in release 2.0 and later only. - - Points to an instance of . This class describes the properties of the global rendering environment. This provides information such as the renderer in use, the project type for rendering, the output device width and height, several matrices for transforming between camera and world coordinates, the environment map, the atmospheric effects, the current time, field rendering information, and motion blur information. - - *atmosSkipLight; - - The light description of lights to prevent self shadowing by volumetric lights. - - *globContext; - - A pointer to the rendering global context. - - out; - - This is where the material should leave its results. - - The following is a discussion of blending the ShadeContext.out.c and ShadeContext.out.t together to get the final color: - - The (c,t) returned by shaders is interpreted as follows: t.r is the (premultiplied) alpha for the r-channel, etc. - - So if you want to composite (c,t) over a background b, - - color = b*t + c ( where the multiplication of b and t multiplies the individual components ). - - When you want to convert a (c,t) to a simple R,G,B,Alpha, just average together the components of t to get Alpha. (and use the r,g,b components of c directly). - - - - - The rendering mode in which the shade context is currently operating. Maybe be used by materials and texmaps to modify their behaviour. - - - - - Sets the surface color output and surface transparency output to Black. - Parameters: - int n = -1 - - By supplying a negative value this method will clear elements but leave the number of elements unchanged. - - - - - Returns the of this . This is used to distinguish different ShadeContexts. - Default Implementation: - ; } - - - - - Returns TRUE if this rendering is for the material editor sample sphere (geometry); otherwise FALSE. - - - - - Returns the state of the antialiasing switch in the renderer dialog - TRUE if on; FALSE if off. - Default Implementation: - {return 0;} - - - - - This method returns the projection type. - A value of 0 indicates perspective projection; a value of 1 indicates parallel projection. - Default Implementation: - {return 0;} - - - - - This method returns the 'i-th' light. Use data member nLights to get the total number of lights. - Parameters: - int n - - Specifies the light to return. - - - - - Returns the current time value (the position of the frame slider). - The current time. - - - - - Returns the node ID for the item being rendered or -1 if not set. This ID is assigned when the scene is being rendered - each node is simply given an ID - 0, 1, 2, 3, etc. - Default Implementation: - {return -1;} - - - - - Returns the pointer of the node being rendered. This pointer allows a developer to access the properties of the node. See Class . - Default Implementation: - { return NULL; } - - - - - Returns the evaluated object for this node. When rendering, usually one calls GetRenderMesh() to get the mesh to render. However, at certain times you might want to get the object itself from the node. For example, you could then call ClassID() on the object and determine its type. Then the object could be operated on procedurally (for instance you could recognize it as a true sphere, cylinder or torus). Note that this method will return NULL if object is motion blurred. - - For example, here is how you can check if the object is a particle system: - - - Default Implementation: - { return NULL; } - - - - - The coordinates relative to triangular face. The barycentric coordinates of a point p relative to a triangle describe that point as a weighted sum of the vertices of the triangle. If the barycentric coordinates are b0, b1, and b2, then: - - p = b0*p0 + b1*p1 + b2*p2; - - where p0, p1, and p2 are the vertices of the triangle. The returned by this method has the barycentric coordinates stored in the its three coordinates. These coordinates are relative to the current triangular face being rendered. These barycentric coordinates can be used to interpolate any quantity whose value is known at the vertices of the triangle. For example, if a radiosity shader had available the illumination values at each of the three vertices, it could determine the illumination at the current point using the barycentric coordinates. - Default Implementation: - ;} - - - - - Returns the index of the face being rendered. For the scan-line renderer, which renders only triangle meshes, this is the index of the face in the data structure. This is meant for use in plug-in utilities such as a radiosity renderer, which stores a table of data, indexed on face number, in the Nodes's AppData, for use in a companion material. - - - - - Returns the interpolated normal (in camera space). This is the value of the face normal facing towards the camera. This is affected by SetNormal() below. - - - - - Returns the original surface normal (not affected by SetNormal() above.) - Default Implementation: - Normal(); } - - - - - This returns the geometric normal. For triangular mesh objects this means the face normal. Normals are unit vectors. - - - - - This is an estimate of how fast the normal is varying. For example if you are doing environment mapping this value may be used to determine how big an area of the environment to sample. If the normal is changing very fast a large area must be sampled otherwise you'll get aliasing. This is an estimate of dN/dsx, dN/dsy put into a single value. - - - - - This method returns the unit view vector, from the camera towards P, in camera space. - - - - - Sets the view vector as returned by V(). - Parameters: - p - - The view vector set. - - - - - This is the original view vector that was not affected by ShadeContext::SetView(). - Default Implementation: - V(); } - - - - - This takes the current view vector and the current normal vector and calculates a vector that would result from reflecting the view vector in the surface. This returns the reflection vector. - - - - - This is similar to the method above however it calculates the view vector being refracted in the surface. This returns the refraction vector. - Parameters: - float ior - - The relative index of refraction between the air and the material. - - - - - Returns the index of refraction. - Default Implementation: - { return 1.0f; } - - - - - Returns the camera position in camera space. For the 3ds Max renderer this will always be 0,0,0. - - - - - Returns the point to be shaded in camera space. - - - - - This returns the derivative of P, relative to the pixel. This gives the renderer or shader information about how fast the position is changing relative to the screen. - - - - - This returns the derivative of P, relative to the pixel - same as above. This method just breaks it down into x and y. - - - - - Returns the point to be shaded in object coordinates. - - - - - Returns the derivative of PObj(), relative to the pixel. - - - - - Returns the object extents bounding box in object coordinates. - - - - - Returns the point to be shaded relative to the object box where each component is in the range of -1 to +1. - - - - - Returns the derivative of PObjRelBox(). This is the derivative of the point relative to the object box where each component is in the range of -1 to +1. - - - - - Retrieves the point relative to the screen where the lower left corner is 0,0 and the upper right corner is 1,1. - Parameters: - & uv - - The point. - - &duv - - The derivative of the point. - - - - - Returns the integer screen coordinate (from the upper left). - - - - - Return the surface point at the center of the fragment in floating point screen coordinates. See the documentation for Sampler::DoSample() for an explanation of the use of this method. See Class . - Default Implementation: - (0.0,0.0); } - - - - - Returns the UVW coordinates for the point. - Parameters: - int channel=0; - - Specifies the channel for the values. One of the following: - - 0: Vertex Channel. - - 1 through 99: Mapping Channels. - - - - - This method returns the UVW derivatives for the point. This is used for filtering texture maps and antialiasing procedurals that are using UVW. Note that in standard 3ds Max textures, the class is used, and it calls this method itself. See the methods UVGen::GetBumpDP() for more details for using . If you are not using then you can use this method and UVW(). UVW() gets the UVW coordinates of the point and DUVW() gets the change in the UVWs for the point. This tells you a maximum change for each of UVW. This tells you how much of the area of the map to sample. So when you call the method *ptr) this tells you how big the sample should be. This lets you filter or average over this area to keep the map from aliasing. - Parameters: - int channel=0; - - Specifies the channel for the values. One of the following: - - 0: Vertex Channel. - - 1 through 99: Mapping Channels. - - - - - This returns the bump basis vectors for UVW in camera space. Note that if you want to retrieve these bump basis vectors that are altered by the instance use the method UVGen::GetBumpDP(). Also see the Advanced Topics section ~{ Materials, Textures and Maps }~ for more details on bump mapping. - Parameters: - dP[3] - - The bump basic vectors. dP[0] is a vector corresponding to the U direction. dp[1] corresponds to V, and dP[2] corresponds to W. - - int channel=0; - - Specifies the channel for the values. One of the following: - - 0: Vertex Channel. - - 1 through 99: Mapping Channels. - - - - - This method should replace DpDUVW over time but is left in place as not to break 3rd party plugins. If this method returns 1, that is assumed to mean it is implemented, and it will be used instead of DpDUVW. - Parameters: - dP[2] - - The bump basic vectors. dP[0] is a vector corresponding to the U direction. dp[1] corresponds to V, and dP[2] corresponds to W. - - int axis - - Specified the 2D cases for: AXIS_UV, AXIS_VW, or AXIS_WU. - - int channel=0; - - Specifies the channel for the values. One of the following: - - 0: Vertex Channel. - - 1 through 99: Mapping Channels. - Default Implementation: - { return 0; } - - - - - This method returns a vector in UVW space normal to the face in UVW space. This can be CrossProd(U[1]-U[0],U[2]-U[1]), where U[i] is the texture coordinate at the i-th vertex of the current face. This may be used for hiding textures on back side of objects. - Parameters: - int channel=0; - - Specifies the channel for the values. One of the following: - - 0: Vertex Channel. - - 1 through 99: Mapping Channels. - Default Implementation: - ; } - - - - - Returns the diameter of the ray cone at the pixel point (the point it intersects the surface being shaded). This is a dimension in world units. As a ray is propagated it is updated for each new surface that is encountered. - Default Implementation: - { return Length(DP()); } - - - - - Returns the angle of a ray cone hitting this point. It gets increased/decreased by curvature on reflection. - - Visualize a small pyramid, with the top at the eye point, and its sides running through each corner of the pixel to be rendered, then onto the scene. Then visualize a small cone fitting inside this pyramid. This method returns the angle of that cone. When rendering, if the ray cone goes out and hits a flat surface, the angle of reflection will always be constant for each pixel. However, if the ray cone hits a curved surface, the angle will change between pixels. This change in value give some indication of how fast the sample size is getting bigger. - Default Implementation: - { return 0.0f; } - - - - - This is used by the Standard material to do the reflection maps and the refraction maps. Given the map, and a direction from which you want to view it, this method changes the view vector to be the specified vector and evaluates the function. - Parameters: - *map - - The map to evaluate. - - view - - The view direction. - The color of the map, in r, g, b, alpha. - - - - - Retrieves the background color and the background transparency. - Parameters: - &bgCol - - The returned background color. - - &transp - - The returned transparency. - - int fogBG - - Specifies you want the current atmospheric shaders to be applied to the background color. If TRUE the shaders are applied; if FALSE they are not. - - - - - Returns the camera near range set by the user in the camera's user interface. - - - - - Returns the camera far range set by the user in the camera's user interface. - - - - - Transforms the specified point from internal camera space to the specified space. - Parameters: - & p - - The point to transform. - - RefFrame ito - - The space to transform the point to. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - The transformed point, in the specified space. - - - - - Transforms the specified point from the specified coordinate system to internal camera space. - Parameters: - & p - - The point to transform. - - RefFrame ifrom - - The space to transform the point from. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - The transformed point in camera space. - - - - - Transform the vector from internal camera space to the specified space. - Parameters: - & p - - The vector to transform. - - RefFrame ito - - The space to transform the vector to. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - - - - - Transform the vector from the specified space to internal camera space. - Parameters: - & p - - The vector to transform. - - RefFrame ifrom - - The space to transform the vector from. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - - - - - Transform the vector from internal camera space to the specified space without scaling. - Parameters: - & p - - The vector to transform. - - RefFrame ito - - The space to transform the vector to. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - - - - - Transform the vector from the specified space to internal camera space without scaling. - - Note: This method was added to correct a problem that was occurring in 3D Textures when the bump perturbation vectors were transformed from object space to camera space, so they are oriented correctly as the object rotates. If the object has been scaled, this transformation causes the perturbation vectors to be scale also, which amplifies the bump effect. This method is used to rotate the perturbation vectors so they are correctly oriented in space, without scaling them. - Parameters: - & p - - The vector to transform. - - RefFrame ifrom - - RefFrame ifrom - - The space to transform the vector from. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - - - - - Returns the transformation matrix to transform from internal camera space to the specified space. - Parameters: - RefFrame ito - - The space to transform to. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - The transformation matrix to transform to the specified space. - - - - - Returns the transformation matrix to transform from the specified coordinate system to internal camera space. - Parameters: - RefFrame ifrom - - The space to transform from. One of the following values: - - REF_CAMERA - - REF_WORLD - - REF_OBJECT - The transformation matrix to transform to internal camera space. - - - - - When a map or material is evaluated (in Shade(), EvalColor() or EvalMono()), if it has a non-zero gbufID, it should call this routine to store the gbid into the shade context. - - Note: Normally a texmap calls this method so the index would be set for all of the area covered by the texture. There is no reason that this has to be done for every pixel however. A texture could just set the ID for particular pixels. This could allow post processing routines (for example a glow) to only process part of a texture and not the entire thing. For example, at the beginning of texmap's EvalColor() one typically has code that does: - - if (gbufid) sc.SetGBufferID(gbufid); - - This takes the gbufid (which is in ) and (if it is non-zero) stores it into the shade context. The renderer, after evaluating the Shade() function for the material at a pixel, looks at the gbufferID left in the shade context, and stores it into the gbuffer at that pixel. So if the texmap adds another condition like - - - It will do it for just the chosen pixels. - Parameters: - int gbid - - The ID to store. - - - - - This method is used internally. - - - - - Returns the color of the global environment map from the given view direction. - Parameters: - dir - - Specifies the direction of view. - Default Implementation: - ; } - - - - - This method is used with texture maps only. If a map is multiply instanced within the same material, say on the diffuse channel and on the shininess channel, it will return the same value each time its evaluated. Its a waste of processor time to re-evaluate the map twice. This method allows you to cache the value so it won't need to be computed more than once. - - Note that the cache is automatically cleared after each call. This is used within one evaluation of a material hierarchy. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - &c - - The color to store. - TRUE if the color was returned; otherwise FALSE. - Default Implementation: - { return FALSE; } - Sample Code: - This code from /MAXSDK/SAMPLES/MATERIALS/NOISE.CPP and shows how the cache is retrieved and stored: - - - - - - - Retrieves a floating point value from the cache. See the version above for details. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - float &f - - The value to store. - TRUE if the value was returned; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - Retrieves a value from the cache. See the version above for details. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - &p - - The point to store. - TRUE if the value was returned; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - Puts a color to the cache. See the method &c) above for details. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - &c - - The color to store. - Default Implementation: - {} - - - - - Puts a floating point value to the cache. See the method &c) above for details. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - const float f - - The floating point value to store. - Default Implementation: - {} - - - - - Puts a floating point value to the cache. See the method &c) above for details. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - - &p - - The value to store. - Default Implementation: - {} - - - - - Removes the specified cache. - Parameters: - *map - - Points to the texmap storing the cache (usually the plug-ins this pointer). - Default Implementation: - {} - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - - This is reserved for future use. - Parameters: - int cmd - - The command to execute. - - ULONG arg1=0 - - Optional argument 1 (defined uniquely for each cmd). - - ULONG arg2=0 - - Optional argument 2. - - ULONG arg3=0 - - Optional argument 3. - An integer return value (defined uniquely for each cmd). - Default Implementation: - { return 0; } - - - - - This method, along with SetAtmosSkipLight() below, are used by the lights to avoid self-shadowing when applying atmospheric shadows. This method returns a pointer to the instance currently calling the Atmosphere::Shade() method when computing atmospheric shadows. - - Here's how they are used: - - (1) When computing the atmospheric shadows:(somewhere in LightDesc::Illuminate()) do the following: - - sc.SetAtmosSkipLight(this); - - sc.globContext->atmos->Shade(sc, lightPos, sc.P(), col, trans); - - sc.SetAtmosSkipLight(NULL); - - (2) In LightDesc::TraverseVolume() do the following: - - if (sc.GetAtmosSkipLight()==this) - - return; - Default Implementation: - { return atmosSkipLight; } - volumetric light should be prevented from generating self-shadows. - Default Implementation: - { return atmosSkipLight; } - - - - - - - Returns the number of render elements. - Default Implementation: - NRenderElements(); } - - - - - Returns an interface to the 'i-th' render element. - Parameters: - int n - - The zero based index of the render element to return. - Default Implementation: - { return globContext->GetRenderElement(n); } - - - - - Computes and returns the incoming diffuse illumination color (for matte/shadow). - - - - - Description: - An instance of this class is a data member of the . This is used to contain the computed color and transparency of the pixel being shaded by a material. All methods of this class are implemented by the system. - Data Members: - ULONG flags; - - These flags are not currently used. - - c; - - Shaded color of the pixel. - - t; - - Transparency of the pixel. - - float ior; - - Index of refraction of the pixel. - - int gbufId; - - The G-buffer ID. This allows the MixIn() method to pick the id of the material which was blended in the highest proportion. - - - - - This method is used to blend the output of two texmaps, for example, in the Mix texmap. The function is as follows: - This does a blend of a with (*this). This blend is applied to the color, transparency, and index of refraction. The flags of are OR'ed together. - Parameters: - & a - - The output of the texmap to blend in. - - float f - - The amount to blend in, i.e.: - - a.MixIn(b, 1.0f) results in 100% of a and none of b. - - - - - Implemented by the System. - - This method resets the data member such that: c is set to black, t is set to black, ior is set to 1.0, gbufId is set to 0, and the flags are set to 0. - Parameters: - int n = -1 - - By supplying a negative value this method will clear elements but leave the number of elements unchanged. - - - - - Description: - This class is used by a Shadow Type plug-in to generate the shadows. It only exists during a render, with one per instance of the light. Methods of this class perform the shadow buffer creation and sampling. - - The API allows for two methods of sampling: A generator can use either a "generic" sampling method: - - & color); - - Or, if it the generator is to work with Volumetric lights, it must use the following sampling shadow-map style interface: To indicate that the latter interface is used, the method ShadowType::SupportStdMapInterface() must return TRUE; - - - - - This method is called on every frame to create a new shadow buffer for that frame. For example, the objects in the scene will have moved to different position, etc., so a new shadow buffer will need to be set up. See Class for a helper class used for generating shadow map buffers. - Parameters: - TimeValue t - - The time for the update. - - & rendCntxt - - The render context - this is used for the progress bar. - - *rgc - - This is used to get an instance list. - - & lightToWorld - - The light to world space transformation matrix. This is not necessarily the same as that of the light. - - float aspect - - This is the aspect ratio for non-square buffers. The aspect gives the height/width ratio of the shadow rectangle. The shadow buffer bitmap is always the same number of pixels wide as it is high, but it can be mapped into a non-square rectangle. - - float param - - This is the field-of-view of the light in radians for perspective projections or the width in world coordinates for parallel projections. - - float clipDist = DONTCLIP - - This parameter specifies the far clipping distance for the light. This is used when the far distance attenuation is turned on, and can result in much more efficient shadow buffer creation. If you have a small scene in the middle of a large complex scene, and the small scene is lit by, for instance, a shadow-casting omni, if you don't use far attenuation the omni has to take into account the entire large scene in its shadow map. Using far attenuation will clip all this outside stuff. Also omnis free up any of their 6 shadow buffer that end up being empty, so this can save memory usage. - Nonzero on success; otherwise zero. - - - - - If things such as automatic cubic maps or mirror are used, the rendering is done from several different points of view. This method is called to allow the view matrix to be computed and cached so it won't have to be computed over and over again. The shadow buffer caches the matrix that does the transformation from the current view coordinates into its coordinates. - Parameters: - & worldToCam - - This is the direction the view is looking from. coordinates are relative to this 'camera'. This is not always a 'camera', it is just world to whatever view is needed, for example from a mirror. - Nonzero on success; otherwise zero. - - - - - This method is used to delete the memory associated with the buffer. - - - - - shadow sampling function. Implement this when ShadowType::SupportStdMapInterface() returns FALSE. - - This is the Sample method used for ray traced shadows, for example. It takes the color that would illuminate the surface if there were no shadows, and returns a modified value. The shade context provides the point on the surface (sc.P()) and norm is the normal to the surface. - Parameters: - &sc - - The shade context provides the point on the surface (sc.P()). - - &norm - - This is the normal to the surface. - - & color - - The input color. - It returns an attenuation, where 1.0 indicates it is not in shadow, and 0.0 indicates it is in shadow. - Default Implementation: - { return 1.0f; } - - - - - Implement this method when ShadowType::SupportStdMapInterface() returns TRUE. This interface allows illuminated atmospherics. - - This method is called to determine how much the point (x, y, z) is in shadow. It returns an attenuation, where 1.0 indicates it is not in shadow, and 0.0 indicates it is in shadow, and potentially a small negative number. A small negative number should be returned when the sample falls outside of the buffer (this is needed in order to fix a problem occuring with Omni Lights when using shadow maps). All shadow generators that implement this function need to do this. The value itself isn't important, as long as it is negative and very small (for instance (-float(1.0e-30)). - Parameters: - &sc - - The shade context. - - float x - - The x coordinate of the point to check. This point is normalized into shadow buffer space. For example if the shadow buffer was 256x256 a point at the center would be 128, 128. - - float y - - The y coordinate of the point to check. This point is normalized into shadow buffer space. - - float z - - The z coordinate of the point to check. This is the distance perpendicular to the light where 0.0 is right at the light. - - float xslope - - This indicates the slope of the surface relative to the shadow buffer in x. - - float yslope - - This indicates the slope of the surface relative to the shadow buffer in y. - Default Implementation: - { return 1.0f; } - - - - - Implement this method when ShadowType::SupportStdMapInterface() returns TRUE. This interface allows illuminated atmospherics. - - This method determines if the given point is in a shadow. It samples a single pixel in the shadow map. - Parameters: - int x - - The x coordinate of the point to check. This point is normalized into shadow buffer space. For example if the shadow buffer was 256x256 a point at the center would be 128, 128. - - int y - - The y coordinate of the point to check. This point is normalized into shadow buffer space. - - float z - - The z coordinate of the point to check. This is the distance perpendicular to the light where 0.0 is right at the light. - TRUE if the point is in shadow; otherwise FALSE. - Default Implementation: - { return 1; } - - - - - Implement this method when ShadowType::SupportStdMapInterface() returns TRUE. This interface allows illuminated atmospherics. - - This method is called to determine how much the point (x, y, z) is in shadow. It returns an attenuation, where 1.0 indicates it is not in shadow, and 0.0 indicates it is in shadow. The method QuickSample() above looks at a single pixel in the shadow buffer. This method looks at either 4 or 8 pixels (based on the level parameter) to compute the result. The center pixel is given the highest weighting, while the other pixels are given lesser weightings. However this method is still fairly quick, since it doesn't base the weighting on the location within the pixel. This is in contrast to the Sample() method above, where the blending of the adjacent pixels is weighted by the position within the sub-pixel. - Parameters: - int x - - The x coordinate of the point to check. This point is normalized into shadow buffer space. For example if the shadow buffer was 256x256 a point at the center would be 128, 128. - - int y - - The y coordinate of the point to check. This point is normalized into shadow buffer space. - - float z - - The z coordinate of the point to check. This is the distance perpendicular to the light where 0.0 is right at the light. - - int level - - This may be 0 or 1. If 0, four neighboring pixels are blended in. If 1, eight neighboring pixels are blended in. - A value in the range 0.0 to 1.0. - Default Implementation: - { return 1.0f; } - - - - - Implement this method when ShadowType::SupportStdMapInterface() returns TRUE. This interface allows illuminated atmospherics. - - This method is called to sample the shadow map along a line segment. It uses a line between x1, y1 and x2, y2. The z values are interpolated between z1 and z2 and compared to the z value in the shadow map for that pixel. - Parameters: - int x1 - - The start x coordinate of the line. This point is normalized into shadow buffer space. For example if the shadow buffer was 256x256 a point at the center would be 128, 128. - - int y1 - - The start y coordinate of the line. This point is normalized into shadow buffer space. - - float z1 - - The start z coordinate of the line. This is the distance perpendicular to the light where 0.0 is right at the light. - - int x2 - - The end x coordinate of the line. This point is normalized into shadow buffer space. - - int y2 - - The end y coordinate of the line. This point is normalized into shadow buffer space. - - float z2 - - The end z coordinate of the line. This is the distance perpendicular to the light where 0.0 is right at the light. - A value in the range 0.0 to 1.0 which represents how much of the ray was inside the light and how much was outside the light. - Default Implementation: - { return 1.0f; } - - - - - Description: - A developer derives a class from this class to provide the user interface for the Shadow Generator plug-in. The DeleteThis() method deletes this object when done. An instance of this class is returned from ShadowType::CreateShadowParamDlg(). - - - - - This class is only available in release 5 or later. - The user of GetAreaShadowType() is a linear or area light. The usage is: - - Sampling the area shadows is a little tricky to allow for some optimizaton. This is an example of the code needed in AreaShadowLightObjDesc::Illuminate. The variable, sampler, should be local to allow multithreading. Once the sampler has been initialized, you can calculate the visibility between any point on the light and the point being shaded by using: The value of pointOnLight depends on the type of light we are sampling. If the light is parallel, then pointOnLight needs to be in the local light coordinates. If the light is not parallel, then pointOnLight needs to be in camera coordinates. - - - - - Description: - This class is used to generate a Shadow Buffer which may be used to determine if a point is in shadow or not. The 3ds Max shadow maps use this object internally, for example. - - There is a global function that creates one of these objects. With one of these developers can call its Render() method to generate (render) a Shadow Buffer. - - The rendered shadow buffer stores a Z distance at every point in the buffer. This can then be used to determine if something is in shadow. To check a certain point you simply see if the Z value is behind the one in the buffer. That is, a shadow buffer tells one, from the point of view of a light, how far it is to the first object for each pixel in the buffer. If the Z point of the thing being shadowed is farther than (behind) the corresponding Z value in the buffer then the thing is in shadow. If it's closer than it is not in shadow. - - The main Render() method is typically called from the Update() method of class which is called on every frame to create a new shadow buffer. - - To use this class you basically do the following: - - Allocate an array of floating point values, one float for each point in the shadow buffer: - - buffer = new float[shadsize*shadsize]; - - Then create a default Shadow Buffer using the global function provided: - - ; - - Then you setup all the parameters for the view, etc prior to calling the Render() method to render the buffer. (These parameters are passed in to the ShadowGenerator::Update() method). - - int nRendered = sbr->Render(rc, RGC, buffer, parallel, shadsize, param, aspect, clipDist, ltDesc, worldToLight); - - You can check the return value to determine if any objects were intersected by the shadow volume. If none were, the shadow buffer can be freed. All methods of this class are implemented by the system. - - - - - Compute a shadow Z buffer for the current scene from the viewpoint of the light. NOTE: The computed shadow buffer has positive Z values as you go away from the light, which is the reverse of the 3ds Max coordinate system. - Parameters: - &rc - - The which is used for the progress bar API. - - *RGC - - Points to the RenerGlobalContext which is used to retireve information about the global rendering enviornment (to get an instance list). - - float *buf - - This is the buffer to render to. This is a pre-allocated array of floats (shadsize*shadsize). - - BOOL parallel - - The projection type. TRUE if parallel projection; FALSE if perspective projection. - - int shadsize - - The size of the buffer (shadsize by shadsize pixels). - - float param - - The view parameter. For a perspective this is the:field-of-view (in radians). For a parallel view this is the width in world coordinates. - - float aspect - - This is the aspect ratio of the buffer projection. - - float clipDist - - The clipping distance. This tells the shadow buffer renderer to not consider objects farther than this distance from light. - - *ltDesc - - This is the descriptor for light that was passed in to CreateShadowGenerator(). - - worldToLight - - The world to light transformation matrix for the light. - Returns the number of objects that the shadow volume intersected. If this value is 0, the shadow buffer can be freed to save memory. - - - - - After a render, this method returns the farthest Z in the shadow buffer. - - - - - After a render, this method returns the closest Z in the shadow buffer. - - - - - Description: - This class has a method used for retrieving other shapes in the current editing context. This class provides a way for the BezierShape::PerformTrimOrExtend method to access the shapes being trimmed. - - - - - This method will be called with a pointer; the function should return the shape for that context. This is only used in modifier applications, where more than one shape object is being modified. See /MAXSDK/SAMPLES/MODIFIERS/EDITSPL.CPP for an example of its use. - Parameters: - *context - - Points to the for the shape the modifier is applied to. - A pointer to the for the context. - - - - - Description: - This class stores the hierarchy tree of a shape object. In addition it stores a with an entry for each polygon in the shape which indicates whether that polygon should be reversed in order to provide the proper clockwise/counterclockwise ordering for the nested shapes. All methods of this class are implemented by the system. - Data Members: - hier; - - Describes the hierarchy. - - reverse; - - Indicates whether that polygon should be reversed in order to provide the proper clockwise / counterclockwise ordering for the nested shapes. There is one bit in the bit array for every polygon in the shape. For example, if you pass in two nested circles and they are both clockwise, the outermost circle will have its reverse bit set to indicate it should be reversed in order to be properly extruded or lofted. This is because for nested shapes the outermost circle should be counterclockwise. - - - - - This methods clears out the hierarchy, sets the number of polygons to poly and clears all the bits in the . - Parameters: - int polys = 0 - - The number of polygons in the hierarchy. - Operators: - - - - - Assignment operator. - Parameters: - &from - - The source shape hierarchy. - - - - - Description: - This is a storage class for hit records used in hit testing to know which specific shape object was hit. When this data is logged with the system, the memory is owned and freed by the System. - Data Members: - *shape; - - The shape that was hit. - - int poly; - - The polygon of the shape that was hit. - - int index; - - The index of the sub-object entity that was hit. - - - - - Description: - This class provides a storage and access mechanism for a named vertex selection clipboard. - Data Members: - MSTR name; - - The name of the clipboard. - - <ShapePSel*> sets; - - This table stores the selection data for the clipboard. - - - - - Description: - This class provides a storage and access mechanism for a named segment selection clipboard. - Data Members: - MSTR name; - - The name of the clipboard. - - <ShapeSSel*> sets; - - This table stores the selection data for the clipboard. - - - - - Description: - This class provides a storage and access mechanism for a named vertex selection clipboard. - Data Members: - MSTR name; - - The name of the clipboard. - - <ShapeVSel*> sets; - - This table stores the selection data for the clipboard. - - - - - ShapeObjects are open or closed hierarchical shapes made up of one or more pieces. This base class defines a set of methods that plug-in shapes must implement. Note: Many plug-in shapes may be derived from Class rather than this class and have fewer methods to implement. See that class for more details. Any classes subclassing off of should be sure to call the constructor in their constructor, in order to properly initialize the fields contained in the . This is the thickness field, which specifies the thickness of the mesh generated from the shape at rendering time. For example: Also, the contains Load and Save methods, which handle the storage of the data contained within the . In order to properly store this information, classes which subclass off of need to call the Load and Save methods before storing their information. For example: The number of references/subanims are defined as SHAPE_OBJ_NUM_REFS and SHAPE_OBJ_NUM_SUBS in /include/object.h and are set to the number of references and subanims in the class, you can use them to make your code more bullet-proof should the number of references change in the future. See maxsdk/include/splshape.h for an example of how they can be used. - - - - - - In order to simplify things for subclasses of , this method is now available. It should be called whenever the ShapeObject-based object is copied. It takes care of copying all the data to the from another ShapeObject-based object Implemented by the System. - - The to copy from. - - - - Implemented by the System. Returns the shape's thickness setting. - - The time to obtain the thickness. - The validity interval. - - - - This method returns the number of sides for the cross-section of the rendering mesh version of the shape for the specified time. - - The time to obtain the thickness. - The validity interval. - - - - This method returns the angle that the cross-section of the rendering mesh will be rotated to, for the specified time. - - The time to obtain the thickness. - The validity interval. - - - - This method returns the thickness of the viewport version of the rendering mesh. This is not an animated parameter. - - - - - This method returns the number of sides for the cross-section for the viewport version of the rendering mesh. This is not an animated parameter. - - - - - This method returns the angle that the cross-section of the viewport version of the rendering mesh will be rotated to. This is not an animated parameter. - - - - - Implemented by the System. The class now has a "renderable" flag contained within it. Access to this is via this method and SetRenderable(). If this is set to TRUE and the node is set to renderable, the spline will be rendered. This defaults to FALSE. - - - - - Implemented by the System. Returns TRUE if the generate UVs switch is on; FALSE if off. - - - - - This method returns TRUE if the "Display Render Mesh" switch is on. FALSE when the switch is off. - - - - - This method returns TRUE if the "Use Viewport Settings" switch is on. FALSE when the switch is off. - - - - - This method returns the value of the Viewport/Render switch and either returns GENMESH_VIEWPORT or GENMESH_RENDER. - - - - - Implemented by the System. Sets the thickness setting of the shape to the specified value. - - The time at which to set the thickness. - The new thickness setting for the shape. - - - - This method allows you to set the number of sides for the rendering mesh version of the shape for the specified time. The allowable ranges for this parameter are 3-100. - - The time at which to set the number of sides. - The number of sides you wish to set. - - - - This method allows you to set the cross-section rotation angle for the rendering mesh version of the shape, in degrees, for the specified time. - - The time at which to set the angle. - The angle you wish to set, in degrees. - - - - Returns information on the rendering mesh. Implemented by the System. - - The time to get the information. - The node associated with the mesh. - Describes properties of the view associated with the render. See Class . - The number of vertices in the render mesh. - The number of faces in the render mesh. - - - - This method will generate a mesh based on either the viewport or rendering parameters for the specified time. - - The time at which to generate the mesh. - The option can be either GENMESH_VIEWPORT, GENMESH_RENDER, or GENMESH_DEFAULT. When using the default definition the mesh generator will use whatever is in the Viewport/Render switch in the parameter block. - A pointer to a object. If this is set to NULL, the mesh will be generated and cached, but not returned. - - - - This method is used by the Summary Info and Properties dialogs to inform the user how many vertices or CVs are in the object. The method is passed a TimeValue and a curve index; if the curve index is <0, the function should return the number of vertices/CVs in the entire shape. Otherwise, it should return the number of vertices/CVs in the specified curve. - - The time at which the number of vertices is to be computed. - The curve index. See note above. - - - - Returns the number of polygons in the shape at the given time - the number of polygons in the shape. - - The time to check. - - - - This method is called to determine if the specified curve of the shape is closed at the time passed. - TRUE if the curve is closed; otherwise FALSE. - - The time to check. - The index of the curve to check. - - - - This method returns a point interpolated on the entire curve. This method returns the point but you don't know which segment the point falls on. See method InterpPiece3D(). - The interpolated point on the curve. - - The time to evaluate. - The index of the curve to evaluate. - The 'distance' along the curve where 0 is the start and 1 is the end. - The parameter type for spline interpolation. See . - - - - This method returns a tangent vector interpolated on the entire curve. Also see method TangentPiece3D(). - The tangent vector - - The time at which to evaluate the curve. - The index of the curve to evaluate. - The 'distance' along the curve where 0.0 is the start and 1.0 is the end. - The parameter type for spline interpolation. See . - - - - Returns the length of the specified curve. Note: This method makes no allowance for non-uniform scaling in the object transform. To do that, see the following code fragment (os is the with the shape object and xfm is the NodeTM of the shape object node). - - The time at which to compute the length. - The index of the curve. - - - - Returns the number of sub-curves in a curve. - - The time at which to check. - The index of the curve. - - - - This method returns the interpolated point along the specified sub-curve (segment). For example consider a shape that is a single circle with four knots. If you called this method with curve=0 and piece=0 and param=0.0 you'd get back the point at knot 0. If you passed the same parameters except param=1.0 you'd get back the point at knot 1. - The point in world space. - - The time to evaluate the sub-curve. - The curve to evaluate. - The segment to evaluate. - The position along the curve to return where 0.0 is the start and 1.0 is the end. - The parameter type for spline interpolation. See . - - - - Returns the tangent vector on a sub-curve at the specified 'distance' along the curve. - The tangent vector. - - The time to evaluate the sub-curve. - The curve to evaluate. - The sub-curve (segment) to evaluate. - The position along the curve to return where 0 is the start and 1 is the end. - The parameter type for spline interpolation. See . - - - - This method provides access to the material IDs of the shape. It returns the material ID of the specified segment of the specified curve of this shape at the time passed. There is a default implementation so there is no need to implement this method if the shape does not support material IDs. Note: typedef unsigned short MtlID; - - The time to evaluate the sub-curve. - The zero based index of the curve to evaluate. - The sub-curve (segment) to evaluate. - - - - This method is called to determine if the shape can be converted to a bezier representation. - TRUE if the shape can turn into a bezier representation; otherwise FALSE. - - - - - Creates the bezier representation of the shape. - - The time to convert. - The bezier representation is stored here. - - - - This method is called to prepare the shape for lofting, extrusion, etc. This methods looks at the shape organization, and puts together a shape hierarchy. This provides information on how the shapes are nested. - - The time to organize the curves. - This class provides information about the hierarchy. See Class . - - - - Create a representation with optional fixed steps. - - The time to make the . - The representation is stored here. - The number of steps between knots. Values >=0 indicates the use of fixed steps: PSHAPE_BUILTIN_STEPS Use the shape's built-in steps/adaptive settings (default). PSHAPE_ADAPTIVE_STEPS Force adaptive steps. - If TRUE intermediate steps are removed from linear segments. - - - - This method generates a mesh capping info for the shape. - Nonzero if the cap info was generated; otherwise zero. - - The time to create the cap info. - The cap info to update. - See . - - - - This method creates a patch cap info out of the shape. Only implement this method if CanMakeBezier() returns TRUE. - Nonzero if the cap info was generated; otherwise zero. - - The time to create the cap info. - The cap info to update. - - - - This method is called to attach the shape of attachNode to thisNode at the specified time. If any endpoints of the curves in the shape being attached are within the threshold distance to endpoints of an existing curve, and the weld flag is TRUE, they should be welded. - Return TRUE if attached; otherwise FALSE. - - The time to attach. - This is the node associated with this shape object. - The node of the shape to attach. - If TRUE the endpoints of the shape should be welded together (based on the threshold below). If FALSE no welding is necessary. - If any endpoints of the curves in the shape being attached are within this threshold distance to endpoints of an existing curve, and the weld flag is TRUE, they should be welded - - - - This method returns the parameter dimension of the parameter whose index is passed. - Pointer to a . - - The index of the parameter to return the dimension of. - - - - This method returns the name of the parameter whose index is passed. - - The index of the parameter to return the dimension of. - If true, then the parameter name returned should be localized in the language 3ds is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - - - - This method gets the validity interval for the 's internal parameters only. It DOES NOT include those of the derived classes. So, if you called this method on a that was a circle with an animated radius, you wouldn't see the effect of the animated radius on the interval - - - - - This method returns a bounding box for the shape, if it's active, if the "Display Render Mesh" switch is on. It is necessary to include this box when computing the bounding box for a shape, otherwise the viewport display will not work properly. - - The time to get the bounding box. - The points of are transformed by this matrix prior to the bounding box computations. - - - - This method is very important - It causes the to flush its cached rendering mesh. Most objects have their own "InvalidateGeomCache" methods; simply call this when a shape derived from changes and it will ensure that the rendering mesh is regenerated the next time it is evaluated. Failure to call this method will result in improper rendering mesh updates. - - - - - Queries whether if real world texture size is used or not. - - - - - Queries the twist correction switch. - - - - - Queries the main capping switch. - - - - - Queries the quad capping switch. - - - - - Get/Set the cap segments count. This value is used for quad capping and allowable ranges are from 1 to 200 Queries the cap segments value at the specified time. - - The time at which to obtain the segment count. - The validity interval. - - - - Sets the cap segments value for the specified time. - - The time at which to set the segment count. - The count you wish to set. - - - - Get/Set the sphere capping value used in quad capping. Range is 0 (flat cap) to 1 (spherical). Queries the sphere cap value. - - The time at which to obtain the segment count. - The validity interval. - - - - Sets the sphere capping value (0-1). - - The time at which to set the sphere amount. - The value you wish to set. - - - - Description: - This class stores and provides access to shape polygon (spline) selection data. All methods of this class are implemented by the system. - Data Members: - int polys; - - The number of splines in the shape. - - sel; - - One bit for each spline in the shape. - - - - - Assignment operator. - - - - - Resizes the sel to include a new bit at the specified location. - Parameters: - int where - - The location for the new bit in the . - - - - - Deletes the specified bit from the . - Parameters: - int where - - Indicates which bit to delete. - - - - - Sets the number of splines and resizes the based on the shape passed. - Parameters: - & shape - - The shape whose splines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - Sets the number of splines and resizes the based on the shape passed. - Parameters: - & shape - - The shape whose lines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - Sets the bit specified by the index to 1. - Parameters: - int index - - The bit to set. - - - - - Sets the bit specified by the index to the value passed. - Parameters: - int index - - The bit to set or clear. - - int value - - The value to set, either 0 or 1. - - - - - Clears the bit specified by the index to 1. - Parameters: - int index - - The bit to clear. - - - - - access operator. - - - - - Clears all the bits in the array (sets them to 0). - - - - - Sets the size of sel to 0. - - - - - Saves the to disk. - - - - - Loads the from disk. - Operators: - - - - - Delete multiple entries at once. - - - Deleting multiple entries at once is faster than deleting one by one by calling Delete(), because the internal bookkeeping only needs to be done once. - false if any of the vertex indices are invalid. - - Pointer to an array of indices to delete. Indices should be unique, and sorted in ascending order. - of entries in the indices array. - - - - Description: - This class contains a hit record for sub-shape hit testing. All methods of this class are implemented by the system. - Data Members: - DWORD dist; - - The distance of the hit. If the user is in wireframe mode, this is the distance in pixels to the item that was hit. If the user is in shaded mode, this is the Z depth distance. Smaller numbers indicate a closer hit. - - BezierShape* shape; - - The shape that was hit. - - int poly; - - The polygon that was hit. - - int index; - - The index of the sub-object component that was hit. - - - - - Returns the next sub hit record. - - - - - Description: - This class stores and provides access to shape segment selection data. All methods of this class are implemented by the system. - Data Members: - int polys; - - The number of splines in the shape. - - *sel; - - An array of BitArrays, one for each spline. - - - - - Assignment operator. - - - - - Creates and inserts a new into sel. - Parameters: - int where - - The index into sel indicating where to insert the new . - - int count=0 - - The number of bits in the new . - - - - - Deletes the specified from the sel list. - Parameters: - int where - - The index into sel indicating which to delete. - - - - - Sets the number of splines and allocates the corresponding number of BitArrays based on the shape passed. The size of each is set to the number of segments in each polyline. - Parameters: - & shape - - The shape whose splines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - Sets the number of splines and allocates the corresponding number of BitArrays based on the shape passed. The size of each is set to the number of segments in each spline. - Parameters: - & shape - - The shape whose lines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - Clears every bit for every poly. - - - - - Sets the size of every poly to 0. - - - - - Saves the to disk. - - - - - Loads the from disk. - Operators: - - - - - Delete multiple entries at once. - - - Deleting multiple entries at once is faster than deleting one by one by calling Delete(), because the internal bookkeeping only needs to be done once. - false if any of the vertex indices are invalid. - - Pointer to an array of indices to delete. Indices should be unique, and sorted in ascending order. - of entries in the indices array. - - - - Description: - This class stores and provides access to shape vertex selection data. All methods of this class are implemented by the system. - Data Members: - int polys; - - The number of splines in the shape. - - *sel; - - An array of BitArrays, one for each spline. - - - - - Assignment operator. - - - - - Creates and inserts a new into sel. - Parameters: - int where - - The index into sel indicating where to insert the new . - - int count=0 - - The number of bits in the new . - - - - - Deletes the specified from the sel list. - Parameters: - int where - - The index into sel indicating which to delete. - - - - - Sets the number of splines and allocates the corresponding number of BitArrays based on the shape passed. The size of each is set to the number of vertices in each polyline. - Parameters: - & shape - - The shape whose splines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - - - Sets the number of splines and allocates the corresponding number of BitArrays based on the shape passed. The size of each is set to the number of vertices in each spline. - Parameters: - & shape - - The shape whose lines determine the sizes set. - - BOOL save=FALSE - - TRUE to keep the previous contents. FALSE to discard it. - - - - - Clears every bit for every poly. - - - - - Sets the size of every poly to 0. - - - - - Saves the to disk. - - - - - Loads the from disk. - Operators: - - - - - Delete multiple entries at once. - - - Deleting multiple entries at once is faster than deleting one by one by calling Delete(), because the internal bookkeeping only needs to be done once. - false if any of the vertex indices are invalid. - - Pointer to an array of indices to delete. Indices should be unique, and sorted in ascending order. - of entries in the indices array. - - - - This is the exception that is thrown if the user breaks execution by pressing and holding the escape key. - - - - - Description: - The class provides a framework for implementing many common manipulators. It provides the following services: - - It supports an arbitrary number of gizmos made from and/or objects. - - It creates and maintains tool tips in the viewport. - - It does hit testing, display and bounding box computations of the gizmos. - - It maintains an for the parameters of the . - - This class maintains a pointer to a parameter block. If the client of uses a single parameter block then can manage all the methods associated with SubAnims and References for the client. - - If the client of maintains several parameter blocks then the client must implement the methods NumSubs(), GetReference(i) and SetReference(i) and call the methods when 'i' refers to the parameters maintained by . - - Samples of Manipulators can be found in the SDK, /MAXSDK/SAMPLES/MANIPULATORS. - - The Function Publishing interface to SimpleManipulators is defined as: - - #define SIMPLE_MANIP_INTERFACE - - The following functions are not part of this class but are available for use with it in the making of gizmo objects: - - - - - Implemented by the system. - - This method allows you to set the scale of the gizmo. - Parameters: - float gizmoScale - - The scale factor. - - - - - Implemented by the system. - - This method returns the tooltip string. Used internally. - Default Implementation: - { return mToolTip; } - - - - - Implemented by the system. - - Used internally. - - - - - Implemented by the system. - - Used internally. - - - - - Implemented by the system. - - This method returns a pointer to the parameter block. - Default Implementation: - { return mpPblock; } - - These must be implemented in the sub-class of - - - - - Implemented by the system. - - Used internally. - Default Implementation: - {} - - - - - This method returns the handle to the manipulator reference target. - Default Implementation: - { return mhTarget; } - - - - - - - This method sets the state of the mouse. - Parameters: - MouseState state - - One of the following values: - - kMouseIdle - - The mouse is idle, manipulator not active and the mouse is not over it. - - kMouseDragging - - The mouse is currently dragging the manipulator. - - kMouseOverManip - - The mouse is over the manipulator, but it is not being dragged. - Default Implementation: - { mState = state; } - - - - - Implemented by the system. - - This method returns the position of the tooltip. Used internally. - Default Implementation: - { return mToolTipPos; } - - - - - This method invalidates the validity interval. - Default Implementation: - { mValid = NEVER; } - - - - - This method unregisters the notifications so changes in the view are no longer registered. - - - - - Used internally. - - - - - This method will destroy the tooltip and its timer and cleans up. - - - - - This method returns the color of the gizmo when unselected. - - - - - This method returns the number of gizmos defined. - - - - - This method returns the specified gizmo. - - - - - Description: - This is a special storage class for hit records that keep track of which manipulator was hit and is provided as a simple class for developers to sub-class from. - - - - - Base class for parameter block 1 (PB) based object space modifiers. - - - Description: - This class maintains a pointer to a parameter block. Derived classes that use a single parameter block don't need to overwrite methods for managing sub-anims and references since 's implementation of the respective methods takes care of this. - - This is a base class that is intended to be derived from, rather than be instantiated directly. - - It manages the same references as class , but adds a param block reference. - - Typically, 3rd party modifiers that derive from class would derive preferably from class in order to benefit from the features of ParameterBlock2 (see class ). - - For more information see class . - - - - - When clients are cloning themselves, they should call this method on the clone to copy 's data. Note that this method clones the paramblock and calls SimpleModBase::SimpleModBaseClone. - Parameters : - *smodSource - - Specifies the that is being cloned. - - & remap - - The . - - - - - Returns the dimension of the parameter whose index is passed. See Class . - Parameters: - int pbIndex - - The index of the parameter. - Default Implementation: - {return defaultDim;} - A pointer to the dimension of the parameter. - - - - - Returns the name of the parameter whose index is passed. - Parameters: - int pbIndex - - Index of the parameter. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - Default Implementation: - {return MSTR(_M("Parameter"));} - The name of the parameter. - - - - - Base class for parameter block 2 (PB2) based object space modifiers. - - - Description: - This class maintains a pointer to a parameter block 2. Derived classes that use a single parameter block 2 don't need to overwrite methods for managing sub-anims and references since 's implementation of the respective methods takes care of this. - - This is a base class that is intended to be derived from, rather than be instantiated directly. - - It manages the same references as class , but adds a param block 2 reference. - - For more information see class . - - - - - When clients are cloning themselves, they should call this method on the clone to copy 's data. Note that this method clones the paramblock and calls SimpleModBase::SimpleModBaseClone. - Parameters : - *smodSource - - Specifies the that is being cloned. - - & remap - - The . - - - - - Base class for object space modifiers. - - - Description: - The class supplies most of the methods needed to implement an object space modifier. - - This is a base class that is intended to be derived from, rather than be instantiated directly. - - Modifiers that have only one parameter block (see class ) should derive from class . - - To be a 'Simple' modifier, the following assumptions are made: - - The modifier only modifies the geometry channel. - - The modifier uses an instance of a class derived from to do the modifying. - - The modifier's gizmo is represented as a 3D box that has had the modifier applied to it. - - Derived classes that maintains several parameter blocks must overwrite the methods NumSubs(), GetReference(i) and SetReference(i) and call the methods when 'i' refers to the parameters maintained by . - - When objects derived from are cloning themselves, they should call this method on the clone to copy 's data: - - SimpleModBaseClone(SimpleModBase *smodSource, RemapDir& remap); - - Classes derived from probably want to override these. If they do, they should call these from within their implementation of these methods. - - BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev); - - EndEditParams(IObjParam *ip, ULONG flags,Animatable *next); - Data Members: - *tmControl; - - Points to the transform controller for the Gizmo. - - *posControl; - - Points to the position controller for the Center. - - *ip; - - Storage for the interface pointer. - - *moveMode; - - Storage for the move modifier box command mode. - - *rotMode; - - Storage for the rotate modifier box command mode. - - *uscaleMode; - - Storage for the uniform scale modifier box command mode. - - *nuscaleMode; - - Storage for the non-uniform scale modifier box command mode. - - *squashMode; - - Storage for the squash modifier box command mode. - - *editMod; - - Storage for the instance of that is being edited in the command panel. - - - - - When clients are cloning themselves, they should call this method on the clone to copy 's data. - Parameters: - *smodSource - - Specifies the that is being cloned. - - & remap - - The . - - - - - This method is used to retrieve the callback object that will handle the deformation. - Parameters: - TimeValue t - - Specifies the time the modification is being performed. - - &mc - - A reference to the . - - & mat - - A reference to a matrix that describes the space the modification is supposed to happen in. This is computed from the matrix and the controllers controlling the gizmo and center of the modifier. The plug-in developers job is simply to transform each point to be deformed by this matrix before it performs its own deformation to the point. After the modifier applies its own deformation to the point, the developer transforms the point by the inverse of this matrix (passed below). - - & invmat - - This is the inverse of the matrix above. See the comment above for how this is used. - A C++ reference to the deformer callback object. - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - Example: - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: pmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - - - - - The class calls this method to retrieve the validity interval of the modifier. The modifier provides this interval by starting an interval at FOREVER and intersecting it with each of its parameters validity intervals. - Parameters: - TimeValue t - - The time to compute the validity interval. - Default Implementation: - {return FOREVER;} - The validity interval of the modifier. - - - - - - - If the effect can be limited (like the way bend/taper/twist/etc. can be limited) then it should specify the min and max limits and the axis that it is limited along. will then display the limits as part of the Gizmo. If it does not support limits then it should return FALSE or simply not implement this method. - Parameters: - TimeValue t - - The time to get the limits. - - float &zmin - - The min limit. - - float &zmax - - The max limit. - - int &axis - - The axis that it is limited along: x=0, y=1, z=2. - TRUE if limits are supported; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - Description: - This class adds parameter block 1 system support to the class. It has a public data member *pblock instead of the *pblock2 provided by . It also provides implementations of ReferenceMaker::GetReference() and SetReference() which get and set the pblock pointer. It is highly recommended that plugin classes not derive from , rather that they derive from . The class will be deprecated in a future version of 3ds Max. - Data Members: - IParamBlock* pblock; - - Points to the ParamBlock instance used by this class. This is the only reference maintained by the class. - - - - - This method returns the parameter dimension of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the dimension of. - Pointer to a . - Example: - return stdNormalizedDim; - Default Implementation: - The default implementation returns defaultDim. - - - - - - - This method returns the name of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the name of. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - The name of the parameter. - Default Implementation: - The default implementation returns MSTR(_M("Parameter")) - - - - - Description: - This class adds parameter block 2 system support to the class. It has a public data member *pblock2 instead of the *pblock provided by . It also provides implementations of ReferenceMaker::GetReference() and SetReference() which get and set the pblock2 pointer. - Data Members: - IParamBlock2* pblock2; - - Points to the ParamBlock2 instance used by this class. This is the only reference maintained by the class. - - - - - Description: - This is a base class for creating procedural objects. This class implements many of the methods required to create a procedural object. The only limitation for a procedural object using as a base class is that it must represent itself with a mesh. - Data Members: - Note: Methods of the base class refer to these data members. For example the base class implementations of the bounding box methods use the mesh data member. Therefore the plug-in derived from must use these same data members. - - mesh; - - The mesh object that is built by BuildMesh(). - - ivalid; - - The validity interval for the mesh. This interval is used to determine how BuildMesh() is called. If this interval is not set BuildMesh() will be called over and over as the system won't know when the mesh is valid or not. Make sure you set this interval to accurately reflect the validity interval for the mesh. - - BOOL suspendSnap; - - If TRUE, this causes no snapping to occur. This is commonly used to prevent an object from snapping to itself when it is creating. For example, in the mouse proc used to create an object, the following code is often used when snapping mouse points: - - ob->suspendSnap = TRUE; - - p0 = vpt->SnapPoint(m,m,nullptr,SNAP_IN_PLANE); - - This disables snapping temporarily to keep the object from snapping to itself. - - Procedural plug-ins which subclass off must implement these methods. The default implementations are noted. - - - - - This method is called to build the mesh representation of the object using its parameter settings at the time passed. The plug-in should use the data member mesh to store the built mesh. - Parameters: - TimeValue t - - The time at which to build the mesh. - - - - - This method returns a BOOL to indicate if it is okay to draw the object at the time passed. Normally it is always OK to draw the object, so the default implementation returns TRUE. However for certain objects it might be a degenerate case to draw the object at a certain time (perhaps the size went to zero for example), so these objects could return FALSE. - Parameters: - TimeValue t - - The time at which the object would be displayed. - Default Implementation: - { return TRUE; } - TRUE if the object may be displayed; otherwise FALSE. - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - Example: - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: If the plug-in uses ParamBlock2, it may call a method on the to handle this: If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers: - - - - - Description: - This class is used by class to help create World Space Modifiers out of Space Modifiers. - - - - - - - Description: - This class is used to allow any Space derived from to easily be turned into a World Space (Space Warp). - - This is very simple to do because a modifier version already contains just about everything that needs to be done. This is because the modifier works the same - it is just in world space instead of object space. - - All a developer needs to do to turn their modifier into the WSM version is implement a class derived from this one and call the SimpleOSMTOWSMObject constructor from their constructor. See the sample code below (for the full sample code using this class see /MAXSDK/SAMPLES/MODIFIERS/BEND.CPP). - - These new modifier-based space warps are accessed in the drop-down category list of the Space Warps branch of the Create command panel. Choose Modifier-Based from the list to display buttons for each of the new space warps. - Data Members : - *mod; - - Points to the instance this is based on. - - *pmapParam; - - Points to the parameter map used to handle the user interface for this WSM. These are the parameter block indices for the pmap : - - - - - - - Implemented by the System. - - This class enhances the deformation done by the object space modifier to include a decay parameter. This allows the deformation to decay over distance. This helper method is used internally in this. - - - - - Description: - This class provides a base class from which you may derive Particle System plug-ins. This class may be used by particle systems that fit within its form. The form is primarily dictated by the data members maintain by the class. The class maintains an instance of class that describes the particles. It also has a table of force fields and collision objects. The emitter for the particles is represented by a mesh. There is also a parameter block pointer available. - - Particle system plug-ins that don't fit this form may derive from a base class without any constraints. See Class for more details. - Data Members: - *pblock; - - The parameter block pointer. - - parts; - - This is a description of the particles themselves (their count, position, velocities, ...). - - TimeValue tvalid; - - A particle system derived from is valid at a particular time only (it does not have a validity interval). It is assumed to be always changing. This data member holds the time at which it is valid (when valid is TRUE). - - BOOL valid; - - This flag indicates if the particle system is valid. If TRUE, tvalid should contain the time it is valid for. - - <ForceField*> fields; - - The table of force fields affecting the particles. - - <CollisionObject*> cobjs; - - The table of collision objects affecting the particles. - - mesh; - - The mesh object that represents the emitter. - - mvalid; - - The validity interval for the emitter mesh. If the mesh is invalid BuildEmitter() will be called. - - *editOb; - - The object that is being edited between BeginEditParams() and EndEditParams(). - - *ip; - - Storage for the interface pointer passed into BeginEditParams(). This pointer is only valid between BeginEditParams() and EndEditParams(). - - - - - This method is available in release 3.0 and later only. - - Sets the position of the specified particle at the specified time. - Parameters: - TimeValue t - - The time at which to set the particle position. - - int i - - The zero based index of the particle to set. - - pos - - The position to set. - - - - - This method is available in release 3.0 and later only. - - Sets the velocity of the specified particle at the specified time (in 3ds Max units per tick). - Parameters: - TimeValue t - - The time at which to set the particle velocity. - - int i - - The zero based index of the particle to set. - - vel - - The velocity to set. - - - - - This method is available in release 3.0 and later only. - - Sets the age of the specified particle at the specified time. - Parameters: - TimeValue t - - The time at which to set the particle age. - - int i - - The zero based index of the particle to set. - - TimeValue age - - The age to set. - - - - - This method is called so the particle system can update its state to reflect the current time passed. This may involve generating new particle that are born, eliminating old particles that have expired, computing the impact of collisions or force field effects, and modify the positions and velocities of the particles. - Parameters: - TimeValue t - - The particles should be updated to reflect this time. - - *node - - This is the emitter node. Particles system are world space objects so they are not instanced. This means that the particle system can depend on the node's world space position. - Sample Code: - For example code see /MAXSDK/SAMPLES/OBJECTS/RAIN.CPP. - - - - - This method is called to allow the plug-in to provide a representation of its emitter in the 3D viewports. - Parameters: - TimeValue t - - Specifies the time to build the emitter. - - & amesh - - Store the built mesh representation here. - - - - - This method is called to retrieve the validity time of the particle system emitter. - Parameters: - TimeValue t - - The time to compute the validity interval. - The validity interval of the particle system emitter at the specified time. - - - - - Returns one of the defined marker types to use when displaying particles. - One of the following values: - - See the MarkerType enum. - Default Implementation: - {return POINT_MRKR;} - - - - - This method is called to determine if the particle emitter is okay to display at the specified time. If at certain times it is not okay to display this method should return FALSE. This might occur if a size goes to 0. Normally however it is always okay to display so the default implementation returns TRUE. - Parameters: - TimeValue t - - The time to display the emitter. - TRUE if it is okay to display, FALSE otherwise. - Default Implementation: - {return TRUE;} - - - - - This method is called to determine if the particle emitter is visible in the viewports. If the plug-in provides a UI control to toggle the emitter on and off, this method should return the state of this control. - TRUE if the emitter is visible; otherwise FALSE. - Default Implementation: - {return TRUE;} - - - - - It is important the user interface controls display values that reflect the current time. This method is called if the user interface parameters needs to be updated because the user moved to a new time. - Example: - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: pmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - *pblock). - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - - - - - This method returns the parameter dimension of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the dimension of. - Pointer to a . - Example: - return stdNormalizedDim; - Default Implementation: - The default implementation returns defaultDim. - - - - - - - This method returns the name of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the name of. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - The name of the parameter. - Default Implementation: - The default implementation returns MSTR(_M("Parameter")) - - - - - This is a base class for creating procedural objects compatible with Editable Poly. This class implements many of the methods required to create a procedural object. The only limitation for a procedural object using as a base class is that it must represent itself with an . These objects allow non-triangular faces and support edge and vertex creasing for OpenSubdiv and other subdivision systems. - - Procedural plug-ins which subclass off must implement some methods. These are noted, as are default implementations of other methods. - - Note: Methods of the base class refer to the protected data members. For example the base class implementations of the bounding box methods use the polyMesh data member. Therefore the plug-in derived from must use these same data members. - - - - - This method is called to build the mesh representation of the object using its parameter settings at the time passed. The plug-in should use the data member polyMesh to store the built mesh. - - This method must be implemented by the derived class. - - - The time at which to build the mesh. - - - - This method returns a BOOL to indicate if it is okay to draw the object at the time passed. Normally it is always OK to draw the object, so the default implementation returns TRUE. However for certain objects it might be a degenerate case to draw the object at a certain time (perhaps the size went to zero for example), so these objects could return FALSE. - TRUE if the object may be displayed; otherwise FALSE. - - - The time at which the object would be displayed. - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - - - - - This method returns the random number sign, either -1 or 1. - - - - - This method return a random number between 0.0f and 1.0f. - - - - - This method return a random number between -1.0f and 1.0f. - - - - - This method return a random number between -0.5f and 0.5f. - - - - - This method return a random number between 0 and maxnum. - - - - - Description: - This class defines a simple shape object to make procedural shape primitives easier to create. For example, the 3ds Max Helix plug-in is derived from this class. There are a set of mandatory and optional methods to implement. - - Revised for 3ds Max 2.0 SimpleShape-based objects have a new 'General' rollup, which contains renderable shape options: Renderable checkbox, Thickness spinner, and a Mapping coords checkbox. These are supported automatically. To support the new features of the renderable splines, the derived class of needs to work with a few new methods - see SimpleShapeClone() and ReadyGeneralParameters() below for details. - Data Members: - *pblock; - - The parameter block for managing the shape's parameters. - - *ip; - - This data member is available in release 2.0 and later only. - - This is the interface pointer stored by the class. - - static HWND hGenParams; - - This data member is available in release 2.0 and later only. - - The window handle to the 'General' rollup. - - static BOOL dlgRenderable; - - This data member is available in release 2.0 and later only. - - The 'Renderable' flag in the 'General' rollup. - - static float dlgThickness; - - This data member is available in release 2.0 and later only. - - The 'Thickness' setting in the 'General' rollup. - - static BOOL dlgGenUVs; - - This data member is available in release 2.0 and later only. - - The 'Generate Mapping Coords' flag in the 'General' rollup. - - shape; - - The shape cache. - - ivalid; - - The validity interval for the shape cache. - - BOOL suspendSnap; - - A flag to suspend snapping used during the creation process. - - *editOb; - - The shape that is currently being edited in the command panel. - - *thickSpin; - - Points to the spinner control used for the thickness parameter. - - - - - This method is available in release 2.0 and later only. - - To support the new features of the renderable splines, in the derived class's constructor, call ReadyGeneralParameters(). This will set up the general parameters in the base class to the proper defaults. Failure to make this call will cause SimpleShape-based objects to be created with default general parameters rather than those of the previously-created object. - - - - - This method is available in release 2.0 and later only. - - To support the new features of the renderable splines, the derived class of needs to, in the Clone method, call this method. This will insure that the base class parameters are copied to the cloned object. Failure to make this call will cause cloned SimpleShape-based objects to revert to the default rendering parameters. - Parameters: - *sshpSource - - The source shape for the clone. - - - - - This method is called to build the shape at the specified time and store the result into the passed. - Parameters: - TimeValue t - - The time to build the shape. - - & ashape - - The built shape is stored here. - - - - - This method indicates if the shape may be displayed at the time passed. At certain times, for certain shapes, the shape may not be in a displayable form. For example, the size of the shape may go to zero at a certain point and would be inappropriate to display. - Parameters: - TimeValue t - - The time to check. - TRUE if the shape may be displayed at the specified time; otherwise FALSE. - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: ipmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - *pblock). - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - Default Implementation: - {} - - - - - Description: - Defines a simple spline object class to make spline primitives easier to create. This class provides default implementations for most of the methods. The plug-in derived from must only implement a handful of methods to create a shape plug-in. - - plug-ins use a Super Class ID of SHAPE_CLASS_ID. - Data Members: - *ipblock; - - Interpolation parameter block (handled by ). - - *pblock; - - User's parameter block. See Class . - - *ipmapParam; - - The parameter map. See Class . - - static int dlgSteps; - - The dialog steps settings. - - static BOOL dlgOptimize; - - The dialog Optimize toggle. - - static BOOL dlgAdaptive; - - The dialog Adaptive toggle. - - shape; - - The Spline cache. - - ivalid; - - The validity interval for the spline. See Class . - - BOOL suspendSnap; - - Flag to suspend snapping used during creation. - - *editOb; - - This is the spline being edited in the command panel. - - - - - This method is called to build the shape at the specified time and store the results in ashape. - Parameters: - TimeValue t - - The time to build the shape. - - & ashape - - The created shape is store here. - - - - - Returns TRUE if it is okay to display the shape at the time passed; otherwise FALSE. Certain shapes may not want to be displayed at a certain time, for example if their size goes to zero at some point. - Parameters: - TimeValue t - - The time to check. - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: ipmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - *pblock). - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - - - - - Returns TRUE if the Simple Spline should display vertex ticks during its creation; otherwise FALSE. - Default Implementation: - { return TRUE; } - - - - - Description: - The class supplies most of the methods needed to implement a world space modifier. - - To be a 'Simple' WSM modifier, the following assumptions are made: - - The modifier only modifies the geometry channel. - - The modifier uses an instance of a class derived from to do the modifying. - - This class maintains a pointer to a parameter block. If the client of uses a single parameter block then can manage all the methods associated with SubAnims and References for the client. - - If the client of maintains several parameter blocks then the client must implement the methods NumSubs(), GetReference(i) and SetReference(i) and call the methods when 'i' refers to the parameters maintained by . - Data Members: - Clients of should use the following pointers when the references are created. - - protected: - - *pblock; - - Pointer to a parameter block. - - *obRef; - - Pointer to the world space modifier object referenced by the WSMModifier. - - *nodeRef; - - Pointer to the node in the scene referenced by the WSMModifier. - - *ip; - - Storage for the interface pointer. - - *editMod; - - Storage for the modifier currently being edited in the command panel. - - Clients of should use the following values as the reference indexes of the object, node and parameter block. - - - - - - - Implemented by the System. - - Evaluates the node reference and returns the WSM object. If you look in /MAXSDK/SAMPLES/HOWTO/MISC/SIMPMOD.CPP you'll see that all this method does is call EvalWorldState() on the Node reference. - Parameters: - TimeValue t - - The time to get the . - - - - - - - When clients are cloning themselves, they should call this method on the clone to copy 's data. - Parameters: - *smodSource - - Specifies the that is being cloned. - - & remap - - The . - - - - - This method is used to retrieve the callback object that will handle the deformation. - Parameters: - TimeValue t - - Specifies the time the modification is being performed. - - &mc - - A reference to the . - - & mat - - A reference to a matrix that describes the space the modification is supposed to happen in. This is computed from the matrix and the controllers controlling the gizmo and center of the modifier. The plug-in developers job is simply to transform each point to be deformed by this matrix before it performs its own deformation to the point. After the modifier applies its own deformation to the point, the developer transforms the point by the inverse of this matrix (passed below). - - & invmat - - This is the inverse of the matrix above. See the comment above for how this is used. - A C++ reference to the deformer callback object. - - - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - Example: - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: pmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - - - - - The class calls this method to retrieve the validity interval of the modifier. The modifier provides this interval by starting an interval at FOREVER and intersecting it with each of its parameters validity intervals. - Parameters: - TimeValue t - - The time to compute the validity interval. - Default Implementation: - {return FOREVER;} - The validity interval of the modifier. - - - - - - - Returns the dimension of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter. - Default Implementation: - {return defaultDim;} - The dimension of the parameter. - - - - - - - Returns the name of the parameter whose index is passed. - Parameters: - int pbIndex - - Index of the parameter. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - Default Implementation: - {return MSTR(_M("Parameter"));} - The name of the parameter. - - - - - Description: - This is the base class for creating space warp objects. This class implements many of the methods required to create a space warp object. The only limitation for a space warp object using as a base class is that it must represent itself with a mesh. - Data Members: - Note: Methods of the base class refer to these data members. For example the base class implementations of the bounding box methods use the mesh data member. Therefore the plug-in derived from must use these same data members. These are listed below: - - *pblock; - - Pointer to a parameter block. Clients of should use this pointer when the pblock reference is created. - - mesh; - - The mesh object that is built by BuildMesh(). - - ivalid; - - The validity interval of the mesh. - Space warp object plug-ins which subclass off must implement these methods. The default implementations are noted. - - - - - This method is called to build the mesh representation of the object using its parameter settings at the time passed. - Parameters: - TimeValue t - - The time at which to build the mesh. - - - - - This method returns a BOOL to indicate if it is okay to draw the object at the time passed. Normally it is always OK to draw the object, so the default implementation returns TRUE. However for certain objects it might be a degenerate case to draw the object at a certain time (perhaps the size went to zero for example), so these objects could return FALSE. - Parameters: - TimeValue t - - The time at which the object would be displayed. - Default Implementation: - { return TRUE; } - TRUE if the object may be displayed; otherwise FALSE. - - - - - This is called if the user interface parameters needs to be updated because the user moved to a new time. The UI controls must display values for the current time. - Example: - If the plug-in uses a parameter map for handling its UI, it may call a method of the parameter map to handle this: pmapParam->Invalidate(); - - If the plug-in does not use parameter maps, it should call the SetValue() method on each of its controls that display a value, for example the spinner controls. This will cause to the control to update the value displayed. The code below shows how this may be done for a spinner control. Note that ip and pblock are assumed to be initialized interface and parameter block pointers - - *pblock). - - float newval; - - valid=FOREVER; - - TimeValue t=ip->GetTime(); - - // Get the value from the parameter block at the current time. - - pblock->GetValue( PB_ANGLE, t, newval, valid ); - - the value. Note that the notify argument is passed as FALSE. - - // This ensures no messages are sent when the value changes. - - angleSpin->SetValue( newval, FALSE ); - - - - - This method returns the parameter dimension of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the dimension of. - Pointer to a . - Example: - return stdNormalizedDim; - Default Implementation: - The default implementation returns defaultDim. - - - - - - - This method returns the name of the parameter whose index is passed. - Parameters: - int pbIndex - - The index of the parameter to return the name of. bool localized - - If true, then the parameter name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the parameter name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the parameter name in English. - The name of the parameter. - Default Implementation: - The default implementation returns MSTR(_M("Parameter")) - - - - - Reference to single entity. - - - Examples: - See Standard shaders switch maxsdk\samples\materials\stdmtl2.cpp for sample usage. - See also maxsdk\samples\mesh\editablemesh. - - - - - Get the Reference. - - - - - Get whether/when to auto drop the Reference on shutdown. - - - - - Get whether was specified as a static instance. - - - - - class : public - - - Description: - This class is only available in release 5 or later. - - is used by the radiosity system and LightTracer to sample the radiance of the sky in a specific direction. - - - - - - - Returns the spectral radiance along a ray of given origin and direction in world space. Return true if the intensity is in MAX units, or false if intensity is in international units. The radiance is stored in the parameter radiance. - - - - - Returns the class id of the class that created this . This is used by IsSameSky to determine whether the sky has changed. - - - - - Compare two skys. Return true if the Gather method will return the same result. The implementation should determine whether the objects are the same type using ClassID(). If they are different types, return false. If they are the same type, the parameters should be compared to see if the Gather method will return the same values for the two objects. - - - - - Description: - This is the base class for the creation of sound plug-ins. The 3ds Max user may choose a sound plug-in using the File / Preferences... Animation / Sound Plug-In option. - - There is always one sound object in the scene. A sound object's primary purpose is to provide a sound track for the scene. The sound object also serves as a clock that controls timing when an animation is played. This ensure the animation is synched to the sound object. This class has methods to start and stop the sound playing, play a specified range of the sound, and toggle the sound on and off. - - A sound plug-in can participate in Track by implementing the methods of such as PaintTrack(). See the Advanced Topics section ~{ Track }~ for details. - - Sound plug-ins use a Super Class ID of SOUNDOBJ_CLASS_ID. - - - - - When the system calls this method the plug-in should loop the playing of sound from time t0 to t1 beginning at time tStart. It should continue to loop until Stop() is called. - Parameters: - TimeValue tStart - - The time to start playing the sound. - - TimeValue t0 - - The loop begin range. - - TimeValue t1 - - The loop end range. - - TimeValue frameStep - - The frame increment. - TRUE if the sound was played; FALSE otherwise. - - - - - Implementation of this method is optional. The plug-in should play the amount of sound between time t0 and t1. The sound should only be played once. - Parameters: - TimeValue t0 - - The start time for playback. - - TimeValue t1 - - The end time for playback. - - - - - This stops the sound from playing. - The time at which the sound was stopped. - - - - - This returns the current time as managed by the . - The current time. - - - - - Returns TRUE if the sound is playing; otherwise FALSE. - - - - - This saves the sound between the specified times to the specified file. - Parameters: - PAVIFILE pfile - - The file to save the sound track to. - - TimeValue t0 - - The start of the time range to save. - - TimeValue t1 - - The end of the time range to save. - - - - - Sets the sound to mute or toggles it back on. This will be called if the Active checkbox is toggled for example. - Parameters: - BOOL mute - - Specifies if the sound should be muted. TRUE indicates the sound should be muted; FALSE indicates the sound should be enabled. - - - - - Returns TRUE if the sound is muted; otherwise FALSE. - - - - - Description: - This is the callback object for the method Interface::DoSpaceArrayDialog *sacb=NULL)=0 - - This is the method which brings up the Spacing tool. This lets the user distribute objects based on the current selection along a path defined by a spline or a pair of points. - - The callback is mostly for use for plug-ins that need to use the spacing tool as a way of generating spacing information. If one wants to customize the default behaviour of the dialog, they derive a class from this one and implement the virtual methods. The non-virtuals simply provide access to the spacing information. This is both for setting the defaults before calling the spacing tool as well as getting out the information after using the spacing tool. - - - - - Implemented by the Plug-in. - - If this method returns false, the dialog is presented as a modeless dialog. - Default Implementation: - { return true; } - - - - - Implemented by the Plug-in. - - If this method returns true, the path picking buttons are turned on. - Default Implementation: - { return false; } - - - - - Implemented by the Plug-in. - - Returns the title for the dialog (e.g. Space Tool). - Default Implementation: - { return _M(""); } - - - - - Implemented by the Plug-in. - - Returns the message to be displayed in the static display right after the dialog comes up. - Default Implementation: - { return _M(""); } - - - - - Implemented by the Plug-in. - - Returns the button text. - Default Implementation: - { return _M("OK"); } - - - - - Implemented by the Plug-in. - - If this method returns true, the spacing tool generates points, but the actual dialog is not presented to the user. This is currently used, for example, by the Stairs in VIZ to generate spacing information for the mesh. - Default Implementation: - { return false; } - - - - - Implemented by the Plug-in. - - If this method returns false, then the Instance, Copy, Reference radio buttons are disabled (greyed out). - Default Implementation: - { return true; } - - - - - Implemented by the Plug-in. - - This method is called after the spacing information is generated. It is here that a developer using this callback could get the updated values, perform some calculation of their own, etc. - Default Implementation: - {} - - - - - Implemented by the System. - - Returns a pointer to the path . - - - - - Implemented by the System. - - Sets the points for the path. - Parameters: - pt1 - - One of the endpoints. - - pt2 - - The other endpoint. - - - - - Implemented by the System. - - Sets the path used. - Parameters: - *s - - Points to the path to use. - - - - - Implemented by the System. - - Returns the start offset. - - - - - Implemented by the System. - - Returns the end offset. - - - - - Implemented by the System. - - Returns the spacing. - - - - - Implemented by the System. - - Returns the object count. - - - - - Implemented by the System. - - Returns the context. See setContext() above. - - - - - Implemented by the System. - - Returns the width. This is the width of the object to be arrayed. It is a single value so can be calculated any way the user wishes. In the default spacing tool this is calculated based on the x size of the bounding box. - - - - - Implemented by the System. - - Returns true if Follow is set (checked); otherwise false. - - - - - Implemented by the System. - - Sets the context. - Parameters: - CTYPE c - - One of the following values: - - CTXT_FREE - Free Center - - CTXT_CNTRCOUNT - Divide Evenly, Objects at Ends - - CTXT_CNTRSPACE - Centered, Specify Spacing - - CTXT_END - End Offset - - CTXT_ENDCOUNT - End Offset, Divide Evenly - - CTXT_ENDSPACE - End Offset, Specify Spacing - - CTXT_START - Start Offset - - CTXT_STARTCOUNT - Start Offset, Divide Evenly - - CTXT_STARTSPACE - Start Offset, Specify Spacing - - CTXT_FULLSPACE - Specify Offset and Spacing - - CTXT_FULLCOUNT - Specify Offsets, Divide Evenly - - CTXT_ENDLOCK - Space from End, Unbounded - - CTXT_ENDLOCKCOUNT - Space from End, Specify - - CTXT_ENDLOCKSPACE - Space from End, Specify Spacing - - CTXT_STARTLOCK - Space from Start, Unbounded - - CTXT_STARTLOCKCOUNT - Space from Start, Specify - - CTXT_STARTLOCKSPACE - Space from Start, Specify Spacing - - CTXT_FULLLOCKSPACE - Specify Spacing, Matching Offsets - - CTXT_FULLLOCKCOUNT - Divide Evenly, No Objects at Ends - - - - - Implemented by the System. - - Returns the object creation type. One of the following values: - - NODE_CPY - Copy - - NODE_INST - Instance - - NODE_REF - Reference - - - - - Implemented by the System. - - Returns the spacing type. One of the following values: - - SPACE_CENTER - - SPACE_EDGE - - - - - Implemented by the System. - - Sets the message string. - - - - - Implemented by the System. - - Returns the limit on the count. - - - - - Description: - This is the base class for , , and Plug-Ins. It contains a few methods common to each of those plug-in classes. - Data Members: - MSTR name; - - This is the name which appears in Track . - - - - - This method is used to retrieve the name for the plug-in. This name will appear in the track view and the list of current atmospheric or rendering effects. - Parameters: - bool localized - - If true, then the name returned should be localized in the language 3ds Max is currently using. Otherwise it should be the name in English. If a plugin does not provide localized string resources, it can disregard this parameter and always return the name in English. - - - - - Returns TRUE if the effect is active; otherwise FALSE. - Parameters: - TimeValue t - - The time at which to check. - Default Implementation: - { return FALSE; } - - - - - This method is called once per frame when the renderer begins. This gives the atmospheric or rendering effect the chance to cache any values it uses internally so they don't have to be computed on every frame. - Parameters: - TimeValue t - - The current time of the call. - - & valid - - The validity interval of the cache created by the plug-in. The plug-in may set this for its own use. The plug-in can then check if the cache is up to date and update it if not. - - - - - This method creates and returns a new instance of a class derived from to manage the user interface. This put up a modal dialog that lets the user edit the plug-ins parameters. - Parameters: - *ip - - This is the interface given to the plug-in so it may display its parameters. - Default Implementation: - { return NULL; } - - - - - Implement this if you are using the ParamMap2 AUTO_UI system and the effect has secondary dialogs that don't have the effect as their 'thing'. Called once for each secondary dialog for you to install the correct thing. - - Note: Developers needing more information on this method can see the remarks for which describes a similar example of this method in use (in that case it's for use by a texture map plug-in). - Parameters: - SFXParamDlg* dlg - - Points to the . - Return TRUE if you process the dialog; otherwise FALSE. - Default Implementation: - { return FALSE; } - - - - - If an atmospheric or rendering effect has references to gizmos or other objects in the scene it can optionally provide access to the object list. This method returns the number of gizmos or objects the plug-in has. - Default Implementation: - {return 0;} - - - - - Returns a pointer to the 'i-th' gizmo or object node. - Parameters: - int i - - The index of the gizmo to return. - Default Implementation: - {return NULL;} - - - - - Deletes the 'i-th' gizmo or object from those used by the plug-in. - Parameters: - int i - - The index of the gizmo to delete. - Default Implementation: - {} - - - - - Adds the specified node to the end of the list of gizmos used by the plug-in. - Parameters: - *node - - Points to the node to append. - Default Implementation: - {} - - - - - This method is called to approve a node for possible use as gizmo. Return TRUE if the node is okay; otherwise FALSE. - Parameters: - *node - - The node to check. - Default Implementation: - { return FALSE; } - - - - - This method is called to select the specified gizmo and displays parameters for it (if any). - - In the Special Effects section of the light dialog there is a button labelled 'Setup'. The Setup button brings up the Environment dialog (for Atmospherics) or the Render Effects dialog (for Render Effects) and selects the choosen effect. It also selects the "gizmo" within that effect, so if there are particular parameters for each gizmo the user will see them. Pressing that button causes this method to be called. - Parameters: - *node - - The gizmo node. - Default Implementation: - {} - - - - - Inserts the specified gizmo node into the list of gizmos. This method must be defined to use the class. - Parameters: - int i - - The zero based index of the position in the list of where the insertion should take place. - - *node - - The gizmo node to insert. - Default Implementation: - assert(0); } - - - - - Description: - This is a class developer can use to provide a spherical gizmo helper object for their plug-ins. It provides implementations of all the required methods. The following #defines are used to access the parameters from the pblock pointer of the base class . - - The ClassID for this class is defined as: SPHEREGIZMO_CLASSID - - - - - General-purpose 3D spline class. The class has a list of these splines that make up the bezier shape. Methods of this class are used to access the properties of the spline. All methods of this class are implemented by the system. - - - - - Assignment operator. - - - - - Assignment operator. This generates a from the spline, where points are added in between the knots on the spline. For example if the steps value was 5, it will interpolate 5 points in between each knot on the spline. - - - - - Clears out the spline. It frees the knots attributes array and the bezier points array. - - - - - Returns the Knot (point) count. - - - - - Returns the private spline flags. SPLINE_CLOSED This indicates if the spline is closed or not. - - - - - Returns the number of line segments in the spline. For example if you have a 4 knot spline that is open you'll get 3 segments. - - - - - Returns the closed status. Nonzero if closed, zero if not closed. - - - - - Add a knot to the spline at the specified location. - Nonzero on success, zero otherwise. - - The knot to be added. - = -1, The location to add the knot. a negative value indicates the end of the spline. - - - - Sets the 'i-th' knot object which contain the knot point, in and out vectors, knot and line types and auxiliary values. - - Specifies the value to be set to. - The knot to be set. - - - - Returns the 'i-th' knot object which contain the knot point, in and out vectors, knot and line types and auxiliary values. - - Specifies the knot to be retrieved. - - - - Delete the specified knot. - Nonzero if the knot was deleted, zero otherwise. - - The location of the knot to be deleted. - - - - Used internally by the free form line object SPLINE.CPP. This method allows the user to use the mouse to create a line. See the sample code in /MAXSDK/SAMPLES/OBJECTS/SPLINE.CPP for an example of this method in use. - - New for 3ds Max 2.0 is an additional parameter is a pointer to an object, which is used to access the DisplayTempPrompt() mechanism. The parameter is optional; omitting it allows the spline operation to work as in 3ds Max 1.x. Adding the parameter causes the spline to display the delta, distance and angle of the current segment being edited. - - - - - Used internally by the free form line object SPLINE.CPP. See the sample code in /MAXSDK/SAMPLES/OBJECTS/SPLINE.CPP for an example of this method in use. - - - - - Returns the knot type from the specified knot. - - The index of the knot type to return. - - - - Sets the knot type of the specified knot or, if one of the special indices is specified, sets the knot type used on initial click or when the user clicks and drags the mouse. - Nonzero if set, zero otherwise. - - The index of the knot to be set. If SPLINE_INITIAL_TYPE_INDEX, sets the knot type applied at the initial mouse click when creating or inserting (see private member 'initialType'). If SPLINE_DRAG_TYPE_INDEX, sets the knot type used when the user clicks and drags (see private member 'dragType'). - The Spline knot type - - - - Returns the type of line segment between knots for the specified segment. - Spline line types - - The index of the segment whose line type will be returned. - - - - Sets the line type of the specified segment. - Nonzero if set, zero otherwise. - - The index of the segment. - The Spline line type - - - - This method should be called whenever you finish changing points on the spline. This updates all the information internal to the spline needed to calculate all the bezier handles. - - - - - Finds segment and parameter for whole-curve parameter. - - - - - Returns a point interpolated on a segment between two knots. - The interpolated point. - - The index of the segment to interpolate. - A value in the range of 0.0 to 1.0. 0 is the first knot and 1 is the second knot. - = SPLINE_INTERP_SIMPLE; The spline type to use. - - - - Returns a point interpolated on a segment between two knots using the SPLINE_INTERP_NORMALIZED method. - The interpolated point. - - The index of the segment to interpolate. - A value in the range of 0.0 to 1.0. 0 is the first knot and 1 is the second knot. - The effective parameter value derived by travelling along the segment to value t. - - - - Returns a point interpolated on the entire curve. However, does not tell which segment the point falls on. Typically the method InterpBezier3D() will give better control of the curve as it interpolates a bezier segment. - The interpolated point. - - A value in the range of 0.0 to 1.0 for the entire curve. - = SPLINE_INTERP_SIMPLE; The spline type to use. - - - - Returns a tangent vector interpolated on a segment between two knots. - The tangent vector. - - The index of the segment. - A value in the range of 0.0 to 1.0. 0 is the first knot and 1 is the second knot. - = SPLINE_INTERP_SIMPLE; The spline type to use. - - - - Returns a tangent vector interpolated on the entire curve. - The tangent vector. - - A value in the range of 0.0 to 1.0 for the entire curve. - = SPLINE_INTERP_SIMPLE; The spline type to use. - - - - Returns nonzero if the knot type is KTYPE_AUTO. Zero otherwise. - - The index of the knot. - - - - Returns nonzero if the knot type is KTYPE_BEZIER. Zero otherwise. - - The index of the knot. - - - - Returns nonzero if the knot type is KTYPE_CORNER, zero otherwise. - - The index of the knot. - - - - Returns the bounding box of the curve in the space specified by the tm in the input parameters. - - This parameter is not used. - The tm to transform the points by prior to computing the bounding box. - The bounding box - - - - Opens or closes the spline. If the optional parameter is not specified it is closed. - Nonzero if changed, zero if not changed. - - = 1. Nonzero to close; zero to open. - - - - Sets the spline to open. - Nonzero if changed, zero if not changed. - - - - - Displays data about the specified knot using DebugPrints(). See ~{ Troubleshooting }~. - - The index of the knot. - - - - Returns the 'i-th' in vector position in absolute coordinates. - - The vector position to be retrieved. - - - - Sets the 'i-th' in vector position in absolute coordinates. - - The position to be altered. - The value to be set in absolute coordinates. - - - - Returns the 'i-th' in vector position relative to the knot point. - - The position to be returned. - - - - Sets the 'i-th' bezier in vector position relative to the knot point. - - The vector to be set. - The vector data to set, relative to the knot point. - - - - Returns the 'i-th' knot point. - - The knot point to be returned. - - - - Sets the 'i-th' knot point to the specified value. - - The knot point to be set. - The value to be set to. - - - - Returns the 'i-th' out vector position in absolute coordinates. - - The out vector point to be returned. - - - - Sets the 'i-th' out vector position in absolute coordinates. - - The out vector point to get. - The out vector to set in absolute coordinates. - - - - Returns the 'i-th' out vector position relative to the knot point. - - Specifies the point to get. - - - - Sets the 'i-th' out vector position relative to the knot point. - - Specifies the point to be set. - The out vector position to set relative to the knot point. - - - - Get the user flags for a specified knot. SPLINEKNOT_USER1 through SPLINEKNOT_USER8 - - Specifies the point to get flags for - The DWORD mask of the flag(s) to get - - - - the user flags for a specified knot. SPLINEKNOT_USER1 through SPLINEKNOT_USER8 - - Specifies the point to set flags for - The DWORD mask of the flag(s) to set - TRUE to set the flag, FALSE to clear the flag - - - - Clear the user flags for a specified knot. SPLINEKNOT_USER1 through SPLINEKNOT_USER8 - - Specifies the point to clear flags for - The DWORD mask of the flag(s) to clear - - - - Returns an item in the in vector. Each control point is made up of three points. The in vector coming off the bezier control point, the knot point itself, and the out vector. There are these three points for every control point. This method will return any item in this list. - - The index into the vertex list. - - - - Sets the the position of the given Vertex - - - - - Returns the number of vertices. This is always the number of knots times 3. - - - - - Returns the auxiliary data associated with the specified knot. This is used internally for tracking topological changes to the spline during editing. Developers can use it for temporary purposes but it will be altered by the EditableSpline () code. - - The knot from whom the data is retrieved. - - - - Sets the first integer auxiliary data associated with the specified knot. - - The knot whose auxiliary will be set. - The value to be set to. - - - - Returns the second integer auxiliary data associated with the specified knot - - The knot from whom the data is retrieved. - - - - Sets the second integer auxiliary data associated with the specified knot. - - The knot whose auxiliary data will be set. - The value to set to. - - - - Returns the third integer auxiliary data associated with the specified knot. This field is available for any use. - - The knot whose auxiliary data is returned. - - - - Sets the third integer auxiliary data associated with the specified knot. This field is available for any use. - - The knot whose auxiliary data will be set. - The value to set to. - - - - Returns the specified integer auxiliary data associated with the specified knot. - - The knot whose auxiliary data is returned. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - - - - Sets the specified integer auxiliary data associated with the specified knot. - - Specifies the knot whose auxiliary data will be set. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3 . - The value to set to. - - - - Returns the specified integer auxiliary data associated with the specified in vector. - - Specifies the knot whose auxiliary data will be returned. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - - - - Sets the specified integer auxiliary data associated with the specified in vector. - - The knot whose auxiliary data will be set. - The auxiliary field. The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - The value to set to. - - - - Returns the specified integer auxiliary data associated with the specified out vector. - - The knot whose auxiliary data will be returned. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - - - - Sets the specified integer auxiliary data associated with the specified out vector. - - The knot whose auxiliary data will be set. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - The value to be set to. - - - - Returns the specified integer auxiliary data associated with the specified bezier vertex. - - The zero based bezier vertex index. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - - - - Sets the specified integer auxilliary data associated with the specified bezier vertex. - - The zero based bezier vertex index. - The auxiliary field. 0=aux1, 1=aux2 and 2=aux3. - The value to be set to. - - - - Returns the material ID for the specified spline segment. - - The zero based index of the segment. - - - - Sets the material ID for the specified spline segment. - - The zero based index of the segment. - The material ID to be set to. - - - - Returns the length of the spline. - - - - - Returns the length of the specified segment of this spline. - - The zero based index of the segment to check. - - - - Transforms the points of the spline into another space defined by the specified transformation matrix. - - The pointer to the transformation matrix. - - - - Reverses all the points of the spline. - - Defaults to FALSE in order to retain backwards compatibility. Setting it to TRUE insures that a closed spline will have the same vertex as its first point when it is reversed. The parameter is ignored on open splines. - - - - Appends the specified spline onto the end of this one. The splines should both be opened. - - The spline to append. - Defaults to TRUE. this to TRUE to weld coincident first vertices. Setting it to FALSE will disable welding. Returns TRUE if first point auto-welded - - - - Takes the specified spline and puts it on the front of this spline. - true if last point auto-welded, false otherwise. - - The spline to prepend. - Defaults to TRUE. this to TRUE to weld coincident last vertices. Setting it to FALSE will disable welding. Returns TRUE if first point auto-welded - - - - true if the spline is clockwise in the XY plane (it ignores Z), false otherwise. This call is meaningless if the shape self intersects. - - - - - true if the spline intersects itself in the XY plane (it ignores Z), false otherwise. - - - - - Tells if the input spline intersects the specified spline in the XY plane (ignoring Z) or not. - true if this spline intersects the specified spline in the XY plane (ignoring Z), false otherwise. - - The pointer to the spline to check. - - - - Tells if the specified 2-D point is surrounded (contained within) this spline or not. - true if the specified point is surrounded (contained within) the current spline, false otherwise. - - The point to check. - - - - Creates a from this spline given a steps setting and an optimize parameter. Note the following constraints on this method. When a is asked to output a with a given number of steps and FALSE is specified for optimization, it must output a with [steps * pieces + pieces + 1] vertices if it's an open shape and [steps * pieces + pieces] vertices if it's closed. - - The result is stored here. - Defaults to -1. The number of steps between knots in the spline. - Defaults to FALSE. If TRUE, linear segments between control points in the spline will not generate steps in between. It will just be one line segment. - - - - This method makes sure the shape has flushed out any cached data it may have had. - - - - - This method allows this to create a map of smoothing groups that eases the creation of meshes. It fills in a developer supplied IntTab with smoothing groups for each segment of the spline. A spline with 4 segments will cause the IntTab to be set to 4 entries, for example. Five smoothing groups are used for this operation, 1<<0 through 1<<4. Once you have them, you can shift them as needed for your application. The smoothing groups are set up so that segments connected by knots with KTYPE_SMOOTH or KTYPE_BEZIER types are smoothed together. - - A table of integers. See Class . - - - - Describes a single knot in a spline. It is used by plug-ins to get and set knot information in the class. This is primarily here for backward-compatibility with versions prior to MAXr3. In 3ds Max 2.0 and later there are methods which provide full access to the private data members of the class. All methods of this class are implemented by the system. To understand this class better, picture a bezier spline with three knots, going from left to right: - A - >AB- - BA< - B - >BC- - CB< - C The knot points are A, B and C. The vectors are labeled the same as patch vectors (AB is the vector from A going toward B, the vector from B to A is labeled BA, and so on). In this diagram, AB is the OUT vector for knot A. BA is the IN vector for knot B. BC is the OUT vector for knot B, and CB is the IN vector for knot C. Because this is an open spline, knot A doesn't use its IN vector, and knot C doesn't use its OUT vector. The IN and OUT terminology is based on the way a spline flows from the first knot to the last. If the spline is reversed, the IN and OUT sense is reversed, as well. Regarding the vectors, the only difference between a circle and a square is that the square has vectors that are at the same location as the knot point (in other words, zero length vectors) causing sharp corners. The circle uses vectors which cause each segment to bulge to form a quarter-circle. Take a look at the /MAXSDK/SAMPLES/OBJECTS/NGON.CPP source file for an example of how the vectors are generated to form a linear NGON versus a circular one. - - - - - Returns the knot type. - - - - - Returns the line type. - - - - - Provides access to the first integer chunk of auxiliary data for the knot. - - - - - Provides access to the second integer of auxiliary data for the knot. - - - - - Sets the second integer of auxiliary data for the knot. - - The value to be set to. - - - - Returns the point location for the knot. - - - - - Returns the in vector for the knot. - - - - - Returns the out vector for the knot. - - - - - Used for the internal storage of spline knot assemblies in the class - - - - - Allow access as if the in/knot/out components are contained vertices. - - - 0=inVec 1=knot 2=outVec - 0=aux1 1=aux2 2=aux3 - - - - Allow access as if the in/knot/out components are contained vertices. - - - 0=inVec 1=knot 2=outVec - 0=aux1 1=aux2 2=aux3 - - - - - Allow access as if the in/knot/out components are contained vertices. - - - 0=inVec 1=knot 2=outVec - - - - Allow access as if the in/knot/out components are contained vertices. - - - 0=inVec 1=knot 2=outVec - 0=aux1 1=aux2 2=aux3 - - - - Provides the vertex-level point information for the class. 'aux' fields in spline are available in 3 channels: 0: Used in capping process 1: Used to track topology changes in spline editing 2: Available to user - - - - - Description: - Defines a spline object class. The is the object that flows down the 3ds Max geometry pipeline. This class is a container for the shape. All methods of this class are implemented by the system. - - Spline Shape plug-ins use a Super Class ID of SHAPE_CLASS_ID. - Data Members: - shape; - - The shapes of this . - - - - - Returns the data member maintained by this class. - - - - - this has the same effect as pressing the Cross Section button in the Spline's Geometry rollout - - - - - should be used before a sequence of calls to DoCrossSection() - - - - - should be used after a sequence of calls to DoCrossSection() - - - - - creates a cross section of the current selected spline or segement with the given spline(s). This can be called multiple times in sequence, once for each section in the cross section. - - - - - this simply performs a linear search through the given list, returning the index of the given point - - - - - this has the same effect as pressing the Copy button in the "Tangent" section of the Spline UI, when in Vertex sub-object mode - - - - - this has the same effect as pressing the Paste button in the "Tangent" section of the Spline UI, when in Vertex sub-object mode - - - - - should be used before a call to PasteTangent() - - - - - should be used following a call to PasteTangent() - - - - - copy the given tangent - - - - - paste the given tangent. This should be preceeded by a call to StartPasteTangent() and followed by EndPasteTangent() - - - - - This method is available in release 4.0 and later only. - - This method operates in vertex level only, and sets the vertex selection set based on the segments that are selected. Any vertex which is part of a selected segment will be selected. - Parameters: - BOOL interactive - - If set to FALSE, an Undo object is not created and the method does not initiate a redraw. - - - - - This method is available in release 4.0 and later only. - - This method operates in vertex and segment level only, and sets the vertex or segment selection set based on the splines that are selected. If in vertex mode, any vertex which is part of a selected spline will be selected. If in segment mode, any segment whcich is part of a selected spline will be selected. - Parameters: - BOOL interactive - - If set to FALSE, an Undo object is not created and the method does not initiate a redraw. - - - - - Description: - This class is the main spring system class. This spring system is a multi-point spring-based dynamic system. In order to your the system you must derive from and implement the SpringSysClient::GetForceMatrices() method You are responsible for gathering the spring constraint forces at any given time. - - The spring system uses its own position and velocity to determine its motion, as well as allowing you to add multiple spring constraints to any other objects in the scene. Multiple constraints act like multiple links. - - The solution is calculated using a start time and a step size. Solutions are cached once for the last tick calculated, and once per frame. Performance should be the same one each frame as you step forward, and significantly faster after the first pass if nothing changes. Cached values will be used if going backwards in time. - - - - - Assignment operator. - - - - - This method allows you to copy the data from the specified spring system. - Parameters: - const SpringSys* from - - The spring system to copy the data from. - - - - - This method returns the reference time. - - - - - This method returns a pointer to the array of spring system particles. - - - - - This method returns a pointer to the I-th spring system particle. - Parameters: - int i - - The index of the spring system particle in the array. - - - - - - - - - This method returns the forces acting inside the spring system. - Parameters: - TimeValue t - - The time at which to get the force matrices. - - - - - This method returns the dynamic forces acting inside the spring system. - Parameters: - TimeValue t - - The time at which to get the forces. - - pos - - The position force. - - vel - - The velocity force. - Default Implementation: - ; } - - - - - A simple stack implementation. - - - - - Pushes the specified element on the stack. - Parameters: - T *el - - The item to push. - - - - - Pops an item off the stack. - Parameters: - T *el - - The item popped off the stack is returned here. - - - - - Pops an item off the stack and discards it. The item is not returned. - - - - - Retrieves the item on top of the stack without altering the stack. - Parameters: - T *el - - The top item is returned here. - - - - - Clears the stack. All items are deleted. - - - - - Returns the number of item currently on the stack. - - - - - Removes the 'i-th' item from the stack. - Parameters: - int i - - The item to remove from the stack. - Returns the number of items left in the stack. - - - - - Description: - is a class from which you may derived controller objects. Controllers are the objects in 3ds Max that control animation. Any controller that does not evaluate itself as a function of its input can subclass off this class. - - The purpose of this class is to simplify some aspects of implementing controllers. The only restriction when using this class is that the controller can not evaluate itself as a function of its input. For example, position, rotation, and scale controllers are passed a TM when they are evaluated. They are supposed to calculate their value and apply it to the TM (pre-multiply). It is possible that the controller could calculate its value as some function of this input matrix. For example, a rotation controller could look at the position of the matrix and the position of some other node in the scene and calculate the rotation such that the object is looking at the other node. Most controllers don't do this so they can subclass off this class which handles processing ORTs (Out of Range Types), ease curves and multiplier curves. - - This class implements GetValue() and SetValue() but requires the derived class to implement two new methods: GetValueLocalTime() and SetValueLocalTime(). - - The implementations of GetValue() and SetValue() handle processing the ORTs and ease and multiplier curves. - Plug-In Information: - Class Defined In CONTROL.H - - Super Class ID CTRL_FLOAT_CLASS_ID - Used by float controllers. - - CTRL_POINT3_CLASS_ID - Used by controllers. - - CTRL_MATRIX3_CLASS_ID - Used by controllers. - - CTRL_POSITION_CLASS_ID - Used by position controllers. - - CTRL_ROTATION_CLASS_ID - Used by rotation controllers. - - CTRL_SCALE_CLASS_ID - Used by scale controllers. - - CTRL_MORPH_CLASS_ID - Used by morph controllers. - - Standard File Extension DLC - - Extra Include File Needed None - - - - - This method is called to have the controller evaluate itself at the given time. In this class the system implements the method GetValue(). GetValue() calls this method to retrieves the value of the controller at the specified time. The implementation of GetValue() then takes care of handling the ORTs, ease curves and multiplier curves. The plug-in must only return the value of the controller. - - The time to retrieve the value. - This points to a variable to hold the computed value of the controller at the specified time. What the plug-in needs to do to store the value of the controller depends on the controller type. There are six controller types as follows: points to a float points to a points to a points to a points to a points to a - The interval into which the validity of the evaluated parameters is intersected. - This will always be: . It indicates the controller should simply store its value in . - - - - In this class the system implements the method SetValue(). SetValue() calls this method to store the value of the controller at the specified time. The system takes care of handling the ORTs and multiplier curves. The plug-in must only store the value of the controller. - - The time to store the value. - Storage for the value to set. See in for the possible data types passed here. - If this parameter is zero, the controller should save the value at the given time before setting the value. If commit is nonzero, the controller doesn't need to actually update its keys or tangents. See methods and . - One of the following values: Indicates the plug-in should add the value to the existing value (i.e. Move/Rotate/Scale) Indicates the plug-in should just set the value. - - - - This method is used to calculate some of the Out of Range Types (ORTs). There are several kinds of extrapolations that need to be done based on the ORT type. There are template functions implemented in CONTROL.H to do them. See Template Extrapolation Functions. - Sample Code: - The following sample code shows the implementation in the Simple Wave Controller (MAXSDK/samples/controllers/wavectrl/simpwave.cpp). - - The range that must be extrapolated. - The time outside the range to extrapolate. - Storage for the extrapolated value. See in for the possible data types passed here. - The interval into which the validity of the evaluated parameters is intersected. - See . - - - - When processing the ORTs the system might need a temporary variable to hold an intermediate value. Since the system doesn't know the type of the data that the controller is controlling it can't allocate the right amount of temporary storage. It calls this method to do so. The plug-in's implementation of this method should allocate storage to hold its type of data and return a pointer to it. - - - - - This method simply deletes the memory allocated by CreateTempValue(). - - Points to the memory allocated by . - - - - Applies the given value to the given input value. For position, rotation, and scale controllers, the input value will be a matrix and the value being applied will be a , Quaternion, or , respectively. For other controllers the input value is the same type as the value being applied. - - The value to update. - The value to apply. - - - - If the controller has multiplier curves then the system will calculate the factor from all the multiplier curves and then ask the controller to multiply the scalar value to the particular data type. - - The value to update. - The scalar value to multiply by. - - - - Description: - This class provides access to the parameters of the standard 3ds Max Reflect/Refract texture. All methods of this class are implemented by the system. - - - - - Sets the map size parameter. - Parameters: - int n - - The size in pixels. - - TimeValue t - - The time to set the value. - - - - - Sets the blur setting to the specified value at the specified time. - Parameters: - float b - - The value to set. - - TimeValue t - - The time to set the value. - - - - - Sets the blur offset setting to the specified value at the specified time. - Parameters: - float b - - The value to set. - - TimeValue t - - The time to set the value. - - - - - Sets if the reflect / refract texture uses high dynamic range bitmaps or not. See ~{ Working With Bitmaps }~ for details on high dynamic range bitmaps. - Parameters: - BOOL onoff - - Pass TRUE for on; FALSE for off. - - - - - Returns the size setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Returns the state of the 'Every Nth Frame' or 'First Frame Only' toggle. - BOOL onoff - - TRUE is 'Every Nth Frame'; FALSE is 'First Frame Only'. - - - - - Returns the Nth Frame setting. - - - - - Returns the state of the 'Apply blur' checkbox. - TRUE is on; FALSE is off. - - - - - Returns the blur setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Returns the blur offset setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Description: - This class provides access to the settings of the Standard Fog plug-in of 3ds Max. All methods of this class are implemented by the system. - - - - - Sets the fog color. - Parameters: - c - - The color to set. - - TimeValue t - - The time to set the color. - - - - - Sets the standard fog near percentage. - Parameters: - float v - - The value to set in the range 0 to 1. - - TimeValue t - - The time to set the value. - - - - - Sets the standard fog far percentage. - Parameters: - float v - - The value to set in the range 0 to 1. - - TimeValue t - - The time to set the value. - - - - - Sets the layered fog top value. - Parameters: - float v - - The value to set. - - TimeValue t - - The time to set the value. - - - - - Sets the layered fog bottom value. - Parameters: - float v - - The value to set. - - TimeValue t - - The time to set the value. - - - - - Sets the layered fog density setting. - Parameters: - float v - - The value to set (> 0). - - TimeValue t - - The time to set the value. - - - - - the 'Horizon Noise Size' setting. - Parameters: - float v - - The value to set. - - TimeValue t - - The time to set the value. - - - - - the 'Horizon Noise Angle' setting. - Parameters: - float v - - The value to set in radians. - - TimeValue t - - The time to set the value. - - - - - the 'Horizon Noise Phase' setting. - Parameters: - float v - - The value to set. - - TimeValue t - - The time to set the value. - - - - - Returns the fog color at the time passed. - Parameters: - TimeValue t - - The time to get the color. - - - - - Returns the state of the 'Use Map' toggle. - TRUE is on; FALSE is off. - - - - - Returns the state of the use opacity map toggle. - TRUE is on; FALSE is off. - - - - - Returns the color map used. - - - - - Returns the opacity map used. - - - - - Returns the state of the fog background toggle. - TRUE is on; FALSE is off. - - - - - Returns the type of fog, layered or standard. - The type of fog: 0 = Standard; 1 = Layered. - - - - - Returns the standard fog near percentage. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the standard fog far percentage. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the layered fog top value. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the layered fog bottom value. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the layered fog density setting. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the falloff type to top, bottom or none. - One of the following values: - - FALLOFF_TOP - - FALLOFF_BOTTOM - - FALLOFF_NONE - - - - - Returns the state of the 'Horizon Noise' toggle. - TRUE is on; FALSE is off. - - - - - Returns the 'Horizon Noise Size' setting. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the 'Horizon Noise Angle' setting. - Parameters: - TimeValue t - - The time to get the value. - - - - - Returns the 'Horizon Noise Phase' setting. - Parameters: - TimeValue t - - The time to get the value. - - - - - Description: - This class provides access to the properties of the 3ds Max Standard material. All methods of this class are implemented by the system. - - Note that some properties such as the texture maps used are accessed using methods of the base class . See that class, or the Advanced Topics section ~{ Materials, Textures and Maps }~ for more details. - - - - - Sets the 'Soften' setting on or off. - Parameters: - BOOL onoff - - TRUE to turn on; FALSE to turn off. - - - - - Sets the ' Map' setting on or off. - Parameters: - BOOL onoff - - TRUE to turn on; FALSE to turn off. - - - - - Sets the '2 Sided' setting on or off. - Parameters: - BOOL onoff - - TRUE to turn on; FALSE to turn off. - - - - - Sets the 'Wire' setting on or off. - Parameters: - BOOL onoff - - TRUE to turn on; FALSE to turn off. - - - - - Sets the wire size to pixels or units. - Parameters: - BOOL onoff - - TRUE for units; FALSE for pixels. - - - - - Sets the opacity falloff setting to out or in. - Parameters: - BOOL onoff - - TRUE for Out; FALSE for In. - - - - - Sets the additive transparency setting. - Parameters: - int type - - One of the following values: - - TRANSP_SUBTRACTIVE - - TRANSP_ADDITIVE - - TRANSP_FILTER - - - - - Sets the filter color to the specified value at the time passed. - Parameters: - c - - The color to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the shininess strength to the specified value at the time passed. - Parameters: - float v - - The value to set in the range 0 - 1. - - TimeValue t - - The time at which to set the value. - - - - - Sets the self illumination to the specified value at the time passed. - Parameters: - float v - - The value to set in the range 0 - 1. - - TimeValue t - - The time at which to set the value. - - - - - Sets the opacity to the specified value at the time passed. - Parameters: - float v - - The value to set in the range 0 - 1. - - TimeValue t - - The time at which to set the value. - - - - - Sets the opacity falloff to the specified value at the time passed. - Parameters: - float v - - The value to set in the range 0 - 1. - - TimeValue t - - The time at which to set the value. - - - - - Sets the wire size to the specified value at the time passed. - Parameters: - float s - - The value to set. This value should be > 0. - - TimeValue t - - The time at which to set the value. - - - - - Sets the index of refraction to the specified value at the time passed. - Parameters: - float v - - The value to set in the range 0 - 10. - - TimeValue t - - The time at which to set the value. - - - - - Locks or unlocks the ambient/diffuse textures together. - Parameters: - BOOL onOff - - TRUE to lock; FALSE to unlock. - - - - - super sampling on or off (enabled or disabled). - Parameters: - BOOL on - - TRUE for on; FALSE for off. - - - - - Sets the shading limit for the material. - Parameters: - int s - - One of the following values: - - SHADE_CONST - - SHADE_PHONG - - SHADE_METAL - - SHADE_BLINN - - - - - Enables or disables the specified map type. - Parameters: - int i - - See List of Material Texture Map Indices. BOOL onoff - - TRUE to enable; FALSE to disable. - - - - - Returns TRUE if the specified map is enabled; otherwise FALSE. - Parameters: - int i - - See List of Material Texture Map Indices. - - - - - This method is used to change the 'Amount' setting of the specified map. - Parameters: - int imap - - See List of Material Texture Map Indices. float amt - - The amount to set in the range of 0-1. - - TimeValue t - - The time at which to set the amount. - - - - - Returns the amount setting of the specified texture map at the time passed. The returned range is 0 to 1. - Parameters: - int imap - - See List of Material Texture Map Indices. TimeValue t - - The amount at this time is returned. - - - - - Returns the shading limit. One of the following values: - - SHADE_CONST - - SHADE_PHONG - - SHADE_METAL - - SHADE_BLINN - - - - - Returns TRUE if soften is on; otherwise FALSE. - - - - - Returns TRUE if face mapping is on; otherwise FALSE. - - - - - Returns TRUE if two sided is on; otherwise FALSE. - - - - - Returns TRUE if wire is on; otherwise FALSE. - - - - - Returns TRUE if the wire size is in units; FALSE if the wire size is in pixels. - - - - - Returns the opacity falloff setting: 1 = Out, 0 = In. - - - - - Returns the transparency type. - int type - - One of the following values: - - TRANSP_SUBTRACTIVE - - TRANSP_ADDITIVE - - TRANSP_FILTER - - - - - Returns the ambient color setting at the specified time. - Parameters: - TimeValue t - - The time to return the color. - - - - - Returns the diffuse color setting at the specified time. - Parameters: - TimeValue t - - The time to return the color. - - - - - Returns the specular color setting at the specified time. - Parameters: - TimeValue t - - The time to return the color. - - - - - Returns the filter color setting at the specified time. - Parameters: - TimeValue t - - The time to return the color. - - - - - Returns the shininess setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the shininess strength setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the self illumination setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the opacity setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the opacity falloff setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the wire size setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns the index of refraction setting at the specified time. - Parameters: - TimeValue t - - The value at this time is returned. - - - - - Returns TRUE if the ambient-diffuse texture lock is set; otherwise FALSE. - - - - - Description: - This is the base class for all materials supporting the plug-in shader mechanism. The 3ds Max Standard material is derived from this class. - - - - - Checks if the material parameter has a key set at the specified time. - TRUE if the specified parameter whose ID is passed has a key at the time passed; otherwise FALSE. - - - The ID of the parameter to check. - - The time to check. - - - - Returns a value to indicate the state of the specified map. One of the following values: - - 0: No map present. - - 1: Map present but disabled. - - 2: Map present and on. - Parameters: - int indx - - The index of the map to check. See List of Material Texture Map Indices. - - - - - Returns the name of the map whose index is passed. - Parameters: - int indx - - The index of the map to check. See List of Material Texture Map Indices. - - - - - This method is called when the state of the Ambient/Diffuse Texture lock is toggled. The material should store the setting and update the UI as required. - Parameters: - BOOL lockOn - - TRUE for on; FALSE for off. - - - - - This method is called when a new has been selected. - Parameters: - id - - The of the new shader to switch to. - - - - - Returns a pointer to the in use. See Class for details on this plug-in type. - - - - - Returns TRUE if the shader is faceted; otherwise FALSE. The pre-R3 Constant shader is faceted. The other shaders are not. - - - - - Sets the faceted setting of the . - Parameters: - BOOL on - - TRUE if it is faceted; FALSE if not. - - - - - Returns the index of the mapping channels which corresponds to the specified Standard materials texture map ID. - Parameters: - long id - - The ID whose corresponding channel to return. See List of Material Texture Map Indices. - The zero based index of the channel. If there is not a corresponding channel return -1. - - - - - This method is called when the active is switched. - Parameters: - id - - The of the new . - - - - - Returns the Self Illumination setting at the specified time. - Parameters: - TimeValue t - - The time at which to get the color. - - - - - Sets the Self Illumination On setting - Parameters: - BOOL on - - TRUE for on; FALSE for off. - - - - - Sets the Self Illumination setting at the specified time. - Parameters: - c - - The color to set. - - TimeValue t - - The time at which to set the color. - - - - - Description: - This class provides access to the 3ds Max Flat Mirror material. All methods of this class are implemented by the system. - - - - - Sets the specified blur value at the specified time. - Parameters: - float b - - The blur value to set in the range 0.0 to 100.0 - - TimeValue t - - The time at which to set the blur value. - - - - - Sets if the mirror texture uses high dynamic range bitmaps or not. See ~{ Working With Bitmaps }~ for details on high dynamic range bitmaps. - Parameters: - BOOL onoff - - Pass TRUE for on; FALSE for off. - - - - - Determines if 'Every Nth Frame' or 'First Frame Only' is used. - TRUE if Every Nth Frame is in use; FALSE if First Frame Only is in use. - - - - - Returns the Nth Frame setting. - - - - - Returns TRUE if the Apply Blur check box is on; otherwise FALSE. - - - - - Returns the blur setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the blur setting. - - - - - Description: - This class provides access to the Texture Output object. These are the parameters available in the Output rollup in the Materials Editor for a 2D map. - - - - - Returns TRUE if this is the standard 3ds Max Texout object; FALSE if it's a 3rd party Texout. - Default Implementation: - { return TRUE; } - - - - - Returns the Clamp on / off state. TRUE is on; FALSE is off. - - - - - Returns the Alpha from RGB Intensity on / off state. TRUE is on; FALSE is off. - - - - - Returns the RGB Level at the specified time. - Parameters: - TimeValue t - - The time at which to get the value. - - - - - Returns the RGB Offset at the specified time. - Parameters: - TimeValue t - - The time at which to get the value. - - - - - Returns the Output Amount at the specified time. - Parameters: - TimeValue t - - The time at which to get the value. - - - - - Returns the Bump Amount at the specified time. - Parameters: - TimeValue t - - The time at which to get the value. - - - - - Returns TRUE if the specified flag(s) are set; otherwise FALSE. These flags reflect the same setings as the individual methods. - Parameters: - ULONG f - - One or more of the following values: - - TEXOUT_INVERT - - TEXOUT_CLAMP - - TEXOUT_ALPHA_RGB - - TEXOUT_COLOR_MAP - - TEXOUT_COLOR_MAP_RGB - - - - - Sets the RGB Level at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the RGB Offset parameter at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the Output Amount at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the Bump Amount at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the state of the flags. - Parameters: - ULONG f - - One or more of the following values: - - TEXOUT_INVERT - - TEXOUT_CLAMP - - TEXOUT_ALPHA_RGB - - TEXOUT_COLOR_MAP - - TEXOUT_COLOR_MAP_RGB - - ULONG val - - Non-zero to set the specified flags; zero to clear the flags. - - - - - Description: - This class provides access to the parameters of the 3ds Max class. These are the settings in the 'Coordinates' and 'Noise' rollups such as UV offsets, angle, blur, noise level, etc. All methods of this class are implemented by the system. - - - - - Sets the mapping type to one of the specified values. - Parameters: - int - - The mapping type. One of the following values: - - UVMAP_EXPLICIT - - Explicit Texture mapping. - - UVMAP_SPHERE_ENV - - Spherical Environment mapping. - - UVMAP_CYL_ENV - - Cylindrical Environment mapping. - - UVMAP_SHRINK_ENV - - Shrink Wrap Environment mapping. - - UVMAP_SCREEN_ENV - - Screen Environment mapping. - - - - - Sets the U Offset setting to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the V Offset setting to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the U tiling setting to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the V tiling setting to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the angle setting to the specified value at the time passed. - Parameters: - float f - - The value to set in radians. - - TimeValue t - - The time at which to set the value. - - - - - Sets the U Angle setting the specified value at the time passed. - Parameters: - float f - - The angle to set in radians. - - TimeValue t - - The time at which to set the angle. - - - - - Sets the V Angle setting the specified value at the time passed. - Parameters: - float f - - The angle to set in radians. - - TimeValue t - - The time at which to set the angle. - - - - - Sets the W Angle setting the specified value at the time passed. - Parameters: - float f - - The angle to set in radians. - - TimeValue t - - The time at which to set the angle. - - - - - Sets the blur to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the blur offset to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the noise amount to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the noise size to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the noise level to the specified value at the time passed. - Parameters: - int i - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the noise phase to the specified value at the time passed. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - This method allows you to set the flags. - Parameters: - ULONG f - - See Texture Symmetry FlagsULONG val - - The value to set. - - - - - This method allows you to set the hide map back flag. - Parameters: - BOOL b - - TRUE to set the flag; FALSE to disable. - - - - - Sets whether to use real world mapping. - - - - - - - Retrieves the coordinate mapping type. - Parameters: - int - - This parameter is not used. - One of the following values: - - UVMAP_EXPLICIT - - UVMAP_SPHERE_ENV - - UVMAP_CYL_ENV - - UVMAP_SHRINK_ENV - - UVMAP_SCREEN_ENV - - - - - Retrieves the U Offset setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the V Offset setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the U Tiling setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the V Tiling setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the angle setting in radians. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Returns the U Angle setting (in radians) at the specified time. - Parameters: - TimeValue t - - The time at which to return the angle. - - - - - Returns the V Angle setting (in radians) at the specified time. - Parameters: - TimeValue t - - The time at which to return the angle. - - - - - Returns the W Angle setting (in radians) at the specified time. - Parameters: - TimeValue t - - The time at which to return the angle. - - - - - Retrieves the blur setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the blur offset setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the noise amount setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the noise size setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the noise level setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - Retrieves the noise phase setting at the specified time. - Parameters: - TimeValue t - - The time to retrieve the value. - - - - - This method returns the flag status of the . - Parameters: - ULONG f - - See Texture Symmetry Flags - - - - - This method returns the state of the hide map back flag. - - - - - Queries whether real world mapping is used. - - - - - Description: - This class provides access to the parameters of the 3ds Max class. The class puts up the 3D 'Coordinates' rollup. - - - - - Sets the Blur setting to the specified value at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the Blur Offset setting to the specified value at the specified time. - Parameters: - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the specified Offset setting to the specified value at the specified time. - Parameters: - int axis - - The axis to set. 0 for X, 1 for Y, 2 for Z. - - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the specified Tiling (Scale) setting to the specified value at the specified time. - Parameters: - int axis - - The axis to set. 0 for X, 1 for Y, 2 for Z. - - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Sets the specified Angle setting to the specified value at the specified time. - Parameters: - int axis - - The axis to set. 0 for X, 1 for Y, 2 for Z. - - float f - - The value to set. - - TimeValue t - - The time at which to set the value. - - - - - Returns the coordinate system in use. One of the following values: - - XYZ_COORDS - XYZ - - UVW_COORDS - Explicit Map Channel - - UVW2_COORDS - Vertex Channel - - XYZ_WORLD_COORDS - World XYZ. This option is available in release 3.0 and later only. - - - - - Returns the Blur setting at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the value. - - - - - Returns the Blur Offset setting at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the value. - - - - - Returns the Tiling (Scale) setting for the specified axis at the specified time. - Parameters: - int axis - - The axis to set. 0 for X, 1 for Y, 2 for Z. - - TimeValue t - - The time at which to retrieve the value. - - - - - Returns the Angle setting for the specified axis at the specified time. - Parameters: - int axis - - The axis to set. 0 for X, 1 for Y, 2 for Z. - - TimeValue t - - The time at which to retrieve the value. - - - - - Returns the mapping channel. - - - - - Graphics Class. - - - - - A collection of objects that have the same super class id. Clients can get a via ClassDirectory::GetClassList(). - - - - - Returns a reference to the 'i-th' for this super class. - - - The index of the entry to return. Valid values begin at an index of 1. - - - - Returns the index in the list of sub-classes of the class whose is passed. - - - Specifies which class to return the index of. - - - - Returns the index in the list of sub-classes of the class whose ClassName() is passed. - - - Specifies which class to return the index of. - - - - Returns the number of sub-classes that match the specified access type. - - - One of the following values: ACC_PUBLIC - public classes ACC_PRIVATE - non-public classes ACC_ALL - both of the above (ACC_PUBLIC|ACC_PRIVATE). - - - - Returns the Super class ID corresponding to this sub-class list. - - - - - Returns the index of the first of the specified type in the list of sub-classes. - - - One of the following values: ACC_PUBLIC - public classes ACC_PRIVATE - non-public classes - - - - Returns the index of the next of the specified type (or -1 at the end). - - - One of the following values: ACC_PUBLIC - public classes ACC_PRIVATE - non-public classes - - - - Equality operator. - - - - - This method returns additional user interface related information on a given superclass. Returns NULL if no superclass information was assigned. - - - - - Description: - The callback is used by the two methods GetSubObjectCenters() and GetSubObjectTMs() found in the classes and . - - - - - Implemented by the System. - - This method is called to specify the individual coordinate system center for the axes whose id is passed. - - The center point. - The id of the axis. - - - - Implemented by the System. - - This method is called to specify the individual coordinate system transformation for the axes whose id is passed. - - The transformation matrix. - The id of the axis. - - - - Implemented by the System. - - The user has three options for center of the coordinate system, center of the selection set, or pivot. For center of the coordinate system the system does not need to call GetSubObjCenters(). The plug-in may call this method to determine which center option it is returning the Centers and TMs for. - One of the following values: - - SO_CENTER_SELECTION - - SO_CENTER_PIVOT - - - - - This class describes a list of sub-object hit records. All methods of this class are implemented by the system. - - - - - - Allocates and adds a new hit record to the list. - - The distance to the hit. - The index of the hit. - The second level index of the sub-object component, for example the diagonal selection in an . The default is -1, not used. - - - - Reserve memory to reduce allocation time. - - size of the memory to reserve - - - - Returns true if the hit list contains no record. - - - - - Resets the container and frees all its memory. - - - - - Description: - This class describes a list of sub-patch hit records. Methods are available to return the first in the list, and to add hits to the list. All methods of this class are implemented by the system. - - - - - Returns the first sub hit record. - - - - - Creates a new sub hit record and adds it to the list. - Parameters: - DWORD dist - - The distance of the hit. If the user is in wireframe mode, this is the distance in pixels to the item that was hit. If the user is in shaded mode, this is the Z depth distance. Smaller numbers indicate a closer hit. - - *patch - - The associated with this sub-patch hit. - - int index - - The index of the sub-object component. For example, if vertices were being hit tested, this would be the index into the vertex table. - - int type - - The type of the hit. One of the following values: - - PATCH_HIT_PATCH - - PATCH_HIT_EDGE - - PATCH_HIT_VERTEX - - PATCH_HIT_VECTOR - - PATCH_HIT_INTERIOR - - - - - class - Description: - This class provides methods for accessing the first hit list record and adding hits to the list. All methods of this class are implemented by the system. - - - - - - Returns the first hit in the list. - - - - - Adds a hit record to the list. - Parameters: - DWORD dist - - The distance of the hit. If the user is in wireframe mode, this is the distance in pixels to the item that was hit. If the user is in shaded mode, this is the Z depth distance. Smaller numbers indicate a closer hit. - - *shape - - The shape that was hit. - - int poly - - The polygon that was hit. - - int index - - The index of the sub-object component that was hit. - - - - - Suspends various system states in an exception safe manner. - - - In certain cases, it is desirable to suspend animation, undo/redo, etc. while your plugin executes certain operations that should not create animation keys, be undo-able, etc. In these cases, create an instance of this class to suspend the desired system states. When the instance is destructed, the states will automatically be restored to their previous value, in a way that is safe in the presence of exceptions. - - - - - Restores the suspended system states. - - - - - A small container type class that associates graph nodes with traversal status. - - - - - Points to the interface for the node in the schematic view - - - - - The traversal status. - - - - - This class allows developers to provide some additional information on a superclass. Currently this includes a color, and a method which draws a representative image in a Windows Device Context. DrawRepresentation(...) can return false to indicate that no image was drawn. DrawRepresentation(...) should cache its image (if applicable) as the method is called repeatedly while drawing certain UI components (like the schematic view). - - - - - - - - Returns a color associated with the specified super class. This is currently used to draw nodes in the schematic view at extreme zoom-outs where it is impossible to draw legible node names. - Parameters: - SClass_ID superClassID The Super Class whose associated color to return. - - - - - Draws an image which represents the superclass (usually an icon) in a rectangle in a given Windows DC. The implementation should attempt to draw the image as fast as possible as this method is called repeatedly while drawing certain UI components. - Parameters: - SClass_ID superClassID The super class to draw. COLORREF bkColor This is the average background color of the surface on which the image is being drawn. It can be used, if desired, to antialias the image. HDC hDC The handle to the device context. Rect &rect The rectangle to draw in. - Return false if no image was drawn and a generic stand-in image will be used. - Default Implementation: - { return false; } - - - - - Description: - An instance of this class is returned by a rendering effect, atmopsheric plug-in, or sampler when it is asked to put up its rollup page in the user interface. - - - - - Returns the unique of this item. - - - - - This returns the current filter, sampler, atmospheric or rendering effect being edited. - - - - - This method is called when the current time has changed. This gives the developer an opportunity to update any user interface data that may need adjusting due to the change in time. - Parameters: - TimeValue t - - The new current time. - Default Implementation: - {} - - - - - This is a general purpose function that allows the Max SDK to be extended in the future. The 3ds Max development team can assign new command numbers and continue to add functionality to this class without having to 'break' the Max SDK. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - Default Implementation: - { return 0; } - - - - - - - - - This bone index is used to identify the bone. Usually refers to a reference index, or paramblock index. - - - - - The control nodes stored position. - - - - - The control nodes stored velocity. - - - - - Assignment operator. - - - - - This method allows you to copy the data from the specified . - Parameters: - from - - The object to copy from. - - - - - This method returns the value of the index. - - - - - This method returns the position data. - - - - - This method returns the velocity data. - - - - - Compares this class instance to another one - - - - - - - - - Assignment operator. - - - - - This method allows you to copy the data from the specified . - Parameters: - from - - The spring system particle to copy from. - - - - - This method returns the spring particle mass. - - - - - This method returns the spring particle drag. - - - - - This method returns the spring particle position. - - - - - This method returns the spring particle velocity. - - - - - This method returns the spring particle force. - - - - - This method returns a pointer to the collection of springs. - - - - - This method returns a pointer to the I-th spring in the array. - Parameters: - int i - - The index of the spring to return. - - - - - This method allows you to set the specified spring at the specified I-th index in the array. - Parameters: - int i - - The index of the spring to set. - - spring - - The spring to set. - - - - - This method allows you to delete a spring. - Parameters: - int index - - The index in the array of the spring to delete. - - - - - Compares this class instance to another one - - - - - - - - - The control node stored position. - - - - - The control node stored velocity. - - - - - The array of spring system constraint points. - - - - - - - - - Assignment operator. - - - - - This method allows you to copy the data from the specified spring object. - Parameters: - from - - The spring to copy from. - - - - - This method returns the tension value. - - - - - This method returns the dampening value. - - - - - This method returns the length of the spring. - - - - - This method returns the point constraint data. - - - - - This method allos you to set the point constraint data. - Parameters: - int id - - The index. - - pos - - The position data. - - vel - - The velocity data. - - - - - Compares this class instance to another one - - - - - container class. - - - This is a type-safe variable length array class which also supports list-like operations of insertion, appending and deleting. Two instance variables are maintained: nalloc is the number items allocated in the array; count is the number actual used (count<=nalloc). Allocation is performed automatically when Insert or Append operations are performed. It can also be done manually by calling Resize() or Shrink(). - Delete does not resize the storage: to do this call Shrink(). If you are going to do a sequence of Appends, its more efficient to first call Resize() to make room for them. Beware of using the Addr() function: it returns a pointer which may be invalid after subsequent Insert(), Append(), Delete(), Resize(), or Shrink() operations. - In 3ds max 1.x, the method SetCount(n) will set the count to n, but will not assure that only n items are allocated. To do that you should call Resize(n). This sets the number allocated. It will also make sure that count<=numAlloc. To make sure that exactly n are allocated and that count = n, call both Resize(n) and SetCount(n). In 3ds max 2.x and later using SetCount() will also effectively call Resize(). - This structure is not meant to support more than 2G items; if you need to have more items, consider using an STL container which does not have the 2G barrier and is most likely more optimized than this version. - The implementation minimizes the storage of empty Tables: they are represented by a single NULL pointer. Also, the major part of the code is generic, shared by different Tabs for different types of items. - Tabs may be used on the stack, i.e. they may be declared as a local variable of a function or method. You can set the number of items in the table, work with them, and then when the function returns, the destructor of the is called, and the memory will be deallocated. - Tabs are only appropriate for use with classes that don't allocate memory. For example, is fine while Tab<MSTR> is problematic (MSTR is the class used for strings in 3ds max). In this case, the MSTR class itself allocates memory for the string. It relies on its constructor or destructor to allocate and free the memory. The problem is the class will not call the constructors and destructors for all the items in the table, nor will it call the copy operator. As an example of this, when you assign a string to another string, the MSTR class does not just copy the pointer to the string buffer (which would result in two items pointing to the same block of memory). Rather it will allocate new memory and copy the contents of the source buffer. In this way you have two individual pointers pointing at two individual buffers. When each of the MSTR destructors is called it will free each piece of memory. So, the problem with using a Tab<MSTR> is that when you assign a to another , the copy constructor will copy all the items in the table, but it will not call the copy operator on the individual items. Thus, if you had a Tab<MSTR> and you assigned it to another Tab<MSTR>, you'd have two MSTRs pointing to the same memory. Then when the second one gets deleted it will be trying to double free that memory. - So again, you should only put things in a that don't allocate and deallocate memory in their destructors. Thus, this class should not be used with classes that implement an assignment operator and or destructor because neither are guaranteed to be called. The way around this is to use a table of pointers to the items. For example, instead of Tab<MSTR> use <MSTR *>. As another example, is OK, while Tab<BitArray> would be no good. In the case one should use class pointers, i.e. Tab<BitArray *>. - All methods of this class are implemented by the system except the compare function used in sorting (see Sort()). - - - - - Initializes a instance. - - - Provides a way of initializing a instance outside of its constructor, such as when they are are in-place constructed (constructed in pre-allocated memory). - - - - - Retrieves the number of items in the . - - - The number of items in use in the - - - - - Retrieves the number of items in the . Standard compliant. - - - The number of items in the tab. - - - - - Resets the number of used items to zero. - - - WARNING: Using this method does not free any of the allocated memory stored. - - - - - Sets the number of used items. - - - - The number of used items to set - If TRUE, the is resized to n items - - - - Returns the address of the i-th item. - - - Pointer to the i-th item - This method returns a pointer which may be invalid after subsequent Insert, Append, Delete, Resize, or Shrink operations. - - The index of the item whose address is to be returned. If the index is out of bounds it will throw a exception. - - - - Returns a pointer to the data buffer of tab. Standard compliant. - - - A pointer to the tab data buffer. - - - - - Inserts items in the at a specified position. - - - If the insertion was successful, returns the value of at. - - Index where to insert the items. - of items to insert - Pointer to the start of an array of items to insert - - - - Appends items at the end of the . - - - Returns the number of items in use (count of items) prior to appending - - of items to append - Pointer to the start of an array of items to insert - of extra elements to be allocated in order to enlarge the . - - - - Deletes items from the . - - - The number of items left in the table - - The index of the item the deletion starts at - The number of items to be deleted - - - - Changes the number of items allocated in memory. - - - Resize sets the amount of allocated memory, but doesn't change the actual number of items said to be in the tab So if you know you will want a with 1000 items, you could use Resize to pre-allocate the memory for the 1000 items, and then use Append to add each item without taking a hit on reallocs as the count increases - Nonzero if the array was resized; otherwise 0. - - The new size (in number of items) of the array - - - - Frees unused items to reduce memory footprint. - - - - - Sorts the array using the compare function. - - - : Sort() uses the C library qsort function. 3rd party developers must implement the CompareFnc function. The return value of CompareFnc is show below: < 0 - if item1 less than item2 0 - if item 1 is identical to item2 - - Pointer to the comparison function to the used by Sort to compare items. - - - - Assignment operator. - - - The objects pointed to by the items are not copied, only the items are copied. - Reference to this - - The to copy the items from - - - - Accesses the i-th item. - - - Reference to the object in the i-th item. - - The index of the item to access. If the index is out of bounds it will throw a exception. The index is bounds checked. - - - - Accesses the begin iterator, which is a plain pointer in this case. - - - - - Accesses the end iterator (one past last valid element). Do not dereference. - - - - - This method is called whenever a tablet event is detected. All attributes of the event are available via the 's access methods. When plugins receive this callback, they can query the as desired to retrieve more information about the tablet event. - - - - - The provides a convenient centralized interface for working with pressure-sensitive graphics tablets in 3ds Max. Plugins register a object that receives notifications whenever a user interacts with a graphics tablet. For example code showing the use of the , see maxsdk/samples/PainterInterface - - - - - This method is called to register a object. This object's Event method will be called whenever a connected graphics tablet sends an event message. The user of the tablet can then call the various methods to access the tablet stylus position, pressure, tilt, etc. - true if the callback was registered, false otherwise - - - The object that will receive the event updates - - - - This method is called to unregister a object previously registered via RegisterTabletCallback. - true if the callback was unregistered, false otherwise - - - The object that will be unregistered - - - - This method returns whether or not the tablet pen is touching the tablet surface. - true if the stylus is touching the tablet surface, false otherwise - - - - - This method returns the pressure with which the tablet stylus is touching the tablet surface. Range is 0.0 - 1.0. - The stylus pressure, range 0.0 - 1.0 - - - - - This method returns the rotation angle of the tablet stylus, if the stylus supports rotation angle output. Returns the rotation of the current tool in degrees, where zero means the tip of the stylus is pointing towards the top of the tablet, a positive value means it's turned to the right, and a negative value means it's turned to the left. If the device does not support rotation, this value is always 0.0. - The stylus rotation angle - - - - - This method returns the tangential pressure for the device, if it is supported. This is typically given by a finger wheel on an airbrush tool. The range is from -1.0 to 1.0. 0.0 indicates a neutral position. If the device does not support tangential pressure, this value is always 0.0. - The stylus tangential pressure - - - - - This method returns the x position of the device. - The x position - - - - - This method returns the y position of the device. - The y position - - - - - This method returns the z position of the device. Typically this is represented by a wheel on a 4D Mouse. If the device does not support a Z-axis, this value is always zero. - The z position - - - - - This method returns the angle between the device (a pen, for example) and the perpendicular in the direction of the x axis. Positive values are towards the tablet's physical right. The angle is in the range -60 to +60 degrees. - The x tilt - - - - - This method returns the angle between the device (a pen, for example) and the perpendicular in the direction of the y axis. Positive values are towards the tablet's physical right. The angle is in the range -60 to +60 degrees. - The y tilt - - - - - This method returns the type of stylus or pointing device that generated the event. - The pointer type - - - - - Description: - This smart pointer is used to simplify scope management - - - - - Description: - This class defines a 2D template object. This object is used to test shapes for self-intersection, clockwise status, point surrounding and intersection with other templates. The last and first points will be the same if it is closed. All methods of this class are implemented by the system. - - Note: Developers should normally use the class instead of this class. It provides methods for the same purposes; the class additionally provides the ability to optionally use more precise double-precision math in the SurroundsPoint(), SelfIntersects() and Intersects() methods. - Data Members: - int points; - - The number of points in the template. - - BOOL closed; - - Indicates if the template is closed. - - *pts; - - The template points. - - - - - Updates the template with the data from the specified . - Parameters: - *line - - Builds the template from this polyline. - - - - - Returns the number of points. - - - - - Returns TRUE if the specified point is surrounded (contained within) this . (Legacy single-precision version) - Parameters: - & point - - The point to check. - - - - - Returns TRUE if the specified point is surrounded (contained within) this , optionally using double-precision math for improved accuracy. - Parameters: - BOOL useDoubleMath - - When TRUE, uses double-precision math for calculations for more precise results, at some additional computational cost. - - & point - - The point to check. - - - - - Returns TRUE if the is clockwise in the XY plane (it ignores Z); otherwise FALSE. If the self intersects, the results from this method are meaningless. - - - - - Returns TRUE if the intersects itself in the XY plane (it ignores Z); otherwise FALSE. (Legacy single-precision version) - Parameters: - BOOL findAll = FALSE - - TRUE to find all self intersections. FALSE to find only the first self intersection. - - *cb = NULL - - A pointer to an class. - - - - - Returns TRUE if the intersects itself in the XY plane (it ignores Z); otherwise FALSE, optionally using double-precision math for improved accuracy. - Parameters: - BOOL useDoubleMath - - When TRUE, uses double-precision math for intersection calculations for more precise results, at some additional computational cost. - - BOOL findAll = FALSE - - TRUE to find all self intersections. FALSE to find only the first self intersection. - - *cb = NULL - - A pointer to an class. - - - - - Returns TRUE if the specified intersects this in the XY plane (it ignores Z); otherwise FALSE. (Legacy single-precision version) - Parameters: - &t - - The to check. - - BOOL findAll = FALSE - - TRUE to find all self intersections. FALSE to find only the first self intersection. - - *cb = NULL - - A pointer to an class. - - - - - Returns TRUE if the specified intersects this in the XY plane (it ignores Z); otherwise FALSE, optionally using double-precision math for improved accuracy. - Parameters: - BOOL useDoubleMath - - When TRUE, uses double-precision math for intersection calculations for more precise results, at some additional computational cost. - - &t - - The to check. - - BOOL findAll = FALSE - - TRUE to find all self intersections. FALSE to find only the first self intersection. - - *cb = NULL - - A pointer to an class. - - - - - Returns an instance of the class that contains two corner points defining the bounding box size of this template. - - - - - Description: - This class is used as a place to store values during Hold/Restore periods. All methods of this class are implemented by the system. For each key of data stored, you can only store 1 chunk of memory of different sizes. For example, 1 x 4 byte element, 1 x 8 byte element, etc. - - tmpStore; - - This is a global instance of whose methods may be called to store the values. For instance: - - tmpStore.PutBytes(sizeof(Quat), &curval, this); - - Note that the above code uses the plug-in's this pointer as the key to identify the owner of the data in the store. - - - - - This empties out the store. - - - - - This method puts bytes to the storage. - Parameters: - size_t num_bytes - - The number of bytes to put. - - const void *data - - Points to the data to put. - - const void *key - - A key to identify the data in the store. The address is the identifier. - - - - - This method gets bytes from the storage. The stored bytes will be copied into data. - Parameters: - size_t num_bytes - - The number of bytes to get. - - void *data - - Points to the data to get. - - void *key - - A key to identify the data in the store. The address is the identifier. - - - - - Remove a single entry from the storage. - Parameters: - const void *key - - A key to identify the data in the store. - - - - - Puts the specified floating point value to the storage. - Parameters: - float f - - The value to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves a floating point value from the storage. - Parameters: - float *f - - The value to retrieve is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Puts an int value in the storage. - Parameters: - int f - - The value to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves an integer point value from the storage. - Parameters: - int *f - - The value to retrieve is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Puts a value to the storage. - Parameters: - f - - The value to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves a value from the storage. - Parameters: - *f - - The value to retrieve is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Puts a value to the storage. - Parameters: - f - - The value to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves a value from the storage. - Parameters: - *f - - The value to retrieve is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Puts a quaternion value to the storage. - Parameters: - f - - The quaternion to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves a quaternion from the storage. - Parameters: - *f - - The quaternion retrieved is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Puts a to the storage. - Parameters: - f - - The value to store. - - const void *key - - A key to identify the data in the store. - - - - - Retrieves a from the storage. - Parameters: - *f - - The retrieved value is stored here. - - const void *key - - A key to identify the data in the store. - - - - - Description: - This class describes the properties of a tesselation approximation to the mathematical surface. - - All methods of this class are implemented by the system. - Data Members: - TessType type; - - These are the types of tesselation (one of which is obsolete). One of the following values: - - TESS_SET - - This is the old form of tesselation for Bezier Patches. This is also the default for these patches. For instance, if you create a Quad and apply an Edit modifier, then exit sub-object mode, you'll see a panel in the rollup for 'Tesselation'. The top choice is 'Fixed (original)'. This is the same type of tesselation done in 3ds Max 1.x. - - TESS_PARAM - - Specifies parametric tesselation. This provides for a fixed number of u by v tesselations. There are u times v quadrilaterals and each one is split up into two triangles. - - TESS_SPATIAL - - Specifies spatial tesselation. This uses edge as its parameter. This specifies that the size of the tesselation will be the edge length (see below). In view dependent tesselation edge is specified in pixels. - - TESS_CURVE - - Specifies view dependent tesselation. This uses the ang and dist data members described below. - - TESS_LDA - - This option is available in release 3.0 and later only. - - Specifies a method which combines the spatial (edge-length) method and the curvature (distance and angle) methods. This uses the ang, dist and edge data members below. - - TESS_REGULAR - - This option is available in release 3.0 and later only. - - Generates a fixed, regular tessellation across the surface. There are no additional parameters. - - TESS_ISO - - Obsolete - Do Not Use. - - ViewConfig vpt_cfg; - - This determines what is displayed in the interactive renderer. These correspond to the controls in the user interface (under Surface/Approximation/Viewports). This is not available for bezier patches. One of the following values: - - ISO_ONLY - - Only Iso lines. Iso(parametric) lines are similar to contour lines. The lines show where the NURBS surface has a constant U value or V value or both. Iso line representations can be less crowded and easier to visualize than wire mesh representations.. - - ISO_AND_MESH - - Iso lines and the mesh. When chosen, wireframe viewports display iso line representations of the surface, and shaded viewports display the shaded surface. - - MESH_ONLY - - Just the mesh. When chosen, wireframe viewports display the surface as a wire mesh, and shaded viewports display the shaded surface. In wireframe viewports, this option lets you see the curve approximation used for viewports. - - TessSubdivStyle subdiv; - - This data member is available in release 3.0 and later only. - - The type of subdivision. One of the following values: - - SUBDIV_TREE - - Subdivides the surface using a binary tree. - - SUBDIV_GRID - - Subdivides the surface using a regular grid. - - SUBDIV_DELAUNAY - - Subdivides the surface using nearly equilateral triangles. - - BOOL view; - - Specifies if this is view dependent tesselation. If TRUE this will tesselate less finely the farther away from the camera the object is. If FALSE the tesselation does not change based on distance from the camera. - - int u; - - This is used for parametric tesselation. This is the number of tesselations in u. This is the number of sub-divisions for a knot span for the surface. - - int v; - - This is used for parametric tesselation. This is the number of tesselations in v. - - int u_iso; - - This is used with the ISO line display. This is the number of additional interior iso lines in u (there are always lines along the outter edges). - - int v_iso; - - This is used with the ISO line display. This is the number of additional interior iso lines in v (there are always lines along the outter edges). - - float ang; - - This is used in curvature dependent tesselation (TESS_CURVE). If 0.0 is specified this is ignored. If specified this ensure that no two adjacent face normals exceed this angle between them. This value is specified in radians. - - float dist; - - This is used in curvature dependent tesselation (TESS_CURVE). If 0.0 is specified this is ignored. This specifies a distance that cannot be exceeded between a vertex on the mesh and the mathematical surface. This is defined as a percentage of the diagonal of the bounding box of the individual surface in object space. For instance if this was set to 1.0, the allowable error in generating a tesselation would be 1% of the bounding box diagonal distance of the surface. This would be 1/100 (1 %) of the diagonal distance of the bounding box. In this way if an object is scaled the tesselation remains the same. Additionally, if you have an object with a big surface and a little surface, the smaller surface will get tesselated more finely because its own bounding box is used. This prevents the smaller surface from just becoming a single triangle for example. - - float edge; - - This is the length of an edge to use in spatial (TESS_SPATIAL) tesselation. In view dependent tesselation this is specified in pixels. If not in view dependent tesselation this is a percentage of the bounding box diagonal length. - - int minSub; - - This data member is available in release 3.0 and later only. - - For Grid or Tree subdivisions, this limit controls the number of recursive decompositions that are performed during tessellation. This is the minimum number of recursions. - - int maxSub; - - This data member is available in release 3.0 and later only. - - For Grid or Tree subdivisions, this limit controls the number of recursive decompositions that are performed during tessellation. This is the maximum number of recursions. - - int maxTris; - - This data member is available in release 3.0 and later only. - - For Delaunay subdivision, this specifies the maximum mumber of triangles into which the surface will be divided. - - - - - Assignment operator. - Parameters: - &tess - - The object to assign. - - - - - Equality operator. Returns nonzero if they are equal; otherwise zero. - Parameters: - &tess - - The object to compare. - - - - - Description: - Developers that have created a 3D Studio/DOS SXP and a corresponding 3ds Max texture plug-in may want to subclass from this class. It provides a way to have an instance of your 3ds Max texture plug-in created automatically when the corresponding SXP is found in a 3DS file being imported. - - This works as follows: - - In the 3ds Max texture plug-in's implementation of DllMain() the following function is called: - - void RegisterSXPReader(const MCHAR *sxpName, Class_ID cid); - - The plug-in passes its own SXP name (i.e. "MARBLE_I.SXP") and its own . - - The system then remembers this. When the 3DStudio import plug-ins is loading a .3DS file and it encounters an SXP with this name, it will create an instance of the plug-in class (using the ) and call the method of this class ReadSXPData(). The plug-in can then initialize itself with proper values by reading the old SXP data. - - A sample plug-in that uses this technique is the 3ds Max Marble texture. It imports the settings from the 3D Studio Marble SXP. See the sample code in /MAXSDK/SAMPLES/MATERIALS/MARBLE.CPP. - - - - - This method is called when the 3D Studio/DOS import plug-in encounters an SXP with the name registered by RegisterSXPReader(). - Parameters: - MCHAR *pName - - The name of the SXP. - - void *sxpdata - - This is the SXP's initialization data. The plug-in can look at this data to see what numbers it was initialized to in the .3DS file being imported. It can then set its initial value to match the SXP settings. - - - - - Description: - This is the base class for the creation of texture map plug-ins. It provides methods for things such as calculating the color of the map for a given location, and computing a perturbation to apply to a normal for bump mapping. - - Note: Developers creating procedural textures should be aware that these textures may appear less than perfect when a 3ds Max user is using the "QuickRenderer" in the Materials Editor. This is not the fault of the plug-in texture, it is simply that the "Quick Renderer" uses an algorithm that is quicker but less accurate than the standard scanline renderer. Therefore, don't be concerned if your texture does not show up perfectly when using "QuickRenderer". - Plug-In Information: - Class Defined In IMTL.H - - Super Class ID TEXMAP_CLASS_ID - - Standard File Extension DLT - - Extra Include Files Needed IMTL.H (and optionally TEXUTIL.H) - Additional Information Related to Bump Mapping: - The following function evaluates the normal perturbation vector in the texture. - The function GetBumpDP() returns the "bump basis vectors". These are the gradient vectors of the UVW mapping - in the object coordinate space. The following function is used to compute the U and V bump basis vectors for a triangle given the texture coordinates at the three vertices of the triangle ( tv[ ] ) and the 3D coordinates at the vertices ( v[ ] ). It is simply a solution using linear algebra for the U and V axes in terms of the XYZ coordinates. It returns: - - - The three 's returned in bvec are stored away, and then simply returned in the function SContext::GetBumpDP(). The function UVGen::EvalDeriv() evaluates the local derivative of the texture map in the U and V directions, taking into account symmetry and scaling. The resulting derivative, dM, is scaled down from the value returned by EvalDeriv to keep the bump perturbations in a more reasonable range. The perturbation vector is calculated as: - - And, then passed through the texout->Filter function, which is just the following: - - - - - - - This method is called to evaluate the color of the texture map for the context. This is for channels that have a color such as diffuse, specular, ambient, etc. This method is called for every pixel of the texture. - Parameters: - & sc - - Describes the properties of the pixel to evaluate. - An object which stores the r, g, b, a values. Note: The alpha is pre multiplied, and the alpha value goes into AColor::a. - - - - - Evaluate the map for a "mono" channel. Mono channels are those that don't have a color, but rather a single value. This is for things like shininess, transparency, etc. This just permits a bit of optimization. - Parameters: - & sc - - Describes the properties of the pixel to evaluate. - A floating point value for the mono channel. - Default Implementation: - {return Intens(EvalColor(sc));} - - - - - This method is used for bump mapping to retrieve a perturbation to apply to a normal. - Parameters: - & sc - - Describes the properties of the pixel to evaluate. - A deflection vector for perturbing the normal. - - - - - This query is made of maps plugged into the Reflection or Refraction slots: Normally the view vector is replaced with a reflected or refracted one before calling the map: if the plugged in map doesn't need this, it should return TRUE. - Default Implementation: - { return FALSE; } - - - - - This method is called to retrieve the UV transformation matrix for use in the viewports. If a developer is using an instance of , a method of that class may be called to retrieve the value: - - (i.e. { uvGen->GetUVTransform(uvtrans); } ). - Parameters: - &uvtrans - - The transformation matrix is returned here. - Default Implementation: - {} - - - - - This method is called to get the tiling state of the texture for use in the viewports. This is described by a set of symmetry flags that may be ORed together. If you are using an instance of to handle the UV user interface you may simply call a method of to handle this. - - For example: GetTextureTiling(); } - See Texture Symmetry Flags. - Default Implementation: - { return U_WRAP|V_WRAP; } - - - - - Returns a value indicating where to get the texture vertices for the . - One of the following values: - - UVWSRC_EXPLICIT - - Use explicit mesh texture vertices from one of the mapping channels (see GetMapChannel() below to determine which one). This uses the UVW coordinates assigned to the object, either through the Generate Mapping Coordinates option in the object's creation parameters, or through mapping modifiers, such as UVW Map. - - UVWSRC_EXPLICIT2 - - Use explicit mesh texture vertices from the Vertex Channel. - - UVWSRC_OBJXYZ - - Generate planar UVW mapping coordinates from the object local XYZ on-the-fly. This corresponds to the "Planar from Object XYZ" option. - - UVWSRC_WORLDXYZ - - This value is available in release 3.0 and later only. - - Generate planar UVW mapping coordinates from the world XYZ on-the-fly. This corresponds to the "Planar From World XYZ" option. Note: this value used for the UVW is the world XYZ, taken directly, with out normalization to the objects bounding box. This differs from "Planar from Object XYZ", where the values are normalized to the object's bounding box. - Default Implementation: - { return UVWSRC_EXPLICIT; } - - - - - Returns the map channel being used by the texmap if GetUVWSource() returns UVWSRC_EXPLICIT. The return value should be at least 1. A value of 0 is not acceptable. - Default Implementation: - { return 1; } - - - - - This method is called to initialize the slot type. This sets the proper button in the coordinate user interface rollup page. If you are using an instance of to handle the UV user interface you may simply call a method of to handle this. For example: { if (uvGen) uvGen->InitSlotType(sType); } - Parameters: - int sType - - See Map Slot Types. - Default Implementation: - {} - - - - - Texture maps that use a should implement this method to return a pointer to it. - Default Implementation: - { return NULL; } - - - - - Texture maps that use a should implement this method to return a pointer to it. - Default Implementation: - { return NULL; } - - - - - Sets the output level at the specified time. It is used to set the output level of the embedded Texout object, principally by importing plug-ins. It is implemented in all Texmaps. - Parameters: - TimeValue t - - The time to set the output level. - - float v - - The value to set. - Default Implementation: - {} - - - - - Implemented by the system. - - Returns true only if all submaps and itself have a meaningful output. - - Returns false if at least one sub-texmap or itself does not have a meaningful output - - The output of a texmap is meaningful in a given if it is the same as when the scene is rendered. If the map cannot determine whether the output value is the same as when rendered, it should not be meaningful. This method can be called before EvalColor() or EvalMono() on a texmap in order to decide whether to call these methods at all or if their return values should be used in further calculations. - Parameters: - & sc - - This describes the context of the question. - - - - - Returns TRUE if the output of this texmap is meaningful for the given context; it should not take into account subtexmaps. This method is called by IsOutputMeaningful(). - Parameters: - & sc - - This describes the context of the question. - Default Implementation: - { return false; } - - - - - This method is called prior to rendering to allow the plug-in to load any bitmap files it requires. - - Note that LoadMapFiles() is called to load map files only, not to list the missing files. The missing files are listed using the EnumAuxFiles() method, which allows enumerating them without loading them. - - Also Note: There is currently not an UnloadMapFiles() method. There are a couple of ways to do this however. One is to call Interface::FreeAllBitmaps(). That method traverses the scene reference hierarchy and calls Animatable::FreeAllBitmaps() on each item. Another approach is to evaluate the / TextureMap hierarchy on each material. Then call Animatable::FreeAllBitmaps() yourself in the MtlEnum::proc() shown below. - - Now just define a subclass of MtlEnum that does what you want, and call EnumMtlTree. In this particular case it is more efficient than enumerating the entire reference hierarchy. If you do want to enumerate the entire reference hierarchy, here's how: - - Just define a subclass of that does what you want, and call EnumRefs on the part of the reference hierarchy you want to enumerate. For example: - - - Parameters: - TimeValue t - - The time the maps are being loaded. - Always return nonzero from this method. - Default Implementation: - { return 1; } - - - - - This method is used to render a 2D bitmap version of this texmap. - Parameters: - TimeValue t - - The time at which to render the texmap to the bitmap. - - *bm - - A pointer to a bitmap to render to. This bitmap must be created at the resolution you wish to render to. - - float scale3D=1.0f - - This is a scale factor applied to 3D Texmaps. This is the scale of the surface in 3d space that is mapped to UV. This controls how much of the texture appears in the bitmap representation. - - BOOL filter = FALSE - - If TRUE the bitmap is filtered. It is quite a bit slower to rescale bitmaps with filtering on. - Default Implementation: - The default implementation calls Interface::RenderTexmap(). - - - - - This gets the viewport display bitmap in DIB format, useful when combining several maps for hardware-supported multiple texture display. If mono is TRUE, the map should do a mono evaluation and place the result in RGB. forceW and forceH, if non-zero, override dimensions specified by thmaker. - Parameters: - TimeValue t - - The time to get the bitmap at. - - & thmaker - - This class provides methods for creating a texture handle from a 3ds Max bitmap and a Windows DIB. It also has a method to retrieve the required size of the texture map. See Class . - - &valid - - The validity interval of the returned bitmap. - - BOOL mono - - Indicates whether a map should do mono evaluation. - - int forceW - - Overrides the bitmap width usually supplied by thmaker. - - int forceH - - Overrides the bitmap height usually supplied by thmaker. - - - - - Implemented by the System. - - This method is used internally to set the slot type for all subtexmaps in a tree. - - - - - Returns nonzero if the texture is returning high dynamic range data; otherwise zero. - Default Implementation: - { return false; } - - - - - Description: - This is simply a class that provides an implementation of Animatable::SuperClassID() to return TEXMAP_CONTAINER_CLASS_ID. In 3ds Max 2.0 and later this new super class has been added. This is used by the Standard material to contain its Texmaps. The track view filter code has been modified so it now looks for this class and will filter it out when maps are being filtered out, instead of having special purpose code for the Standard . This will permit plug-in developers to put their Texmaps down in a sub-directory like the Standard material does. - - - - - Description: - This class describes a texture used by the interactive renderer. This includes all the information about the mapping channel, tiling, etc. A table of these is maintained by the texture data member of class . - - There are data members related to maps which specify how the texture should be applied. These are specified independently for color and alpha and include a scale. For example, for normal multiplication (modulation) application of a texture, the entries would be: - - colorOp = GW_TEX_MODULATE - - colorAlphaSource = GW_TEX_TEXTURE - - colorScale = GW_TEX_SCALE_1X - - alphaOp = GW_TEX_MODULATE - - alphaAlphaSource = GW_TEX_TEXTURE - - alphaScale = GW_TEX_SCALE_1X - - For applying a texture with alpha blending, the entry would be: - - colorOp = GW_TEX_ALPHA_BLEND - - colorAlphaSource = GW_TEX_TEXTURE - - colorScale = GW_TEX_SCALE_1X - - alphaOp = GW_TEX_LEAVE - - alphaAlphaSource = GW_TEX_TEXTURE - - alphaScale = GW_TEX_SCALE_1X - - For applying an opacity map, the entry would be: - - colorOp = GW_TEX_LEAVE - - colorAlphaSource = GW_TEX_TEXTURE - - colorScale = GW_TEX_SCALE_1X - - alphaOp = GW_TEX_REPLACE - - alphaAlphaSource = GW_TEX_TEXTURE - - alphaScale = GW_TEX_SCALE_1X - Data Members: - int useTex; - - Indicates if the material uses textures. Nonzero indicates textures are used. - - int faceMap; - - Indicates if the material is face mapped. Nonzero indicates it is. - - DWORD_PTR textHandle; - - The texture handle. - - int uvwSource; - - The UVW source used. - - UVSOURCE_MESH - - Use UVW coordinates from a standard map channel. - - UVSOURCE_XYZ - - Compute UVW from object XYZ. - - UVSOURCE_MESH2 - - Use UVW2 (Vertex ) coordinates. - - UVSOURCE_WORLDXYZ - - Use World XYZ as UVW. - - int mapChannel; - - The mapping channel used. - - textTM; - - The texture transformation matrix. - - UBYTE tiling[3]; - - The UVW tiling. One of the following values: - - GW_TEX_REPEAT - - GW_TEX_MIRROR - - GW_TEX_NO_TILING - - UBYTE colorOp; - - The color texture operation. One of the following values: - - GW_TEX_LEAVE - - Use the source pixel value - - GW_TEX_REPLACE - - Use the texture pixel value - - GW_TEX_MODULATE - - Multiply the source with the texture - - GW_TEX_ADD - - Add the source and texture - - GW_TEX_ADD_SIGNED - - Add the source and texture with an 0.5 subtraction - - GW_TEX_SUBTRACT - - Subtract the source from the texture - - GW_TEX_ADD_SMOOTH - - Add the source and the texture then subtract their product - - GW_TEX_ALPHA_BLEND - - Alpha blend the texture with the source - - GW_TEX_PREMULT_ALPHA_BLEND - - Alpha blend the source with a premultiplied alpha - - UBYTE colorAlphaSource; - - The color blend alpha source. One of the following values: - - GW_TEX_ZERO - - Use no alpha value - - GW_TEX_SOURCE - - Use the source alpha - - GW_TEX_TEXTURE - - Use the texture alpha - - GW_TEX_CONSTANT - - Use a constant BGRA color as an alpha - - GW_TEX_PREVIOUS - - Use the previous texture stage alpha - - UBYTE colorScale; - - The color scale factor. One of the following values: - - GW_TEX_SCALE_1X - - Multiply the tex op result by 1 - - GW_TEX_SCALE_2X - - Multiply the tex op result by 2 - - GW_TEX_SCALE_4X - - Multiply the tex op result by 4 - - UBYTE alphaOp; - - The alpha texture operation. One of the following values: - - GW_TEX_LEAVE - - Use the source pixel value - - GW_TEX_REPLACE - - Use the texture pixel value - - GW_TEX_MODULATE - - Multiply the source with the texture - - GW_TEX_ADD - - Add the source and texture - - GW_TEX_ADD_SIGNED - - Add the source and texture with an 0.5 subtraction - - GW_TEX_SUBTRACT - - Subtract the source from the texture - - GW_TEX_ADD_SMOOTH - - Add the source and the texture then subtract their product - - GW_TEX_ALPHA_BLEND - - Alpha blend the texture with the source - - GW_TEX_PREMULT_ALPHA_BLEND - - Alpha blend the source with a premultiplied alpha - - UBYTE alphaAlphaSource; - - The alpha blend alpha source. One of the following values: - - GW_TEX_ZERO - - Use no alpha value - - GW_TEX_SOURCE - - Use the source alpha - - GW_TEX_TEXTURE - - Use the texture alpha - - GW_TEX_CONSTANT - - Use a constant BGRA color as an alpha - - GW_TEX_PREVIOUS - - Use the previous texture stage alpha - - UBYTE alphaScale; - - The alpha scale factor. One of the following values: - - GW_TEX_SCALE_1X - - Multiply the tex op result by 1 - - GW_TEX_SCALE_2X - - Multiply the tex op result by 2 - - GW_TEX_SCALE_4X - - Multiply the tex op result by 4 - - - - - Compares this class instance to another one - - - - - Description: - This class is used by texture maps to put up the 'Output' rollup in the materials editor, and perform the output filtering. Currently this provides control over the Output Amount, RGB Level, and RGB Offset. In the future this may be enhanced to include other things that are often desirable on the output stage. These are things like tinting, color shifting, etc. All methods of this class are implemented by the system. - - A plug-in will typically call these methods from the implementations of EvalColor(), EvalMono(), etc. This is just done as a final adjustment to scale or offset the value. The code below is from the Gradient texture map. - - - - - Filters the specified and returns it. - Parameters: - c - - The color to filter. - The filtered color as an . - - - - - Filters the specified float value and returns it. - Parameters: - float f - - The value to filter. - The filtered value. - - - - - Filters the specified value and returns it. - Parameters: - p - - The to filter. - The filtered . - - - - - Returns the output level (amount) at the specified time. - Parameters: - TimeValue t - - The time at which to retrieve the output level. - - - - - Sets the output level at the specified time. - Parameters: - TimeValue t - - The time to set the output level. - - float v - - The value of the output level. - - - - - Returns the state of the 'Invert' toggle in the Output rollup. - TRUE is on; FALSE is off. - - - - - Returns the open or closed state of the 'Output' rollup. - TRUE for open; FALSE for closed. - - - - - Description: - Use this class to provide drag and drop functionality for materials sub-Texmaps. It provides implementations of the methods of . If this class is used the method FindSubTexFromHWND() must be implemented. - - - - - Description: - This class defines a texture handle. A pointer to an instance of this class is returned from the methods of . Methods of this class allow the handle to be retrieved and to delete the handle. - - - - - This method is called to retrieve the texture handle. - - - - - Description: - This class provides several ways to create a texture handle. The handle may be created from a 3ds Max bitmap or a Windows Device Independent . This class also provides methods to determine the desired size of the bitmap. - - - - - - Implemented by the System - - This method is called to create a texture handle from a 3ds Max bitmap. - Parameters: - *bm - - The bitmap to create a handle to. - - int symflags=0 - - See Texture Symmetry Flagsint extraFlags=0; - - One of the following values: - - EX_MULT_ALPHA - - this flag if alpha is not pre-multiplied in the . - - EX_RGB_FROM_ALPHA - - this flag to make the map using the alpha channel of the bitmap to define the gray level. - - EX_OPAQUE_ALPHA - - Specifies to make the map using opaque alpha. - - EX_ALPHA_FROM_RGB - - Specifies to make alpha from the intensity of the map. - A pointer to the texture handle. - - - - - This method creates a 32 bit Windows Device Independent with the specified symflags and extraflags already incorporated and returns a pointer to the associated . - Parameters: - *bm - - Points to the bitmap to create the handle to. - - int symflags - - See Texture Symmetry Flagsint extraFlags - - One of the following values: - - EX_MULT_ALPHA - - this flag if alpha is not pre-multiplied in the . - - EX_RGB_FROM_ALPHA - - this flag to make the map using the alpha channel of the bitmap to define the gray level. - - EX_OPAQUE_ALPHA - - Specifies to make the map using opaque alpha. - - EX_ALPHA_FROM_RGB - - Specifies to make alpha from the intensity of the map. - - BOOL forceW=0 - - If this parameter is non-zero it is used as the width of the final DIB. - - BOOL forceH=0 - - If this parameter is non-zero it is used as the height of the final DIB - - - - - Returns TRUE if the bitmap does not need to be square and FALSE if it does need to be square. - - - - - Implemented by the System. - - This method may be called to determine the desired size for the bitmap. The system ultimately needs a square bitmap that is a power of 2 in width and height. If you already have a bitmap around, just pass it in to CreateHandle() and it will be converted. If you are creating a bitmap from scratch (i.e. a procedural texture), then you should make it Size() in width in height, and save the system an extra step. In either case you own your bitmap, and are responsible for ultimately freeing it. - The size of the desired bitmap. - - - - - Description: - This class provides a callback when the user moves the Video Post time slider. This happens internally, developers must only respond to the FLT_TIMECHANGED message. See ImageFilter-Related Messages. - Data Members: - BOOL set; - - Indicate the callback is register with 3ds Max. - - *filter; - - Points to the filter who's notified on the time change. - - - - - Description: - A callback object passed to Interface::RegisterTimeChangeCallback(). The method TimeChanged()is called every time the current animation time is changed. - - - - - This method is called every time the current animation time is changed. - Parameters: - TimeValue t - - The new animation time value. - - - - - - - Description: - This class is used by Animatable::MapKeys(). It provides a method map() that is used to apply the mapping required by the system to the TimeValue passed. - - - - - Implemented by the System. - - This is a time map function that takes a TimeValue and returns a TimeValue. A plug-in developer just calls this map method to alter the TimeValue. - Parameters: - TimeValue t - - This is the input time. - The modified time. - - - - - This method is not used. - - - - - This is the base class for plugins which perform tone mapping operations in 3ds Max. - - - The tone mapping process - - Renderers typically perform lighting simulation in physical space, using units like candelas or watts to represent the intensity of light. If they do not strictly use physical units, they will at least perform calculations in linear space. Rendered images, however, are typically expressed in RGB space (usually sRGB), which is usually non-linear. The purpose of the tone operator (or tone mapper) is to transform linear, physical quantities into (potentially non-linear) RGB values. This process is similar to what happens when photographic film or sensors convert photons into colors (either chemically or electronically). - The physical scale - - The physical scale is used to reconcile physical and non-physical light sources in a scene; it defines the equivalence between a photometric light that emits in candelas and a standard light that emits in arbtrary units. For example, a physical scale of 1500 would cause a non-physical emissive surface with a value of PI (3.1416) to emit 1500 cd/m^2. The physical scale affects environment lighting as well; non-physical envrionment lighting will be affected in the same way. - - The tone operator expects that all physical values be pre-divided by the physical scale. That is, any value fed to ScaledToRGB() is expected to be expressed in candela/physical_scale. The physical scale therefore adjusts physical values, rather than non-physical ones, in order to preserve compatibility with legacy features that were implemented before the concept of physical units was introduced to 3ds Max. The will multiply any values fed to ScaledToRGB() by the physical scale to undo this division. - Inverse tone mapping - - The process of converting an RGB value back into physical quantities is called inverse tone mapping. This process is especially useful when rendering with a backgorund or environment image which is already expressed in non-linear, RGB values. The image in question must first be inverse-tone-mapped to ensure that, once it goes through the rendering and tone mapping processes, it looks exactly as it did originally. Ideally, all environment images fed to the renderer should be expressed in physical, linear quantities - but that is not always possible. - - - - - Initializes the tone operator at the given time, and with the given camera & view options. This method needs to be called before any functionality is used - for example, before ScaledToRGB() is called. It enables the to initialize itself with the given view parameters, as well as cache data which would be costly to compute for every pixel. Using the tone operator without previously calling this method will result in incorrect tone mapping: the parameters being used may not be updated for the correct time or camera. - - - - The time at which the tone operator is to be evaluated. - The camera node being used for rendering. The tone operator is free to affect the tone mapping process based on the camera parameters. - The resolution being rendered, used to determine the position in raster space when calling ScaleToRGB(). - The pixel aspect ratio, which can be used to derive an image aspect ratio. - The validity of the parameters which were evaluated by the call. - - - - Scales a value from physical space to RGB space. Rendered images, as directly output by renderers, will store values in physical units (candelas per meter-squared) which must be transformed into RGB space before they can be viewed on a monitor. This method performs this transformation. - - - - The physical RGB value, which gets converted in-place into an RGB value. - The x/y coordinate of the pixel being scaled, the valid range being [0, renderResolution] (renderResolution having been passed to ). - - - - Scales a grayscale value from physical space to RGB space. - - - - The physical RGB value, which gets converted in-place into an RGB value. - The x/y coordinate of the pixel being scaled, the valid range being [0, renderResolution] (renderResolution having been passed to ). - - - - Equivalent of virtual void ScaledToRGB(float energy[3], const Point2& xyCoord) const, but without any support for view-dependent tone mapping. - - - - - Equivalent of virtual void ScaledToRGB(float energy, const Point2& xyCoord) const, but without any support for view-dependent tone mapping. - - - - - For a full description of the physical scale, see the details description for class . - - The time at which to fetch the phyisical scale. - The validity of the physical scale value is intersected into this interval. - - - - Sets the physical scale to be used when rendering. - - - For a full description of the physical scale, see the details description for class . - - The new physical scale. - The time at which to set the new physical scale. - - - - Scale physical values so they can be used in the renderer. The first version of the method converts a color value and the second converts a monochrome value. The converted color value is stored in energy. The converted monochrome value is returned. This method assumes that Update has been called to cache the various values needed by the tone operator. By using a float array to pass in color values, we can use the same routine to handle the various classes used to store color information, for example, , and . The red, green and blue components are stored in that order in the array. - This method is used to scale a physical color value so it may be used in the renderer. - - This method assumes that Update has been called to cache the various values needed by the tone operator. - - Note: By using a float array to pass in color values, we can use the same routine to handle the various classes used to store color information, for example, , and . - - The input and output (converted) color value. The colors are stored as red=energy[0], green=energy[1], and blue=energy[2]. - - - - Grayscale version of virtual void ScalePhysical(float energy[3]) const - - - - - Scale RGB values, just supplied to invert ScalePhysical. The first version of the method converts a color value and the second converts a monochrome value. The converted color value is stored in energy. The converted monochrome value is returned. This method assumes that Update has been called to cache the various values needed by the tone operator. By using a float array to pass in color values, we can use the same routine to handle the various classes used to store color information, for example, , and . The red, green and blue components are stored in that order in the array. - This method is called to scale RGB values (the inverse of ScalePhysical()). - - This method assumes that Update has been called to cache the various values needed by the tone operator. - - The input values to scale and storage for the output scaled values as well. The colors are stored as red=energy[0], green=energy[1], and blue=energy[2]. The output values are in the range 0-1. - - - - Grayscale version of virtual void ScaleRGB(float color[3]) const - - - - - Returns whether this supports the inversion functions. The inversion functions enable a to convert an RGB value back into physical units. This is especially useful for inverse tone-mapping the background map, should it not be affected by the tone operator. - - - - - Convers an RGB value back into physical space. This is effectively the inverse of ScaledToRGB(). - The must be initialized with Update() before this may be called. - - - - - Convers an RGB value back into physical space. This is effectively the inverse of ScaledToRGB(). - The must be initialized with Update() before this may be called. - - - - - Equivalent of virtual void InverseMap(float rgb[3], const Point2& xyCoord) const, but without any support for view-dependent tone mapping. - - - - - Equivalent of virtual void InverseMap(float rgb, const Point2& xyCoord) const, but without any support for view-dependent tone mapping. - - - - - Alias for InverseMap() - - - - - Alias for InverseMap() - - - - - Alias for InverseMap() - - - - - Alias for InverseMap() - - - - - This method indicates whether the tone operator is active. - The default implementation does not use the TimeValue t. The result of the default implementation can be retrieved using SpecialFX::GetActive. If you override this method and change the mechanism for storing this state, you should also override SpecialFX::GetActive so the correct state is returned. - - A boolean indicating if the tone operator is active. - The time at which the active check is made. - - - - Returns the state of A_TONEOP_PROCESS_BG, indicating whether the will be processing the background. - - - - - Returns whether tone mapping should apply to indirect lighting only. - - - - - This method is called for the operator to do any work it needs to do prior to rendering. Rendering using the uses the identity tone operator. - This method is called for the operator to do any work it needs to do prior to rendering. You may use this method to perform a subrender to sample the rendered output for histogramming or automatic exposure. - True means this method succeeded. False means it didn't. This method should return false if it the sub-render fails or if it can't allocate memory or some other error occurs. If BuildMaps returns false, the render is aborted. - - The time at which the rendering is taking place. - The context of the map rendering. - - - - This method is called during subrenders to give the tone operator a chance to sample the image with full dynamic range. If your operator needs to sample the image, you can set a flag so you know when you are sampling. - - - - - Allocates an interface which enables processing of the tone operator from arbitrary (or multiple) threads. - - - A pointer to a newly allocated interface which is then owned exclusively by the caller. The caller is responsible for deleting the pointer once done. May return null if the tone operator doesn't implement support for the interface, in which case the tone operator must be processed from the main thread, using ToneOperator::ScaledToRGB(). - This method may only be called from the main thread - as every other method in in this class. - The tone operator must be updated using ToneOperator::Update()before calling this method. The processor to be returned will reflect the parameter values setup by the last call to Update(). - - - - - Description: - This class allows plug-ins and the scripter to get access to the tone operator assigned to a scene. You can get a pointer to the interface using the global interface pointer in this manner: - - ToneOperatorInterace* toneOpInt = static_cast<ToneOperatorInterface*>( GetCOREInterface(TONE_OPERATOR_INTERFACE)); - - If the return value is NULL, the running version of 3ds Max doesn't support tone operators. If the return value is not NULL, you can use these methods to perform some scene management. - - - - - This method returns the current tone operator assigned to a scene. If no tone operator is assigned NULL is returned. - - - - - This method registers a callback that is called when the tone operator is changed. Note the definition of ToneChangeCallback: - - newOp, ToneOperator* oldOp, void* param); - Parameters: - ToneChangeCallback callback - - The callback to register. - - void* param - - This parameter is passed to the callback function as the parameter argument when it is called. - - - - - This method un-registers a callback that was registered by RegisterToneOperatorChangeNotification. Note the definition of ToneChangeCallback: - - newOp, ToneOperator* oldOp, void* param); - Parameters: - ToneChangeCallback callback - - The callback to un-register. - - void* param - - This parameter is passed to the callback function as the parameter argument when it is called. - - - - - This class describes the properties of a 3ds Max custom toolbar button. - - - Each one of these items represents a UI widget on a Toolbar in 3dsmax user interface. - - - - - Out Enabled. - - - The following four data members (iOutEn, iInEn, iOutDis, iInDis) are indices into the image list. They indicate which images to use for each of the four possible button states. You may specify a unique image for each one of these states by passing a different index for each state. Or you may supply a single image to be used for all the states by specifying the same index four times. - - - - - In Enabled. - - - - - Out Disabled. - - - - - In Disabled. - - - - - The width of the button image. - - - - - The height of the button image. - - - - - The label describing the tool button item. - - - - - A pointer to the icon image associated with the button. - - - - - A pointer to the pressed (or in) icon image associated with the button. - - - - - The icon name for loading a multi-resolution icon associated with the button. - - - - - Description: - This class allows a developer to use an image in the toolbar. This is used internally as part of the object snap code. All methods of this class are implemented by the system. - - - - - Description: - This class describes the properties of an item in a 3ds Max custom toolbar. - Data Members: - ToolItemType type; - - See Tool Item Typesint id - - The ID for the control. - - DWORD helpID - - For plug-in developers this id should be set to 0. Basically, the main 3ds Max help file contains help tags that are tied to various parts of the 3ds MaxUI, allowing the right help page to come up when UI help is requested. In particular, if you press the ? button on the toolbar, then press another toolbar button, you'll get help on that button's functionality. This is because internally pressing the button yields a help ID that indexes into the help file. But since the same help ID must be compiled into the help file and into MAX, and since the main 3ds Max help file can not be rebuilt by developers, they cannot use this functionality. - - int w - - The width of the button image. - - int h - - The height of the button image. - - int orient; - - The orientation of the item. One of the following values: - - CTB_HORIZ - - CTB_VERT - - CTB_FLOAT - - - - - Description: - This class allows a macro item control to be added to the toolbar. The identity of a macro button is determined by an action table id and a command id. - - - Data Members: - md; - - Points to the macro button data for this tool item. - - - - - Description: - This class is used to add any user defined or standard Windows control to a 3ds Max custom toolbar. - Data Members: - int y; - - The vertical justification. - - DWORD style; - - The control window style. - - MCHAR *className; - - The class name of the control. For the 3ds Max custom controls you may use one of the following #defines: - - SPINNERWINDOWCLASS - - ROLLUPWINDOWCLASS - - CUSTEDITWINDOWCLASS - - CUSTBUTTONWINDOWCLASS - - CUSTSTATUSWINDOWCLASS - - CUSTTOOLBARWINDOWCLASS - - CUSTIMAGEWINDOWCLASS - - COLORSWATCHWINDOWCLASS - - Or it may be a literal string such as: - - "COMBOBOX" - - See the Win32 API help under CreateWindow() for a list of the options here. - - MCHAR *windowText; - - The window text. This is displayed in controls that have text in them. - - - - - Description: - This class provides a toolbar separator object. This is used to space out buttons in the toolbar. - Data Members: - int vis; - - Visibility setting. - - - - - Description: - This class allows a status control to be added to the toolbar. - Data Members: - BOOL fixed; - - TRUE indicates a fixed width. If it is not fixed, then it will auto size itself horizontally based on the size of the toolbar. For an example of this see the status bar in the track view. - - - - - Internal use only. Hidden internal implementation for . - - - Description: - This class allows a developer to add tooltips to one or more window controls. Controls of all types are supported. One extender object can support all tooltips for a dialog, it's not necessary to create one extender per tooltip. This is useful for control types which do not have native tooltip support. - - - - - Sets a tooltip for an arbitrary UI control. Calling this twice for a single control is safe, and will remove the first tooltip. Calling this for multiple controls is allowed, as this class supports an unlimited number of tooltips. Note that tooltip resources are not automatically freed when a control is destroyed. Resources are freed when the extender is destroyed, or by calling RemoveToolTip() or Reset(). - - - - Handle to the window control. - ToolTip string. The string is copied, so the caller may safely delete this. - - - - Gets the tooltip for an arbitrary UI control. This only functions for tooltips set with this class. Returns an empty string if no tooltip is set. - - - - Handle to the window control. - ToolTipOutput string. The method will resize the string as necessary. - - - - Removes the tooltip from an arbitrary UI control. This only functions for tooltips set with this class. Note that tooltip resources are not automatically freed when a control is destroyed. Resources are freed when the extender is destroyed, or by calling this function or Reset(). - - - - Handle to the window control. - - - - Removes all tooltips and releases heap memory. - - - - - Returns a handle to the operating system's ToolTip object. This provides access to extended tooltip functionality. See the operating system's documentation for TOOLTIPS_CLASS. - - - - - Description: - If a plug-in supports track view copy/paste operations this object is used. A plug-in should derive a class from this base class to store the data associated with the objects tracks, and implement the methods that identify the creator of the clip object. - - - - - Specifies the interval of time clipped. - - - - - This method is used to identify the creator of the clip object by returning the SuperClassID of the creator. - - - - - Returns the ClassID of the creator of the clip object. - - - - - This method is available in release 2.0 and later only. - - Returns the number of keys in the clip object. - Default Implementation: - {return 0;} - - - - - This method is available in release 2.0 and later only. - - Retrieves the value of the 'i-th' key. - Parameters: - int i - - Specifies the key to return. - - void *val - - The value of the key is stored here. - TRUE if the value was retrieved; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - This method is available in release 2.0 and later only. - - Sets the value of the 'i-th' key. - Parameters: - int i - - Specifies the key to store. - - void *val - - The value of the key is passed here. - TRUE if the value was stored; otherwise FALSE. - Default Implementation: - {return FALSE;} - - - - - Description: - When hit testing is done, this class has data members used to identify the key that was hit. The manner these are used is up to the developer. For example, the hit member may be used as an index into the table of keys. If a developer needed additional information, the flags could be used. The system does not use these itself - the developer just needs to establish a consistent way to recognize its own keys and tag them as hit. - - There is a typedef that defines a table of these TrackHitRecords. It is defined as: - - > TrackHitTab; - - - - - Description: - This is the callback object for handling TrackView actions. - - - Data Members: - HWND mhWnd; - - The handle to the.window. - - - - - This method sets the window handle. - Parameters: - HWND hWnd - - The handle to the window you wish to set. - Default Implementation: - { mhWnd = hWnd; } - - - - - Description: - This is the callback object used to filter selections in the track view. - - - - - - This is the callback object proc used to filter selections in the track view. - Parameters: - *anim - - The item the user picked. - - *client - - The owner of the anim. - - int subNum - - The sub-animatable number of the anim. - Return TRUE to accept the anim as selectable; otherwise FALSE. - - - - - This method allows the filter to control the color of the label text used for the anim. - Parameters: - *anim - - The item the user picked. - - *client - - The owner of the anim. - - int subNum - - The sub-animatable number of the anim. - - COLORREF& color - - The color for the label text. See . - TRUE for the Treeview to use the color in the color argument, FALSE to ignore that color and use the system default. - Default Implementation: - { return FALSE; } - - - - - Description: - This class stores the result of a selection from the Track Pick dialog. - Data Members: - *anim; - - The item the user picked. - - *client; - - The owner of the anim. - - int subNum; - - Sub-animatable number of the anim. - - - - - Compares this class instance to another one - - - - - Description: - This is the base class for Track Utility plug-ins. These plug-ins are launched via the 'Track Utility' icon just to the left of the track view name field in the toolbar. Clicking on this button brings up a dialog of all the track view utilities currently installed in the system. Most utilities will probably be modeless floating dialogs, however modal utilities may be created as well. - - The developer will derive their classes from this class. Methods are provided to bracket the beginning and ending of parameter editing, and responding to various changes in Track (such as key selection, time selection, node selection, etc.). There is also a method to delete this instance of the plug-in class. Sample code is available in /MAXSDK/SAMPLES/UTILITIES/RANDKEYS.CPP, ORTKEYS.CPP and SELKEYS.CPP. - - - Plug-In Information: - Class Defined In: TVUTIL.H - Super Class ID: TRACKVIEW_UTILITY_CLASS_ID - Standard File Extension: DLU - Extra Include File Needed: None - - - - - - This method is called to begin editing of the Track utility plug-in's parameters. - Parameters: - *ip - - An interface for calling functions provided by 3ds Max. - - *iu - - An interface for allowing track view utilities to access the Track they are launched from. - Default Implementation: - {} - - - - - This method is called when the user has closed the Track utility or Track itself. - Parameters: - *ip - - An interface for calling functions provided by 3ds Max. - - *iu - - An interface for allowing track view utilities to access the Track they are launched from. - Default Implementation: - {} - - - - - This method is called when the selection of tracks has changed. - Default Implementation: - {} - - - - - This method is called when the selection of nodes has changed. - Default Implementation: - {} - - - - - This method is called when the selection of keys has changed. - Default Implementation: - {} - - - - - This method is called when the amount of time selected changes in Edit Time mode. See ITVUtility::GetTimeSelection(). - Default Implementation: - {} - - - - - This method is called if the current mode of Track changes. These are the modes such as Edit Keys, Edit Time, Edit Ranges, Position Ranges, and Edit Curves. See ITVUtility::GetMajorMode(). - Default Implementation: - {} - - - - - This method is called when the Track list is rebuild. This is the list of items that are visible (currently open). - Default Implementation: - {} - - - - - Description: - This class represents a renderable, deformable, triangle mesh object. All procedural objects must be able to convert themselves to TriObjects. This class provides implementations of all the required methods of , , , , , and . All methods of this class are implemented by the system. - Data Members: - mesh; - - This is the mesh of the . See Class for methods to manipulate this mesh. - - The following data members are used by the Displacement Mapping mechanism in 3ds Max. - - mDispApprox; - - The object which describes the properties of the tesselation approximation of the mesh. - - bool mSubDivideDisplacement; - - The subdivision displacement flag. When TRUE, displacement mapping mechanism subdivides mesh faces to accurately displace the map, using the method and settings you specify in the Subdivision Presets and Subdivision Method group boxes. When FALSE, the modifier applies the map by moving vertices in the mesh, the way the Displace modifier does. - - bool mDisableDisplacement; - - TRUE to disable displacement mapping; FALSE to enable it. - - bool mSplitMesh; - - The split mesh flag. This flag affects texture mapping as done by the displacement mapping mechanism. When on, the modifier splits the mesh into individual faces before displacing them: this helps preserve texture mapping. When off, the modifier uses an internal method to assign texture mapping. Default=On. - - - - - This method is available in release 3.0 and later only. - - Returns a reference to the mDispApprox data member. - - - - - This method is available in release 3.0 and later only. - - Returns a reference to the boolean mSubDivideDisplacement data member. - - - - - This method is available in release 3.0 and later only. - - Returns a reference to the boolean mSplitMesh data member. - - - - - This method is available in release 3.0 and later only. - - This method is used internally to set the mDispApprox data member to one of the low/medium/high subdivision presets. - - - - - This method is available in release 3.0 and later only. - - Sets the mDisableDisplacement data member to the given state. - Parameters: - BOOL disable - - TRUE to disable; FALSE to enable. - - - - - This method is available in release 3.0 and later only. - - Returns a reference to the mesh data member of this . - - - - - This method adds vertex color data to a vertex. This method is usually used together with AddVertN and AddVertexUV methods to set each vertex's data flexibly. - - The color channel index must be less than GFX_MAX_COLORS.\ - The vertex color data. - - - - This method adds a set of 2d texture coordinate to a vertex. This method is usually used together with AddVertN and AddVertexCol methods to set each vertex's data flexibly. - - The texture coordinate index must be less than GFX_MAX_TEXTURES.\ - The texture coordinate data. - - - - Get the typed Reference. - - - - - the typed Reference. - - - - - Get the typed Reference by reference. - - - - - Get the typed Reference for dereferencing. - - - - - the typed Reference by assignment. - - - - - Description: - The TCB Graph control displays a tension/continuity/bias graph in the control. - - If you are going to use the TCB Graph control you must initialize it by calling - - InitTCBGraph(HINSTANCE hInst); - - from DLLMain() - - The value to use in the Class field of the Custom Properties dialog is: TCBGraph - - Send this message to the graph control with lParam pointing to a structure to set the graph parameters. - - WM_SETTCBGRAPHPARAMS - - For example: - - gp; - - gp.tens = 0.0f; gp.bias = 0.0f;gp.cont = 0.0f; - - gp.easeFrom = 0.0f; gp.easeTo = 0.0f; - - HWND hGraph = GetDlgItem(hDlg, IDC_TCB_GRAPH); - - EnableWindow(hGraph, TRUE); - - SendMessage(hGraph,WM_SETTCBGRAPHPARAMS,0,(LPARAM)&gp); - - UpdateWindow(hGraph); - - Note that this control is not derived from ICustControl and thus does not have Enable(), Disable(), etc. methods. - Data Members: - float tens, cont, bias, easeFrom, easeTo; - - The tension, continuity, bias, ease from and ease to parameters. Each value may range from 0.0 to 1.0. - - - - - This class is used for texture faces as well as vertex colors. The class maintains an array of three indices into the object's tVerts array. See the class for details on how its array of TVFaces and tVerts relate. All methods of this class are implemented by the system. - - - - - These are indices into the mesh object's tVerts array. - - - - - Sets the texture vertices. - - An array of indices into the tVerts array for vertices 0, 1, and 2. - - - - Sets the textured vertices. - - Specifies the index into the tVerts array for vertex 0. - Specifies the index into the tVerts array for vertex 1. - Specifies the index into the tVerts array for vertex 2. - - - - Retrieves one of the texture vertices. - The texture vertex. - - Specifies the index of the texture vertex to retrieve. You may use 0, 1 or 2. - - - - Returns a pointer to the array of texture vertices. - - - - - Returns the index of the specified texture vertex in this texture face's vertex list (0, 1 or 2). If not found 3 is returned. - - The zero based index of the texture vertex to check. - - - - Returns the first texture vertex in this texture face that isn't v0 or v1. - - The zero based index of one of the vertices to check. - The zero based index of the other vertex to check. - - - - Indicates the order in which vertices v0 and v1 appear in the texture face. - 1 if v1 follows v0 in sequence. -1 if v0 follows v1 in sequence. 0 if v0 or v1 are not on the face. - - One vertex on this texture face. - Another vertex on this texture face. - - - - This method switches v0,v1 if needed to put them in face-order. If v0 and v1 are in the order in which they appear in the texture face, or if one or both of them are not actually on the texture face, nothing happens. If however v0 follows v1, the values of the parameters are switched, so that they are then in the correct order for this texture face. - - One vertex on this texture face. - Another vertex on this texture face. - - - - Description: - This class is the callback object for ITrackViewNode::RegisterTVNodeNotify(). Developers should derive their class from this class and implement the NotifyRefChanged() method. This allows the Track Node to intercept reference notifications when they use a Track Node. - - For an example of this class in use by plug-ins see class in /MAXSDK/INCLUDE/FILTERS.H. It is sub-classed from this class and provides an implementation of NotifyRefChanged(). - - All methods of this class are virtual. - - - - - A plug-in which makes references must implement this method to receive and respond to messages broadcast by its dependents. - Parameters: - & changeInt - - This is the interval of time over which the message is active. Currently, all plug-ins will receive FOREVER for this interval. - - RefTargetHandle hTarget - - This is the handle of the reference target the message was sent by. The reference maker uses this handle to know specifically which reference target sent the message. - - PartID& partID - - This contains information specific to the message passed in. Some messages don't use the partID at all. See the section Reference Messages and PartID for more information about the meaning of the partID for some common messages. - - RefMessage message - - The message parameters passed into this method is the specific message which needs to be handled. See Reference Messages. BOOL propagate - - If called through ReferenceMaker::NotifyDependents(), the value of 'propagate' passed to it. Used if calling NotifyDependents() from within NotifyRefChanged() - The return value from this method is of type RefResult. This is usually REF_SUCCEED indicating the message was processed. Sometimes, the return value may be REF_STOP. This return value is used to stop the message from being propagated to the dependents of the item. - - - - - Description: - This is a texture vertex patch structure. This is similar to the class used with a . All methods of this class are implemented by the system. - Data Members: - int tv[4]; - - Texture vertices. There are always four here, even for Tri Patches. These are indices in the 's tVerts array. - - int handles[8]; - - The UVW vertices for the handles. - - int interiors[4]; - - The UVW interior handles. - - - - - Performs initialization by setting the texture vertices to 0. - - - - - Sets the specified number of texture vertices. - Parameters: - int *vrt - - The array of verts to set. - - int count - - The number to set. - - - - - Sets the texture vertices for a Quad . - Parameters: - int a, int b, int c, int d = 0 - - The vertices to set: tv[0]=a; tv[1]=b; tv[2]=c; tv[3]=d; - - - - - Sets the specified number of texture (UVW) handles. - Parameters: - int *vrt - - The array of handles to set. - - int count - - The number to set. - - - - - Sets the texture (UVW) handles for a Quad . - Parameters: - int a, int b, int c, int d, int e, int f, int g = 0, int h = 0 - - The handles to set: handles[0]=a; handles[1]=b; handles[2]=c; handles[3]=d; handles[4]=e; handles[5]=f; handles[6]=g; handles[7]=h; - - - - - Sets the specified number of interior texture (UVW) handles. - Parameters: - int *vrt - - The array of interior handles to set. - - int count - - The number to set. - - - - - Sets the interior texture (UVW) handles for a Quad . - Parameters: - int a, int b, int c, int d = 0 - - The interior handles to set: interiors[0]=a; interiors[1]=b; interiors[2]=c; interiors[3]=d; - - - - - Returns the texture vertex specified by the index. - Parameters: - int index - - The index of the texture vertex to return. - - - - - Returns a pointer to the array of texture vertices. - - - - - Assignment operator. - Parameters: - & from - - The texture vertex patch to copy from. - - - - - This method is used internally in saving to the MAX file. - - - - - This method is used internally in loading from the MAX file. - Operators: - - - - - Description: - This class can be used so an plug-in can get notified on a change to one of its Track Nodes. - - This class provides an implementation of the NotifyRefChanged() method of class . The constructor of this class stores a window handle. Usually this is the control dialog window handle of the plug-in using this class. Upon receipt of a message via TVNodeNotify::NotifyRefChanged() this implementation sends a FLT_UNDO message to the control dialog window proc and invalidates the window. Most filters will set a flag indicating that an undo has occurred when they get the FLT_UNDO message, and actually update the UI controls when they process the WM_PAINT message. This is because the FLT_UNDO message may be sent many time and the controls shouldn't be updated each time (as they might appear to 'flicker'). See the code for the Negative filter in /MAXSDK/SAMPLES/FILTERS/NEGATIVE/NEGATIVE.CPP for details. - - All methods of this class are implemented by the system. - - - - - Description: - 3ds Max utility plug-ins are derived from this class. Methods are provided for editing the utilities parameters and responding to changes in the current selection set. An interface pointer is provided for calling the utility methods provided by MAX. - - Note: Utility plug-ins are not a direct participant in the geometry pipeline system of 3ds Max in the same way modifiers or space warps are. For this reason, plug-ins are not suitable for modifying objects flowing down the pipeline. Use or plug-ins for this purpose. - - Also note: It is possible to create a utility plug-in that uses a modeless dialog box. When 3ds Max itself uses modeless dialogs, it disables input to the other open windows such as the Track , the Materials Editor, etc. In this way, the user cannot perform some action that could disturb the operation of the modeless dialog. For example using Track , a user could assign a different controller to a node, and a utility plug-in might be accessing keys from the node's previous controller. Since utility plug-ins cannot currently prevent the user from operating these other parts of MAX, developers need to be careful about the use of modeless dialogs. - - - - - This method is called when the utility plug-in may be used in the Utility branch of the command panel. The plug-in may add rollup pages to the command panel in this method for example. - - An interface pointer you may use to call methods of the class. - An interface pointer you may use to close the current utility in the command panel. - - - - This method is called when the utility plug-in is done being used in the Utility branch of the command panel (for example if the user changes to the Create branch). - - An interface pointer you may use to call methods of the class. - An interface pointer you may use to close the current utility in the command panel. - - - - This method is called when the selection set changes. A plug-in may implement this method to respond to this condition. - - An interface pointer you may use to call methods of the class. - An interface pointer you may use to close the current utility in the command panel. - - - - This method is called after BeginEditParams() when the user starts the utility from the command line with the option -U and passes an argument to the utility. - Default Implementation: - {} - - The command line argument is passed here. - - - - Description: - The class is a <MCHAR*> utility class that is used by certain components in the Drag and Drop manager to hold and pass around packages of file URLs. The class manages its own local copies of URL strings. This class represents the additional API support by , over-and-above that provided by any <> template instantiation. - Data Members: - protected: - - BOOL downloaded; - - This flag is set to indicate the URL package has been downloaded and names will reflect local copies. - - - - - This method adds a URL string to the package. A local copy of the string will be made. - Parameters: - MCHAR* url - - The URL string to add. - - - - - This method replaces the i'th element by deletes the old string, taking a local copy of the new one. This is used by the various loaders to replace a URL with its local copy path name upon download. - Parameters: - int i - - The index of the URL to replace. - - MCHAR* url - - The new URL string. - - - - - This method clears the package (deletes all the strings), zeros the <> and resets 'downloaded' to FALSE. - - - - - Description: - A UTF8 encoded character string class. This class uses UTF8 encode to hold each character. This class provide very basic functionality Methods and operators are provided for calculating lengths, concatenation, case conversion, comparison. - The memory occupied by a object is cannot be larger than 2Gb. - - - - - Returns a pointer to this string which can be written to with up to 'nchars' characters. - The terminating null character is not included in nchars, so technically up to nchars+1 characters may be written. - - The minimum number of characters to allocate in the string buffer (excluding the terminating null character). A value of -1 specifies that the existing buffer should be re-used. - - - - Returns a const pointer to the string. If the string is NULL, a pointer to 0 is returned. - - - - - Reallocates the string to contain nchars characters. If the string is enlarged it is padded with blanks. - Parameters: - int nchars - - Specifies the new number of characters for the string. - - - - - Returns the number of chars used to store the string in memory, including spaces, but excluding the terminating NULL character. - - - - - Returns the number of chars used to store the string in memory, including spaces, but excluding the terminating NULL character. - - - - - Returns the number of bytes used to store the string in memory, including spaces, but excluding the terminating NULL character. - - - - - Returns the number of natural language characters the string is represented on, including spaces, but excluding the terminal NULL character. This may be equal or less than the amount of bytes used to store the string in memory. For example, a Chinese character might take up to 4 bytes. Length() or ByteCount() will count the character as up to 4 distinct chars. LanguageCharacterCount() will count it as a single char. - - - - - Returns the total number of char allocated to store the string. Including the NULL character and any unused char. - - - - - Returns TRUE if the string length is 0; otherwise FALSE. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - Assignment operator. - - - - - Assignment operator. In release 3.0 and later this method check for self-assignment. - - - - - Concatenation operator. Returns a new string that is this string with string cs appended. - - - - - Concatenation. Returns this string with cs appended. - - - - - Concatenation. Returns this string with cs appended. - - - - - Concatenation. Returns this string with cs appended to the end. - - - - - Returns a substring of this string, beginning at multi-byte character position firstCharacterIndex, of length numberOfMBCharacters. - - - - - Returns the first byte index value of the multi-byte character position characterIndex. - - - - - Returns the last byte index value of the multi-byte character position characterIndex. - - - - - Equality operator. - true if the strings are equal; otherwise false. - - - - - Converts all character of this string to uppercase. - - - - - Converts all character of this string to lowercase. - - - - - Write a formatted string into this . Writes the format string, filled in by the optional arguments into this . See the ISO C++ documentation for more information on printf and format strings. Note: do not use ls formatting since conversion from wide string to narrow string will occur using active code page encoding rather than utf8 encoding. - - - format is not null. - There are the correct number of elliptical arguments to fill the format string. - This string is replaced with the formatted string. - The number of characters written to this string, not including the null terminating character, or a negative value if an error occurs. - - Specifies how to format the destination string. - optional arguments to format into the destination string. - - - - Returns the string in memory allocated by SysAllocString. Caller is responsible for freeing memory using SysFreeString. - - - - - Returns true if the string ends with s; otherwise returns false. - - The string to be searched. - If it is true(default), the search is case sensitive; otherwise the search is case insensitive. - - - - Returns true if the string starts with s; otherwise returns false. - - The string to be searched. - If it is true(default), the search is case sensitive; otherwise the search is case insensitive. - - - - Returns the number of line feeds inside a string. - - - - - Description: - Most texture maps that use UV coordinates will use an instance of this class. This class encapsulates much of the user interface functionality for setting mirroring, tiling and so on. These are the settings found in the 'Coordinate' and 'Noise' rollup pages. This class generates UV coordinates based on the results of a UV source provided by the plug-in and the user specified transformations. An instance of this class is referenced by all the 2D texture maps. All methods of this class are implemented by the system. - The following four methods are the only ones a plug-in needs to call typically: - - - - - This method is not normally called directly. It retrieves the UV coordinates (depending on if they are explicit, shrinked-wrapped environment, etc.) and transforms them using the offsets and noise parameters entered by the user. It does not do the mirroring or tiling. It then returns the texture coordinates and derivatives for antialiasing. - Parameters: - & sc - - Describes the properties of the point to evaluate. - - & UV - - The UV texture coordinates for the point. - - & dUV - - The derivatives of UV for the point to shade. This describes how big of a range in UV space the current pixel covers. - - - - - This method is called to evaluate the color of the map based on the . It takes into account the users selections for mirroring, tiling, noise, etc. from the rollups. - Parameters: - &sc - - Describes the properties of the point to evaluate. - - MapSampler* samp - - This is a callback used to sample the map. The plug-in creates an instance of this class, and implements its methods. A pointer to the instance is passed here. The methods of the class sample the texture for a single UV coordinate. - - BOOL filter=TRUE - - If TRUE the texture will be filtered. - The result as an . - - - - - This method is called to evaluate the value of the map based on the . It takes into account the users selections for mirroring, tiling, noise, etc. from the rollups. - Parameters: - &sc - - Describes the properties of the point to evaluate. - - MapSampler* samp - - This is a callback used to sample the map. The plug-in creates an instance of this class, and implements its methods. A pointer to the instance is passed here. The methods of the class sample the texture for a single UV coordinate. - - BOOL filter=TRUE - - If TRUE the texture will be filtered. - The result as a float. - - The following two methods are called for bump mapping to retrieve a normal perturbation. The calling sequence for these methods is shown in the sample code below. This code takes the sum of the U derivative times the U bump vector, and the V derivative times the V bump vector. The result is the normal perturbation returned from EvalNormalPerturb(). - Note: In the following code you'll see the 'text book' Blinn's algorithm and the 'Lazy' approach that is actually used. During testing it was determined that these two methods are visually identical. The 'Lazy' algorithm avoids the cross products however. - - - - - This gets the amount that U and V are changing. It takes into account the users selections for mirroring, tiling, noise, etc. from the rollups. - Parameters: - & sc - - Describes the properties of the point to evaluate. - - MapSampler* samp - - This is a callback used to sample the map. The plug-in creates an instance of this class, and implements its methods. A pointer to the instance is passed here. The methods of the class sample the texture for a single UV coordinate. - - BOOL filter=TRUE - - If TRUE the texture will be filtered. - df/du, df/dv as a . - - - - - This method may be called to compute dPdu and dPdv bump basis vectors for bump mapping. These are two vector in 3D space that give you the U and V axis of the map space. This is like taking the map space into 3D space so you can determine where the U axis is and where the V axis is. - - Note: In 3ds Max 3.0 and later these vectors are always normalized. This change makes it so bump mapping is invariant when a Rescale World Units is performed. - - See the Advanced Topics section on ~{ Materials, Textures and Maps }~ for more information on bump mapping. - Parameters: - & sc - - Describes the properties of the point to evaluate. - - & dPdv - - The bump basis vectors are returned here. - - - - - This method is used internally to provide information to the interactive renderer. - - - - - This method is used internally to provide information to the interactive renderer. - - - - - This method returns the source for the texture vertices. - One of the following values: - - UVWSRC_EXPLICIT - - Use explicit mesh texture vertices from channel 1. - - UVWSRC_EXPLICIT2 - - Use explicit mesh texture vertices from channel 2. - - UVWSRC_OBJXYZ - - Generate planar UVW mapping coordinates from the object XYZ on-the-fly. - - - - - This method is used internally. - - - - - Developers typically don't need to call this method. In the Coordinates rollup in the user interface for a texture map are two options. These options are Texture or Environment. The slot type is one of these two options. There are a variety of texture coordinate types. There are the type assigned to the object and the environment type (Spherical, Cylindrical, Shrink-wrap, Screen). This method is used initialize the radio button in the dialog based on the sType passed and update the drop down list. - Parameters: - int sType - - One of the following values: - - MAPSLOT_TEXTURE - - This is either texture coordinates. - - MAPSLOT_ENVIRON - - Environment coordinates. - - - - - Return the axis (mapping coordinate system) used. - One of the following values: - - AXIS_UV - - AXIS_VW - - AXIS_WU - - - - - This method returns the clip flag. The clip flag controls whether the U,V values passed to by EvalUVMap() and EvalUVMapMono() are clipped to the [0..1] interval or not. It defaults to ON (i.e., clipped). See SetClipFlag() above. - TRUE for clipped; FALSE if not clipped. - - - - - This method asks the question 'Is this class an instance of ?'. The derived class implements this to return TRUE. Others use the default implementation to return FALSE. - Default Implementation: - { return FALSE; } - - - - - Returns the open or closed state of the rollup. - TRUE is open; FALSE is closed. - - - - - This class represents the notion of a mesh edit UVW vertex assignment. The public data members provide the index of the vertex as well as the UVWVert. - - - - - The index of the vertex. - - - - - The UVW vertex. - - - - - Assignment operator. - - - - - Description: - Prior to release 3.0, developers could implement Object::ApplyUVWMap() in their objects, but didn't have access to the algorithm 3ds Max uses internally to turn the mapping types (MAP_BOX, MAP_PLANE, etc) into an actual vertex-to-mapping-coordinate function. This class now makes this available. - - The constructors for the class initialize the data members with information about the mapping desired. The main method, MapPoint(), maps a point in object space into the UVW map defined by this mapper. - - Note: UVVert; - Data Members: - int type; - - The mapping type. One of the following values: - - MAP_PLANAR - - MAP_CYLINDRICAL - - MAP_SPHERICAL - - MAP_BALL - - MAP_BOX - - MAP_FACE - - int cap; - - This is used with MAP_CYLINDRICAL. If nonzero, then any face normal that is pointing more vertically than horizontally will be mapped using planar coordinates. - - float utile; - - of tiles in the U direction. - - float vtile; - - of tiles in the V direction. - - float wtile; - - of tiles in the W direction. - - int uflip; - - If nonzero the U values are mirrored. - - int vflip - - If nonzero the V values are mirrored. - - int wflip; - - If nonzero the W values are mirrored. - - tm; - - This defines the mapping space. As each point is mapped, it is multiplied by this matrix, and then it is mapped. - - - - - This method maps a point in object space into the UVW map defined by this mapper. This gives the UVW coordinates for the specified point according to this mapper's mapping scheme. - Parameters: - p - - The location of a vertex, i.e. the point being mapped. This point should NOT be transformed by the 's tm, as this happens internally. - - & norm - - The direction of the surface normal at p. This information is only required for types MAP_BOX or MAP_CYLINDRICAL. See the method NormalMatters() below. - - int *nan=NULL - - If non-NULL, this points to an int which should be set to FALSE if this mapping is good for all faces using this vertex, or TRUE if different faces should have different mapping coordinates. This is generally set to TRUE more often than absolutely necessary to make sure nothing is missed. - The mapped point. - - - - - Applies the UVWMap's tile and flip parameters to the given UVVert, and returns the result.. - Parameters: - UVVert uvw - - The input UVVert. - The modified UVVert. - - - - - This method indicates which direction the given vector "chiefly points", after vector transformation by the 's transform. - Parameters: - & n - - The input vector whose main axis is determined. - One of the following values: - - 0: tm.VectorTransform(n) points mainly in the +x direction. - - 1: tm.VectorTransform(n) points mainly in the +y direction. - - 2: tm.VectorTransform(n) points mainly in the +z direction. - - 3: tm.VectorTransform(n) points mainly in the -x direction. - - 4: tm.VectorTransform(n) points mainly in the -y direction. - - 5: tm.VectorTransform(n) points mainly in the -z direction. - - - - - This method lets you know whether the current mapping type uses the normal information. If FALSE, it doesn't matter what value you pass as a normal to MapPoint. If TRUE, the MainAxis of the normal is used to determine the mapping. - - - - - Compare whether 2 values are equivalent. The ValuesEqual method is used by the deepEqual function to test to see if two values are equivalent. This allows, for example, testing to see if 2 arrays are equivalent. (The == operator on arrays just tests to see if the two arrays are the same array). Classes that implement this method are , , , and MXSDictionary - True if the value is equivalent, false if not. - Example implementations: - - The value to compare against this value - If true, the type of 'other' must be the same as this value. If false, 'other' must just be comparable with this value using the eq_vf method. So, for example, value 1 and value 1 would compare as false if strictCompare is true, and true if strictCompare is false. - - - - A vertex buffer, containing a and color. - - - - - This class represents the notion of a mesh edit vertex move. The public data members provide the index of the vertex moved as well as the amount of the move in X, Y, Z. - - - - - The id of the vertex moved. - - - - - The amount of the move. - - - - - Assignment operator. - - - - - This class is passed in to GeomObject::GetRenderMesh() to allow objects to do view dependent rendering. It is also passed to Control::EvalVisibility(). For example particle systems use this to have the particles exactly face the camera (if this option is enabled). If GetRenderMesh() is called by the renderer, the methods of this class are implemented by the system. If a plug-in is calling this method, they must implement these methods. The sample code below shown a null implementation that may be used if a viewport is not involved: - - - - - The screen width in pixels - - - - - The screen height in pixels - - - - - A transformation matrix from world into view space. This is into the camera's space. - - - - - The view projection type: 0 is perspective, 1 is parallel. - - - - - The field of view in radians. - - - - - The pixel size setting. - - - - - World to camera transformation matrix. - - - - - Defined in Flags for the View class - - - - - This method is used to convert a point in view space to screen space. This includes any perspective projection. - The point in screen space (in pixel coordinates). - - The point in view space. - - - - This method should be used by GetRenderMesh() implementations that require a lot of processing time. This allows these processes to be interrupted by the user. An example of this in use is the extensive computations done for displacement mapping. These may be interrupted by the user during a render. So, any implementation of GetRenderMesh() which takes a long time should periodically call this method to see if the user has canceled the render. - true if user has canceled, false otherwise. - - - - - expansion function - - - - - Enables non-geometric plugins to draw in the viewport. This class is a callback object that enables plug-ins that aren't actually objects (such as utility plug-ins) to draw in the 3ds Max viewports. Plugin classes that sub-class this can also assign a numerical priority to their callbacks by also implementing the interface. See the following methods in class that register and unregister this callback object: - - - - - - - This method is called to allow the plug-in to draw in the viewports. - - - The current time when this method is called. - - An interface into the viewport. - - These flags are used internally. - - - - Retrieves the dimensions of the specified viewport given an interface to it. - - - The time to get the viewport rectangle. - - Specifies which viewport - - The rectangle is returned here. - - - - Flags whether to draw in the foreground or background plane. This method should return TRUE if the object changes a lot or FALSE if it doesn't change very much. This method relates to the foreground/background display system used by 3ds Max. Basically, items that change a lot are placed in the foreground buffer. Items that don't change much are placed in the background buffer and simply blitted to the display. See the Advanced Topics section on ~{ Foreground / Background Planes }~ for more details. Most plug-ins can simply return TRUE because they are not likely to be very heavyweight objects (they are usually just a gizmo or apparatus image) and can simply go into the foreground. On the other hand, some items, for instance the 3ds Max home grid, don't change and can always go into the background. The home grid only changes when the view direction is changed in which case everything is redrawn. - - - - - A simple text based button implementation of the . - - - A new viewport text button that is used to cerate the new viewport buttons in 3ds max 2010 It create a [XXXXX] button format, and support mouse over high lights. Developers can derive from this class to provide their own actions and update functions. TO use this class you must import CORE.LIB into your projects. - Please read the help section for an explanation of the methods. - - - - - Description: - This class provides methods to access properties of the viewport, convert points between viewport and world coordinates, snap points and lengths, etc. Many methods associated with hit testing are also here. All the methods of this class are implemented by the system. - - - - - Returns a point in world space on the current construction plane based on the specified screen coordinate. - The world space coordinate on the current construction plane. - - The 2D screen point to convert to a 3D world space coordinate. - - - - This method returns a length in world space given a start screen point, an end screen point, a base point and a direction vector. For example, when creating a cylinder, the user clicks the mouse down to define the center point of the cylinder (base), then drags out a radius. They then drag out a height for the cylinder. This method is used to return intermediate and final heights for the cylinder based on the initial base point, the direction vector (the Z axis), the start mouse point, and the current point the user is interactively adjusting. - The length in world space based on the screen points and their projection onto the direction vector. - Sample Code: - From /MAXSDK/SAMPLES/OBJECTS/CYL.CPP in CylinderObjCreateCallBack::proc - - Base point in object space. - Direction vector in object space. - Screen start point. This is the point where the user clicked down with the mouse. - Screen end point. This is the point where the user let up the mouse. - - - - - Given a point on the screen (in window coordinates), and a depth in view coordinates, this method maps the point into view coordinates. This is just a scaling operation for parallel projections, but involves a divide by Z for perspective projections. - Point in view coordinates. - Sample Code: - - Point in window coordinates. - Depth in view coordinates. - - - - Creates a in world space passing through the specified pixel directed toward the scene in the direction of view. - - The x screen coordinate. - The y screen coordinate. - The in world space. See Class . - - - - This method sets the viewport affine transformation and returns TRUE if the view is a user view (isometric or perspective). If the view is not a user view then the transformation is not changed and the method returns FALSE. See SetViewUser() below. - - The transformation matrix to set. - - - - This method retrieves the affineTM which transforms from World coordinates to coordinates. See the sample code below for an example of its use. - - The matrix to hold the affine TM. Note: You can also get the view position from this matrix. For example, in the above code, the statement: gets the point in space the view is taken from. - - - - Returns the screen scale factor for a point given in world coordinates. This factor gives the width in world-space units at the point's distance of the viewport. - The screen scale factor in world space units. - - The point in world coordinates. - - - - Returns the viewport screen width factor in world space at a point in world space. - The viewport screen width factor in world space. - - The point in world space. - - - - Given a point on the construction plane this method returns the corresponding world space point. For example, if you use GetPointOnCP() to convert a screen coordinate to a point on the construction plane, you could then call this method to convert that point on the construction plane to a world space point. - The world space point. - - The point on the construction plane. - - - - The value returned from this method may be used as a scale factor that will counteract the viewport zoom. For example, lights, cameras, and tape helper objects use this factor so the size of the node in the scene remains constant when the viewport is zoomed in and out. - - This value is affected by the 'Non-Scaling Size' spinner in the Viewport Preferences dialog, so the user has some control over this as well. - Sample Code: - This sample is from /MAXSDK/SAMPLES/OBJECTS/TAPEHELP.CPP. The computed matrix is used in several places like displaying, snapping, hit testing, etc. - - - - - Given a 2D screen coordinate, this method returns a 3D point on the current construction plane based on the current snap settings and flags passed. - The snapped 3D point in construction plane coordinates. - - The 2D screen coordinate to snap. - The snapped 2D screen coordinate. This is used if you need to move the mouse position to the snapped location. - This optional argument allows you to use any plane (not just the current construction plane). - See . - - - - This is a method used as part of the osnap system in 3ds Max. It is the method that displays the snap marker in the viewports prior to the first point event. It's really just a call to SnapPoint() which returns nothing. This method should be called in response to a MOUSE_FREEMOVE event from any creation or transformation proc which calls SnapPoint(). Here's an example creation proc: - Sample Code: - - The 2D screen coordinate to snap. - The snapped 2D screen coordinate. This is used if you need to move the mouse position to the snapped location. - This optional argument allows you to use any plane (not just the current construction plane). - See . - - - - This method is used internally. It fills up it's arguments with the world space extents of the home grid (i.e. the extents of the grid as displayed). It doesn't work for grid helper which always display to their size limits. This was exposed so 3ds Max could do the grid snapping and is not needed by plug-in developers. - - - - - Given the distance passed, this method snaps the length to the nearest snap increment and returns the snapped distance. - The snapped distance. - - The input distance to be snapped. - - - - Returns a pointer to the instance of associated with this viewport. - - Note: A always has a transform associated with it, for faster object-to-screen space conversions. The * returned by this method may have a non-identity transform already in place. A developer can call gw->setTransform() with a node's transform for fast work in Display routines. But this value must be explicitly set to the identity for world-to-screen displays. - - - - - Determines if this viewport is in wire-frame rendering mode (as opposed to a shaded mode). - Nonzero if the viewport is in wire-frame rendering mode; otherwise 0. - - - - - Returns the damaged rectangle of the viewport. This is the area that needs to be updated on the next screen refresh. This can be used for example, to pass into the method render() to only display the damaged area of the object. A developer could also use this in the implementation of their own Display() method. - Sample Code: - - - - - Retrieves the transformation matrix of the construction plane. - - The transformation matrix is returned here. - - - - Returns the construction grid spacing. This is the grid spacing on a per viewport basis. It is dependent on how far zoomed in or out the user is. This is the exact same value that you can see in the right most status panel below the viewports. - - - - - Returns TRUE if the grid is turned on for this viewport; otherwise FALSE. - - - - - - - the grid visibility for this viewport. - - - - - - - Returns the grid type. One of the following values (from OBJECT.H): - - GRID_PLANE_NONE - - GRID_PLANE_TOP - - GRID_PLANE_LEFT - - GRID_PLANE_FRONT - - GRID_PLANE_BOTTOM - - GRID_PLANE_RIGHT - - GRID_PLANE_BACK - - - - - This method is used to turn on and off the background image display in this viewport. Note that it is necessary to redraw the viewports in order to see the effect of this method. Use the method Interface::RedrawViews() to do this. - TRUE if the image was set; otherwise FALSE. - - TRUE to turn the background image on; FALSE to turn it off. - - - - Returns nonzero if the background image is displayed in this viewport; otherwise 0. - - - - - Returns nonzero if the safe frame is displayed in this viewport; otherwise 0. - - - - - This returns the window handle of the viewport - this is the transparent window that catches mouse input. Note that this window handle is different than the handle that can be retrieved from the viewport's . getGW()->getHWnd() is the window that things are drawn on. - The window handle of the viewport. - - - - - Returns TRUE if the viewport is the active on; otherwise FALSE. - - - - - Returns TRUE if the viewport is enabled; FALSE if disabled. - - - - - Returns the type of view. One of the following values: - - enum ViewType { - - VIEW_LEFT,VIEW_RIGHT,VIEW_TOP,VIEW_BOTTOM,VIEW_FRONT,VIEW_BACK, - - VIEW_ISO_USER, VIEW_PERSP_USER, VIEW_CAMERA, VIEW_GRID, VIEW_NONE, - - VIEW_TRACK, VIEW_SPOT, VIEW_SHAPE, VIEW_SCHEMATIC, VIEW_OTHER - - }; - - - - - Returns TRUE if the viewport is a perspective view; otherwise returns FALSE. - - - - - Returns TRUE if the viewport is 2D canvas navigation mode; otherwise returns FALSE. - - - - - Returns the field of view of a perspective viewport in radians. - - - - - - - Returns the focal distance of a perspective view. - - - - - Returns the pointer of the camera associated with this viewport. If this is not a camera view then NULL is returned. - - - - - This method sets the viewport to be a user view, with the persp argument indicating whether this should be a perspective or iso view. Note that the user viewport defaults are used for field-of-view, etc. - - TRUE for perspective; FALSE for isometric. - - - - Returns the pointer of the spotlight associated with this viewport. If this is not a spotlight view then NULL is returned. - - - - - Implemented by the System. - - Clears the list of node level hit records. - - - - - Implemented by the System. - - Returns the pointer of the node that was the closest of all those hit. If none were hit, NULL is returned. - - - - - Returns the pointer of the 'i-th' node level hit. - - The index of the hit to retrieve. - - - - Implemented by the System. - - Returns the number of hits recorded by the last node level hit test. - - - - - This method records a sub-object level hit record with the system using the specified parameters. This hit can later be retrieved using the method GetSubObjHitList() and the methods of class . - - - - The node that was hit. - The of the modifier. - The 'distance' of the hit. What the distance actually represents depends on the rendering level of the viewport. For wireframe modes, it refers to the distance in the screen XY plane from the mouse to the sub-object component. In a shaded mode, it refers to the Z depth of the sub-object component. In both cases, smaller values indicate that the sub-object component is 'closer' to the mouse cursor. - Identifies the sub-object component that was hit. - If the info data member is insufficient to indicate the sub-object component that was hit, pass an instance of the class that contains the needed information. The system will be responsible for freeing the memory for the . - - - - Returns the sub-object hit list. See Class . - - - - - Clears the sub-object hit list. This deletes all previously saved HitRecords. - - - - - Returns the number of sub-object hits recorded. - - - - - This method records a controller sub-object level hit record with the system using the specified parameters. This hit can later be retrieved using the method GetCtrlHitList() and the methods of class . - - The node that was hit. - The 'distance' of the hit. What the distance actually represents depends on the rendering level of the viewport. For wireframe modes, it refers to the distance in the screen XY plane from the mouse to the sub-object component. In a shaded mode, it refers to the Z depth of the sub-object component. In both cases, smaller values indicate that the sub-object component is 'closer' to the mouse cursor. - A general unsigned long value. Most controllers will just need this to identity the sub-object element. The meaning of this value (how it is used to identify the element) is up to the plug-in. - If the above data member is not sufficient to describe the sub-object element this data member may be used as well. - - - - Returns the list of controller gizmo hits recorded. See Class . - - - - - Clears the controller hit list. This deletes all the HitRecords previously recorded. - - - - - If AutoGrid is enabled, this method determines a grid coordinate system by casting a ray into the scene through the screen coordinate m, obtaining a surface normal from the closest node , and using the "arbitrary axis algorithm" to orient the xy axes. You can get this coordinate system back by passing in a pointer to a matrix. A tripod is displayed in the viewports showing the orientation. - - The 2D screen point that the user clicked on. - The implicit grid coordinate system matrix can be retrieved by passing a pointer to a matrix here. - See . - - - - If AutoGrid is enabled, this method creates a grid and activates it. The mouseflags parameter is used to determine if the ALT key is down. If it is, this grid will not be deactivated in ReleaseImplicitGrid()(below). - - The 2D screen point that the user clicked on. - These flags describe the state of the mouse buttons. See . - Developers can get the implicit grid coordinate system back by passing in a pointer to a matrix here. - - - - This method deactivates an implicit grid and restores the previously active grid. If the implicit grid was committed with ALT-key held down, then this call does nothing. - - - - - Return the unique ID of the viewport represented by the . NOTE: Each view panel can have 4 viewports whose indexes are usually all from 0 to 3. But their view IDs are unique. Besides, view ID is persistent during FileIO. So user can store this ID during saving. And then after loading, user can use the stored ID to retrieve the same viewExp interface by calling Interface14::GetViewExpByID(int id) - the view ID of the viewport - - - - - Given a point with view coordinates, this method maps the point into screen(windows) coordinates. - Point in screen coordinates. - Sample Code: - - Point in view coordinates. - - - - Get the FPS from the active viewport. - - - Return the frame per second of the active viewport. - - - - - the viewport background color mode as solid color mode or gradient color mode. - - if true, solid color mode will be set. Otherwise set gradient color mode will be set. - - - - Get the current viewport background color mode. - Return true if in solid color mode. Return false if in gradient color mode. - - - - - Reset viewport background color mode. - - - - - This is a better way method to invalidate a viewport only if the area define by the Rect argument is not the whole size of the viewport. Calling InvalidateRect on a Rect defined like this: rect.top = 0; rect.bottom = gw->getWinSizeY(); rect.left = 0; rect.right = gw->getWinSizeX(); Will have the same effect of invalidating the viewport. - - The Rect that define the region on the viewport to be invalidated. - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - The index of the command to execute. - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - Optional argument 2. - Optional argument 3. - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Pans the viewport. - - - - - Screen space pan amount. - - - - Zooms the viewport. This is equivalent to the Interactive Zoom tool in the UI. When used on a perspective view, it ultimately modifies the focal distance, and moves the camera. When used on an orthogonal or isometric view, it simply calls an internal zoom function. Values between 0.0 and 1.0 will zoom in, and values greater than 1.0 will zoom out. For instance, zooming in with a value of 0.5 will enlarge the apparent display, and effectively half the focal distance for perspective views. Zooming out with a value of 2.0 will effectively double the focal distance for perspective views. Note: Setting this value to zero will set the focal distance to zero. This is highly discouraged. To recover from a zero assignment, either set the focal distance to a positive number, or zoom using the middle mouse button. - - - - - Zoom factor to apply to the viewport. - - - - Rotates the viewport. This is equivalent to the Viewport Rotation tool in the UI. - - - - - Rotation to apply to the viewport. - - pivot on which the viewport rotation is based. - - - - Sets the focal distance of the viewport. - - - - - The new distance for the focal length - - - - Call this method before any change to the viewpoint or viewport parameters. Usually this method is called from within a MouseCallback::proc method in response to the start of a user interaction (MOUSE_POINT, MOUSE_KEYBOARD) - - - - - Marks the end of recording viewport changes for undo. - - - Call this method after a change to the viewpoint or viewport parameters. Usually this method is called from within a MouseCallback::proc method in response to the end of a user interaction (MOUSE_POINT sent to MouseCallback::proc with the last point) - - - - - A call to Interface::RedrawViews will cause the viewport to be redrawn - - - If true, only the foreground plane is invalidated. If false, both foreground and background planes are invalidated. - - - - Retrieves the validity state of the viewport foreground. - - - true if the viewport foreground is valid, false otherwise - - - - - Gets Adaptive Deg. goal FPS. - - - Gets Adaptive Deg. goal FPS. This is the frame rate the adaptive deg system wants to hold - - - - - Gets the state of the display mode current display option. - - - Gets the state of the display mode current display option - - - - - Gets the state of the display mode Fast Shaded display option. - - - Gets the state of the display mode Fast Shaded display option - - - - - Gets the state of the display mode Wireframe display option. - - - Gets the state of the display mode Wireframe display option - - - - - Gets the state of the display mode BoundingBox display option. - - - Gets the state of the display mode BoundingBox display option - - - - - Gets the state of the display mode Point display option. - - - Gets the state of the display mode Point display option - - - - - Gets the state of the display mode Hide display option. - - - Gets the state of the display mode Hide display option - - - - - Gets the state of the Draw Backface option. - - - Gets the state of the Draw Backface option. When on backfaces will be drawn when degrading improving performance - - - - - Gets the state of the Never Degrade Selected option. - - - Gets the state of the Never Degrade Selected option. When on selected objects will never get degraded allowing the user to focus on them - - - - - Gets the state of the Degrade to Default option. - - - Gets the state of the Degrade to Default option. When on the system will degrade the lights to just the default over the shoulder light - - - - - Gets the state of the Never Redraw After Degrade option. - - - Gets the state of the Never Redraw After Degrade option. When on the system will remain in degraded state even after a mouse up. On large scenes this helps pauses on full redraws - - - - - Gets the state of the Distance From Priority option. - - - Gets the state of the Distance From Priority option. This weights whether the distance from camera or screen size is used to determine what gets degraded - - - - - Gets the state of the Screen Size Priority option. - - - Gets the state of the Screen Size Priority option. This weights whether the distance from camera or screen size is used to determine what gets degraded - - - - - Gets the state of the Minimum Draw Size option. - - - Gets the state of the Minimum Draw Size option. Anything smaller than the Minimum Draw Size in screen space will not be drawn when the system is degrading - - - - - Sets the Field of for the viewport. - - - This can be used on Perspective and views. That is VIEW_PERSP_USER or VIEW_CAMERA from enum ViewType. To see the results of this call the viewports will have to be updated. For instance you could call: Interface::RedrawViews() - TRUE if successful or FALSE if not. - - - The field of view in Radians to set the viewport to. Valid values are 0.0 to 2 PI. - - - - Gets the state of the active viewport current fps. - - - Gets the state of the active viewport current play back fps. NOTE GetFPS returns the Adaptive degradation goal frame rate - - - - - Gets the state of the active viewport clip scale value. - - - This gets the state of the viewport clip scale value. The minimum clip value is computed by taking the scene bounding box and multiplying by this value. Making this value larger will make the scene display more accurately but bring the near clip plane farther from the camera. Making this value smaller will bring the near clip plane closer but have a more likely chance of have close polygons render incorrectly - - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Gets whether or not we are in the process of drawing the viewports in an degraded state. - - - Gets whether or not we are drawing the viewports in an degraded state. This flag thus can be queried when an object is displaying itself and wants to do any custom drawing when adaptive degradation is occurring. - - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Is this viewport using default lights ? - - - Return true if it is using default lights. - - - - - Get the default lights data and their number at the same time. - Returns the number of we have filled in the array. It should be 0, 1 or 2. 0 meaning no default lights are used by this viewport. - - - The array of , it should be initialized before calling this method and it will be filled. It should have a maximum size of 2 as we use a maximum of 2 lights for a viewport. - - The size of the pDefaultLights array initialized before that call. - - Tells if we should we apply or not the global tint and level from the Render Environment on the lights data ? - - - - Updates the viewport label, if the display mode has changed. - - - May be needed when displaying a camera view, and the camera name is changed. Primarily for internal use. - - - - - Get the zoom value of the viewport. - - - Gets the zoom value of the viewport. - - - - - Get the hither clipping value of the viewport. - - - Get the hither clipping value of the viewport. - - - - - Get the yon clipping value of the viewport. - - - Get the yon clipping value of the viewport. - - - - - Returns the viewport region rectangle as a . - - - Gets the viewport region rectangle, similar to Interface7::GetRegionRect(), but with coordinates in the range [0..1] instead of in pixels. - - - - - Returns the viewport blow-up rectangle as a . - - - Gets the viewport blow-up rectangle, similar to Interface7::GetBlowupRect(), but with coordinates in the range [0..1] instead of in pixels. - - - - - Returns the viewport bounding box of the current node selection, as a . - - - Gets the viewport bounding box rectangle of the selection, at the given slider time, with coordinates in the range [0..1] instead of in pixels . - - - - - Gets if drawing edges faces is turned on in the viewport. - - - Returns non-zero if edged faces is on. - - - - - Query the world space intersection point under the specified cursor position. - - - Returns true if the cursor hit any scene object, otherwise return false. - - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Get access to a nitrous render view instance. - - - - - Append string on current viewport's popup tooltip This function only available during NOTIFY_PRE_VIEWPORT_TOOLTIP. Max event callback "preViewportTooltip" uses this notification to let script user modify current tooltip. Each callback can append string to current tip content. The string format follows QT's rich text rule. - - The string append to current tip. - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Returns the picking selection radius scaling factor. This is used with the mouse cursor size to calculate the selection radius. The selection radius scale is a global property. - Returns the selection radius scaling factor. - - - - - Returns the picking selection radius in pixels. The selection radius is a function of the cursor size (which scales with the screen DPI) and the selection radius scale factor. The selection radius scale is a global property. - Returns the selection radius in pixels. - - - - - this in presentation mode on or off The presentation mode works only on viewport in floating view panels. It is a mode where there are no title bar, no grid, no view cube, no gizmos... The view in presentation mode is always updated even if it is not the active view - - - - - Is this in presentation mode ? The presentation mode works only on viewport in floating view panels. It is a mode where there are no title bar, no grid, no view cube, no gizmos... The view in presentation mode is always updated even if it is not the active view - Return true if it is in presentation mode. - - - - - Extends . - - - The following code example shows how to get access to this interface: - - - - - Get access to the IPerViewportFilter to know if an is filtered in a Viewport. - - - - - class - Description: - This class allows a developer to replace the file viewer used by 3ds Max (This is the "View File" option in 3ds Max's File menu). By creating a DLL from this class, and replacing the standard 3ds Max. DLL the system will always use the developer defined version. Note: To execute this plug-in, put the DLL in the same directory as the 3DSMAX.EXE executable. - - The following two functions are called by the system to create and delete the instance of this class that handles the file viewing. - - void *ViewFileCreate(); - - This function is implemented by the plug-in to create a new instance of this class. For example: This function is implemented by the plug-in to delete the instance of this class created above. For example: - - - - - This method is called by the system to bring up the file viewer. - Parameters: - HWND hWnd - - The parent window handle. - - - - - - - Describes the properties of a view that is being rendered. These are properties such as the type of view (parallel or perspective), its clipping distances, width, height, zoom factor, field-of-view, etc. - Data Members: - prevAffineTM; - - This is the world space to camera space transformation matrix computed 2 ticks before the affineTM matrix below. - - affineTM; - - This matrix will take a point in world space and convert it to camera space (or world to view space if it's a viewport). The camera coordinates are set up looking down the -Z axis, X is to the right, and Y is up. - - int projType; - - One of the following values: - - PROJ_PERSPECTIVE - - The view is a perspective projection. - - PROJ_PARALLEL - - The view is a parallel projection. - - float hither, yon; - - The hither and yon clipping distances. - - float distance; - - The distance from the view point to the image (view) plane. - - float zoom; - - The zoom factor of the viewport for parallel projection. The zoom factor gives the amount of magnification relative to a standard view width of 400 pixels. This is best explained via the following code fragment: ComputeViewParams() computes the projection factors for a given view, and MapToScreen() applies these factors to map a point from 3D camera coordinates to 2D screen coordinates.float fov; - - Field of view in radians for perspective projections. - - float nearRange; - - The near environment range setting (used for fog effects). - - float farRange; - - The far environment setting (used for fog effects). - - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds Max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - - The index of the command to execute. - - ULONG_PTR arg1=0 - - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG_PTR arg2=0 - - Optional argument 2. - - ULONG_PTR arg3=0 - - Optional argument 3. - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - Description: - This the base class for the creation of non-3D windows that appear in a 3ds Max viewport. These views are called "Extended Viewports". In order for a window to appear inside a viewport, you need to derive a class from this class. An instance of the derived class must be registered via the RegisterViewWindow() call in the class. A given derivative should only be registered once. - - When developers have registered their window types, the list of available extended views will appear in the view selection pop-up (either in the right-click viewport menu or the Viewport Configuration dialog) as a submenu of the "Extended" view label. - - There are two items which should be made in the extended viewport dialog proc code: - - Interface::MakeExtendedViewportActive() should be called whenever the user clicks in the non-3D window (so as to deactivate the current 3D window, and redirect commands like the Min/Max toggle to the non-3D viewport window). - - Interface::PutUpViewMenu() should be called when the user right-clicks in a dead region of the non-3D window. This brings up the view selection menu so that the user can choose to replace the current window with a 3D or other non-3D window without having to go to the Views | Viewport Config dialog directly. - - All methods of this class are virtual. - Sample Code: - - - - - Returns the name of the window type. For example, "AssetManager". - - - - - Creates and returns a handle to a new extended view window. - Parameters: - HWND hParent - - The handle of the parent window. - - int x - - The x coordinate of the window's upper left corner. - - int y - - The y coordinate of the window's upper left corner. - - int w - - The window width. - - int h - - The window height. - - - - - Destroys the previously created window as specified by the handle. - Parameters: - HWND hWnd - - The handle of the window to destroy. - - - - - Returns TRUE if the can be created; otherwise FALSE. This method can be overridden to return FALSE if a can only have a single instance, and that instance is already present. If this method returns FALSE, then the menu item for this will be grayed out. - Default Implementation: - { return TRUE; } - - - - - This method returns the number of instances of a given window that can be created. This allows, for example, the UI to know without physically creating a window that only a limited number of windows of that type can be created. A -1 implies that the count is not known. - Default Implementation: - { return -1; } - - - - - Description: - is a way for a to keep track of per-vertex information. Like vertex selection, this information is explicitly set after all topological changes performed by the , so any active vertex data channels are always set to the size outVNum() for the related . An example of this being used is in Edit , where you can assign or modify vertex weights. All these changes and assignments are stored in the Edit 's main . - Data Members: - *out; This is where the output vertex data is kept, if the given vertex data channel has been activated. - - - - - Sets the size of the output vertex data to the value specified. - Parameters: - int nv The number of elements to allocate. BOOL keep=FALSE If TRUE previous values are kept (copied to the new storage); otherwise they are discarded. - - - - - If the output vertex data has not been allocated this method allocates it with the specified number of elements. - Parameters: - int vnum The number of elements to allocate. int vdID The channel to allocate. One of the following values: VDATA_SELECTVDATA_WEIGHT - - - - - Sets the specified number of elements of vertex data at the location passed. - Parameters: - int where The zero based index of the destination in the out array. void *data The source data. int num=1 The number of elements to set. - - - - - Description: - This class represents the VIZable File URL. - - - - - This is a base class for creating world space modifiers. It simply provides a default implementation of SuperClassID(). World Space plug-ins use a Super Class ID of WSM_CLASS_ID. - - - - - - This class is a base class used to derived the helper object for a space warp modifier (WSM ). World Space plug-ins use a Super Class ID of WSM_OBJECT_CLASS_ID. - - - - - When the user binds a node to a space warp, a new modifier must be created and added to the node's WSM derived object. This method creates the new modifier. - A pointer to the new modifier. - - The node of the . - - - - Returns TRUE if spacewarp or collision object supports Dynamics; otherwise FALSE. - - - - - Returns a pointer to a . This pointer can be used during dynamics calculations, but should not be hung on to after that. For example, you shouldn't have the pointer long enough for it to be possible for the user to delete the space warp object. When you're done using the call its DeleteThis() method. This method may be called several times on the same space warp object with different INode* if it is instanced. - - This is the space warp object's node. - - - - This method returns the collision object for the WSM. This works just like GetForceField() documented above. - - This is the space warp object's node. - - - - This class contains a set of six command mode pointers that make up the XForm modes. Plug-in developers can specify these for their sub-object types. See the method BaseObject::ActivateSubobjSel() or class for more details. - - - - - Standard command mode to process Move. - - - - - Standard command mode to process Rotate. - - - - - Standard command mode to process Non-Uniform Scale. - - - - - Standard command mode to process Uniform Scale. - - - - - Standard command mode to process Squash. - - - - - Standard command mode to process Selection. - - - - - class that's used for storing a controller track. - - - Class used to specify a controller/animation track that is then used by the load save and mixer systems. They will reside in the . - - - - - The animatable track. - - - The animatable track - - - - - The animatable track's parent. - - - The animatable track's parent - - - - - The sub anim number of the anim under the client. - - - The sub anim number of the anim under the client - - - - - The name of the track. This plus the unique identifier is used to uniquely identify a track. - - - The name of the track. This plus the unique identifier is used to uniquely identify a track - - - - - used to specify how many other controllers exist before this one in the with the same name. - - - The number used to specify how many other controllers exist before this one in the with the same name - - - - - The name of the track that this track is mapped to. - - - The name of the track that this track is mapped to - - - - - Unique number for the track that it is mapped to. - - - The unique number for the track that it is mapped to. - - - - - Returns true if the object is the passed in type. - - - True if that type, false otherwise - - The type to check against - - - - The possible type of the anim track as defined in the enum Type definition. - - - Stored as an int instead of as an enum in order to speed up comparison operations. - The type - - - - - Compares this class instance to another one - - - - - The list of tracks, that will then be loaded onto, or saved out, or put into the mixer. - - - The class contains pointers to the objects and allocates and deletes these objects itself. This class is contained within the object. - - - - - Returns the i'th . - - - The item for tha index, NULL if the index is out of range - - The index of the item you want - - - - Deletes all of the XMLAnimTreeEntries in the list. - - - - - Find the specified anim in the list. - - - The index where the entry is, -1 if not found - - The anim you want to find. - Where you want to start looking from - - - - Find this particular based off it's pointer value. - - - The index where the entry is, -1 if not found - - you want to find - - - - The index where the entry is, -1 if not found - - The name of the track you want to find - Whether or not the track is unique - - - - - The index of the items subAnim parents you want to find. - The indices of the items parents. It will be empty if it has no subAnim parents. - - - - Fnd the subAnim children of the specified item. - - - - The index whose children you want to find. - The indices of the items children. It will be empty if it has no subAnim children. - - - - This class represents a container class for XTCObjects. - - - - - A pointer to the . - - - - - The priority. - - - - - The branch identifier. - - - - - Description: - This is the base class for an Extension Channel plug-in. These plug-ins are used to allow a developer defined object to flow down the geometry pipeline. This class provides an interface to the extension object. This is the virtual base class that developers can derive objects from, that should be inserted into the extension channel of the object flowing up the stack. Extension Channels will expand the geometry pipeline by allowing one to add a custom object to the pipeline object that can flow down the pipeline. This object will get notified whenever something in the pipeline changes. For example, if you want to indicate when a certain object becomes invalid for export to their game engine, invalid skin-vertex assignments, bound patches etc. By inserting an Extension Channel (, for short) into the pipeline you can accomplish this, by constantly checking the structure of the object and displaying wrong faces/vertices etc. in the viewport. - - You can specify which other channels it depends on using DependsOn(). The extension object has callback methods that get called before and after a modifier modifies a channel that the extension object depends on using PreChanChangedNotify() and PostChanChangedNotify(). The extension object can declare additional channels that it modifies using ChannelsChanged(), so that it can make any changes to the mesh before and after the modification by the modifier. - - In general, the Extension Channel is a transient data structure that gets recreated on every pipeline evaluation. So the object that adds an extension channel to the modifier stack automatically makes it persistent. However, when the user collapses the stack, the user might want the Extension Channel to be preserved as well. In order to accomplish that, please refer to the Class and the methods NotifyPreCollapse() and NotifyPostCollapse(). These methods will be called by the collapse code. It will give the modifier or , that adds an XTC object to the stack the possibility to apply a modifier, that inserts these XTC objects onto the stack after the collapse. Through this mechanism, the XTC will survive a stack collapse. The Pre and Post notifications will be called through a pipeline enumeration downstream (for more info see Class ). Developers, who are collapsing the stack programmatically, have to call this method. In case this method is not called, the XTC objects will by default be copied as well, since they are part of the object in the wsCache. However, they won't survive a save/load operation. In addition to all this, XTC objects also have the possibility to display their data in the viewports. Any Extension Channel can disable the display of the object itself and take over the entire display itself, by returning true in the method SuspendObjectDisplay(). - - Note: Modifiers which change the type of object that flows up the stack have to copy the Extension Channel from the old object into the new one using CopyAdditionalChannels() (e.g. the extrude modifier has to copy the XTC from the incoming spline to the , or NURBS object). - - Note: Compound objects have to merge the Extension Channel of the branched pipelines into the resulting pipeline. This is in general a simple copy of the Extension Channel into the new Extension Channel. When the CompoundObject evaluates is branches it would call CopyAdditionalChannels(os->obj), so that the Extension Channels of the branches are copied over. In the ConvertToType() method it then has to copy the Extension Channels from itself to the converted object using obj->CopyAdditionalChannels(this). - - Also note that the Extension Channel itself is implemented in Class . This means, that it will be available for all pipeline objects that get implemented in 3ds Max. For additional methods related to extension objects see the methods in Class -> . - - All methods of this class are virtual. Default implementations are shown. - - - - - - This method returns the unique identifier for the object. - - - - - This method is called to create a cloned copy of the object. The object should create a copy of itself and return a pointer to it. - - - - - This method returns a ChannelMask which specifies the channels that the depends on. If a modifier changes a channel that a depends on, its PreChanChangedNotify() and PostChanChangedNotify() methods will be called. - See Object Channels. - Default Implementation: - { return 0; } - - - - - This method returns a ChannelMask which specifies the channels that the extension object changes in the PreChanChangedNotify() and PostChanChangedNotify() methods. - See Object Channels. - Default Implementation: - { return 0; } - - - - - This method returns a ChannelMask which specifies the channels that the extension object uses in the PreChanChangedNotify() and PostChanChangedNotify() methods. - See Object Channels. - Default Implementation: - { return 0; } - - - - - If an wants to display itself in the viewport it can overwrite this method. - Parameters: - TimeValue t - - The time at which the object is to be displayed. - - INode* inode - - Points to the node for the object. - - *vpt - - Points to the viewport interface for the object. - - int flags - - See Display Flags *pObj - - Points to the object that the extension object is a part of. - The return value is not currently used. - Default Implementation: - { return 0; } - - - - - This method is called before a modifier is applied that changes a channel that the depends on. - Parameters: - TimeValue t - - The time at which the channel will be modified. - - &mc - - The modifier context. - - ObjectState* os - - The objectstate of the object. - - *node - - A pointer to the node. - - *mod - - A pointer to the modifier being applied. - - bool bEndOfPipeline - - TRUE to indicate that this is the last change before the wsCache. - Default Implementation: - { } - - - - - This method will be called after a modifier is applied that changes a channel that the XTC object depends on. - Parameters: - TimeValue t - - The time at which the channel will be modified. - - &mc - - The modifier context. - - ObjectState* os - - The objectstate of the object. - - *node - - A pointer to the node. - - *mod - - A pointer to the modifier being applied. - - bool bEndOfPipeline - - TRUE to indicate that this is the last change before the wsCache. - Default Implementation: - { } - - - - - If the returns TRUE from this method the object is not displayed in the viewport; if FALSE is returned the Display() method will be called to display the object. - Default Implementation: - { return false; } - - - - - This method allows the object to enlarge its viewport rectangle if it wants to. The system will call this method for all XTCObjects when calculating the viewport rectangle; the can enlarge the rectangle if desired. - Parameters: - *gw - - Points to the instance associated with the viewport the object is displayed in. - - Rect &rect - - The viewport rectangle for the object which may be modified. - Default Implementation: - { } - - - - - By default the existing XTCObjects will be deleted if a branch updates In case the wants to do more intelligent branching (not simply delete and add), it can return false from this method so that it can later (see MergeXTCObject() below) copy the data from this and other branches into an existing . - Parameters: - *obFrom - - Points to the source object. - - *obTo - - Points to the destination object. - Returns true if the object will be deleted; false to do more processing via MergeXTCObject. - Default Implementation: - { return true; } - - - - - The default implementation just adds the to the to object. In case the should do a more intelligent merge with already existing XTCObjects in the obTo, it has to overwrite this method. - Parameters: - *obFrom - - Points to the source object. - - *obTo - - Points to the destination object. - - int prio - - The priority to set. - - int branchID - - The branch identifier to set. - TRUE if successful, otherwise FALSE. - Default Implementation: - { obTo->AddXTCObject(this,prio,branchID); return true;} - - - - - In case a branch of a compound object is deleted the will be asked if the should be deleted as well. In case the represents a merge of all branches the might want to return false to this method and reassign itself to another branch, so that the merged information is not lost. - Parameters: - *ComObj - - A pointer to the compound object. - - int branchID - - The branch identifier to set. - - bool branchWillBeReordered - - TRUE if the branch should be reordered, otherwise FALSE. - TRUE if successful, otherwise FALSE. - Default Implementation: - { return true; } - - - - - Description: - This class generates coordinates based on the . A reference to one of these is referenced by all 3D texture maps. does for 3D Texmaps what does for 2D Texmaps. It puts up the 3D "Coordinates" rollup, and supplies the 3D with transformed 3D coordinates. All methods of this class are implemented by the system. - - - - - This method retrieves coordinates and derivatives for antialiasing. It returns the coordinates in the "Object CoordinateSystem", scaled and rotated by the parameters given in the Coordinates rollup. The default transformation is the identity transform, so you just get coordinates. For instance, if you have a sphere of radius 100, you will get coordinates ranging from -100 to +100. - - A developer might wonder why 3ds Max don't use some normalized coordinates space. This was considered, but it has some real problems. Say you make something by assembling several boxes, of varying sizes, and then apply a wood texture to the whole thing. You want the wood texture to be at the same scale for all the pieces, not smaller on the smaller pieces, and thus that doesn't work. - Parameters: - & sc - - Describes the properties of the point to be shaded. - - & p - - The 3D point is returned here. - - & dp - - The derivative of the 3D point is returned here. - - - - - Returns the open or closed state of the rollup. - TRUE is open; FALSE is closed. - - - - - This method returns the transformed bump unit vectors for 3D bump mapping. The 3D textures need to use these in computing the gradient. - Parameters: - & sc - - Describes the properties of the point to be shaded. - - Point3* dP - - The 3 unit vectors for computing differentials are returned here. - Default Implementation: - {} - Sample Code: - Here is a typical use of XYZGen->GetBumpDP() to compute the bump mapping for a 3D texture: - - - - - - - Contains the data for the bind points. - - - - - Spline that is to be bound. - - - - - Spline that contains the segment to bind to. - - - - - Segment that the point is bound to. - - - - - Position in space of the bind point. - - - - - Position in space of the start segment point. - - - - - Whether the bound point is the end or beginning of the spline. - - - - - the specified parent hwnd, if any. - - - - - Description of a command for building action tables from static data This is a helper structure used for building ActionTables. A static array of these descriptors is passed to the constructor. - - - - - A unique identifier for the command (must be unique per table). When an action is executed this is the command ID passed to ActionCallback::ExecuteAction(). - This should be a 16 bit value (in the range of 0-65,535) as it is also used as a Windows accelerator command ID for keyboard shortcuts, which is a WORD (16 bit unsigned short). - - - - - A string resource id that describes the command. - - - - - A string resource ID for a short name for the action. This name appears in the list of Actions in the Customize User dialog. - - - - - A string resource ID for the category of an operation. This name appears in the Category drop down list in the Customize User dialog. - - - - - This structure and the associated functions provide a way to decompose an arbitrary into its translation, rotation, and scale components. - - To use these APIs put the following statement in your source file: - For a full discussion of this decomposition see Graphics Gems IV - Polar Matrix Decomposition by Ken Shoemake. ISBN 0-12-336155-9. - T F R U K U' - T - translation matrix - F - either an identity matrix or negative identity matrix - R - rotation defined by q. - U - rotates you into the coordinates system where the scaling or stretching is done - K - scaling matrix - U' - inverse of u. - See Functions: - SpectralDecomp(Matrix3 m, Point3 &s, Quat& q); decomp_affine(Matrix3 A, AffineParts *parts); invert_affine(AffineParts *parts, AffineParts *inverse); - - - - - The translation components. - - - - - The essential rotation. - - - - - The stretch rotation. This is the axis system of the scaling application. - - - - - The stretch factors. These are the scale factors for x, y and z. - - - - - Sign of the determinant. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about the alert notifications. - - - - - This flag specifies if the alerts are enabled. - - - - - This bitmap represents the enabled alerts, which are following values: - - - - - Use every n-th frame for a progress report. - - - - - Helper struct to temporarily disable and re-enable Autobackup during a computation - - - - - 24 bit color: 8 bits each for Red, Green, and Blue. - - - - - - - 32 bit color: 8 bits each for Red, Green, Blue, and Alpha. - - - - - - - 48 bit color: 16 bits each for Red, Green, and Blue. - - - - - - - 64 bit color: 16 bits each for Red, Green, Blue, and Alpha. - - - - - - - High Dynamic Range bitmaps make use of this class to store color information using floating point values. - - - - - - - Storage for the floating point color information. - - - - - High Dynamic Range bitmaps make use of this class to store color information using floating point values. - - - - - - - Storage for the floating point color information. - - - - - Note: The camera looks down the negative Z axis, with X to the right and Y up. - - - - - Flag to indicate if the camera uses orthographic projection (TRUE) or perspective (FALSE). - - - - - The camera field-of-view in radians. - - - - - Target distance for free cameras. - - - - - Horizon line display state. - - - - - Flag to indicate if camera has manual clipping enabled. - - - - - Hither clipping plane distance. - - - - - Yon clipping plane distance. - - - - - Near camera range radius. - - - - - Far camera range radius. - - - - - The call parameter that accompanies the notification code NOTIFY_CLASSDESC_REPLACED A pointer to an instance of this structure is passed to BroadcastNotification after a is replaced by another one in a . This occurs when the dll containing a deferred loaded plugin is loaded. - - - - - The old class descriptor. - - - - - The new class descriptor. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about a Client. - - - - - The size of the structure, being sizeof(ClientInfo). - - - - - The version information, defined by _CLIENTINFO_VERSION. - - - - - The network system configuration data. Refer to this structure for more information. - - - - - TRUE if the Client is currently controlling the queue. - - - - - The UDP port being used for network communications. - - - - - Reserved for future use. - - - - - 8 bits for each of the Red, Green and Blue components. - - - Structure , Structure . - - - - - 16 bits for each of the Red, Green and Blue components. - - - - - - - 16 bits for each of the Red, Green, Blue, and Alpha components. - - - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about the system. - - - - - The number of processors in the system, retrieved through GetSystemInfo(). - - - - - The systems major version, retrieved through GetVersionEx(). - - - - - The systems minor version, retrieved through GetVersionEx(). - - - - - The systems build number, retrieved through GetVersionEx(). - - - - - The systems platform ID, retrieved through GetVersionEx(). - - - - - The systems CSD version, retrieved through GetVersionEx(). - - - - - The logged in users name, retrieved through GetUserName(). - - - - - The temporary directory, retrieved through ExpandEnvironmentStrings(). - - - - - The name of the computer, retrieved through GetComputerName(). - - - - - The disk, indexed by drive letter, used for server files such as incoming jobs. The index is alphabetical, disk A = 0, disk B = 1, etc. - - - - - The bit map representing the available disks. Disk A = 0x1, B = 0x2, C = 0x4, etc. - - - - - The space available on disks in MegaBytes, indexed by drive letter. Disk A = diskSpace[0], B = diskSpace[1], etc. - - - - - The computer NIC hardware address (00:00:00:00:00:00), which is 6 bytes and 2 padding bytes. - - - - - Reserved for future use. - - - - - This structure is sent to the Constraint function. - - - - - - - velocity of a delegate - - - - - speed of a delegate - - - - - position of a delegate - - - - - goal of a delegate - - - - - Represents a circular region when doing hit testing. - - - - - This is the display information structure. This structure holds the information describing 3ds Max's current system of measurement. This includes the type of units used, how they are displayed and any custom unit name and scale. - - - - - Unit Display Type. One of the following values: - - - - - Metric display option. One of the following values: - - - - - US display option. One of the following values: - - - - - US fraction option. One of the following values: - - - - - Custom unit name. - - - - - Custom unit value. - - - - - Custom unit reference. - Note: The three custom settings above are related as follows: If for example the customName is set to "FL" for furlongs (which is equal to 660 feet), customValue should equal 660.0 and customUnit should equal UNITS_FEET. - - - - - A generalized representation of a geometric or texture edge as a pair of vertex indices and face indices. - - - - - The indices of the two faces bordering the edge. - - - - - The indices of the two vertices spanned by the edge. - - - - - A generalized representation of a geometric or texture face as an array of vertex indices. - - - - - The number of vertices in the face. - - - - - An array of vertex indices for the face. - - - - - A generic set of parameters defining how soft selection weights are calculated. - - - - - If TRUE, soft selection weights are enabled and active, otherwise FALSE if soft selection is not active. - - - - - If TRUE, the distance between vertices is computed along edges. If FALSE, it's computed directly through space. - - - - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.) - - WARNING: If useEdgeDist is FALSE, this is an n-squared algorithm: it compares every vertex not in the cluster with every vertex in it. If useEdgeDist is TRUE, the time it takes is proportional to the number of verts in the cluster multiplied by edgeIts. - - - - - If TRUE, vertices with a normal that points more than 90 degrees away from the average normal of the selection are not given any partial selections. They're either 1 if selected or 0 otherwise. - - - - - The limit distance of the effect. If distance > falloff, the function will always return 0. - - - - - Use this to affect the tangency of the curve near distance=0. Positive values produce a pointed tip, with a negative slope at 0, while negative values produce a dimple, with positive slope - - - - - Use this to change the curvature of the function. A value of 1.0 produces a half-dome. As you reduce this value, the sides of the dome slope more steeply. Negative values lower the base of the curve below 0. - - - - - This structure is used by the and code to hold the G-Buffer data. - - - - - The floating point depth value at the center of the fragment that is foremost in the sorted list of a-buffer fragments. - - - - - The ID assigned to the material via the Editor. - - - - - This is the ID assigned to node via the Properties / G-buffer ID spinner. - - - - - UV coordinates, stored as a . - - - - - Normal vector in view space, compressed. - - - - - Non clamped colors in "RealPixel" format. - - - - - Pixel coverage of the front surface. - - - - - The renderer will set this ID for all rendered nodes, and will set all non-rendered nodes to 0xffff. - - - - - This is color returned by the material shader for the fragment. - - - - - This is transparency returned by the material shader for the fragment. - - - - - This is the sub-pixel weight of a fragment. - - - - - This gives the velocity vector of the fragment relative to the screen, in screen coordinates. - - - - - Used by the Network Rendering API as a handle to a server. - - - - - The handle to a server by its mac (Ethernet) address. - - - - - This structure is available in release 2.0 and later only. - This structure is updated by the RenderGlobalContext::IntersectWorld() and RenderGlobalContext::IntersectRay() methods. It stores information about the intersection of a ray and a single triangle in a mesh. - - - - - The ray that was intersected has a unit vector specifying a direction. The ray defines an infinite line in the specified direction. If you take this value t and multiply it by the direction itself it gives a point on the ray. This specifies a distance along the vector. For instance if this way 5.0, the point would 5.0 units along the ray vector. This is the point of intersection along the ray. - - - - - TRUE if the ray is exiting the object; otherwise FALSE. - - - - - TRUE if the ray hits a back face of the triangle; otherwise FALSE. - - - - - Points to the render instance associated with this triangle hit. - - - - - The face number of the triangle. - - - - - The barycentric coordinates of the intersection. - - - - - The intersection point in object coordinates. - - - - - The intersection point in camera coordinates. - - - - - The material requirements of the intersected face. See Material Requirements Flags. - - - - - The material number for a multi-material. - - - - - Points to the next structure in the list. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about a job. - - - - - The size of the structure, being sizeof(Job). - - - - - The structure version information, defined by _JOB_VERSION. - - - - - The server Process ID which is used by 3ds max to check server's health. - - - - - The job flags, defined as the following values: - - - - - Handle to the job, assigned by the Manager when a job is created/submitted. This handle will be read-only after its creation. - - - - - The name of the job. - - - - - Used internally when transferring archive (size of archive file) - - - This variable is used internally when transferring an archive and specifies its size. - - - - - Used internally when transferring archive (size of expanded archive) - - - This variable is used internally when transferring an archive and specifies its uncompressed size. - - - - - The system time, set when a job is created/submitted. - - - - - The system time, set when a job starts. - - - - - The system time, set when a job is completed. - - - - - The number of servers defined for the job (can be 0 if JOB_ALLSERVERS is set). - - - - - The alert notification data structure. - - - - - The number of JobTextInfo records. - - - - - The first frame in the range. - - - - - The last frame in the range. - - - - - The frame step value (i.e. every n-th frame). - - - - - The frame output dimensions (width / height). - - - - - The number of frames completed. - - - - - The job priority level. - - - - - Reserved for future use. - - - - - Specific information about a job pertaining to 3ds Max. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information the state of a job. - - - - - The structure containing the job details. - - - - - The handle to the job. - - - - - The current state of the job, which is one of the following values: - - - - - This structure is available in release 4.0 and later only. - - This structure contains the details on a specific Render Element for a job. - - - - - This flag indicates if the Render Element is enabled or disabled. - - - - - This flag indicates if filters are enabled or disabled for the Render Element. - - - - - This flag indicates if atmospheric effects are enabled or disabled for the Render . - - - - - This flag indicates if shadows are to be applied for the Render . - - - - - The name of the Render . - - - - - The output path and file name of the resulting Render Element. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about the servers in the job queue. - - - - - The handle to the server. - - - - - The current state of the server, which is one of the following values: - - - - - This variable is used internally. - - - - - Indicates that the server is active in the job. - - - - - The frame which is currently being rendered. - - - - - The total hours the server has spent rendering. - - - - - The total number of frames the server has rendered. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store textural information regarding a job. - - - - - The Job Text type. See JOB_TEXT_TYPE for details. - - - - - The text buffer contents. - - - - - The output text buffer. - - - - - The Render Elements details of the job. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store a jobs frame progress information. - - - - - The current state of this frame which is one of the following values: - - - - - The frame number. - - - - - The handle to the server rendering this frame. - - - - - The time it took to render this frame, in milliseconds. - - - - - The call parameter that accompanies the notification code NOTIFY_NODE_LAYER_CHANGED. - - - - - The call parameter that accompanies the notification code NOTIFY_LAYER_PARENT_CHANGED. - - - - - pointer on the layer that has changed parent - - - - - pointer on the old parent of the layer - - - - - This structure describes the properties of a light. - - - - - One of the following values from enum LightType: - OMNI_LGT - Omnidirectional - SPOT_LGT - Spot (cone) - DIRECT_LGT - Directional (parallel) - AMBIENT_LGT - Global - - - - - The transformation matrix of the light. - - - - - The color of the light (its intensity). - - - - - The multiplier applied to the color. - - - - - The hotspot size in degrees. - - - - - The hotspot falloff size in degrees. - - - - - Nonzero if near attenuation is used; otherwise zero. - - - - - The near attenuation start value. - - - - - The near attenuation end value. - - - - - Nonzero if (far) attenuation is used; otherwise zero. - - - - - The (far) start attenuation value. - - - - - The (far) end attenuation value. - - - - - One of the following values: - RECT_LIGHT, CIRCLE_LIGHT - - - - - The aspect ratio of the light. - - - - - TRUE if the light supports overshoot; otherwise FALSE. - - - - - TRUE if shadows are on; otherwise FALSE. - - - - - TRUE if the light is on; otherwise FALSE. - - - - - TRUE if affect diffuse is on; otherwise FALSE. - - - - - TRUE if affect specular is on; otherwise FALSE. - - - - - Structure specifying which controllers to load from a BIP file. - - - - - The type of controller to load: position = 0, rotation = 1, scale = 2. - - - - - - - - - Storage for the pixel value. - - - - - Assignment operator. - Parameters: - const float c[3] - The array of color values to assign in RGB order. - - - - - This structure is available in release 4.0 and later only. - - This structure is a 32 bit pixel format that stores 1 bit for sign, 15 bits for the log of the luminance, and 16 bits of chroma. - - This class stores colors in XYZ space. XYZ color space is the space define by the CIE by the red (X), green (Y) and blue (Z) response curves of the eye. So to calculate a color in XYZ space, you take the incoming light, multiply it by each response curvey and integrate the result over the visible spectrum. There are several RGB spaces, all depending on what XYZ coordinates get assigned to the red, green and blue primaries of the space. The transformations between XYZ and RGB space are all linear and can be represented as 3 by 3 matrices. - - The mapping used by XYZtoRGB and RGBtoXYZ is for CCIR-709 primaries and was taken from the code in the tiff reader for the LogLUV32 format. Both XYZ and RGB methods are supplied, so developers can supply different XYZ to RGB transforms, if desired. - - This transform is important, because in the LogLUV32 format the log is taken of the Y coordinate in XYZ space. So, it is important that Y not be 0. The transform helps guarantee this. In fact, Y is zero only when r, g and b are all 0. - - - - - Storage for the pixel value. - - - - - Assignment operator. - Parameters: - const float c[3] - The array of color values to assign in RGB order. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about a Manager. - - - - - The size of the structure, being sizeof(ManagerInfo). - - - - - The version information, defined by _MANAGER_INFO_VERSION. - - - - - The network system configuration data. Refer to this structure for more information. - - - - - The network status information. - - - - - The number of servers registered. - - - - - The number of jobs. - - - - - Reserved for future use. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about a 3ds Max specific job. - - - - - This flag determines if the structure is valid. - - - - - This flag determines is gamma correction is used. - - - - - The input gamma value for maps. - - - - - The output gamma value for output images. - - - - - The pixel aspect ratio. - - - - - - - - - - The scene information data structure. - - - - - The render elements data structure. - - - - - Reserved for future use. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to enable or disable Render Elements. - - - - - This flag determines if render elements are enabled or not. - - - - - A struct to allow us to expose more node information. - - - - - This class allows access to the sub-object hit records used in hit testing. All methods of this class are implemented by the system. use instead of linked-list in Max 2017 for performance of large amount of data. The constructor's change is to keep code compatibility. Although internal storage changed, client code only needs recompile without any modification. - - - - - The distance of the hit. An implementation defined value that is lower for hits that are closer. - - - - - The index of the sub-object component. For example, if faces were being hit tested, this would be the index of the mesh's FaceSel(). For edges, this is the index into the EdgeSel() , where the index is 3*faceIndex+edgeIndex. - - - - - The second level index of the sub-object component. Usually it is used for 's diagonal selection, in this case the index is the poly face index while index2 is the diagonal index within the poly face. - - - - - The name change call parameter structure. - - - The call parameter that accompanies any notification that involves a name change of an object(The name change notifications.), which contains information of both the old name and the new name of the changed object. - - - - - The old name of the changed object. - - - - - The new name that is assigned to the changed object. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store network status information. - - - - - The number of packets dropped due to buffer overflows. - - - - - The number of bad formed packets. - - - - - The total number of TCP requests since boot time. - - - - - The total number of UDP requests since boot time. - - - - - The system boot time. - - - - - Reserved for future use. - - - - - The call parameter that accompanies the notification code NOTIFY_NODE_NAME_SET. - - - - - The call parameter that accompanies the notification codes NOTIFY_CUSTOM_ATTRIBUTES_ADDED and NOTIFY_CUSTOM_ATTRIBUTES_REMOVED. - - - - - The owner of the custom attribute that was added or is about to be removed. - - - - - The custom attribuet that was added or is about to be removed. - - - - - The call parameter that accompanies the notification code NOTIFY_FAILED_DIRECTX_MATERIAL_TEXTURE_LOAD. - - - - - The call parameter that accompanies the notification code NOTIFY_FILE_CHECK_STATUS. - - - - - The call parameter that accompanies the notification codes. - - - - - The type of operation. See notify_file_process_type. - - - - - The full path of the file being processed. - - - - - Whether the file open or save was successful. - - - - - The call parameter that accompanies the notification codes NOTIFY_IMPORT_FAILED, NOTIFY_EXPORT_FAILED. - - - - - The full path to the file being imported/exported. This can be null if no file was selected. - - - - - The return code of the importer/exporter. Can be either IMPEXP_FAIL or IMPEXP_CANCEL. - - - - - Type of all notification codes. - - - 3ds Max supports a system where a plug-in can ask to receive a callback when certain events occur. These are events such as the system unit settings changing, system time setting changing, or the user executing File/Reset, File/New, etc. - - This structure is part of this system. It is available in release 2.0 and later only. The class has related methods for registering callbacks. - - The plug-in creates a callback function to process the notification. The notification callback function (NOTIFYPROC) is defined as follows: - *info); - The structure is passed to the NOTIFYPROC to inform it of what it's being notified about. - - The sample code below shows how this system may be used. - Sample Code: - See Functions: - RegisterNotification(NOTIFYPROC proc, void* param, NotifyCode code); - UnRegisterNotification(NOTIFYPROC proc, void* param, NotifyCode code); - BroadcastNotification(NotifyCode code); - BroadcastNotification(NotifyCode code, void* callParam); - UnRegisterNotification(NOTIFYPROC proc, void *param); - - - - - The call parameter that accompanies the notification codes. - - - - - The call parameter that accompanies the notification code NOTIFY_FILE_POST_MERGE3. - - - - - size of this struct - - - - - fileSaveVersion stores the result of ILoad::GetFileSaveVersion() - - - - - fileSaveAsVersion stores the result of ILoad::FileSaveAsVersion() - - - - - The call parameter that accompanies the notification code NOTIFY_POST_NODES_CLONED. - - - - - The call parameter that accompanies the notification code NOTIFY_FILE_POST_OPEN. - - - - - the type of the file that was opened - - - - - - - fileSaveVersion stores the result of ILoad::GetFileSaveVersion() - - - - - fileSaveAsVersion stores the result of ILoad::FileSaveAsVersion() - - - - - The call parameter that accompanies the notification code NOTIFY_MODPANEL_SUBOBJECTLEVEL_CHANGED. - - - - - The object redefinition call parameter structure. - - - Instance of this structure is passed as call param on NOTIFY_OBJECT_DEFINITION_CHANGE_BEGIN/NOTIFY_OBJECT_DEFINITION_CHANGE_END broadcast notifications. - - - - - The type of object definition being redefined. - - - - - A pointer whose type is dependent on the type of object definition being redefined. - - - - - This structure provides information about a parameter alias. Aliases allow individual parameters or <> parameter elements to be named. See the methods IParamBlock2::DefineParamAlias, FindParamAlias, etc. - - - - - The name of the alias. - - - - - The permanent ID of the parameter. - - - - - If the parameter is a <> this is the zero based index into the table of the parameter. If the parameter is not a table this is -1. - - - - - The data members of this class provide a definition of a parameter. An array of these parameter definitions is a data member of class . - - - - - This is the permanent, position independent ID of the parameter. - - - - - This is a fixed internal name of the parameter. This name is not localized. Internal names are meant to be parsable as identifiers. As such they should begin with an alpha character, have only alphanumerics, and have no spaces, punctuations, etc. The convention for multi-word names is to use studly-caps, eg, paintRadius. - - - - - This is the fixed non-localized (English) name of the parameter. This name is used by script engines for SubAnim name resolution for when the script specifies the SubAnim name in English but 3ds Max is running with a non-English language pack. By default, this contains the same pointer as specified by int_name. If the specified internal name is not the same as the English name, the non-localized name should be specified using the p_nonLocalizedName paramtag. - - - - - This is the type of the parameter. See ParamType2. - - - - - They are the per-parameter constructor flags (P_ANIMATABLE, P_TRANSIENT, etc.) Normally, the flags are set up as a result of things you specify in the constructor and should generally be read-only at runtime. - - - - - This is the string table resource ID for the localized (sub-anim) name. - - - - - This is the parameter dimension. See Class . - - - - - The default value for the parameter. - - - - - This is the default value for MAXScript and the . - - - - - This is the current 'sticky' default value, used to maintain creation defaults within a session. - - - - - This is a one sentence description. Use a string resource ID. - - - - - This indicates the low allowable range used in MAXScript validation and spinner setup. - - - - - This indicates the high allowable range used in MAXScript validation and spinner setup. - - - - - Points to an instance of the validator object. This object has a Validate() method used to check if the parameter is valid. - - - - - Points to an instance of an accessor object. Any parameter in a block can have an accessor callback object that has its Get() or method called whenever the parameter is accessed. This may be used to provide access to dynamically-computed virtual parameters and sometimes to allow parameter-specific processing by the class as the parameter in the block is modified. - - - - - If the parameter is a table (<>) this is the initial table size. - - - - - This is a block-owner's reference number for non-hosted ReferenceTargets parameters. - - - - - This is a block-owner's SubTex index for parameters in owners. - - - - - This is the validator for reference targets. - - - - - This is the SClass_ID validator for reference targets (similar to above). - - - - - This is the type of user interface control. - - - - - This is the spinner type if the associated UI control is a spinner. One of the following values may be used: - - - - - This is the array of control IDs for this parameter. - - - - - This is the number of controls in the ctrl_IDs array above. - - - - - This is the scale given to the , as is used in SetupFloatSpinner(), for example. - - - - - This is the slider segments count. - - - - - The array of which other parameters have their UI controls automatically enabled by this parameter. - - - - - This is the number of parameter IDs in the enable_ctrls array above. - - - - - The status line prompt string resource ID for various picker buttons. - - - - - The caption string resource ID for open/save file dialogs. - - - - - The ToolTip string res ID. - - - - - The initial filename for open/save file dialogs. - - - - - The file types string resource ID for open/save file dialogs (in MAXScript type: form) - - - - - Maps IDs if in a multi-map block (block flag P_MULTIMAP) - - - - - A list of file types to be used for Open/Save dialogs - - - - - parameter type (only for TYPE_FILENAME and TYPE_FILENAME_TAB) - - - - - color context (only for TYPE_RGBA, TYPE_FRGBA, TYPE_RGBA_TAB and TYPE_FRGBA_TAB) - - - - - Returns true if the parameter is defined as an asset. A parameter is considered an asset if it's type if TYPE_FILENAME or TYPE_FILENAME_TAB and is flagged with P_HAS_ASSETTYPE or P_HAS_ASSETTYPENAME. - - - - - This structure is sent to the Perform function. - - - - - - - a force acting upon a delegate - - - - - a world space goal of a delegate - - - - - the speed of a delegate (to be multiplied by the delegate's average speed) - - - - - the intended eventual speed of a delegate - - - - - This structure holds the value in a ParamBlock2 or . - - - - - This is used by: TYPE_INT, TYPE_BOOL, TYPE_TIMEVALUE, TYPE_RADIOBTN_INDEX, TYPE_INDEX. - - - - - This is used by: TYPE_FLOAT, TYPE_ANGLE, TYPE_PCNT_FRAC, TYPE_WORLD, TYPE_COLOR_CHANNEL. - - - - - This is used by: TYPE_POINT2. - - - - - This is used by: TYPE_POINT3, TYPE_RGBA, TYPE_HSV. - - - - - This is used by: TYPE_POINT4, TYPE_FRGBA. - - - - - This is used by TYPE_MATRIX3. Note that TYPE_MATRIX3 items cannot be animated. - - - - - This is used by TYPE_TIMEVALUE. - - - - - This is used by TYPE_FILENAME or TYPE_STRING. - - - - - This is used by TYPE_BITMAP. - - - - - A generic reference target pointer (Mtl*, Texmap*, INode*). - - - - - This value replaces the i, f, p, p4, p2, or t values if they are actually animated (and thus have a controller assigned). - - - - - These flags are for internal use only, do not alter them. - - - - - Returns FALSE if the holds a control that is to be evaluated to get the 's value. - - - - - Frees the memory used by the based on the specified type. - - The type of value held by the . - - - - Initializes the memory used by the based on the specified type. - - The type of value held by the . - - - - Replaces the string used by the with the specified string. - - The new string. - - - - This structure describes color in terms of r, g, b, e. - - This is taken from GraphicsGems II, "Real Pixels" by Greg Ward of Lawrence Berkeley Laboratory. What it means is this: "e" is the base 2 exponent of the maximum RGB component, and r,g,b are the mantissas of R,G,and B, relative to this exponent. It essentially compresses the essential data of a floating point color into 32 bits. - - Quoting from Graphics Gems II: - "It appears that this format favors the largest primary value at the expense of accuracy in the other two primaries. This is true, but it also is true that the largest value dominates the displayed pixel color so that the other primaries become less noticeable". - - One option is to write out the image in format, storing NON CLAMPED colors. This could be used by a Video Post process to detect those areas of the image where the intensity goes beyond 1 and apply halo and flare effects much more realistically. - - There are functions for converting between floating point and format: - ; - and - ExpandRealPixel(RealPixel &rp, float& r, float &g, float& b); - as well as methods in and . - - - - - The mantissas of R,G,and B, relative to this exponent. - - - - - The base 2 exponent of the maximum RGB component. - - - - - Structure specifying which controllers to save in a BIP file. - - - - - The node whose controller will be saved. - - - - - The type of controller to save: position = 0, rotation = 1, scale = 2. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about the scene. - - - - - The number of objects in the scene. - - - - - The total number of faces in the scene. - - - - - The total number of lights in the scene. - - - - - The scene start / end time. - - - - - This variable contains all the flags relating to the scenes rendering options, which are following values: - - - - - Used by the Network Rendering API to store hourly scheduling information. - - - - - This bit map represents the hourly schedule where 24 bits represent the hours. A bit set to 0 indicates it is allowed to work, a bit set to 1 indicates its not allowed to work. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store information about a Server. - - - - - The size of the structure, being sizeof(ServerInfo). - - - - - The version information, defined by _SERVER_INFO_VERSION. - - - - - The total number of frames rendered. - - - - - The total time spent rendering, in hours. - - - - - Performance index - - - - - The network system configuration data. Refer to this structure for more information. - - - - - The network status information. - - - - - Reserved for future use. - - - - - This structure is available in release 4.0 and later only. - - This structure is used by the Network Rendering API to store global server state information. - - If hJob is a valid handle (i.e. non 0) and frame holds a NO_FRAME, this means this server has just be assigned a job or it is in between frames (no frames assigned). Most likely it is loading 3ds Max. The transition in between frames is in the nanosecond level, but seeing as it is possible, it cannot be discarded. - - - - - The handle to the server. - - - - - The current state of the server which is one of the following values: - - - - - The server information structure containing the server details. - - - - - The handle to the job that the server is currently working on, if there is one. - - - - - The frame the server is currently rendering, if there is one. - - - - - The time the server had the frame assigned. - - - - - Describes the snap settings used for snap operations. - - - - - Snap settings. - - - - - - - Maximum snap distance. - - - - - Geometry vertex priority. - - - - - Geometry edge priority. - - - - - Grid intersection priority. - - - - - Grid line priority. - - - - - Snap flags. - - - - - - - to use for snap computations. - - - - - Best snap point found in world space. - - - - - Best snap point found in screen space. - - - - - Best snap point distance. - - - - - Best snap point's priority. - - - - - This structure contains information on rendering for Mirror and Automatic Cubic materials. This is used by the methods of the class. - - - - - The rendering type being done. - - - - - TRUE if field rendering is being used; otherwise FALSE. - - - - - This is used when field rendering. TRUE if doing even numbered scanlines; FALSE for odd numbered. - - - - - This is used as part of implementing the Mirror material. It should be FALSE in all other cases. - - - - - The dimensions in pixels of tobm. - - - - - The aspect ratio of tobm. - - - - - The location on the screen of the upper left corner of the output bitmap. - - - - - The area of the screen being rendered. - - - - - The 2D point at the center of the render blowup region. - - - - - The X and Y scale factors for render blowup. - - - - - This is a general purpose function that allows the API to be extended in the future. The 3ds max development team can assign new cmd numbers and continue to add functionality to this class without having to 'break' the API. - Parameters: - int cmd - The index of the command to execute. - - ULONG arg1=0 - Optional argument 1. See the documentation where the cmd option is discussed for more details on these parameters. - - ULONG arg2=0 - Optional argument 2. - - ULONG arg3=0 - Optional argument 3. - Return Value: - An integer return value. See the documentation where the cmd option is discussed for more details on the meaning of this value. - - - - - This structure is available in release 4.0 and later only. - - This structure contains the actual information for the output text buffer. - - - - - The device flag will be set to TRUE if the output is sent to a device instead of a file. - - - - - The output gamma for the device, which is optional. If the gamma value is set to 0.0, this value will be ignored. - - - - - The text output buffer. - - - - - Description: - The address of this struct passed in LPARAM when you get a WM_NOTIFY, with TABDLGNOTIFY_GETINITINFO as the notify code. This notification is sent to the tab dialog before each page is created. hdr.idFrom is the index of the page about to be created. The value stored in dwInitParam is passed to the InitPage method as lparam. - - - - - this out param contains the ptr to initialization data for the page. - - - - - This structure is available in release 4.0 and later only. - - This structure is for collecting the return results of Control::GetLocalTMComponents. Position, Rotation, or Scale, controllers will put results at the respective component when the corresponding pointer is not NULL. - - - - - If not NULL this is the position. - - - - - If not NULL this points to the validity interval for the position. - - - - - If not NULL this is the rotation and should be a float[4]. - - - - - If not NULL this points to the validity interval for the rotation. - - - - - The rotation representation. This defines what the 4 numbers in the rotation array mean. One of the following enum values: - kXYZ - Same as EULERTYPE_XYZ - kXZY - Same as EULERTYPE_XZY - kYZX - Same as EULERTYPE_YZX - kYXZ - Same as EULERTYPE_YXZ - kZXY - Same as EULERTYPE_ZXY - kZYX - Same as EULERTYPE_ZYX - kXYX - Same as EULERTYPE_XYX - kYZY - Same as EULERTYPE_YZY - kZXZ - Same as EULERTYPE_ZXZ - kQuat - A quaternion representation. - kUnknown - An unknown representation. - - - - - If non-NULL this is the . - - - - - The validity interval for the . - - - - - A User definable Coordinate System. - - - The developer can use this to define the Coordinate System that they are using. Rotation specifies whether it is a Right or Left handed system. The Axis define which way the primary axis point. This will mean that the data extracted is converted correctly, and the winding order is correct for Left and Right handed systems. - In 3ds Max this could be defined as - = {1, //Right Handed1, //X axis goes right4, //Y Axis goes in2, //Z Axis goes up.1, //U Tex axis is left0, //V Tex axis is Up} - - - - - Handedness. - - - 0 specifies Left Handed, 1 specifies Right Handed. - - - - - The X axis. - - - It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out. - - - - - The Y axis. - - - It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out. - - - - - The Z axis. - - - It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out. - - - - - The U Texture axis. - - - It can be one of the following values 0 = left, 1 = right - - - - - The V Texture axis. - - - It can be one of the following values 0 = Up, 1 = down - - - - - Return value of ComputeUVTangents(). - - - - - Meta data of class; it contains the description of how the window is created - - - - - Used by the Network Rendering API to store weekly scheduling information. - - - - - The hourly schedule configuration for each day of the week. - - - - - The attended priority value which is one of the following values: HIGHPRIORITY, LOWPRIORITY, or IDLEPRIORITY. - - - - - The unattended priority value which is one of the following values: HIGHPRIORITY, LOWPRIORITY, or IDLEPRIORITY. - - - - - The colour modes define how CATs rig nodes will be coloured in the veiwport. - - - - - The CATMode defines how the character will behave when interacted with. - - - - - This is the interface class to the manager of the CAT Rig. Here you will find functions create/load/save a rig, and iterate its members. A CATParent is not part of a rig, and not meant to be animated. It is simply a storage vessel for the data common to the entire rig. Sample usage: - - - - - Load a CAT Rig file (.rg3 or .rig). This function should only be called if a rig does not currently exist on the CATParent - The of the CATParent after file load. Loading an RG3 file will delete the current CATParent and , and replace them with the version from the file. If you wish to continue accessing the CATParent after calling this function refresh your pointer with the returned value. - - The rig definition to load - - - - Save the current rig to a rig definition file - TRUE if the rig was successfully saved. - - The file to save the rig too. This can either be a .rig filename for an ascii file or a rg3 binary file - - - - Get the name of the CAT character. This name is used as a prefix for all rig elements - The name of the CAT character - - - - - Returns the rigs CATUnit scale. - The rigs CATUnits scale - - - - - Returns the current mode of the character - the current CATMode - - - - - Sets the current mode of the character - - the current CATMode - - - - - Returns the current colour mode of the character - the current colour mode - - - - - Return the current axis which defines our length. This is the axis that bones look down. - 0 for the X axis, or 2 for the Z axis. - - - - - Returns the aproximate location of the root of the character This value is used by the root node to find its transform - The world space approximation of the root of the character - - The time to find the transform at. - - - - Create a new hub (pelvis) for the character This function will only succeed if the CATParent has no character yet. - TRUE if the hub was successfully created, else FALSE - - - - - Returns the controller for the root hub (pelvis) for the character. - The controller of the root hub, or NULL - - - - - Find a member of the CAT rig by its address. - The inode of the addressed rig element, or NULL if not found - - the address of the rig node - - - - Get the address of this node (the CATParent node) - The address of this controller. - - - - - TODO (Not sure what this does. - - - - - Internal as well. Find a way to hide this. - - - - - Get the of this CATParent. - The of this CATParent. This should never be NULL - - - - - Finds a complete list of all nodes in this rig, including extra bones and other stuff. - A filled with all rig elements. - - - - - Finds a complete list of all layer controls, including extra controllers - A filled with all layer controllers. - - - - - Create a node to be placed under the CAT character. This node can be used as a root for the character (for example, if for exporting the character to a game engine). - - - - - Returns the root node, if it exists, else NULL - the root node, if it exists, else NULL - - - - - Fills out the definition structure with the CAT rig structure. It is not guaranteed that all members of the class will be filled out. - TRUE if the definition was filled out correctly, FALSE if not. Note this does NOT guarantee all the parameters are filled out, it will return TRUE if the CAT rig is valid. - - The definition to fill out - - - - Get the indexed layers color. - This is the color that will be set to a nodes wire color when "Rig Coloring Mode" is set to "by layer". - The color of the specified layer, if valid, or black - - - The index of the layer to get the color of. This must be the index of an absolute layer. - - - - the indexed layers color. - This is the color that will be set to a nodes wire color when "Rig Coloring Mode" is set to "by layer". - True if the color is set correctly, false if the method fails - - - The index of the layer to get the color of. This must be the index of an absolute layer. - - The color being set to the layer. - - - - Returns the absolute/relative ratio. At 1.0f the tip hub is absolute and does not inherit rotations from the base. - - - - - These are our current supported primitive mesh types which we uses with the class. - - - - - This enums list all our possible vertex components for our vertex vbuffer. - - - - - This class is used to help with managing 16 bit hardware index buffer. - - - This class is used to help with managing 16 bit hardware index buffer. it is not designed to be used as representation of an entire index buffer but used to map into an existing buffer. It can be used to overlay an existing index buffer or as temp buffer to be filled out then copied into the final buffer - - - - - Assigns array of WORD to this hw index. - - - This lets you assign a buffer to map into WORD *buffer is the buffer. This will let the HWIndex map into the buffer so you can extract a specific element out of it. - - the array of indices to be mapped - - - - Returns the number of indices per element. - - - This returns the number of indices per element. For instance a triangle would return 3 a line list 2 - - - - - access to each index. - - - access to each index. Out of bounds access <0 || > Count() will default to returning the first index - The index value - - - - - This class is used to help with managing 32 bit hardware index buffer. - - - This class is used to help with managing 32 bit hardware index buffer it is not designed to be used as representation of an entire index buffer but used to map into an existing buffer. - It can be used to overlay an existing index buffer or as temp buffer to be filled out then copied into the final buffer - - - - - Assigns array of DWORD to this hw index. - - - This lets you assign a buffer to map into DWORD *buffer is the buffer. This will let the HWIndex map into the buffer so you can extract a specific element out of it. - - the array of indices to be mapped - - - - Returns the number of indices per element. - - - the number of indices per element. For instance a triangle would return 3 a line list 2 - - - - - access to each index. - - - access to each index. Out of bounds access <0 || > Count() will default to returning the first index - The index value. - - - - - This class is our hw index buffer representation. - - - This class is our hw index buffer representation. It is just basically a list of DWORDs or WORDs and a description of the number of indices per element. - - - - - This frees all our index buffers. - - - This frees all our index buffers and resets the count to 0 - - - - - returns the number of primitives in the index buffer - - - the number of primitives in the index buffer - - - - - Returns the number of indices per primitive. - - - the number of indices per primitive ie a triangle 3, line list 2 etc - - - - - This lets you reset the number of primitives. - - - This lets you reset the number of primitives in the list it will keep the original data. It will returns true if successful. - true is successful otherwise it ran out of memory - - is the new size for the buffer - - - - This returns whether the buffers are 16 or 32 bit. - - - whether the buffers are 16 or 32 bit. Right now we tend to use 16 bit buffers and split up the mesh to fit into those buffers so we can reduce the memory foot print. - - - - - Returns a particular 32 bit HWIndex. - - - Returns a particular 32 bit HWIndex. This is useful if you dont want to look up the offsets by hand /param int index - the index of that you want - a particular 32 bit HWIndex - - - - - Returns a particular 16 bit HWIndex. - - - Returns a particular 16 bit HWIndex. This is useful if you dont want to look up the offsets by hand /param int index - the index of that you want - - - - - This class is a container for vertex and index buffers. - - - This class is a container for vertex and index buffers. It represents mesh that has one material on it. It allows you to generate buffers and fill them out. It has one vertex buffer and 2 index buffers, one for the shaded mesh and one for the wire frame. - - - - - Returns the size of the buffers in bytes. - - - - - This returns the hw vertex buffer for this hw mesh. - - - Typical usage it to create the mesh. Get the hw vertex buffer, set it parameters, create it, then fill it out. - - - - - This lets you add a index buffer to the mesh. - - - We support 2 index buffer per mesh so that different draw primtives can share the same vertex buffer. The first is the shaded face buffer the second is the wire frame line list. It returns the id of this index buffer - - is the number of primitives ie triangleList, lineList etc for this buffer - is the type of primitive it is ie trianglelist, linelist etc. - is whether the buffer buffer will be 16 bit or 32 bit indices - - - - This returns a particular index buffer. - - - - - This lets you delete a particular index buffer. It returns true if successful. - - - - - This returns the number of index buffers. - - - - - This lets you get the material id for this mesh. - - - This lets you associate the mesh with a material. We only allow one material per mesh. - - - - - This lets you get the asssociated with this mesh. - - - The contains the low level hardware buffers specific to the current device ie Direct9, 10, OGL etc - - - - - This allows you to update the buffers. - - - This allows you to change the position and normals of the mesh without recreating the hwmesh. - - - This is a pointer of all the vertices on the mesh - This is a pointer of all the gfx normals on the mesh - This is a pointer of all the face normals on the mesh - This is a bitarray of the changed verts - This is number of vertices in vertex List - - - - This is a container class of our sub meshes. - - - This class is a container for all our sub mesh. We separate each mesh by matid and vertex buffer size - - - - - This frees all the sub meshes and sets the sub mesh count to 0. - - - - - Returns the number of sub meshes. - - - - - Returns a specific sub mesh. - - - - - Appends a sub mesh to the list. - - - The container will manage the life of the pointer - - is the mesh to append to the end of the list - - - - This class is used to help with managing hardware(hw) vertex buffer. - - - It is not designed to be used as representation of an entire vertex buffer but used to map into an existing buffer. - - - - - Lets you get the vertex type. - - - - - This sets the size of each UVW channel. - - - By default a UVW channel is 2 floats just UV. You can change the size to just a U, UV, or UVW with this. This must be set before accessing any of the vertex data or calling SetBuffer - - which channel - the size of the channel 1 to 3 - - - - This gets the size of a specific UVW channel. - - - By default a UVW channel is 2 floats just UV. You can change the size to just a U, UV, or UVW with this. - - - which channel - - - - This lets you map the hw vertex to a buffer. - - - Note you need to call SetUVWSize first before calling this if you want to change the UVW channel sizes - - the buffer that you want to map onto - - - - Returns the stride of the hw vertex in bytes. - - - - - Gets the Position component if there is one. - - - - - Returns the pointer to position portion of the vertex. - - - - - Gets the Normal component if there is one. - - - - - Returns the pointer to normal portion of the vertex. - - - - - Returns the maximum number of supported color channel. - - - - - gets the color component if there is one (RBGA byte format) - - - - is which channel to get set - - - - sets the color component if there is one (RBGA byte format) - - - - is which channel to get set - is the color in RBGA byte format - - - - Returns the pointer to vertex color portion of the vertex. - - - - - Returns the maximum number of supported UVW/texture channel. - - - - - Gets sets the UVW component if there is one returning *float to the start of the uwv coord. - - - - is which channel to get set - - - - Sets sets the UVW component if there is one returning *float to the start of the uwv coord. - - - - is which channel to get set - the uv data to set - - - - gets the Tangent component if there is one - - - - - gets the pointer Tangent component if there is one - - - - - gets the BiNormal component if there is one - - - - - gets the pointer BiNormal component if there is one - - - - - This lets you copy the vertex data from another vertex. - - - - this is the vertex that you want to copy from - - - - Returns a raw pointer the vertex buffer. - - - - - This is a class that lets you create a hw vertex buffer. It allows you to define, create, edit and access the buffer. - - - - - Frees the vertex buffer. - - - - - This sets the size of each UVW channel. - - - By default a UVW channel is 2 point3 a UV. you can change the size to just a U, UV, or UVW with this. This must be set before calling create buffer if you want to change the channel sizes - - which channel - the size of the channel 1 to 3 - - - - This lets you associate a HW texture channel with a max map channel. - - - - the hw channel - the channel - - - - This lets get the map channel associated with a hw channel. - - - - the hw channel - - - - This allocates our buffer. Returns false if the buffer creation failed. - - - true is succeeded, false if failed typically an out of mememory error - - is the number of hw vertices to create for this buffer - - - - returns the stride in bytes of a hw vertex - - - - - returns the size in bytes of the entire buffer - - - - - returns the number of hw vertices in the buffer - - - - - this lets you set the size of the buffer, - - - this lets you set the size of the buffer, it returns true if everything was allocated correctly - /param unsigned int ct the number of vertices to set the buffer count to - - - - - This returns a hwvertex of a specific vertex. - - - - is which vertex you want to look at - - - - returns a raw pointer to the vertex buffer - - - - - This returns whether the vertex buffer has connection data back to the original geometry. - - - - - This lets you set the connection data. - - - This lets you set the connection data. It only tracks position and normals. - - this is the index in the hw vertex buffer - this is the position index in max mesh vertex list - this is the position index in max mesh gfxnormal list, set this value if you want to use the gfxfacenormal list. This is used when the face has no smoothing group - - - - This returns position mapping list. - - - - - This returns normal mapping list. - - - - - This is a wrapper around our low level HW mesh. - - - This is a interface around our low level vertex buffer this will allow you to directly update the low level buffers without recreating them, draw the buffers, and also give you access to release the buffers. This hides the actual vertex and index buffer away from the coder since it may be different depending on the device. Each GFX_MESH::HWMesh has a pointer to one of these. It has a simple reference counter to know when to get deleted since these can be batched up to be drawn and could potentially get deleted before the actual draw. - - - - - This draws the mesh to the display using the current render limits. - - - - the graphics window to draw the mesh to. - if this mesh contains multiple matIDs this is which matID to draw. The old hwmesh stored multiple matIDs per mesh the new one only has one. - - - - Allows you direct access to the low level buffer to change values without recreating the mesh. - - - - This is a pointer of all the vertices on the mesh. The changed vertices should be in the list - This is a pointer of all the gfx normals on the mesh. The changed vertices should be in the list - This is a pointer of all the face normals on the mesh - This is a bitarray that tags which vertices are changed so we only update those vertices - This is number of vertices in vertex List - This is mapping that lets the HW vertex look up which vertex it belongs to - This is mapping that lets the HW vertex look up which normal it belongs to. If this value is negative it is made positive and then face normallist is used to lookup the normal This occurs when there is no smoothing group. - - - - This releases the buffers if the class is no longer referenced by anything. You should not delete this class but call Release on it. - - - - - When ever you reference this pointer and want to hang onto it you need to call this. - - - - - This is a wrapper class around our HW . - - - Both our new and old HW mesh derive from this class and the pointer to this class is used to pass the HW mesh around. The old code would just pass around a DWORD_PTR and then cast it to internal HW . - - - - - Draws the mesh to the display using the current render limits. - - - - The diffuse color - If this mesh contains multiple matIDs this is which matID to draw. The old hwmesh stored multiple matIDs per mesh the new one only has one. - - - - Allows you direct access to the low level buffer to change values without recreating the mesh. - - - - This is a pointer of all the vertices on the mesh - This is a pointer of all the gfx normals on the mesh - This is a pointer of all the face normals on the mesh - This is a bitarray of changed verts - This is number of vertices in vertex List - This is mapping that lets the HW vertex look up which vertex it belongs to - This is mapping that lets the HW vertex look up which normal it belongs to. If this value is negative it is made positive and then face normallist is used to lookup the normal This occurs when there is no smoothing group. - - - - this is a class used to track mesh vertices to hw vertices. Each MeshVertes represents a max mesh vertex and has a list of indices in the buffer which reference that mesh vertex - - - - - clears out the mHWVertex list but does not deallocate it - - - - - sets the size of mHWVertex, this is useful to preallocate blank space to reduce allocates for performance reasons - - - - - This is used to check to see if the mesh vertex already references a matching hw vertex. It returns true if so and returns that index in id. - - - - - this is the raw pointer to the that we want to see if is in our list - - this is the raw pointer of all our current HWVerticess - - this is the stride of each vertex - this is the index that was found - - - - This adds a new hw vert index to our mesh vertex. - - - If IsInList returns false we need to add this vertex - - is the vertex to add - - - - Description: - This class is only available in release 5 or later. - - breaks joints, except for the root joint, of several degrees of freedom into 1 degree of freedom link. Sometimes, joints are more convenient. This is a helper class that helps to iterate over a on the basis of joints. Suppose linkChain is a , following code demonstrates how to iterate over joints. - - - - - - - all joint angles to the respective initial values. - - - - - If a solver overrides "<b>boolIKSolver::UseSlidingJoint()</b>" to return false, the IK system will not include sliding joints in the passed to the solver. If the may include sliding joint, this method informs the iterator to skip, or not to skip, the sliding joint. It should be called before Begin(). - - - - - Use Begin() to begin the iteration. The argument tells whether the pivot of the first joint starts at (0,0,0), if "in_world" is false, or at LinkChain::parentMatrix of the that iterator works on. - - - - - Whether this joint is rotational or sliding. - - - - - The degrees of freedom of this joint and the axes of each degrees of freedom. is string of chars. For 3-dof joint of order XYZ, for example, the would be "xyz". For 2-dof XZ joint, it would be "_xz". Leading underscores are used to fill up the string to 3 chars long. - - - - - Please refer to DofCount() for full explanation. - - - - - The proximal frame is the starting reference frame that this joint is aligned with. The distal frame is to be aligned with the proximal frame of the next joint. - - Pivot() is the position of the proximal frame, and DistalEnd() is the position of the distal frame. The distance between is the length of the bone. - - - - - Please refer to ProximalFrame() for full explanation. - - - - - Please refer to ProximalFrame() for full explanation. - - - - - Please refer to ProximalFrame() for full explanation. - - - - - Please refer to SetJointAngles() for full explanation. - - - - - Use Next() to move to the next joint, until it returns false. - - - - - - - Description: - This class is only available in release 5 or later. This is an interface to a specific type of IK goal, the HI IK goal. The interface id is given the constant kHIIKGoalID. - - The plugin solver that declares its goal type, with IKSolver::ExpectGoal(), as kHIIKGoalID should expect this type of goal from LinkChain::GetIKGoal(). To get the interface pointer, one can - - )linkChain->GetIKGoal()->GetInterface(kHIIKGoalID); - - - - - - - UseVHTarget() tells whether the swivel angle is determined (or computed) by a point in space to that the solver plane is supposed to pass, or is simply provided by a number literally. If it is true, the point is obtained from VHTarget(). Otherwise, the angle is obtained from SwivelAngle(). - - - - - See explanation in UseVHTarget. - - - - - See explanation in UseVHTarget. - - - - - Whether the swivel angle is interpreted in the space in which the start joint lies, or in the space of the goal. - - - - - The normal of the solver plane at the preferred pose, represented in the parent space of the root joint. It serves as the zero reference for the swivel angle. - - - - - Returns the (IK) system provided default for the Zero Map. - - - - - The goal for the end effector. - - - - - Description: - This class is only available in release 5 or later. This is the interface class that various types of IK goal will derive from. The unique interface id will specify what type of goal this interface provides. - - - - - - - - - - - Returns the position of a point on a spline or NURBS curve given its global u-value. The point can be computed in the local or the world space of the curve, represented by the second BOOL argument. The third BOOL argument determines if we should really recompute the curve or use the cached data. - - - - - - - Similar to the above: returns the tangent at a point on a spline or NURBS curve given its global u-value. The point can be computed in the local or the world space of the curve, represented by the second BOOL argument. - - - - - - - Obtained from . I don't think we are currently using it for the SPlineIK. - - - - - - - Grabs the Goal node. - - - - - - - Returns a pointer . - - - - - - - Compute the length of the spline which the IKchain conforms to. - - - - - - - Get the angle of the Start Twist - - - - - - - Get the angle of the End Twist - - - - - - - Get the Start Joint node of the IK Chain - - - - - - - Get the End Joint node of the IK Chain - - - - - - - Returns a . - - - - - - - Returns TRUE/FALSE as to whether curve is open or closed. - - - - - Extension to , the interface of a spline IK goal object. - - - allows access to the data of a spline IK goal for one solve. It extends interface - - - - - Get the solve time of the IK goal. - - - - the time at which the IK is being solved - - - - - Description: - This class represents a single link in the link chain. A is a single degree of freedom rotation followed by a rigidExtend. The DOF axis is specified by dofAxis. It is always active. - Data Members: - DofAxis dofAxis; - - The variable part of a is of one degree of freedom. It can be translational or rotational. One of the following; TransX, TransY, TransZ, RotX, RotY, or RotZ. - - float dofValue; - - The current value with regard to the degree of freedom. - - float initValue; - - The initial value. - - limits; - - The constrained lower and upper limits. [0] for the lower limit and [1] for the upper limit. - - private: - - rigidExtend; - - The rigid extents. - - byte llimited : 1; - - Lower limit flag. - - byte ulimited : 1; - - Upper limit flag. - - - - - This method checks whether the link is a null-link. When TRUE, the rigid extend is logically an identity matrix. - Default Implementation: - { return rigidExtend?false:true; } - - - - - This method checks whether the link has no length. When TRUE, it is a pure rotation matrix. - - - - - This method checks whether the degree of freedom is further constrained by lower limits. TRUE if constrained, otherwise FALSE. - Default Implementation: - { return llimited?true:false; } - - - - - This method checks whether the degree of freedom is further constrained by upper limits. TRUE if constrained, otherwise FALSE. - Default Implementation: - { return ulimited?true:false; } - - - - - This mehod returns the matrix contribution by the degrees of freedom. Either it is a pure rotation or a pure translation, of one axis. The following identity holds; - - LinkMatrix(true) == DofMatrix()LinkMatrix(false) * - - - - - This method allows you to apply a matrix, mat, by the DofMatrix() so that DofMatrix(). - Parameters: - & mat - - The matrix to multiply by the DOF matrix. - A reference to the matrix argument. - - - - - This method returns the link matrix just defined if the argument is TRUE. - Parameters: - bool include_dof = true - - TRUE to return the link matrix, FALSE to return RigidExtend. - The link matrix, otherwise it simply returns RigidExtend. - - - - - This methods applies the LinkMatrix() to the input matrix. - Parameters: - & mat - - The input matrix. - - bool include_dof = true - - When applying the DOF part, or rotation part, to a matrix, this will take place one at a time by calling RootLink::RotateByAxis(). If you want to apply the whole link, while already having applied the rotation part, you would need to set this flag to FALSE. - The reference to the input matrix, mat. - - - - - This method allows you to set the RigidEtend matrix. - Parameters: - & mat - - The rigid extend matrix you wish to set. - - - - - Description: - This class is only available in release 5 or later. - - This class abstracts the data structure that the IK system pass to the plugin solver. With it, an IK problem becomes a pure mathematical one to the plugin solver. - - A starts with a rootLink, followed by a number of 1D link. The rootLink has a whole rotation (c.f. class in ikHierarch.h), as represented by Euler angles of order XYZ, rotXYZ. These angles may be marked as active or not. The exposes the whole rotation to allow the solver to handle the start joint specially. - - The next 1D link is to be pivoted and aligned at the reference frame that is offset from the rotation of the by "rigidExtend". - - - - - This is originally cut off from a transformation space quantified by this matrix. Specifically, it is the matrix that accumulates all transformations from the root of the world to the position component of the start joint. - - - - - - - The i-th 1D link. The next link is pivoted and aligned at - - LinkOf(i).LinkMatrix(true) * LinkOf(i-1).LinkMatrix(true) ... * LinkOf(0).LinkMatrix(true) * rootLink.LinkMatrix(true) - - This is the extremity after the i-th link. The position of the end effector, in particular, is the extremity of the last link. - - - - - The number of 1D links following the rootLink. - - - - - - - A 1D link comprises a degree of freedom, which can be rotational or prismatic (sliding), and an offset transfromation, "rigidExtend". If the length of "rigidExtend" is zero, the next 1D link comes from same joint of this link. PreBone(i) returns the first link that precedes the i-th link that has non-zero "rigidExtend." In other words, LinkOf(PreBone(i) + 1) starts a new joint that includes i-th link as one of its degrees of freedom. PreBone(i) is always less then i. - - - - - - - Bone(i) returns the first index, j, such that j >= i and LinkOf(j).ZeroLength() false. This is the last link of the bone that includes i-th link as a degree of freedom. - - - - - - - Returns an interface pointer to the goal. The actual type of goal can be queried from the interface. (They are documented separately.) - - - - - - - Please refer to SetIKGoal() for full explanation. - - - - - Description: - A consists of a rotation plus a rigidExtend. It transforms like this: - - To_Coordinate_Frame = rigidExtend * rotXYZ * From_Coordinate_Frame - - where rotXYZ = Rot_x(rotXYZ[0]) * Rot_y(rotXYZ[1]) * Rot_z(rotXYZ[2]). - - Note that not all the x, y, and z, are degrees of freedom. Only Active() ones are. We put the whole rotation here so that some solver may choose to use it as a full rotation and then clamp the result to the permissible range. - Data Members: - rotXYZ; - - The xyz rotation. - - initXYZ; - - Corresponds to the PrefRotation() of the Start Joint. - - llimits; - - The lower limits. - - ulimits; - - The upper limits. - - rigidExtend; - - The rigid extents. - - private: - - unsigned flags; - - The root link flags. - - - - - This method informs the Solver whether a particular component is active. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - TRUE if the specified component is active, otherwise FALSE. - Default Implementation: - { return flags&(1<<i)?true:false; } - - - - - This method informs the Solver whether a particular component has its lower limits active. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - TRUE if the specified component is active, otherwise FALSE. - Default Implementation: - { return flags&(1<<(i+3))?true:false; } - - - - - This method informs the Solver whether a particular component has its upper limits active. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - TRUE if the specified component is active, otherwise FALSE. - Default Implementation: - { return flags&(1<<(i+6))?true:false; } - - - - - This method will pre-apply the rotation about the x, y, or z axis. Therefore, starting with the identity matrix mat, - - ApplyLinkMatrix( - - RotateByAxis( - - RotateByAxis( - - RotateByAxis(mat, 2), - - 1), - - 0), - - false) - - should equal to LinkMatrix(true). - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - - - - - This method returns the link matrix just defined if the argument is TRUE. - Parameters: - bool include_rot - - TRUE to return the link matrix, FALSE to return RigidExtend. - The link matrix, otherwise it simply returns RigidExtend. - - - - - This methods applies the LinkMatrix() to the input matrix, or mat = mat * LinkMatrix(include_rot) - Parameters: - & mat - - The input matrix. - - bool include_rot - - When applying the DOF part, or rotation part, to a matrix, this will take place one at a time by calling RootLink::RotateByAxis(). If you want to apply the whole link, while already having applied the rotation part, you would need to set this flag to FALSE. - The reference to the input matrix, mat. - - - - - This method allows you to activate or deactivate a particular component. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - - bool s - - TRUE to activate, FALSE to deactivate. - - - - - This method allows you to activate or deactivate a particular component's lower limits. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - - bool s - - TRUE to activate, FALSE to deactivate. - - - - - This method allows you to activate or deactivate a particular component's upper limits. - Parameters: - unsigned i - - The component, 0 through 3 for x, y, and z, respectively. - - bool s - - TRUE to activate, FALSE to deactivate. - - - - - Description: - This class is defined in IKHierarchy.h and provides the functionality that, given a unit axis, which is to be substituted by the end effector (EE) Axis, produces a unit vector, which will be interpreted as the normal to a plane. For more details see the section on Inverse Kinematics. - - - - - The call operator. - Parameters: - & EEAxis - - The end effector axis. - The unit vector described above. - - - - - The possible lighting models. - - - - - Enumeration indexing available versions of the algorithm implemented by the variants of BuildDiagonals defined below. Version TRIANGULATION_VER_2023_1 is the initial implementation of the algorithm, with improvements for faces containing collinear and/or convex corners, multiply connected faces, and non-planar faces, in comparison to the legacy algorithm implemented in the variants of FindDiagonals. Version TRIANGULATION_VER_2024 further refines the implementation, improving handling of non-planar faces, as well as certain geometric degeneracies, including spur edges and self-intersecting bounding curves. - - - - - Enum for typical usage of OPENFILENAME::lCustData to hold whether the OPENFILENAME instance is used in a GetOpenFileName or a GetSaveFileName function call. Typically used to determine proper messages to be displayed or logged. - - - - - - - A generic array container, with proper support for non-POD types. - - - This template class is a generic, dynamic array container, similar to the STL class "vector". Whereas the classical 3ds Max SDK class supports only POD types, this class supports non-POD types as well. - POD stands for "plain old data", and basically denotes any data type which does not need to be constructed, destructed, and which can be copied with memcpy() rather than requiring a copy operator to be called. - - - - - Subscript operator. - - - A reference to the array element at the specified index. - Does implement bounds checking. - - - Index of array element to access. This index must be within the array bounds. If the index is out of bounds it will throw a MaxSDK::Util::MaxOutOfRangeException exception. - - - - Same as subscript operator. - - - A reference to the array element at the specified index. - Does not implement bounds checking. - - - Index of array element to access. This index must be within the array bounds. - - - - Accesses the first element in the array. - - - A reference to the first element of the array. - It is invalid to call this on an empty array. - - - - - Accesses the last element in the array. - - - A reference to the last element of the array. - It is invalid to call this on an empty array. - - - - - Returns the array storage as a C-style array pointer. - - - Any modification to the contents of the array, through this pointer, may be dangerous. - - - - - Sets a copy of value at the given index. - - - A reference to 'this'. - Does not implement bounds checking. - - - The position in the array where a copy of value is placed. This index must be within the array bounds. - - a reference to the original object. - - - - Appends a copy of value to the array. - - - The number of elements in the array prior to the append operation. - - - A reference to the original value. - - - - Removes the first element of the array. - - - A reference to 'this'. - Must not be called on an empty array. - - - - - Removes the last element of the array. - - - A reference to 'this'. - Must not be called on an empty array. - - - - - Removes all the elements from the array. - - - A reference to 'this'. - - - - - Determines if a value is stored in the array. - - - true if the value was found in the array; false otherwise. - - - The value for which to search for. - - The index at which to start searching. Preceding elements are not searched. - - - - Returns the number of used elements (as opposed to simply allocated/reserved) in the array. - - - - - Returns true if the number of used elements in the array is 0; returns false otherwise. - - - - - Returns the number of elements used (as opposed to simply allocated/reserved) in the array. - - - - - Returns the number of elements allocated/reserved (as opposed to actually used) in the array. - - - - - Returns the growth length of the array. For more information on the growth length, see setGrowLength(). - - - - - Sets the growth length of the array. - - - The growth length is the minimum number elements by which the reserved space is grown whenever the array runs out of reserved space. - - - - - Returns whether the given array index is valid for this array. - - - true if the given index is within the bounds of this array; false otherwise. - - - - - Description: - This class wraps a raw memory buffer and it allows individual access to elements each located with a given stride in bytes. e.g. to iterate over every vertex position: MaxSDK::BufferProxy<const Point3> meshVerticesBuffer(mnmeshVertices, numv, sizeof(MNVert)); - - - - - Retrieves the number of elements in the buffer. - - - The number of elements in the buffer. - - - - - Retrieves the element stride. - - - The element stride. - - - - - Retrieves whether the buffer points to actual memory. - - - The buffer is valid or not. - - - - - Retrieves whether the buffer is empty or not. - - - Whether the buffer is empty or not. - - - - - Allows access to an element of the buffer using the subscript operator. - The element at the provided index. - - - - - DestructorPolicy template for types requiring destruction through DeleteThis. - - - - - Description: - This class describes the edge of to another node edgeIndex is the id of the edge going to the other node nodeIndex is the id of the other node - - - - - Cancels the hold by calling Hold::Cancel. Cannot be called after HoldBegin::Accept is called. Calling this multiple times will have no effect. After calling this, the instance of this class has fulfilled its task and nothing more can be done with it. - - - - - Accepts the hold, and calls Hold::Accept. Cannot be called after HoldBegin::Cancel is called. Calling this multiple times will have no effect. After calling this, the instance of this class has fulfilled its task and nothing more can be done with it. - - - - - Accepts the hold. When this is called, mMessage (specified via HoldBegin::HoldBegin(MCHAR*) is ignored. Cannot be called after HoldBegin::Cancel is called. Calling this multiple times will have no effect. After calling this, the instance of this class has fulfilled its task and nothing more can be done with it. - - - A message to pass to . - - - - The class is used to control the active shade fragment (in-viewport) active shade. - - - - - Toggle the use of Active Shade Fragment in current viewport - Sample code in MAXScript : - Sample code in C++ : - - true if it went fine in toggling - - - - - Sets the render region for the active shade fragment, coordinates are between 0.0 and 1.0 - This region is per viewport and not global to all viewports. - (0.0, 0.0) for the left and top coordinates are the top left corner of the viewport - (1.0, 1.0) for the right and bottom coordinates are the bottom right corner of the viewport - - : the left coordinate of the rectangle for the render region, range is 0.0 is the left of the viewport, 1.0 is the right of the viewport - : the top coordinate of the rectangle for the render region, range is 0.0 is the top of the viewport, 1.0 is the bottom of the viewport - : the left coordinate of the rectangle for the render region, range is 0.0 is the left of the viewport, 1.0 is the right of the viewport - : the bottom coordinate of the rectangle for the render region, range is 0.0 is the top of the viewport, 1.0 is the bottom of the viewport - - - - Remove all running Active Shade fragments from all viewports from all view panels. - - - - - Get the viewports in which the Active Shade Fragments are running. - - - a which are pairs of integers, so the count of the array is a multiple of 2. The first integer of each pair is a 0-based index of a ViewPanel and the second integer is the 0-based index of the viewport from that viewpanel that has active shade fragment running - - - - - Is Active Shade Fragment running in current viewport ? - true if it is running in current viewport - - - - - Is Active Shade Fragment running in this viewport ? - true if it is running in the given viewport - - - is the 0-based index of the viewpanel to use - - is the 0-based index of the viewport to check in the viewpanel - - - - Is Active Shade Fragment running at least in one viewport ? - true if it is running in one viewport at least - - - - - Does current Active Shade renderer support concurrent rendering ? If so we can have multiple active shade sessions running at the same time (for potential future use) - true if it supports concurrent rendering - - - - - Send to the manager the ActiveShadeFragment and get as a result a IRenderProgressCallback* that can be used to forward the messages from the active shade renderer - to the manager through IInteractiveRender::SetProgressCallback so it can display the messages or do progress bars etc. - Is only available through C++ and not through Maxscript - the IRenderProgressCallback* to use with IInteractiveRender::SetProgressCallback or nullptr if a problem occured - - - is a * that is an active shade fragment - - - - Remove from the manager the IRenderProgressCallback* from this ActiveShadeFragment. - true if the manager successfully removed the callback - - - is a * that is an active shade fragment - - - - The class is used to control the ActiveShade fragment (in-viewport ActiveShade) and extends . Get it through Sample code in C++ : - - - - - - Get the ActiveShade fragment resolution multiplier. A multiplier of 0.5 will give a half resolution ActiveShade rendering used and upscaled in the viewport. So a better time performance but resulting in a lower image quality This multiplier has to be a positive, non-zero float number. - the value of the multiplier. - - - - - The can be implemented as an additional interface by any object to provide different edit contexts for the object when being modified. - The Command Panel checks the current modified object for this interface to determine the context of open/close state and ordering of the rollups when the object is being edited. This allows an object to implement different persistent rollup states for different contexts. - - - - - This method is used to retrieve the edit object context for the object. The context is used to determine the rollup ordering and open/close state for the object. - It is perfectly valid to have varying contexts based on internal state. - - TRUE if a context is currently available and successfully retrieved, FALSE otherwise. - - [out] The context string to be filled in by the method. - - - - Provides access to hair strand definitions for a modifier that generates hair. - - - The standard model for generating hair in 3ds Max is by applying a Hair to an existing geometry object. plugins that need the hair strand definition directly may use this interface to gather those definitions. - To retrieve a pointer to this interface, use EnumGeomPipeline() on a given node and perform a dynamic_cast<IHairModifier> on the pointer returned by IDerivedObject::GetModifier(). - - - - - Returns whether this hair modifier is enabled. If this returns false, then this interface should be ignore altogether. This may happen, for example, if the hair modifier is set to generate geometry rather than hair primitives, in which case the evaluated for the node will contain the hair strands. - - - - - Returns the shading parameters defined by this hair modifier. These are the shading parameters that should be used when rendering the hair. The material assigned to the should be ignored in this case. - - The time at which to fetch the shading parameters, which may be animated. - The validity of the returned value is intersected into the input value of this parameter. - - - - Fetches the hair modifier's definition of hair strands. The hair strands are defined as flat surfaces, facing the given normals. Each hair strand may have any number of vertices, the hair segments being linearly defined between the vertices. - True on success, false on failure - for example, on failing to allocate memory. - - The time at which to fetch the hair strands definition. - The hair strand node. - The number of vertices present in each hair strand, with one value for each hair strand. - The position of each vertex. The number of vertices equals the sum of all values in per_hair_vertex_count. - The radius of the hair strand, at each vertex. - The color of the hair strand, at each vertex. - The facing direction of the hair strand, at each vertex. - The velocity of each vertex - that is, the vector defining the direction and amplitude of movement for one full frame of animation. - The opacity of each vertex. - The UV coordinate at each vertex. - - - - This interface provides access to the 3ds Max Help system. To display help related to the product, use the MaxSDK::IHelpSystem::ShowProductHelpForTopic() function. The 3ds Max product help can either be displayed from online servers (default behavior) or from a local path. Can be use to get and set help location preferences. Maxscript help is always accessed online. This is not meant to control "Additional Help" (help for installed third-party plug-ins and add-ons). - - - - - - - Returns the current 3ds Max product help location method. - - - - - Sets the product help location to be Autodesk web site or local network. Saves the value to the ini file. - - - - - Get the current local product help path, that is used when MaxSDK::IHelpSystem::ProductHelpLocation() is OnlineHelp. - - - - - Get the default local product help path to the default local help path setting. - - - - - Shows the 3ds Max Product Help. The current settings are used to determine if help is displayed from an online or a local location. - - - - - Shows the 3ds Max Product Help for a specific topic. The current settings are used to determine if help is displayed from an online or a local location. - - - - - Shows the 3ds Max Product Help for a specific topic provided as a string (if some help system is available). - - - - - Shows the 3ds Max Product Help for a search term (if some help system is available). - - - - - Shows the online Maxscript documentation. - - - - - Shows the online Python documentation. - - - - - Opens a chm file. - - - - - The allows you to register a callback that gets executed when a user creates a material or texture from the material browser in the Schematic or Compact Editor. - This callback is used, for example, in the Texture (see the samples) to launch a file chooser to allow the user to choose a file directly. - To make use of this functionality, the overwritten GetInterface(InterfaceID) function of the material/texture has to return an instance of this interface when asked for the MATERIAL_BROWSER_ENTRY_INSTANCE_CALLBACK_INTERFACE_ID, from which OnInteractiveCreation() is being called by the system. - Sample Code: - This code is from /maxsdk/samples/materials/bmtex.cpp. It is used to immediately launch a file chooser, when the user creates a texture. - - - - - - - This function gets called from the material browser when a user creates a texture/material interactively. - - - - - An alternative progress reporting interface to class , which does not process the window message queue. - - - Production rendering typically reports progress through RendProgressCallback::Progress(), a method which processes the window message queue in order to update the progress bar and determine wheter the user has pressed the cancel button. This behaviour is sometimes undesirable. When updating a scene for ActiveShade, processing the window message queue while reporting progress may cause user interactions to be processed as well - and this may interfere with the scene update. In such cases, this interface should be used. - To retrieve a pointer to this interface, perform a dynamic_cast on a : - - - - - Reports a progress update. - - The number of steps which are currently done. - The total number of steps to be perform. - - - - Access to the properties of the Physical object. - - - This interface provides SDK access to the properties of the Physical object. To retrieve a pointer to this interface, perform a dynamic_cast on a , , or as returned by INode::EvalWorldState(): - - - - - Returns the width of the film plane, in system units. The height is derived from the aspect ratio of the image to be rendered. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the effective focal length of the lens, in system units. - This value may be different from the focal length specified by the user; when focusing, the lens may move thus affecting its effective focal length and the resulting field of view. This returns the result of such movement - the distance between the film plane and the lens. - The crop zoom factor is not taken into account by this method (see GetCropZoomFactor()). - - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the crop zoom factor of the lens. This feature behaves as an image crop. As such, it effectively increases the lens focal length for purposes of calculating the field-of-view. However, exposure and depth of field are not affected. To achieve this, exposure is performed using the f-number (see GetLensApertureFNumber()), while depth of field is performed using the absolute aperture radius relative to the non-zoomed lens (see GetLensApertureRadius()). - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the absolute aperture radius, in system units. The aperture size affects depth of field (larger apertures result in amplified depth of field effect), as well as exposure (if specifying exposure manually through the ISO). - When rendering a circular aperture, this is the radius of the disc. When rendering a bladed aperture, this is NOT the radius of the polygon: instead, the polygon should have an area which is equal to that of a disc with the given radius. This ensures that exposure is unaffected by the presence of blades (blades therefore have only an aesthetic property). When rendering a texture aperture, the texture will be remapped to a square with sides equal to twice the radius. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - When true, and the aperture shape is set to , the correct radius of the polygon will be returned instead of the radius of the disc. When false, the radius of the disc aperture is returned; as noted above, this radius cannot be used directly to generate a bladed polygon aperture. - - - - Returns the aperture size as an f-number. The aperture size affects depth of field (larger apertures result in amplified depth of field effect), as well as exposure (if specifying exposure manually through the ISO). - When rendering a bladed aperture, the radius of the polygon should be adjusted such that the area of the polygon matches that of a disc at this aperture size; this ensures consistent exposure, see - The f-number returned here is relative to the focal length returned by GetEffectiveLensFocalLength(). It may therefore differ from the value supplied by the user, as it takes lens breathing into account. Lens breathing will cause the f-number to grow smaller as the lens focuses closer (though the absolute aperture radius doesn't change), thus affecting exposure. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns whether motion blur is to be enabled. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the shutter open duration, the units being frames at the current frame rate, as returned by GetFrameRate(). - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the shutter open offset, the units being frames at the current frame rate, as returned by GetFrameRate(). - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the distance at which the lens is focused, in system units. - The focus distance is relative to the lens, which is positioned on the camera origin. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the ISO to be used when rendering this camera. This is not necessarily the ISO currently stored in the parameter block; it may be an ISO value derived from the target exposure value. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the EV to be used when rendering this camera. This is not necessarily the EV currently stored in the parameter block; it may be an EV value derived from the target exposure value. - The EV being returned is technically the "equivalent EV at ISO 100", such that increasing the ISO is correctly represented as decreasing the EV (thus making the image brighter). This differs from the standard definition of EV (which would have little use here), and is somtimes known as EV100. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the white point, to be used with exposure control. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the amount of vignetting in the exposure (darkening on the edges of the rendered image), as a non-negative value. Returns 0 if vignetting is disabled. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns whether depth of field effects are enabled. If this returns false, then a pinhole camera should be rendered (everything will be in focus). - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the shape of the bokeh to be rendered. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the number of blades to be rendered, if GetBokehShape() returns BokehShape::Bladed. This is the number of sides to the regular polygon. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the rotation of the aperture, if GetBokehShape() returns BokehShape::Bladed. The regular polygon rendered for a bladed aperture should be rotated by this angle. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the texture to be used as the aperture shape, if GetBokehShape() returns BokehShape::Texture. The aperture texture is specified as a transparency map: white means fully transparent, black means opaque. Colors also work and will tint the result. A texture that contains a white circle, over a black background, that runs to the edges of the texture, should render identically to a circular aperture. The texture will be fit into a square which's side has length equal to the diameter of the circular aperture (twice the radius returned by GetLensApertureRadius()). - If no texture is specified, a circular aperture should be used as a fallback. If the texture cannot be loaded or is invalid (all black), then DOF should be disabled. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns whether the texture aperture shape should affect the exposure. If true, then the aperture shape provided in the texture will affect exposure: a texture with a small white circle will result in a darker image than a texture with a larger white circle. If false, the aperture texture should not impact the overall exposure (though it will certainly impact local exposure): the overall exposure should be compensated such that it is equivalent to a circular aperture. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the amount of optical vignetting to be rendered. Optical vignetting is also know as the cat's eye effect; it is caused by the presence of multiple element in the lens, with multiple circular elements combining to form a shape resembling the pupil of a cat's eye. Values typically range from -1.0 to 1.0, though values outside this range are valid but will produce heavy vignetting. The algorithm to generate the effect is as follows: - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the amount of center bias to be rendered. Center bias is used to generate a non-uniform aperture, with positive values biasing towards a ring shape and negative values biasing towards the center. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the amount of anisotropy present in the bokeh. Anisotropy is used to simulate (apparent) non-circular apertures such as is produced by anamorphic lenses. Positive values stretch the bokeh along X, while negative values stretch along Y. The algorithm for generating this effect is as follows: - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the type of lens distortion to be used. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the amount of distortion to be rendered, if GetLensDistortionType() returns LensDistortionType::Cubic. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the texture to be used, if GetLensDistortionType() returns LensDistortionType::Texture. - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the offset to be applied to the image on the film plane. The value is expressed as a ratio of the film plane width: a value of 1.0 with a film width of 36mm results in an offset of 36mm - or, if the X resolution were 640, an offset of 640 pixels. On the Y axis, the scale is also relative to the film plane width, such that the offset in real-world space is equally scaled in X or Y. The offset in pixels is therefore calculated as follows: - - - - - Returns the offset to be applied to the image on the film plane, in pixels. Whereas GetFilmPlaneOffset() returns the offset as a resolution-indepent value, this method resolves the actual raster-space offset, but requires the resolution to be given to it. - - The resolution of the image to be rendered. - The pixel aspect ratio of the image to be rendered. - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the tilt to be applied to the lens. The value is to be applied as follows, where ray_target is the destination of point of the camera ray onto the focus plane (in camera space): - - The time at which to retrieve the property value. - The validity of the returned value is intersected into the input value of this parameter. - - - - Access to the properties of the Physical Exposure . - - - This interface provides SDK access to the properties of the Physical Exposure control. To retrieve a pointer to this interface, perform a dynamic_cast on a : - - - - - Returns the set of parameters currently used by the tone operator. - ToneOperator::Update(). - - - - - Utility class that provides efficient sampling for a bitmap aperture on the physical camera. - - - When a bitmap aperture is used, uniformly sampling the aperture will result in massively reduced performance or increased noise. This class implements a smarter, weight-based sampling method which will introduce minimal performance degradation from using a bitmap aperture. This class is intended to be used in one of three ways: For directly sampling the bitmap aperture For building the sampling acceleration structures, and then using them in the shading code (e.g. if the shader cannot reference C++ code) As a reference for implementing your own sampler - Max SDK. - - - - - Returns the resolution of the acceleration structure in X. - - - - - Returns the resolution of the acceleration structure in Y. - - - - - Samples a location in the aperture bitmap. - - - - - class for the Scene Security Manager. - - - for the Scene Security Manager class. This class has only one instance. This singleton allows access to the security settings related to safe scene script execution. - - - - - Gets whether the safe scene settings are locked for this 3ds Max session. - - - - - Gets whether safe scene script execution is enabled. - - - - - Gets whether safe script asset execution is enabled. - - - - - Gets whether execution is blocked for a particular scripting language/technology when safe scene script execution is enabled. - - - - - Gets whether the Security Messages window will be automatically opened when a scene script is blocked. - - - - - Gets whether a script editor will be automatically opened when a scene script is blocked. - - - - - Logs a message in the Security Messages window that notifies the user when a command from a scene script has been blocked. - - - The name of the command that was blocked. For example: "HiddenDOSCommand", "python.Execute", "System.Windows.Forms.ListView", etc. This information is displayed by the Security Messages window. - - The type of command that was blocked. For example, if the command that was blocked was a "ShellExecute" command, then ScriptingFeature::MAXScriptSystemCommands should be passed. If it was a "python.ExecuteFile" command, then ScriptingFeature::Python should be passed. If it was a "dotNetClass" command, then ScriptingFeature::DotNet should be passed. This information is used to compose an appropriate message to be displayed by the Security Messages window. - - - - Gets whether the specified file name is a protected .ini file When safe scene script execution is enabled, certain .ini files are to be protected from modification via MAXScript methods. This method returns true if the specified file name is one of these protected .ini files. - True if the file name corresponds to a protected .ini file, false otherwise. - - - The file name to be tested. - - - - Gets whether the extension of the specified file name is a protected extension When safe scene script execution is enabled, files with certain extensions are to be protected from modification via MAXScript methods. This method returns true if the extension of the specified file name is one of these protected extensions. - True if the extension of the specified file name is one of the protected extensions, false otherwise. - - - The file name to be tested. - - - - Checks if the provided filename is protected from writing or creation based on its path (extension, directory or anything that applies) - - - true if write protected - - the filename to check for write/create - - - - Access to functionality and properties of the Sun Positioner object. - - - The Sun Positioner is a light object which is used for the sole purpose of positioning/orienting a sun in a scene. It is meant to be connected with a Sun & Sky environment map - where the environment map does the shading, but uses the Sun Positioner to determine the direction of the sun. - The Sun Positioner also provides access to weather measurement data which may be provided by a weather data file. - To retrieve a pointer to this interface, perform a dynamic_cast on a . - - - - - Returns the direction towards the sun. - - - Returns a unit vector pointing towards the sun, in object space. - - The time at which to evaluate the parameters. - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns weather measurement data from the weather data file, if present. - - - True if weather data file was successfully obtained from a weather data file; false if a weather data file is not specified, missing, or does contain valid weather measurements. - - The measurements are returned through this argument. - The time at which to evaluate the parameters. - The interval into which the validity of the evaluated parameters is intersected. - - - - Returns the day of the year provided by the user, or specified by the weather data file. - - - The day of the year may be necessary for interpreting the measurements within the Perez All-Weather sky model. - False if no date is available (e.g. the sun is manually positioned); true otherwise. - - The 1-based index of the day within the year (i.e. a value in [1, 366]) - The time at which to evaluate the parameters. - The interval into which the validity of the evaluated parameters is intersected. - - - - Container for managing the MaxSDK::MeshChannelData objects. The data in these channels objects are what gets manipulated and copied in the modifier stack. - - - - - Take and share channel objects with another and store them in this container. - - - Specifies the source to copy channel objects from. - - Specifies the channels to reference from fromOb. See . - - - - Makes a complete copy of some channel objects and keeps the copy. This can be used to break the sharing of channel objects with other meshes crated by ShallowCopyChannelData. Syncs the BlockWrite members with the owning using MeshChannelData::SyncParentInterface - - - Specifies which channels to make complete copies of. See . - - - - Drops the specified channel objects, calls ClearParentInterface() on those objects beforehand. - - - Specifies channel objects to free. See . - - - - Based on a channel mask, request the locks for those channels. This should be used avoid race conditions when modifying objects in parallel when some of them share channels. - - - - - Based on a channel mask, release the locks for those channels. - - - - - Container for managing the MaxSDK::MNChannelData objects. The data in these channels objects are what gets manipulated and copied in the modifier stack. - - - - - Take and share channel objects with another and store them in this container. - - - Specifies the source to copy channel objects from. - - Specifies the channels to reference from fromOb. See . - - - - Makes a complete copy of some channel objects and keeps the copy. This can be used to break the sharing of channel objects with other meshes crated by ShallowCopyChannelData. Syncs the BlockWrite members with the owning using MNChannelData::SyncParentInterface - - - Specifies which channels to make complete copies of. See . - - - - Drops the specified channel objects, calls ClearParentInterface() on those objects beforehand. - - - Specifies channel objects to free. See . - - - - Based on a channel mask, request the locks for those channels. This should be used avoid race conditions when modifying objects in parallel when some of them share channels. - - - - - Based on a channel mask, release the locks for those channels. - - - - - Please consult the documentation of for more details. - - - A plugin package may contain various 3ds Max components, including native C++ plug-ins, managed assemblies, maxscripts, macroscripts, various resources such as icons, etc. This interface is used to get the info of a component. - - - - - Get the name of this component. - - - - - Get the version string of this component. - - - - - Get the full installation path of this component. - - - - - Get the textual description of the component. - - - - - Get the plugin upgrade code of the plugin package to which this component belongs. This will be a GUID string. - - - - - A plugin package may contain various pieces of information including name, package description, company email, and so on. regroups all this information. The details of the packaging format can be found in the "Packaging Plug-ins" topic in the 3ds Max Developer's Guide. Please consult the documentation of for more details. - - - - - Get the plugin package name. - - - - - Get version information for this plugin package, in the form of "MMM.mmm.bbb" (major.minor.build) The version information is used by 3ds Max to determine which plugin package to load if multiple plugin packages with the same UpgradeCode are found. - - - - - Get the human readable description of the plugin package. - - - - - Get the UpgradeCode for this plugin package. This will be a GUID string. The UpgradeCode is a unique GUID for the plugin package that must never be changed across all versions of the plugin package. The UpgradeCode is used by the Autodesk App Store website to allow for upgrading from an old version to a newer version of a plugin package without the need to uninstall the plugin package first. The UpgradeCode is used by 3ds Max to uniquely identify plugin packages. - - - - - Get the directory where this plugin package is installed. - - - - - Get the full path name of this plugin package. - - - - - Get name of the company that created this plugin package. - - - - - Get url to reference back to the company that created this plugin package (as a string, no format required in the package format) - - - - - Get email of the company that created this plugin package (as a string, no format required in the plugin package format) - - - - - Get phone of the company that created this plugin package. - - - - - Get AppVersion of this plugin package. - - - - - Get the DependentBundles for this plugin package. These reflect the packages that are required to be present in order for this plugin package to load. - - - - - Clear the DependentBundles for this plugin package. - - - - - Get the UpgradeCodes of the package(s) that are required to load before this plugin package loads. These packages may or may not exist. - - - - - Remove an item from the list of guid strings of the package(s) that are required to load before this plugin package loads. - - - - - Clear the LoadAfterBundles for this plugin package. - - - - - The is a service implemented by 3ds Max. It loads and manages plugin packages that conform to the Autodesk Application Package Format. The class allows client code to discover what plugin packages have been loaded during the startup of 3ds Max, what these packages contain (plugin dlls, managed assemblies, maxscripts, etc.) and from which directories all these components are loaded. The details of the packaging format can be found in the "Packaging Plug-ins" topic in the 3ds Max Developer's Guide. - - - - - Get the path (belonging to the current user) that is scanned for discovering user specific plugin packages. For Example: APPDATA%\Autodesk\ApplicationPlugins\ - The private install path - - - - - Get the path (shared by all users) that is scanned for discovering plugins that are globally installed (for all users of the machine), For example: ALLUSERSPROFILE%\Autodesk\ApplicationPlugins\ - The public install path - - - - - Get the install path of the plugin package specified by upgradeCode. - The install path for the specified plugin package - - the plugin package version-independent unique GUID that has been specified for the plugin package - - - - Get the count of installed plugin packages - the number of installed plugin packages - - - - - Get the available information about the ith plugin package as object - package information as a object or nullptr - - the index of the plugin package (between 0 and - 1) - - - - Get the available information about the plugin package specified by upgradeCode. - package information as a object or nullptr - - the version-independent unique GUID that has been specified for the plugin package - - - - Get the component count of a given plugin package - the count of component items in the ith plugin package - - the index of the plugin package (between 0 and - 1) - the requested plugin package component - - - - Get a given component from a plugin package - the information about the component - - the index of the plugin package (between 0 and - 1) - the requested plugin package component - the index of the component (between 0 and GetPackageComponentCount(i, component)) - - - - Get the global count of a given component. This count represents the number of instances of this component in all plugin packages. - the global count for the specified component type - - the requested plugin package component - - - - Get the information that is available for the specified component (as a object) - the information about the requested component or nullptr - - the requested plugin package component - the index of the component (between 0 and - 1) - - - - Browse all plugin package folders and collect all plugin package information. - - - - - Get the environment variable definition count of a given plugin package - the number of environment variable definitions in the packageIndex plugin package - - the index of the plugin package (between 0 and - 1) - - - - Get the definition of a given environment variable - true if successful false otherwise (ex: index out of range) - - the index of the package from which to retrieve the environment variable definition - the index of the variable (from 0 to count - 1) in the package - the returned name of the environment variable if successful - the returned value of the environment variable definition if successful - the returned type of the environment variable if successful - - - - is a class to share a mesh between different classes. It uses reference counting and gets deleted once its ref count reaches 0. - - - - - Utility base class for a with a single target that does not share ownership of it's . - - - - - - - interface has been deprecated. Texmaps EvalColor() and EvalMono() methods should be thread-safe by definition; renderers will always access them from multiple threads, and they are not allowed to touch the scene data, only data in member variables local in the shader instance, and even those only in a read-only fashion. - For compatibility and as a safety measure, the interface does still exist, but from 3ds Max 2019, texmaps are rightly assumed to be multi-threaded by default, and only if this interface is used and explicitly set the thread safety to FALSE, will rendering revert to single-threading. - Here is the original (deprecated) documentation of the interface: - provides any texture plugin with thread safe support information in 3ds Max 2015. The Max system will use multiple threads to accelerate texmap render if the function is thread safe. This will improve the performance of baking textures for display in the viewport. A typical implementation would look like this, and can be added to the constructor of the plugin class: - - - - - Sets a thread safe flag for a texmap function. This requires the specified TexmapFunction to be implemented as thread safe between different instances of . - - the specified function. - whether the specific function is thread safe. - - - - Returns the specified TexmapFunction's thread safe flag. - thread safe flag. The default is false. - - the specified TexmapFunction. - - - - Specifies the function of the texmap with strict thread safe flag. This requires the specified function to be thread safe within one instance of . This is stricter than SetFunctionFlag(). - - function. - whether the specific function is thread safe. - - - - Returns the specified function's thread safe flag. - thread safe flag. The default is false. - - the specified function. - - - - Holds an handle, its clients handle and the subanim index such that: client->SubAnim(index) == anim. Provides a series of useful methods to work with Animatables. A valid can be just an animatable or just a client and subanim. Safely stores the animatables as handles to avoid dangling pointers. Used by the trackviews tree view. - - - - - Get the name of this entry to display in the UI. - - - - Whether or not to show the controller type in the name. - - - - Determine the super class id, pulls type from paramblocks otherwise straight from the anim. - - - - - Returns true if this entry describes an easy curve controller. - - - - - Returns true if this entry describes a multiplier curve controller. - - - - - Returns true if this entry describes a note track. - - - - - Returns true if this entry describes a visibility controller. - - - - - Returns true if this entry describes a scene node. - - - - - Returns true if this entry describes an object: geometry, camera, shape, helper, etc. - - - - - Returns true if this entry describes a modifier. - - - - - Returns true if this entry or client describes a material or texmap. - - - - - Returns true if this entry has any sub animatables. - - - - - Returns true if the entry represents a paramblock dummy. - - - - - Returns true if the entry represents a paramblock dummy. If true, 'sid' will be set to the dummy's parameter super class id. - - - - - Returns true if this entry is locked by the locked tracks manager ( ). - - - - - Returns true if this entry is a source or destination of a parameter wire. - - - - - Returns true if this entry is able to be animated. - - - - - Returns true if this entry describes a custom attribute. - - - - - Get the typed Reference. - - - - - the typed Reference. - - - - - Get the typed Reference by reference. - - - - - Get the typed Reference for dereferencing. - - - - - the typed Reference by assignment. - - - - - Resets a variable when the object goes out of scope. - - - Following the principle of resource acquisition is allocation, this class, which should always be allocated on the stack, will set a variable to the given value, then set the variable back to its original value when it goes out of score. This is safer than setting things by hand since the destructor will still be executed if an exception is thrown from the guarded block. An example given a member variable mRecursionLocked: - - - - - Retrieves the current value of the guarded variable. - - - - - Sets the variable to the specified value. - - - Upon this guard's destruction, the variable will be reset to the original value found during the guard's construction. - - - the new value the variable should be set to - - - - Retrieves the original value of the guarded variable. - - - - - Restores the variable to its original value Note that the variable will be restored again to its original value when the object instance goes out of scope. - - - - - The class used to compute vertex normals considering smoothing. - - - - - The normal. - - - - - The smoothing groups. - - - - - A pointer to the next normal - this class is a linked list. - - - - - The init variable is used as a flag to indicate if the first normal in the list has been initialized. - - - - - Assignment operator - - - - - Normalize each normal in the list - - - - - Runs a message loop without blocking, allowing only acceptable Windows messages through to their destination UI controls. - - - 's message loop is a common idiom for Win32 progress dialogs. A progress dialog may call WindowsMessageFilter::RunNonBlockingMessageLoop periodically to allows paint messages through. In this way, the UI can refresh and the application appears to respond instead of entering Windows' "Not Responding" state. - also solves a common bug with our hosted WPF (.NET 3.5) UI controls. It appears that the operating system periodically sends a sort of heartbeat message to WPF controls. This message is in the user message range, above WM_USER. If this message is filtered out, as was the case for previous message filtering loops, the controls stop responding for the rest of the session. - The ensures that any messages required by the internal Qt event system are passed through for the Qt UI. This is automatically done within the default implementation of IsAcceptableMessage, which calls the IsQtSystemMessage method. If you provide a custom override for IsAcceptableMessage make sure it contains a call IsQtSystemMessage - without that the Qt UI can freeze. - The default implementation calls PeekMessage, removing messages from the message queue. It inspects each message in turn. If IsAbortMessage returns true for a message, the loop is aborted. If IsAcceptableMessage returns true for the message, it is passed to the application's main Translate and Dispatch message function. If IsAcceptableMessage returns false, and ShouldRepostMessage returns true, the message is reposted to the message queue. See each function's documentation for a description of its behaviour. - The implementation may be customized by creating a derived class and overriding any of IsAcceptableMessage, IsAbortMessage, or ShouldRepostMessage. Alternatively, a derived class may override RunNonBlockingMessageLoop to specialize the message filtering loop itself. - Example: - Generally, a message filtering loop looks like the following. This could be replaced by . Using is recommended over a custom solution, since it allows us to solve bugs like the WPF problem described above in one place for the entire application. - This message filter loop can be replaced with the as shown below. - - - - - Run a message loop without blocking, allowing only acceptable Windows messages through to their destination UI controls. - - - Messages deemed acceptable by IsAcceptableMessage are Translated and Dispatched. An Abort message, as determined by IsAbortMessage is consumed, sets Aborted to true, and exits the loop. A message may be reposted to the end of the message queue if it is not acceptable and if ShouldRepostMessage returns true. The loop exits normally when the message queue is depleted. - Note that this call is ignored if not called from the main thread. - - - - - Abort the current message loop. - - - Sets Aborted to true immediately, then aborts the currently running message loop when control returns. - - - - - Was the last message loop aborted? - - - The Aborted value is reset to false at the start of any call to RunNonBlockingMessageLoop. If the loop terminates by depleting the message queue, Aborted will remain false. On the other hand, if the message loop finds an Abort or Quit message, it will abort, and mark Aborted as true. Similarly, if a client calls AbortMessageLoop, the message loop will abort and set Aborted to true. - true if the message loop aborted early, false otherwise. - - - - - Add a window handle to the list of unfiltered windows. - - - All messages intended for the given window will be allowed through the message filter. - Note that adding duplicate elements will place the same element multiple times in the list. If a set of window handles may be added multiple times, it is better to call clear first. - - Window handle to leave unfiltered. - - - - Remove a currently unfiltered window from the list. - - - This command is ignored if the window is not present in the list. If the window handle was added multiple times, all instances of it will be removed from the list. - - Window handle to remove from the list of unfiltered windows. - - - - Remove all window handles from the list of unfiltered windows. - - - - - Is the given window handle in the list of unfiltered windows? - - - true if the given window handled is in the unfiltered list, false otherwise. - - Window handle for which to look. - - - - Is the given window a child of a registered unfiltered window? - - - true if this window handle is a child of a registered unfiltered window, false otherwise. - - Window handle to examine. - - - - Sets the message types that will be processed by the message loop. - - - - Can be any combination of the following flags: - - - - A plugin package may contain various pieces of information including a list of packages it is dependent on. Those packages must be present in order for the plugin package to load. struct instances are held by instances to reflect this information. - - - - - Returns a string representation of the guid value. - - - The string representation of the guid value - - If true, return string is lower case, otherwise is upper case. - If true, return string contains opening and closing braces. - - - - Returns whether valid guid value (!= CLSID_NULL). - - - - - This function will remove the reference to the Asset on which this asset User points and add a reference to the asset corresponding to the passed. - - - - - Gets the of the asset to which this points. - - - The GUID identifying the asset. - - - - - Gets the of the asset to which this points. - - - A string representation of the GUID identifying the asset. - - - - - Gets the type of the asset to which this points. - - - The type of the asset. - - - - - Gets the current file name of the asset to which this points. - - - The current file name of this asset. - - - - - gets an absolute UNC path of the asset file - a MSTR with an absolute path to where the asset is located if successful; otherwise returns an empty MSTR if it fails to find the asset file - - - - - resolves the physical location of the asset to which this points. - - - gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - - - - resolves the physical location of the asset to which this points. - - - gets an absolute UNC path of an asset file - true if the asset file is located successful; otherwise returns false - - : is set to an absolute UNC path if the asset file is found. If the asset file is not found it is left unchanged. - - - - Flags the asset as having been saved to a max scene file. This method is called if the AsssetId of the asset is stored to the max scene file (typically as a string) rather than the Save method being called on this . This tells the Asset Manager that the metadata for the asset must be saved to the scene file (asset metadata is saved only for those assets actually written to the scene file. Note: If you save the instead of the , on scene load you must pass the read through IAssetManager::RemapLoadedAssetID before getting an using the . - - - - - Resets the current asset id. Remove the reference to the asset held by this and sets the internal value to kInvalidId. - - - - - Called for saving data. - - - Called to allow the asset to save its data. - One of the following values: IO_OK, IO_ERROR. - - - The interface. - - - - Modifies the capitalization of the asset's filename. This method is used when writing the file associated with the asset to disk to ensure that the capitalization of the asset's filename is the same as that of an existing file that has the same filename but with a different capitalization. - - - True if the capitalization of the asset's filename was modified. False otherwise. - - - The filename with the new capitalization. It must only differ from the asset's current filename in its capitalization. If it is different in any other way, the asset's filename is not modified. - - - - Return an object given a file name and an asset type. Automatically adds a reference to the asset identified by the , this reference will be removed at the destruction of the . - - - returns instance created. - - A file name which can be either a full path ("C:\bitmaps\a.bmp"), a relative path("..\bitmaps\a.bmp"), or just a filename("a.bmp"). - The asset type, see AssetType. - if true, if an asset corresponding to the parameters does not exist, a new asset will be created. If false, a new asset will not be created. - - - - Return an object given a file name and an asset type. Automatically adds a reference to the asset identified by the , this reference will be removed at the destruction of the . - - - returns instance created. - - A file name which can be either a full path ("C:\bitmaps\a.bmp"), a relative path("..\bitmaps\a.bmp"), or just a filename("a.bmp"). - The asset type, see AssetType. - if true, if an asset corresponding to the parameters does not exist, a new asset will be created. If false, a new asset will not be created. - - - - Return an object given a file name and an asset type. Automatically adds a reference to the asset identified by the , this reference will be removed at the destruction of the . - - - returns instance created. - - A file name which can be either a full path ("C:\bitmaps\a.bmp"), a relative path("..\bitmaps\a.bmp"), or just a filename("a.bmp"). - The asset type, see AssetType. - if true, if an asset corresponding to the parameters does not exist, a new asset will be created. If false, a new asset will not be created. - - - - Return an object pointing to the id passed Automatically adds a reference to the asset identified by the , this reference will be removed at the destruction of the . - - - returns instance created. - - the asset of the asset - - - - Release the reference to the asset identified by the If the asset doesn't have any other reference it will be removed from the asset manager. - - - true if the asset was successfully found and released. - - asset id to be released - - - - Release the reference to the asset identified by the string. - - - true if the asset was successfully found and released. - - the asset id string to be released - - - - Add a reference to the asset identified by the . - - - true if the asset was successfully found and a reference added. - - asset id for which we want to add a reference - - - - Add a reference to the asset identified by the string. - - - true if the asset was successfully found and a reference added. - - asset id string for which we want to add a reference - - - - Convert an object to a string. - - - the asset id converted to a string - - assetid that will be converted - - - - Try to convert an a string to an . - - - true if the string was successfully converted , false otherwise (if the string wasnt a valid ) - - string to be converted - will be filled with the if the method is successful - - - - Load an asset from the scene file. - - - IO_OK if the asset was successfully loaded , IO_ERROR otherwise - - the interface - will be filled with the if the method is successful - - - - Remaps asset id loaded from scene file to new asset id for the asset. The asset id in the file being loaded may conflict with an existing asset id. Therefor, immediately after loading an asset id it must be passed through this method to get the new asset id. - - - - asset id to remap - - - - A list of the input data types to be passed into the engine. This will be extended as add more exposure to different types in different spaces. - - - - - TBD A custom blind data type for any data that is not covered in OutputDataTypes - - A list of the output data to be passed fomr the engine. This will be extended as add more exposure to different types in different spaces. - - - - - A list of all all the channel types you can write to - - - - - List of vertex channels you can write to - - - - - List of edge channels you can write to - - - - - List of face channels you can write to - - - - - Vertex channels are bit tricky since they are tied to a face index channel this enumerates the different channels - - - - - These are enums that describe the engine type.There are 3 an Input, Operand and Output. An Input Engine just creates data that is sent to the stack. An Operand takes data flowing thru the stack and modifies it and then puts it back on the stack An Output takes the data and pushes it back to the mesh - - - - - This is a black box engine that takes some input and outputs some data. For the DataChannel modifier the input is an and Node and the output can be vertex, edge or face channel data. Engines come in 3 flavors an Input Engine which does not use kType_Stack_Input and just generates a channel, a Operand Engine which takes an input channel and generates an output channel, and finally an Output Engine which does not generate an output channel and usually pushes that stack data (input) to the - - - - - Returns the name to be used in the UI for the Data Channel modifier - - the name to be used in the Data Channel - - - - Returns the Operand Info to be used by the ui (uses Tooltip string by default) - - - - - Returns the tooltip to be used by the ui - - - - - Vertex channels have an face index channel assigned to them. This returns what face index channel the output data is associated with. Only applies if the output channel is a vertex channel - - - - - This is called before the output requirements are called so the engine can respond to a change in the input type and adjust the output appropriately. Only an engine that requires an input channel from the stack ie has an input channel set to kType_Stack_Input needs to listen to this - - is the channel containing the stack array coming in from the stack in response from the kType_Stack_Input flag set as an input requirement - - - - This lets the modifier know that the engine is in valid state with the input data. For instance if the input type changed to a data that was not supported it can send an error message to the user that this is not a valid case - - is a string describing why the engine failed - - - - This allows engines that creates floats to define the domain of there values. This gives the display some hints on how to gradiate the color - - - - - Returns the min value for the domain - - - - - Returns the max value for the domain - - - - - This allows the engine to override the modifier display. Return true and implement display if you want a custom display - - - - - ************** WIP FUTURE THREADING SUPPORT **************************** - This returns whether the engine is thread safe. If the engine is not thread safe only the Process will be called. If all the engines in the stack are thread safe first the engine Threaded_Setup is called on all the engines sequentially to allow for non thread safe operatiuons to be called and cached like getvalue, getobjecttm etc. This lets the engines do any non thread safe operations. Then the engines Threaded_Process will be called on a block of data that the engine is to proces. NOTE operands that write directly to the mnmesh are not thread safe and typically output operands are not thread safe - - - - - Descripes an input entry which consists of an type description and pointer to the data - - - - - Returns the data description - - - - - Returns a pointer to teh actual data - - - - - Descripes an output entry which consists of an type description and pointer to the data Also lets the engine tell the modifier what channel it supports Other data that the engine needs to store per instance can also be stored here since the output data is stored on the modifier local data for modifiers - - - - - Just a quick way to set the data and type - - describes the data to be used for output - pointer to the actual data - - - - Returns the channel that this data is appropriate for - - - - - Returns the index channel that this data is appropriate for - - - - - Returns the data description - - - - - Returns the pointer to the actual data - - - - - Change bit-mask that are passed with color management notification messages. - This bit mask is passed in NotifyInfo::callParam with the NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notification codes. In rare occasions it's possible to get those notifications with none of the bits set, this happens during the "load colormanagement settings" operation for example, where the loaded settings are the same as the previous ones. - - - - - Enum for color management modes. - - - - - Enum for source of the config file that's used in the mode. - - - - - Enum for identifying display/view pair targets. - - - - - Enum for Output conversion options. - - - - - Flags that provide some information on color spaces. More than one flags can be present. - - - - - Flags that can be passed to functions operating on lists (such as GetNumFileIOColorSpaces() ) to control the list content. - - - - - Enum for color space assignment state. - In a modern color management system, color holding entities (such as bitmaps) need to have valid color spaces assigned to them so that they can be converted to and from the working (rendering) color space. Unlike the floating point gamma value used in the simple de-gamma/re-gamma work flows, the assigned color space may not always be a valid value, therefore it's important to keep track of the assigned color space and validity of it all the time. This enum provides different states the color space assignment may be in. - - - - - Enum for indicating the source of the assigned color space. - In a modern color management system, color holding entities (such as bitmaps) need to have valid color spaces assigned to them so that they can be converted to and from the working (rendering) color space. This assignment can be done automatically based on the file name or type or can be done explicitly by the users. 3ds Max keeps track of the source of the color space assignment so that if for some reason color space becomes unavailable (see ColSpaceStatus), an informed decision can be made to re-assign one of the currently available color spaces. Knowing the source of the color space assignment will also make trouble shooting a color space related problems easier. - - - - - This is a fully header-implemented class wrapping for type-safe color conversions. Objects of this class are stateless thus the functions are reentrant and thread safe. You can call IColorPipeline::GetColorConverter() to acquire an instance for the desired input and output image formats. - This class uses specializations to understand the memory layout and structure of the pixels for the given type. By adding specializations for you can extend the support for custom types and pixel formats. - - Type of the source pixels. - Type of the destination pixels. For in-place conversion TSRC and TDST should be identical. - - - - Converts a single scanline with optional pixel stepping. - - - A pointer to source buffer. - A pointer to destination buffer. - The width of the scanline in pixels. - The source pixel stepping. - The destination pixel stepping. - - - - Converts images with contiguous pixel memory layouts - - - A pointer to source buffer. - A pointer to destination buffer. - The width of the image in pixels. - The height of the image in pixels. - - - - Performs in-place color conversion. This function requires the TSRC and TDST template parameters have the same memory layout. If that's not the case, calling this function will create a compile-time error. - - - A pointer to buffer for in-place conversion. - The width of the buffer in pixels. - The height of the buffer in pixels. - - - - Single color conversion. Please note that calling this function in a loop will be much slower than using the functions which operate on 1D or 2D arrays. Unless you really need to convert only a few colors, please use the functions that operate on arrays. - - The converted color. - - source color. - - - - Helper template class for providing memory layout information for various pixel data types. and classes use this to process pixels properly. Specializations of this template class for common 3ds Max SDK pixel structures are provided by the system, but users can specialize the methods to add support for custom types. All member functions are 'static constexpr' thus all the type information is compile-time evaluated. - Specializations for the following types are provided by the system: - , , , , , , , , , and - - - - - This class is used internally by the class. Please see color space related functions of the class for public access to the data this class holds. - - - - - - class for internal color transformation engine, developers should not use this class directly. Please use class which provides convenient, type-safe and life-time managing usage by wrapping the objects. - - - - - - class that defines color conversions from source color space to target color space. User can get an instance by calling one of the GetXXXPipeline() functions of the class . Actual color conversion will be done by a object which can be created by calling IColorPipeline::GetColorConverter() templated factory functions with desired source and destination image formats. - Please note that none of the functions of this class are thread safe and should ideally be called from the main thread. - - - - - Returns the number of dynamic parameters this pipeline has, can be zero. - - - - - Retrieves the pointer to the dynamic parameter object by 0-based index number. - - - - - Retrieves the pointer to the dynamic parameter by the parameter name. Each parameter has a unique name. - - - - - Returns list of operations this pipeline will apply. - This function can be used for diagnostic purposed to check and verify the list of operations the pipeline will apply to transform colors. - List of operations both in non-optimized and optimized form. Operations will be listed in CTF (color transform format). - - - - - Internal function. - - - - - This is the central class for handling system-wide color management related data and tasks. This class supersedes the and IColorCorrectionMgr classes, providing unified settings and optimized color processing features in all color management modes. objects that can be retrieved using the IColorPipelineMgr::Settings() or IColorPipelineMgr::GetModeSettings() functions will contain detailed settings for the color management modes. This class also serves as a factory for creating instances. If any active setting changes this manager will broadcast a set of notifications to notify the listeners. - - Please note that none of the functions of this class are thread safe and should ideally be called from the main thread. - - - - - - - - - of last function that resulted in error. You can use this function along with GetLastErrorText() to know more about the latest failed call to functions. - - The string holding the name name of the last function that resulted in error. If there were no function calls that failed since the last call to ClearLastError then the returned value will be an empty string. - - - - - - Error string for the last occurring error in any of the function calls. If any function returns a fail code, you can use this function to get the details about the failure. Please use GetLastErrorFunction() to see/verify which function set this error text. - - String holding a function-specific explanation of the failure or an empty string if there was no error since the last ClearLastError() call. - - - - - - Resets the last error text and function to empty string. - - - - - - - - Sets the active color management mode. - Please note that changing the color management mode may have permanent effects on the scene data, especially on the input bitmaps and textures, and it may not be possible to revert. If the operation is successful, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 will be broadcast with NotificationChangeMask::modeChanged mask set in the post messages. - Returns true if the operation was successful. If it returns false you can use GetLastErrorText and GetLastErrorFunction to get details. - - one of the ColorPipelineMode enums. If you set the color management mode to you also need to make sure that a valid OCIO configuration file is loaded, otherwise colors won't be managed. - - - - Returns the currently active color management mode. Use Settings function to access the individual settings of the active mode. - Currently active color management mode. - - - - - - - - Returns a pointer to a mutable object of type holding the detailed settings of the currently active color management mode. Through this pointer you can get and set the settings. - Pointer to object to set/get settings of the currently active color management mode. - - - - - Returns an read-only object for the specified mode. This can be used to query the settings of currently inactive the color management modes. To access the settings for the currently active mode, use the Settings() function instead. - Read-only pointer to the settings object for the specified mode. If the specified mode is invalid nullptr will be returned. - - - One of the ColorPipelineMode enum values specifying the mode for which the object will be returned. - - - - - - - Sets the display gamma. Sets the display gamma value that's used in the ColorPipelineMode::kGAMMA mode. It won't have any effect in other color management modes. If the operation is successful, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notifications will be broadcast with GammaModeSettingsChanged flag set. Display gamma value will always be in sync with the . - True if the operation is successful. - - This is the display gamma value to be used. - - - - Retrieves the gamma value used for the display in the ColorPipelineMode::kGAMMA mode. - In other modes this value is not used. - Gamma value set for the display for the ColorPipelineMode::kGAMMA mode. - - - - - - - - Sets the default gamma that's used for the loaded bitmaps in the ColorPipelineMode::kGAMMA mode. If the operation is successful, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notifications will be broadcast with GammaModeSettingsChanged and InputSettingsChanged flags set. - True if the operation is successful. - - default gamma value to be used for bitmap load operations. - - - - Returns the default gamma value that will be used in the bitmap load operations in the ColorPipelineMode::kGAMMA mode. - Default gamma value for the bitmap load operations. - - - - - Sets the default gamma that's used for the saved bitmaps in the ColorPipelineMode::kGAMMA mode. If the operation is successful, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notifications will be broadcast with GammaModeSettingsChanged and OutputSettingsChanged flags set. - True if the operation is successful. - - default gamma value to be used for bitmap save operations. - - - - Returns the default gamma value that will be used in the bitmap save operations in the ColorPipelineMode::kGAMMA mode. - Default gamma value for the bitmap save operations. - - - - - - This function is provided for future use. Not implemented yet. - - - - - This function is provided for future use. Not implemented yet. - - - - - This function is provided for future use. Not implemented yet. - - - - - This function is provided for future use. Not implemented yet. - - - - - This function is provided for future use. Not implemented yet. - - - - - - - - Saves the current color pipeline settings as the marketing defaults. System defaults will be loaded when 3ds Max starts, resets or on new file operation. - - True if the operation was successful. - - - - - Loads the settings from the marketing defaults. Returns false if the operation fails, for example due to the missing OCIO config file. - True if successful. False if the operation fails - for example due to the missing OCIO config file. - - - - - This class holds the detailed settings for each of the color management modes (see ColorPipelineMode). You can get the instance for the currently active mode by calling IColorPipelineMgr::Settings() function. You can also get the read-only instances for the inactive modes via IColorPipelineMgr::GetModeSettings() function. - - Please note that none of the functions of this class are thread safe and should ideally be called from the main thread. - - - - - - - - Returns some descriptive information about the current Mode. - - A MSTR describing the current mode. Might be empty. - - - - - - Returns some descriptive information about the given Color Space. - - A MSTR describing the given Color Space. Might be empty. - - - The Color Space to be queried. - - - - Returns some descriptive information about the given Display and View Transform. - - A MSTR describing the given Display and View. Might be empty. - - - The Display to be queried. - The View to be queried. - - - - Returns flags for the given color space name. - - A bitmask comprised of ColorSpaceFlags values. If the color space does not exist or any error occurs during the operation then 0 will be returned. - - - The name of the color space that's queried. - - - - - - - Returns the number of available Rendering Color Spaces in this setting. - - The number of available Rendering Color Spaces. - - - - - - Returns the name of the Rendering Color Space with the given index. - - The name of the Rendering Color Spaces. with the given index of an empty string (if the given idx is invalid). - - - The index of the Rendering Color Space to be asked. - Options controlling the list to operate on and content of the returned value. see ListOptions for available options. - - - - Returns the index of the Rendering Color Space with the given name or (size_t)(-1) if the color space with the given name cannot be found in the active setting. - - Color Space names comparisons in OCIO are always case-insensitive. - - The index of the Rendering Color Spaces, or (size_t)(-1). - - The name of the Rendering Color Space to be queried. - Options controlling the list to operate on and content of the returned value. see ListOptions for available options. - - - - Returns the name of the current Rendering Color Space used to render the scene. - - The name of the Rendering Color Spaces used. - - - - - Sets the current Rendering Color Space to be used within this setting. If the given Color Space can be applied, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 will be sent. - - Color Space name comparisons in OCIO are always case-insensitive. - - True, if the colorspace could be changed. If the operation was unsuccessful it will return false. IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - - The name of the Rendering Color Space to be used. - - - - - - - Returns the number of Color Spaces available for use in file IO. - - The number of available Color Spaces. - - - Options controlling the list to operate on and content of the returned value. see ListOptions for available options. - - - - Returns the name of the file IO Color Space with the given index. - - The name of the file IO Color Space with the given index or an empty string in case the index is invalid. - - - The index of the file IO Color Space to be returned. - Options controlling the list to operate on and content of the returned value. see ListOptions for available options. - - - - Returns the index of the file IO Color Space with the given name. - - Color Space names comparisons in OCIO are always case-insensitive. - - The index of the file IO Color Space with the given name or size_t(-1) if the passed color space name is not found. - - - The name of the file IO Color Space to be queried. - Options controlling the list to operate on and content of the returned value. see ListOptions for available options. - - - - Returns the number of available file IO rules in this setting. - - The number of available file IO rules. - - - - - - Gets the details of the idx'th file IO rule. Returns true if the information is successfully retrieved. - - Either the (pattern, ext) pair or the regex will be used in each rule. If the (pattern, ext) pair is used then regex will return empty (or vice verse) - - True if the information could be successfully retrieved. - - - The index of the file IO rule to retrieve information on. - The name of the rule. - The pattern of the rule. - The file extension this rule should apply on. This may be an empty string. - A optional regular expression that is used to check if this rule is to be applied - or an empty string. - The name of the file IO Color Space that this rule will resolve to. - - - - Returns if the file IO rules are applied using case-sensitive file names. By default the file rules in 3ds Max are case-insensitive. - - True, if the file io rules resolution is done using case-sensitive informations. - - - - - - Runs the input rules on the passed image file path and returns the resulting color space. - - The color space name to be used. - - The file path to be checked. - Receives the index of the first rule that matched the file path. - - - - - - - Returns the default output conversion. The default output conversion is getting applied when saving a bitmap and the output conversion type is set to "Automatic". - The contents of colorSpaceOrDisplay and viewTransform will have different meanings - based on the return value of this function. - - Returns the default OutputConversion. Based on this value, the contents of the passed in MSTR may have different meaning: - If this function returns OutputConversion::kNO_CONVERSION, both parameters will be ignored. - If the return value is OutputConversion::kCOLOR_SPACE_CONVERSION, colorSpaceOrDisplay will receive the name of the color space and viewTransform will be ignored. - In case it returns OutputConversion::kDISPLAY_VIEWTRANSFORM, colorSpaceOrDisplay will receive the name of the display and viewTransform will receive the name of the view transform. - - - The output bitmap format type for which the defaults are being set. - The MSTR passed in here as an optional pointer may receive the name of the color space or the name of the display. Please refer to the return value of this function on how to interpret this value. - The MSTR passed in here as an optional pointer may receive the name of the view transform. Please refer to the return value of this function on how to interpret this value. - - - - Sets the default output conversion. The default output conversion is getting applied when saving a bitmap and the output conversion type is set to "Automatic". - - Returns true, if the passed parameter combination is available and could be set, false otherwise. - - - The output bitmap format type for which the defaults are being set. - The OutputConversion to be used. - If the param conversion is set to , this is read as the name of the color space to convert to. If the param conversion is set to , this is read as the name of the display, and the viewTransform param is also required. If the param conversion is set to , this parameter is ignored. - If the param conversion is set to , this is read as the name of the view transform. In other conversion modes, this parameter is ignored. - - - - - - - Returns the default Display/View Transform for the given target. - - True, if successful. - - - The DisplayViewTarget to be queried. - Will be set to true, if the given target is set to automatic. Regardless the automatic mode, display and view will be filled with the effective values. - The Display for the given target. - The Transform for the given target. - - - - Sets the default Display/View Transform for the given DisplayViewTarget. - True, if successful. False, if the given combination of display/view-transform isn't available in the current setting. - - - The DisplayViewTarget to be altered. - If be set to true, if the given target is set to automatic. In this case the display and view parameters will be ignored. - If automatic is set to false, this will be the display for the given target. - If automatic is set to false, this will be the view transform for the given target. - - - - - - - Returns the number of displays. - - The number of available displays. - - - - - - Returns the name of the display with the given index. - - The name of the display - or an empty string. - - - The index of the display to be queried. - - - - Returns the index of the given display name. - - Display name comparisons in OCIO are always case-insensitive. - - The index of the given display, or the (size_t)(-1) if the given display could not be found. - - - the name of the display to be queried. - - - - Returns the name of the default display. - - The name of the default display. - - - - - - - - - Returns the number of view transforms available for the given display. - - Display name comparisons in OCIO are always case-insensitive. - - The number of view transforms available for the given display. - - - The display to be queried. - - - - Returns the name of the view transform with the given index for the given display. - - Display name comparisons in OCIO are always case-insensitive. - - The name of the view transform with the given index for the given display. - - - The display to be queried. - The index of the view transform to be retrieved. - - - - Returns the index of the view transform with the given name for the given display. - - Display name comparisons in OCIO are always case-insensitive. - - The index of the view transform with the given index for the given display, or (size_t)(-1) if the given display could not be found in the given context. - - - The display to be queried. - The name of the view transform to be searched. - - - - Returns the name of the default view transform for the given display. - - Display name comparisons in OCIO are always case-insensitive. - - The name of the default view transforms for the given display. - - - The display to be queried. - - - - Returns the number of view transforms available for the given color space and display. - - Display and Color Space name comparisons in OCIO are always case-insensitive. - - The number of view transforms available for the given display. - - - The Color Space to be queried. - The display to be queried. - - - - Returns the name of the idx'th view transform with the given index for the given display and color space. - - Display and Color Space name comparisons in OCIO are always case-insensitive. - - The name of the view transform with the given index for the given display and color space. - - - The Color Space to be queried. - The display to be queried. - The index of the view transform to be retrieved. - - - - Returns the index of the view transform with the given name for the given display and color space. - - Display and Color Space name comparisons in OCIO are always case-insensitive. - - The index of the view transform with the given index for the given display, or (size_t)(-1) if the given display could not be found in the given context. - - - The Color Space to be queried. - The display to be queried. - The name of the view transform to be searched. - - - - Returns the name of the default view transform for the given display and color space. - - Display and Color Space name comparisons in OCIO are always case-insensitive. - - The name of the default view transforms for the given display and color space. - - - The Color Space to be queried. - The display to be queried. - - - - Returns the ColorPipelineMode used in this setting. - - The ColorPipelineMode used in this setting. - - - - - - Returns if the setting is active. - The returned by IColorPipelineMgr::Settings() is always active, while the various returned by IColorPipelineMgr::GetModeSettings() may or may not be active. - - True if the mode is the currently active one. - - - - - - Returns true if this is based on a OCIO configuration. - Convenience function for checking if the ColorPipelineMode is one of the ColorPipelineMode::kOCIO_XXX modes. - - - - - - Returns the initialization state of the mode. - - ModeStatus::kNORMAL if the mode is initialized successfully as intended. If there were problems during initialization (for example due to invalid OCIO config file) then this will return either ModeStatus::kFALLBACK_RAW or ModeStatus::kINVALID. If the return value is ModeStatus::kFALLBACK_RAW it's still possible to use this mode but it will act as "unmanaged" mode. ModeStatus::kINVALID indicates internal error. - - - - - - Will lock/unlock the mode. If the mode is unlocked you can change the OCIO config file it uses. Note that many of the the built-in modes are internally locked and can't be unlocked. - - true if the operation is successful. - - - true to lock, false to unlock. - - - - Returns true if the current mode is locked. Configuration file of the Locked modes cannot be changed from the UI or MaxScript. - - True if the current mode is locked. - - - - - - This will trigger re-initialization of the mode, causing the OCIO config file (if any used in this mode) be re-loaded using the current values of the environment and context variables. If this mode is the active mode then NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notification will be broadcast. - - True if the mode is re-initialized successfully as intended. If there were problems during initialization (such as invalid OCIO config file) then this will return false. It's still possible to use this mode in that case but it will act as "unmanaged" mode. - - - - - Returns the full path of the config file used in the current mode. Returns empty string if the mode uses an in-memory raw config. - - - - - - If the mode is not Locked, this sets the config file to be used in this mode. - If the operation is successful, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 notification messages will be sent and the function will return true. - If the operation was unsuccessful it will return false. IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - True, if the mode is not locked and the config file could be loaded successfully. If the operation was unsuccessful it will return false. IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - - The path to the OCIO config file to load. - - - - Returns the source of the OCIO config file used in this mode. - - The source of the OCIO config file used in this mode. - - - - - - Returns the name of the Color Space that is used for RGB values specified and stored in the scene (such as param blocks). - - The name of the Color Space used for RGB values. - - - - - - Sets the Color Space that is used for specifying and storing RGB values in the scene (such as param blocks). This color space needs to be a scene referred linear color space. - If the given Color Space can be applied, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 will be sent. - - Color Space names comparisons in OCIO are always case-insensitive. - - True if the given Color Space could be set. If the operation was unsuccessful it will return false. IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - - The name of the Color Space to be used. - - - - Returns the name of the Color Space that is used for data colors or data images. Usually the "raw" color space. - - Returns the name of the Color Space that is used for data colors or data images. - - - - - - Sets the Color Space that is used for specifying data colors or data images. Usually the "raw" color space. If the given Color Space can be applied, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 will be sent. - - Color Space name comparisons in OCIO are always case-insensitive. - - True if the given Color Space could be set. If the operation was unsuccessful it will return false. - IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - - The name of the Color Space to be used. - - - - Returns the name of the Color Space in the current config that is equivalent to linear-sRGB color space. This color space is internally used for converting colors which are assumed to be linear sRGB (such as the results of legacy color temperature calculations). - - If a linear-sRGB equivalent color space is found in the current config, name of that color space is returned. If the heuristics fail, this function may return an empty string. - - - - - - Sets the Color Space that is used for specifying linear sRGB colors or images. If the given Color Space can be applied, NOTIFY_COLOR_MANAGEMENT_PRE_CHANGE, NOTIFY_COLOR_MANAGEMENT_POST_CHANGE and NOTIFY_COLOR_MANAGEMENT_POST_CHANGE2 will be sent. - - Color Space name comparisons in OCIO are always case-insensitive. - - True if the given Color Space could be set. If the operation was unsuccessful it will return false. IColorPipelineMgr::GetLastErrorText() may have information about the cause of the failure. - - - The name of the Color Space to be used. - - - - Data type and bit-depth of each color channel of the pixel - - - - - Order of the color channels of the pixels in the memory. - - this value should be in agreement with the value returned by NumChan() function. - - - - - Flags. - - - - - Dynamic parameters for the objects. Use IColorPipeline::GetParameter() to receive the pointers to the parameters the pipeline may have. - - - - - Returns the name of the dynamic parameter. Each dynamic parameter has a unique name. - - - - - Returns the value of the dynamic parameter. - - - - - Sets the value of the dynamic parameter. - - - - - enum values for the private DWORD flag - bits, so powers of 2 - - - - - Helper class for controlling IStorage and IStream deletion. A typical usage is: - - - - - - - stream header consists of WORD version number, a private flag DWORD, and a public flag DWORD - - - - - stream format version number - - - - - flag bits whose flag bit usage is defined by Autodesk - - - - - flag bits whose flag bit usage is defined by the creator or consumer of the stream - - - - - The possible positions of quad inside a quad menu. - - - - - Returns the associated to this menu item. - - - - - Returns the display title of the menu item. If a localized title exists, it is returned, otherwise the non-localized (default) string is returned. If the title string is set by SetTitle(), it is considered the default string, and is always returned by this method. - - - - - Returns true if the sub menu item should be displayed 'flat', otherwise false. - - - - - Adds a sub menu with the specified title. - - - A pointer to the newly created dynamic menu. - - The title of the menu. - - - - Adds a new menu item associated with the action identified by its ActionTableId and persistent ActionId. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The unique ID for the . - The persistent id of the action in the to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the default text of the is used. - - - - Adds a new menu item associated with the action identified by its ActionTableId and ActionId. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The unique ID for the . - The persistent id of the action in the to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the default text of the is used. - - - - Adds a new action item associated with the macroScript action identified by its name and category. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The name of the macroScript to be executed by clicking on the created menu item. - The category of the macroScript to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the button text of the macroScript is used. - - - - Adds a separator item. - - - - - Adds a command id based item to the dynamic menu. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The ID for the menu item. - The name to appear for the menu item. - One or more of the DynamicMenuFlags. - The name of the multi-resolution icon to load. The path, basename and the extension of the file is used to find matching icons. The Extension may be omitted and .png / .svg is assumed to be the default extension. The icon loading location and naming convention is described in detail inside the documentation of ) - The tool tip of the menu item. Note that it is not displayed if it is equal to the title. - - - - Creates a command id based item to the dynamic menu with the given unique id. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The unique id of the menu item to be inserted into the menu. - The ID for the menu item. - The name to appear for the menu item. - One or more of the DynamicMenuFlags. - The unique id of the menu item where the newly created menu item will be inserted before. - - - - Returns the unique id associated with this menu. - - - - - Returns the display title of the menu. If a localized title exists, it is returned, otherwise the non-localized (default) string is returned. If the title string is set by SetTitle(), it is considered the default string, and is always returned by this method. - - - - - Returns true if the sub menu should be displayed 'flat', otherwise false. - - - - - Returns the parent menu of this menu. - - - The parent menu, or nullptr if this menu is a top level menu. - - - - - Returns a list of menus items owned by this menu. - - - A list of menu items. - - - - - Moves a sub menu to a specific menu/menu bar, and at a specific position. - - - ! - - The unique id identifying the menu or menu bar where to insert the menu item. - The unique id of the menu item where the newly created menu item will be inserted before. - - - - Creates a new sub menu associated with the given unique id. - - - A pointer to the newly created sub menu or nullptr if the menu creation failed. - - The unique id of the menu to be created. - The title of the menu. - The unique id of the menu item where the newly created menu item will be inserted before. - - - - Creates a new menu item associated with the action identified by its ActionId. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - For macroScript actions please use the in 3ds Max 2026 introduced CreateAction(const & id, const MSTR& macroScriptName, const MSTR& macroScriptCategory, ...) overload that uses the macroScript name and category for action item identification. For 3ds Max 2025 use this generic method for referencing macroScript actions by menu items. All defined macroScript actions are part of one specific MaxScript action table. The tableId for all the macroScript actions is always 647394. The macroScript action itself is identified by its persistentActionId in that action table, which is constructed of the macro name concatenated with a backtick and the macroScript's non-localized category. Example of referencing a macroScript earlier than in 3ds Max 2026: - - The unique id of the menu item to be created. - The unique ID for the . - The persistent id of the action in the to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the default text of the is used. - The unique id of the menu item before which the newly created menu item will be inserted. - - - - Creates a new menu item associated with the action identified by its ActionId. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The unique id of the menu item to be created. - The unique ID for the . - The persistent id of the action in the to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the default text of the is used. - The unique id of the menu item before which the newly created menu item will be inserted. - - - - Creates a new menu item associated with the macroScript action identified by its name and category. - - - A pointer to the newly created action menu item or nullptr if the menu item creation failed. - - The unique id of the menu item to be created. - The name of the macroScript to be executed by clicking on the created menu item. - The category of the macroScript to be executed by clicking on the created menu item. - The title of the menu item. If no title is provided the button text of the macroScript is used. - The unique id of the menu item before which the newly created menu item will be inserted. - - - - Creates a new separator item with the given unique id. - - - A pointer to the newly created separator menu item or nullptr if the menu item creation failed. - - The unique id of the separator item to be inserted into the menu. - The unique id of the menu item before which the newly created menu item will be inserted. - - - - Deletes the menu item with the given unique id. - - - true if the item was present and has been deleted. - - The unique id of the item to be deleted. - - - - Pops up a context menu at the given position. - - - - The screen position to display the menu. - - - - Pops up a context menu at current mouse position. - - - - - Returns the unique id associated with this menu item. - - - - - Returns if menu item represents a separator. - - - - - Returns if menu item is an action based menu item. - - - - - Returns this menu item as if the item is an action based menu item. - - - - - Returns if menu item represents a sub menu. - - - - - Returns a pointer to the sub menu if the item represents a sub menu. - - - - - Returns if menu item represents a dynamic sub menu. - - - - - Returns the parent menu of this menu item. - - - The parent menu. - - - - - Moves a menu item to a specific menu/menu bar, and at a specific position. - - - ! - - The unique id identifying the menu or menu bar where to insert the menu item. - The unique id of the menu item where the newly created menu item will be inserted before. - - - - Creates a new top level menu with specified unique id. Top level menus can be used as menu bars or standalone context menus. - - - A pointer to the newly created menu, or nullptr if the creation failed. - - The unique id of the menu to be created. - The title of the menu. - - - - Returns a list of all top level menus. - - - A list of top level menus. - - - - - Returns the associated menu for a given unique id. - - - A pointer to the looked up menu or nullptr if no menu for the given id could be found. - - The unique id of the menu which should be retrieved. - - - - Returns the associated menu item for a given unique id. - - - A pointer to the looked up menu item or nullptr if no menu item for the given id could be found. - - The unique id of the menu item which should be retrieved. - - - - Returns the 3dsMax main menu bar. - - - - - Loads the specified user menu configuration or a default 3ds Max menu configuration. - - - true if the new configuration could be loaded, false otherwise. - - The file name of the menu configuration to be loaded. - If true, messages are logged to the cui log file and the max log file. - - - - Returns path to default configuration. - - - the path to the default configuration. - - - - - current configuration path, loads configuration only if path is different. - - - true if the provided path has been set. - - The file name of the menu configuration to be loaded. - If true, messages are logged to the cui log file and the max log file. - - - - Returns the current loaded menu configuration file. - - - - - Returns the Qt menu extension for a given menu. The Qt menu extension can be used to create a Qt specific menu or menu bar. - - - A pointer to the Qt menu extension. - - The unique id of the top level menu for which a Qt menu extension should be retrieved. - - - - Returns the Windows menu extension for a given menu. The Windows menu extension can be used to create a win32 specific menu. - - - A pointer to the windows menu extension. - - The unique id of the top level menu for which a windows menu extension should be retrieved. - - - - Create a localization resource file for a menu file. - - - true if everything went ok - - the path of the menu file to localize - when successful, the not-normalized path where the resource file was written - the path of the folder where the res file should be generated - - - - Returns the message log file path. - - - - - Returns the unique id associated with this quad menu. - - - - - Returns the display title of the quad menu. If a localized title exists, it is returned, otherwise the non-localized (default) string is returned. If the title string is set by SetTitle(), it is considered the default string, and is always returned by this method. - - - - - Creates a new menu at the specified quad position. - - - A pointer to the newly created menu or nullptr if the menu creation failed. - - The unique id of the menu to be created. - The title for the newly created menu. - The section of the quad menu where the new menu will be positioned. - - - - Returns a list of the four menus associated with this quad menu. - - - - - Returns the menu at the specified quad position. - - - - The quad position for the menu that should be retrieved. - - - - Pops up a quad menu. - - - - - Returns the quad menu context to which this quad menu belongs. - - - The owning quad menu context. - - - - - Returns the unique id associated with this quad menu context. - - - - - Returns the display title of the quad menu context. If a localized title exists, it is returned, otherwise the non-localized (default) string is returned. - - - - - Creates a new quad menu with the given unique id and title. - - - A pointer to the newly created quad menu or nullptr if the quad menu creation failed. - - The unique id of the quad menu to be created. - The title for the newly created quad menu. - - - - Returns a list of all quad menus belonging to this quad menu context. - - - - - Associates right click modifiers with the specified quad menu. - - - True if the right click modifier for the specified quad menu were changed. - - The quad menu to which the right click modifiers should be associated. - The right click modifiers which should be assigned to this quad menu. - - - - Returns the right click modifiers for the specified quad menu. - - - - The quad menu for which the associated right click modifiers should be retrieved. - - - - Returns the quad menu which is associated with the according right click modifier, or nullptr if no quad menu is assigned. - - - - - - - Returns the quad menu which is associated with current pressed modifier keys, or nullptr if no quad menu is assigned. - - - - - - - Creates a new quad menu context with the given unique id, and title. - - - A pointer to the newly created quad menu context or nullptr if the quad menu context creation failed. - - The unique id of the context to be created. - The name for the newly created quad menu context. - - - - Returns a list of all quad menu contexts. - - - - - Returns the associated quad menu context for a given unique id. - - - A pointer to the looked up quad menu context or nullptr if no context for the given id could be found. - - The unique id of the context which should be retrieved. - - - - Returns the associated quad menu for a given unique id. - - - A pointer to the looked up quad menu or nullptr if no quad menu for the given id could be found. - - The unique id of the quad menu which should be retrieved. - - - - Returns the associated menu for a given unique id. - - - A pointer to the looked up menu or nullptr if no menu for the given id could be found. - - The unique id of the menu which should be retrieved. - - - - Returns the associated menu item for a given unique id. - - - A pointer to the looked up menu item or nullptr if no menu item for the given id could be found. - - The unique id of the menu item which should be retrieved. - - - - Loads the specified user quad menu configuration or a default 3ds Max quad menu configuration. - - - true if the new configuration could be loaded, false otherwise. - - The file name of the quad menu configuration to be loaded. - If true, messages are logged to the cui log file and the max log file. - - - - Returns path to default configuration. - - - the path to the default configuration. - - - - - current configuration path, loads configuration only if path is different. - - - true if the provided path has been set. - - The file name of the quad menu configuration to be loaded. - If true, messages are logged to the cui log file and the max log file. - - - - Returns the current loaded quad menu configuration file. - - - - - Push a viewport context id on the stack of viewport contexts. - - - - - Pop a viewport context from the stack of viewport contexts. - - - - - Find from the stack of viewport context, which context should handle a given modifier. - - - - - Create a localization resource file for a quad menu file. - - - true if everything went ok - - the path of the menu file to localize - when successful, the not-normalized path where the resource file was written - the path of the folder where the res file should be generated - - - - Returns the message log file path. - - - - - Helper function to pop up a quad menu from the provided context according to current keyboard modifiers. - - - true if both context and quad were found, false otherwise - - Id of quad context to get the quad menu from - handle to parent window of quad menu - - - - A core interface for accessing properties of the customized mode introduced in 3ds Max 2013. The mouse config manager allows plug-ins to get the shortcut of customized pan mode or zoom mode and value of some modes' parameters. - - - - - Plug-ins that have functions of setting customized pan,zoom,rotate or other customized mode will need to get concrete shortcut of different customized mode when users are switching among modes. If the operation mode as input parameter is valid, the output parameters of function GetOperationShortcut() will be the shortcut that has been set in custom user interface or by MAXScript. - - The customized mode indicated by or . - The key of customized mode's shortcut indicated by or . - The mouse button of customized mode's shortcut indicated by or . return true if the customized mode is pan mode. - - - - Plug-ins that have functions such as zoom or the other operation that need to get values of some operation parameters will use this function.For example,plug-ins will need to get the zoom in direction when user is in zoom mode and want to try different zoom in directions.If there is the corresponding operation parameter as input, the return value is true and the input/output parameter will be the value of operation parameter.Otherwise,if there is no corresponding operation paramter as input,the return value is false and the output parameter keep unchanged. - - The parameter of some customized modes indicated by or . - The value of parameter of some customized modes. - - - - In selection mode, using modifier keys add additional behaviors to pure selection. For instance, Ctrl + click is used for add selection, Alt for substract selection. While in Maya mode, Shift is used for add/substract selection, Ctrl for substract selection. This function get whether Max is in Maya selection mode. - true if Max is in Maya selection mode, otherwise false. - - - - - Returns whether we are using the nearest edge/vertex with preview selection. - true if we are using the nearest edge/vertex with preview selection. - - - - - Returns whether we will ignore back facing verts and edges in shaded view mode. Modifiers and objects can query this property to determine if the user wishes to ignore back facing verts and edges in shaded viewport picking. Faces can still be selected if you wait a few seconds and click without moving the mouse. Area/region selection can select back facing verts, edges, and faces. - true if we are ignoring back facing verts and edges in shaded view mode. - - - - - Returns the unique menu id associated with this Qt menu extension. - - - - - Returns the unique menu id associated with this Window menu extension. - - - - - This method will create a new windows menu and return it's handle. - - - - - This method will update the current windows menu. - - - - - This method returns the handle to the current windows menu. - - - - - This method executes an action based on the provided command. - - - - The command ID of the action to execute. - - - - - The command ID. - - - - Constants used in AddItem. - - - - - Class does all the actual skin weight computations. NOTE this uses OGL so you have to set up an OGL context first and also all the data structures are in OGL format - Examples of how to use this interface can be found in the bonesdef.vprog in maxsdk/samples/modifiers/bonesdef - - - - - This makes the current OGL context active - - - - - This creates skin weights based on a voxel data data structure - - this is the mesh that is being skinned - this the skeleton of the mesh being skinned - the update bar to let the system know how far along the solve is and if it should cancel - how smooth the blend weights are 0 is the most smooth 1 is the least smooth - the maximum number of weights per vertex that can be applied - the maximum density of the voxel data structure, the higher the more accurate but slower - can produce better weight results when their are arbitrary voxel results - - - - This creates skin weights based on a heat map algorithm, restrictions are that the mesh be manifold, only the first mesh element will have its weight computed. Usually the voxel algorithm produces better results. - - this is the mesh that is being skinned - this the skeleton of the mesh being skinned - the update bar to let the system know how far along the solve is and if it should cancel - how smooth the blend weights are 0 is the most smooth 1 is the least smooth - the maximum number of weights per vertex that can be applied - - - - Class describes the mesh to be used to compute the skin weights. This is just triangle soup but the heatmap solver requires that this mesh be a manifold mesh and there are no checks here for that. So that needs to be handled before converting to an iMesh - - - - - This adds a vertex to the mesh - - x component - y component - z component - - - - This adds a face to the mesh - - the index of the first vertex of the face - the index of the second vertex of the face - the index of the third vertex of the face - - - - Class just a class that the solver uses to tell how far along the process is and allows the user to cancel out of the process. - - - - - Called at the start of a major operation - - the text description of the operation - is the max value for the amount of time taken - is the current time - - - - Called at the start of a major operation - - - - - Sets the max and current time left - - is the max value for the amount of time taken - is the current time - - - - Sets the current time left - - is the current time left - - - - returns if the operation should abort - - - - - Class describes the weights that are assigned to a skin. Each vertex has an array pair of weight and bone index to describe how skin to deform the vertices - - - - - This returns the total number of vertices - - - - - This returns the number of weights per vertex - - - - - This the returns a a particular weight/bone index pair of vertex - - the index of the vertex - the index of the weight - - - - Class describes the skeleton to be used to compute the skin weights. The skeletons is defined from joint to joint which is slightly different than Max's which uses bounding boxes. - - - - - This adds a joint to the hierarchy NOTE joint names must be unique - - name of the joint - this is the transform of the joint NOTE only the transform component is used and the space is in openGL format - this is name of the parent of the joint you are adding - - - - This clears out all the entries into the hierarchy - - - - - Indicates the type of frame. - - - - - Indicates the dirty flag of render view. - - - - - This enum contains flags that specify certain states of a fragment or fragment graph node. - - - - - This enum describes types of messages a fragment could register and receive from the fragment system. Fragment::OnMessage is invoked whenever a fragment receives the registered messages from the fragment system. - - - - - built-in variable types. For more details please see class . - - - - - types available for vertex fields, e.g. Float4 - - - - - Indicates the usage of a vertex field of a vertex buffer. This enum is used to make hardware shaders understand the usage of vertex buffer. - - - - - Indicates the data source of a vertex field of a mesh vertex buffer. e.g. Position, Normal, Texture, etc. - - - - - Buffers are composed of arrays of elements all of the same type. This enum describes the size and interpretation of the elements in the buffer. Index buffers can have ushort or uint elements. - - - - - BufferUsageType Types for OGS buffer usage. - - - - - Enum type for all visual styles of nitrous viewport - - - - - Enum type for all presets of nitrous viewport - - - - - Enum for the kernel filters for the Bloom effect in the viewport. - - - - - This enum contains flags that can be combined together to specify whether or not certain functions of will be supported. - - - - - This enum defines requirement flags of material additional to mesh stream requirements of . - - - - - This enum describes the type of mesh element to be generated. Each mesh element corresponds to a specific render item generated by calling Mesh::GenerateRenderItems() or MNMesh::GenerateRenderItems(). - - - - - When a mesh is displayed in any sub-object level, this enum help decide which part of the mesh this mesh element belongs to. - - - - - This enum defines some kinds of built-in mesh element descriptions. Developer may query a built-in mesh element description by calling MeshElementDescription::GetBuiltInMeshElementDescription() using any enum value below. - - - - - Supported primitive types. - - - - - This flag describes the way to clear the current buffers. - - - - - blend selector. selects a blend source/destination - - - - - cull type. - - - - - fill mode for polygons - - - - - compare functions - - - - - blend operations - - - - - Stencil buffer operation. - - - - - AccessType Types for accessing buffers. - - - - - TargetFormat indicates which type the target/texture is. - - - - - This enum specifies the feature levels device supported. - - - - - Texture type enums - - - - - Resource usage, used for texture - - - - - Enums for , indicates which query types to issue. Refer D3D11_QUERY in DirectX Graphics Document for detail. - - - - - This enum defines in what group a render item is visible. - - - - - This enum contains flags that can be combined together to specify which part is required by the node when updating render items. - - - - - this class contains an integer which is initialized to zero. One can increase/decrease the value of the integer thread-safely. - - - - - increase the integer value by one. - the increased value. - - - - - decrease the integer value by one. - the decreased value. - - - - - return the integer value. - the value. - - - - - This is a utility class for assigning customized solid material to the solid mesh render item of a render node when generating render items from IMeshDisplay2::GetRenderItems() during the execution of BaseObject::UpdatePerNodeItems() - - - - - Description - This is a utility class for automatically restoring the world matrix when we finished rendering a render item. - - - - - This class implemented interfaces. concrete class can derive from this class to avoid implementing interfaces. - - - - - This is base graphics material class. A material describes how to render the surface of an object. This class, and all its derived classes, are used for viewport display and Quicksilver. The difference between and is that is used by RenderItemHandle::SetCustomMaterial() to describes the surface and is used for and to display. - - - - - Returns the material required streams to tell how to setup mesh data. When a is used by RenderItemHandle::SetCustomMaterial(), it also needs to know about the material requirement streams to setup corresponding mesh data. It could be used by GenerateRenderItems::GenerateRenderItems() for . - the material required streams. - - - - - Activates the material handle with the specified pipeline context. - - The pipeline context. - - - - Terminates the material handle, performing any cleanup required by the material handle. - - - - - Retrieves the number of passes required to render the material handle. - Each geometry to be drawn with the effect must be drawn that number of times. This pass count can only be retrieved while the effect is active. - Returns pass count. - - The pipeline context. - - - - Activates the specified pass of the material handle, at which point it may render geometry as necessary for the pass. - - The pipeline context. - The index of pass. - - - - Called after all of the passes for the material handle have been drawn. - - The pipeline context. - - - - This is our base graphics raster resource class. The graphics raster resource includes and Render Target. is a texture class for material. - - - - - Initialize the instance of raster handle. A should be initialized before it's used - true if succeed or false otherwise - - the width of target. - the height of target. - the format of the target - - - - Returns the width of raster resource. - the raster width. - - - - - Returns the height of raster resource. - the raster height. - - - - - the size of the raster handle. - - the width of the raster handle - the height of the raster handle - - - - Get the format of the raster handle. - the format of the raster handle - - - - - Locks the entire raster handle and access the raster data. - the mapped data of the raster handle - - data access type - byte size of one row - byte size of one slice(for texture handle only) - - - - Unlocks the entire raster handle - - - - - Copy from another raster handle - - the source raster handle - - - - This class holds the blend state for all render targets. - - - - - Get the AlphaToCoverage state. return true if alpha-to-coverage is enabled, false if not - - - - - Get independent blend state /return true if independent blend is enabled, false if not. - - - - - Get the color blending factor. /return the factor - - - - - Get multi-sample mask /return the mask - - - - - Get individual target blend state. /param index index of the target. Max value is MAX_TARGETS_SLOT. /return target blend state handle - - - - - is the base class that manages the connections between view fragments. It stores the connection pointer, a pointer that points back to its owner fragment, and the input/output data type. Only inputs/outputs that have compatible data types can be connected together. - - - - - Gets the pointer to owner view fragment. - the pointer to the owner fragment. - - - - - Gets the data type of this connection point. Once the connection point is created, its data type is fixed and cannot be changed. - the data type of this connection point. - - - - - is a wrapper of . It can be used to add a custom implementation into the Max graphics system without directly deriving from . - - - - - Initialize this handle. The handle is empty after initialization. It doesn't have a default implementation. - - - - - Sets an object to this handle. - - A user-created class that derives from the interface. - - - - Gets the object in this handle. - The object, or nullptr if there is no implementation. - - - - - is the base wrapper class of the custom render stage. - - - - - Initialize this custom render stage. - - - - - Run the custom render stage - - - - - Get the color target of the custom render stage - the color target of the custom render stage - - - - - Get the depth target of the custom render stage - the depth target of the custom render stage - - - - - Get the render world of the custom render stage - the render world of the custom render stage - - - - - Get the visibility group of the custom render stage - the visibility group of the custom render stage - - - - - Get the background color of the custom render stage - the background color of the custom render stage - - - - - Get the viewport of the custom render stage - the viewport of the custom render stage - - - - - Get whether we clear the depth buffer before running the custom render stage - true if we clear the depth buffer before running the custom render stage or false otherwise - - - - - Get whether we clear the color buffer before running the custom render stage - true if we clear the color buffer before running the custom render stage or false otherwise - - - - - Get the override material of the custom render stage - the override material of the custom render stage - - - - - the override effect instance handle to the custom render stage - This call will replace any previously set override material. - Using an override effect instance handle instead of an override material will let you load from the resource a compiled HLSL shader and use GPU debuggers. Use EffectHandle::InitializeWithResource to load a compiled shader from the resource file. - - the override effect instance handle - - - - This class encapsulates a complete depth buffer and stencil buffer state. - - - - - Get depth test state. /return true if enabled, false if not. - - - - - Get whether depth write is allowed. Default value is true /return true if depth write is enabled, false if not - - - - - Get depth buffer compare function. /return current depth compare function - - - - - Get stencil buffer state /return stencil buffer state - - - - - Get stencil buffer read mask. /return current stencil read mask - - - - - Get stencil buffer write mask. /return current stencil write mask - - - - - Get front face stencil operation /return front face stencil operation - - - - - Get back face stencil operation /return back face stencil operation - - - - - Get stencil reference value. /return stencil reference value - - - - - This class contains context which can be queried in - - - - - Used for creating texture handles () and updating texture data managed by the viewport display system. This class is implemented by the system and an instance of it is passed as parameter to ITextureDisplay::SetupTextures(). - - - - - Updates texture information used by the viewport display system. - It extracts mapping channel and texture transform information from the provided . Client code needs to call this method in its implementation of ITextureDisplay::SetupTextures() for each texture map of a material or sub-texture of a texture map plug-in. - - The time at which the texture information is updated. - The map usage which specifies which of the internal texture information will be updated. - The texture map representing the source for the texture information update. - - - - extends to support more textures Used for creating stage texture handles () and updating texture data managed by the viewport display system. This class is implemented by the system and an instance of it is passed as parameter to ITextureDisplay::SetupTextures(). - - - - - Updates texture information used by the viewport display system. - It extracts mapping channel and texture transform information from the provided . Client code needs to call this method in its implementation of ITextureDisplay::SetupTextures() for each texture map of a material or sub-texture of a texture map plug-in. - - The time at which the texture information is updated. - The stage which specifies which of the internal texture information will be updated. - The texture map representing the source for the texture information update. - - - - Typically ICustomRenderItem::Draw() and ICustomRenderItem::HitTest() bring instance of this class as parameter. It contains the complete state of a single item being drawn all system supplied variables are contained here, for example, current virtual device and matrices. Developers may need these information to determine Display and HitTest code paths. - - - - - Get current world matrix Note: If you want change the world matrix, you must first copy it to another instance, then apply the world matrix via SetWorldMatrix(). /return current world matrix. - - - - - current world matrix /param matrix new world matrix. - - - - - Get current view matrix Note: If you want change the view matrix, you must first copy it to another instance, then apply the view matrix via SetViewMatrix(). /return current view matrix. - - - - - Get current projection matrix Note: If you want change the projection matrix, you must first copy it to another instance, then apply the projection matrix via SetProjectionatrix(). /return current projection matrix. - - - - - Get virtual device Note: Don't store the virtual device on client side. You should always use the virtual device in the pipeline context. Because in DX11 multi-thread environment, the device may different in each call. /return virtual device. - - - - - Get current object /return object - - - - - Get node's extended display mode /return extended display mode flag from node - - - - - Get current Note: Legacy object also available in the . But we recommend to use new VirtualDevice object to do rendering task. /return object - - - - - Get current material handle /return current material handle Note: the handle might be invalid. Which means current item don't have material. - - - - - Get current frame stamp return current frame stamp - - - - - Get current animation time return current animation time - - - - - Get the alpha test enabled flag. The default value is false (disabled). /return current alpha test flag. True means enabled, false means disabled. - - - - - Gets the alpha test comparison function. The default value is CompareFunctionAlways. /return current alpha test comparison function. - - - - - Gets the alpha test reference value. The default value is 0.0f. /return alpha test reference value. - - - - - Gets viewport settings /return viewport settings - - - - - Get if this draw context is used for hit test /return true if the draw context is used for hit test pass - - - - - is a class provides features similar as in Direct3D This class is used for viewport display and Quicksilver. It can also be used for realistic material display. See for more details. Example of use: - - - - - Activates the material handle with the specified pipeline context. - - The pipeline context. - - - - Terminates the material handle, performing any cleanup required by the material handle. - - - - - Retrieves the number of passes required to render the material handle. - Each geometry to be drawn with the effect must be drawn that number of times. This pass count can only be retrieved while the effect is active. - Returns pass count. - - The pipeline context. - - - - Activates the specified pass of the material handle, at which point it may render geometry as necessary for the pass. - - The pipeline context. - The index of pass. - - - - Called after all of the passes for the material handle have been drawn. - - The pipeline context. - - - - Initialize an instance of FXEffectHandle. A FXEffectHandle should be initialized before it's used. - true if successfully initialized, false otherwise. - - HLSL shader file name. - - - - Initialize an instance of FXEffectHandle with shader string. A FXEffectHandle should be initialized before it's used. - true if successfully initialized, false otherwise. - - HLSL shader content. - The length of data. - A MSTR pointer, return error strings if effect is failed to load. Can be nullptr. - - - - Initialize an instance of FXEffectHandle from resource. A FXEffectHandle should be initialized before it's used. - true if successfully initialized, false otherwise. - : This method supports loading a compiled HLSL shader. - - resource ID of the shader - module instance handle - resource block name - A MSTR pointer, return error strings if effect is failed to load. Can be nullptr. - - - - Returns the parameter count of material. - the parameter count. - - - - - Returns the index of parameter. - valid index if successful, otherwise -1 - - The unique parameter name of the parameter. - - - - Sets active technique by name Only available for ".fx" based effect. - - of the technique to activate - - - - Gets current active technique index - the active technique index - - - - - Get a string list of technique names in the effect - TechniqueNames a list of string contains technique names in the effect - - - - - Create an new effect instance - new instance of the effect parameter packet. It contains values of all parameters. - - - - - is a class which stores values of parameters in an effect. Typically, is a singleton which represent a single ".fx" file. And each render item contains an to store their own values. Use EffectInstanceHandle::Apply() to apply values to the device. This class is used for viewport display and Quicksilver. How to use: - - - - - Returns the vertex format of this effect instance - the material required streams. - - - - - Sets int parameter. - - The unique parameter name of the parameter. - The int parameter value. - - - - Sets int parameter. - - The parameter index of the parameter. - The int parameter value. - - - - Sets int2 parameter. - - The unique parameter name of the parameter. - The int parameter value. - - - - Sets int2 parameter. - - The parameter index of the parameter. - The int parameter value. - - - - Sets int3 parameter. - - The unique parameter name of the parameter. - The int parameter value. - - - - Sets int3 parameter. - - The parameter index of the parameter. - The int parameter value. - - - - Sets int array parameter. - - The unique parameter name of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int array parameter. - - The parameter index of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int2 array parameter. - - The unique parameter name of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int2 array parameter. - - The parameter index of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int3 array parameter. - - The parameter index of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int3 array parameter. - - The unique parameter name of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets uint parameter. - - The unique parameter name of the parameter. - The int parameter value. - - - - Sets uint parameter. - - The parameter index of the parameter. - The int parameter value. - - - - Sets uint array parameter. - - The unique parameter name of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets uint array parameter. - - The parameter index of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets float parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float2 parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float2 parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float3 parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float3 parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float4 parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float4 parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float array parameter. - - The parameter index of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets float array parameter. - - The unique parameter name of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets float2 array parameter. - - The parameter index of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets float2 array parameter. - - The unique parameter name of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets float3 array parameter. - - The parameter index of the parameter. - The pointer of float3 array parameter value. - The count of float3 array. - - - - Sets float3 array parameter. - - The unique parameter name of the parameter. - The pointer of float3 array parameter value. - The count of float3 array. - - - - Sets float4 array parameter. - - The unique parameter name of the parameter. - The pointer of float4 array parameter value. - The count of float4 array. - - - - Sets float4 array parameter. - - The parameter index of the parameter. - The pointer of float4 array parameter value. - The count of float4 array. - - - - Sets bool parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets bool parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets bool array parameter. - - The unique parameter name of the parameter. - The pointer of bool array parameter value. - The count of bool array. - - - - Sets bool array parameter. - - The parameter index of the parameter. - The pointer of bool array parameter value. - The count of bool array. - - - - Sets matrix parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets matrix parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets matrix array parameter. - - The unique parameter name of the parameter. - The pointer of matrix array parameter value. - The count of matrix array. - - - - Sets matrix array parameter. - - The parameter index of the parameter. - The pointer of matrix array parameter value. - The count of matrix array. - - - - Sets texture parameter. - - The unique parameter name of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The unique parameter name of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The parameter index of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The parameter index of the parameter. - The parameter target handle value. - - - - Sets buffer parameter. - - The unique parameter name of the parameter. - The parameter or value. Note this buffer should be created with BufferUsageStatic | BufferUsageTarget usage flag - - - - Sets buffer parameter. - - The parameter index of the parameter. - The parameter or value. Note this buffer should be created with BufferUsageStatic | BufferUsageTarget usage flag - - - - is the base computation unit in the view system. A fragment has multiple inputs and outputs. Fragments can be connected together as a compute graph via those inputs and outputs. In this way, very complicated view features can be achieved, for example, combining the mental-ray GI pass with the Nitrous gizmo pass. - - - - - Evaluates this fragment. Updates the output values. - true on success, false otherwise. - - context info for evaluation. - - - - Re-evaluates this fragment. We will first clear the FragmentFlagsEvaluated flag and then Call Evaluate(). - true on success, false otherwise. - - context info for evaluation. - - - - Gets the number of inputs for this fragment. - the number of inputs of this fragment. - - - - - Gets the n-th input for this fragment. - the n-th input for this fragment. - - the index of the input. - - - - Gets the n-th input variable for this fragment. - if the given input is connected to an output, this function returns the variable from that output. Otherwise, this function returns NULL. - - the index of the input. - - - - Gets the output of another fragment that is connected to n-th input for this fragment. - if the given input is connected to an output, this function returns that output. Otherwise, this function returns NULL. - - the index of the input. - - - - Connects the input to an output. - true if connected, false otherwise. - - the index of the input. - the pointer to an output of another fragment. Please note the fragment system doesn't accept circular connections. (i.e. A is connected to B, B is connected to C, while C is connected to A). - - - - Gets the number of outputs for this fragment. - the number of outputs of this fragment. - - - - - Gets the n-th output for this fragment. - the n-th output for this fragment. - - the index of the output. - - - - Updates the value of the n-th output. - true if updated successfully, false otherwise. - - the index of the output. - the value to update. - - - - Gets a flag for this fragment - true if this flag is on, false otherwise. - - the flag bit to query - - - - Sets a flag for this fragment - - the flag bit to set - the value for the flag bit. - - - - Gets the parent fragment. - the parent fragment. - - - - - Gets the container of all built-in parameters - the container of all built-in parameters. - - - - - The fragment message handling callback function that is called if any of its registered messages (including the timer message) is invoked. - - The message id and parameters of the message that has been invoked. - - - - Gets the timer ticks value in milliseconds. - the timer ticks value if a timer is registered or TIMER_NONE otherwise. - - - - - Register a message with this fragment. - - the id of the message to register - - - - Deregister a message with this fragment. - - the id of the message to deregister - - - - Gets all the messages that have been registered. - all messages that have been registered. - - - - - Gets the class ID of this fragment. - the class ID of this fragment. - - - - - Create an input instance of this fragment. This function is called by InitializeInputs() when initializing inputs. This function could be overridden if a fragment would like to customize its own implementation of fragment inputs. - the input object corresponding to typeID. - - type of the input - - - - Create an output instance of this fragment. This function is called by InitializeOutputs() when initializing outputs. This function could be overridden if a fragment would like to customize its own implementation of fragment inputs. - the output object corresponding to typeID. - - type of the output - - - - This function will be invoked when any fragment flag gets changed. - - the flag that gets changed - the old value of the flag - - - - This function will be invoked when any fragment flag of a sub fragment gets changed. - - the sub fragment whose flag gets changed - the flag that gets changed - the old value of the flag - - - - Do evaluation. A concrete fragment class must override this function, perform necessary computation in this function, and set value to its output. Please note this function cannot be directly called, it can only be called indirectly by calling Fragment::Evaluate(). - true on success, false otherwise. - - context info for evaluation. - - - - is a graph consisting of fragment nodes. A that has inputs and outputs can also be treated as a fragment node. Various kinds of fragment nodes can be combined together to yield arbitrary multi-passes render pipeline. The class provides several utility functions to create and connect fragment nodes. - - - - - Gets the number of nodes - the count of nodes. - - - - - Gets the name of the node given its index - the name of the node corresponding to index. - - the index of the node. - - - - Removes a fragment node given its name - - the name of the node to be removed. - - - - Wires a connection between a specified input of the graph and a specified input of a fragment node. - true if this connection could be established, false otherwise. Successful connection depends on: - - the index of a specified input - the name of the fragment node - the index of a specified input of the fragment node - - - - Wires a connection between a specified output of the graph and a specified output of a fragment node. - true if this connection could be established, false otherwise. Successful connection depends on: - - the index of a specified output - the name of the fragment node - the index of a specified output of the fragment node - - - - Wires a connection between a specified output of a source node and a specified input of a target node. - true if this connection could be established, false otherwise. Successful connection depends on: - - the name of the source node - the index of a specified output of the source node - the name of the target node - the index of a specified output of the source node - - - - Loads input, output and connection information for a fragment graph from an XML file. After loading the XML file, the completes wiring input, wiring output and wiring nodes. - true on success, false otherwise. - - file path name. - - - - Saves the inputs, outputs and connection information of one fragment graph into one XML file. - true on success, false otherwise. - - file path name. - - - - Check if this fragment graph is valid or not - 0 if valid or non-zero otherwise - - - - - This class contains all information that will be passed to Mesh::GenerateRenderItems() or MNMesh::GenerateRenderItems() to update its display data. All the value of this class are set by system and plugin developers should build render items to satisfy those requirements. - - - - - Get the required streams. Required streams is for generating mesh render items. - - - - - Get the count of mesh element descriptions required to be generated from the given mesh - the count of mesh elements. - - - - - Get the i-th mesh element description - the i-th mesh element description. - - the index of the mesh element description - - - - Find the mesh element description based on the given descriptionBits - the required mesh element description if found or NULL otherwise. - - the description bits of the mesh element description - - - - Find the mesh element description based on the given type and mesh part. - the required mesh element description if found or NULL otherwise. - - mesh element type - mesh part - - - - Add a new mesh element description - - the new mesh element description. - - - - Add a built-in mesh element description - - the type of built-in mesh element description - - - - Clear all mesh element descriptions - - - - - Developer may simply call this function when objectComponentRequirements contains the requirements for all the render items that require to be generated. - If you require some additional render items which are usually displayed when mesh is edited in any sub-object level. Please still use AddMeshElementDescription to specify the required mesh element. - - the object component requirements from the update display context. - - - - Developer may simply call this function when updateDisplayContext contains the requirements for all render items and material streams to be generated. - - the update display context - - - - There are some render items which are invisible in a max node by default with regard to the current state of this node. For e.g., selected edges is not visible in an unselected node or digonals is not visible in a node whose ' Only' property is true, etc. Developers may call this function to remove the descriptions of those invisible render items of a given node. - - the render node for which invisible descriptions will be removed - - - - Add some new material required streams to the context. - - the material required streams to add. - - - - Get instance data. - instance data stored in this context - - - - - This is a special render item which used only by Mesh/MNMesh. User can custom a to define what the mesh geometry looks like. and also can generate default render geometry for this render item. - - - - - Get the material id of the render item. - - - - - This is a hit test context class. It contains functions to get/release a special instance, which is used for CPU based hit test. - - - - - Acquire an new HitTest graphics window instance. Application can acquire multiple graphics window instances for multithread algorithm. The graphics window instance can only perform hit test related operation. Any rendering features are ignored. - - - - - Application should always release the instance acquired from AcquireHitTestGW(). Otherwise the context will create an new instance in the next AcquireHitTestGW() call. - - - - - is a material class to support HLSL custom material. This class is used for viewport display and Quicksilver. It's used by RenderItemHandle::SetCustomMaterial() to describe HLSL custom material. It can also be used for realistic material display. see for more details. How to use: - - - - - Initialize an instance of . A should be initialized before it's used. - true if successfully initialized, false otherwise. - - HLSL shader file name. - - - - Initialize an instance of with shader string. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - HLSL shader content. - - - - Initialize an instance of from resource. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - resource ID of the shader - module instance handle - resource block name - - - - Returns the parameter count of material. - the parameter count. - - - - - Returns the description of parameter. - true if successful, otherwise false. - - The parameter index. - The parameter description - - - - Returns the index of parameter. - valid index if successful, otherwise -1 - - The unique parameter name of the parameter. - - - - Sets int parameter. - - The unique parameter name of the parameter. - The int parameter value. - - - - Sets int parameter. - - The parameter index of the parameter. - The int parameter value. - - - - Sets int array parameter. - - The unique parameter name of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets int array parameter. - - The parameter index of the parameter. - The pointer of int array parameter value. - The count of int array. - - - - Sets float parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float array parameter. - - The unique parameter name of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets float array parameter. - - The parameter index of the parameter. - The pointer of float array parameter value. - The count of float array. - - - - Sets bool parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets bool parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets bool array parameter. - - The unique parameter name of the parameter. - The pointer of bool array parameter value. - The count of bool array. - - - - Sets bool array parameter. - - The parameter index of the parameter. - The pointer of bool array parameter value. - The count of bool array. - - - - Sets float4 parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float4 parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float4 array parameter. - - The unique parameter name of the parameter. - The pointer of float4 array parameter value. - The count of float4 array. - - - - Sets float4 array parameter. - - The parameter index of the parameter. - The pointer of float4 array parameter value. - The count of float4 array. - - - - Sets float3 parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets float3 parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets float3 array parameter. - - The unique parameter name of the parameter. - The pointer of float3 array parameter value. - The count of float3 array. - - - - Sets float3 array parameter. - - The parameter index of the parameter. - The pointer of float3 array parameter value. - The count of float3 array. - - - - Sets matrix parameter. - - The unique parameter name of the parameter. - The parameter value. - - - - Sets matrix parameter. - - The parameter index of the parameter. - The parameter value. - - - - Sets matrix array parameter. - - The unique parameter name of the parameter. - The pointer of matrix array parameter value. - The count of matrix array. - - - - Sets matrix array parameter. - - The parameter index of the parameter. - The pointer of matrix array parameter value. - The count of matrix array. - - - - Sets texture parameter. - - The unique parameter name of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The unique parameter name of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The parameter index of the parameter. - The parameter texture handle value. - - - - Sets texture parameter. - - The parameter index of the parameter. - The parameter texture handle value. - - - - Sets buffer parameter. - - The unique parameter name of the parameter. - The parameter or value. Note this buffer should be created with BufferUsageStatic | BufferUsageTarget usage flag - - - - Sets buffer parameter. - - The parameter index of the parameter. - The parameter or value. Note this buffer should be created with BufferUsageStatic | BufferUsageTarget usage flag - - - - Sets map channel parameter. - - The texture coordinate index of shader. - Map channel value of 3ds max. - - - - Sets technique name parameter. - - The active technique name. - - - - Get shader compilation error information. - shader compilation error information. if shader is correct, the length of shader error information is 0. - - - - - is a class which let application render primitives outside the render loop. Application can create this fragment instance like mouse proc, render primitives onto a separate target and then present it to a separate window or draw it to viewport via retain mode. Typical usage should be: renderFrag; renderFrag.Initialize(); if (renderFrag.Begin()) { renderFrag.SetTarget(); renderFrag.Clear(); renderFrag.DrawCallback(); renderFrag.End(); } - - - - - Initialize the handle. Must be called before using it. - true if success. - - - - - Begin a frame Application must call ImmediateFragment::Begin() before any other methods and call ImmediateFragment::End() when rendering is complete. ImmediateFragment::Begin()/End() pair can't nest. If the function return false, other methods also fail and won't do anything. And no need to call ImmediateFragment::End() - - - - - End a frame Application must call ImmediateFragment::End() before calling ImmediateFragment::Begin() again. This method sends jobs to internal render queue. And application must call this method before presenting a target. - - - - - Gets current target. Default target is NULL after ImmediateFragment::Begin(). This method /returns target set by previous SetTarget() function. - - - - - Clear current target by color Internally this method also clears the depth buffer attached with the color buffer. /param[in] color The color after target is cleared. Typically it's . /return true if successfully cleared the target - - - - - Indicates this fragment if using one depth-stencil buffer.The buffer will not be created internally when the fragment is initialized. /param[in] bUse this fragment will use one depth-stencil buffer or not. - - - - - current world matrix. /param matrix new world matrix. - - - - - This class is used to wrap user defined class. Application which needs immediate mode should add this class to mRenderItemHandles in UpdateDisplay() function. - - - - - Initialize the handle. Must be called before use it. - true if success. - - - - - is a memory buffer that contain index data. Index data, or indices, are integer offsets into vertex buffers and are used to render primitives. - - - - - Initialize a index buffer with initial data - true if successfully initialized, false otherwise. - - The type of the newly created buffer. - initial data, can be nullptr - number of indices in this buffer - usage of the buffer - access flag of the buffer - pool state of the buffer - - - - Get the type of the index buffer. - The type of the index buffer as an IndexType - - - - - Get the number of indices of this buffer. - The number of indices - - - - - This function is used for reading/writing data from/into the index buffer. - the buffer for developers to read/write index data. The size of the buffer is numberOfIndices * indexStride. - - the start index that the lock operation starts - the number of indices that this function will lock. - indicate how to operate on the buffer. - - - - Unlock the buffer to update. This function must be called after Lock. Once this function is called, the buffer that returned by Lock become invalid and should not be used any more. - - - - - Gets the buffer usage type. - buffer usage type - - - - - Gets the buffer pool type. - buffer pool type - - - - - Gets the buffer access type. - buffer access type - - - - - Clone the buffer - the cloned buffer handle - - - - - Get start offset of the index buffer. - The offset - - - - - Copy data from another index buffer Note the source buffer format must match this buffer - - the source buffer to copy to this buffer - - - - Copy partial data from source buffer to specified location of this buffer Note both buffer should ensure they have enough space to copy the data - - the source buffer - offset of the source buffer - number of indices to copy - start offset of this buffer - - - - Copy data from hardware buffer to system buffer - true if the data copy is success. Otherwise false. - - true to reserve hardware memory, false to release the memory. - - - - Copy data from system buffer to hardware buffer - true if the data copy is success. Otherwise false. - - true to reserve system memory, false to release the memory. - - - - Class that stores input information for a fragment. An input can only be connected to an output. - - - - - Gets the data source that connects to this input. - the data source that connects to this input. - - - - - Sets the source of this input. This source could be an output from a fragment node or a fragment graph. - true if the type of source is compatible with the type of this input, false otherwise. - - the source of this input - - - - This class is used to manage ActiveShade in a viewport (called ActiveShadeFragment) A view fragment is a part of the viewport drawing system. The view fragments are assembled in a network to form a view graph used by the viewport. The ActiveShade fragment is part of these view fragments and is always present in a 3D viewport. There is only one instance per 3D viewport and it can be enabled, meaning ActiveShade is running in this viewport, or disabled : meaning ActiveShade is not running in this viewport. To get access to a IActiveShadeFragment*, please do : Link your project with ViewSystem.lib. - - - - - Is ActiveShade enabled ? - true if ActiveShade is running in this viewport, false if it is not running. - - - - - Enable or disable ActiveShade in this viewport (meaning respectively run or stop ActiveShade in this viewport) - - a boolean which is true to run ActiveShade in this viewport or false to stop it - - - - Get the ActiveShade fragment resolution multiplier. A multiplier of 0.5 will give a half resolution ActiveShade rendering used and upscaled in the viewport. So a better time performance but resulting in a lower image quality This multiplier has to be a positive, non-zero float number. - the value of the multiplier. - - - - - Get the ActiveShade renderer instance to use for running ActiveShade in this viewport. This can be an ActiveShade renderer taken from the render settings or an instance you have set using SetActiveShadeRenderer(Renderer* pRenderer). - an ActiveShade renderer pointer used by this viewport if the ActiveShade fragment is enabled. - - - - - The interface of a render camera for nitrous viewport. would be required by as the render camera for a custom render stage. - - - - - Get the view matrix of the camera - the view matrix of the camera - - - - - Get the projection matrix of this camera - the projection matrix of this camera - - - - - Get the target distance of this camera - the target distance of this camera - - - - - Get the position of this camera - the position of this camera - - - - - Get the up vector of this camera - the up vector of this camera - - - - - Get the direction of this camera - the direction of this camera - - - - - Is the projection matrix used by a perspective viewport or not - true if the projection matrix is used by a perspective viewport or false otherwise - - - - - This class is used as a key for a hash table. Render items with the same keys will be sent to a consolidation item. Plugins can implement this interface to provide their own consolidation properties. Since this class stores key data to decide which consolidation item a render item belongs to, we don't recommended you put any volatile variables in the key. Furthermore, since GetInterfaceID is the only way to determine the type of a key, if plugins want to implement their own consolidation method for an existing key type, they must inherit the key and provide a new interface ID. Otherwise, the render items may not be sent to the plugin's consolidation item. - - - - - Returns hash key of this consolidation key. Usually the hash key consists of at least the corresponding consolidation item's interface ID for its initial value. - hash key - - - - - Returns the comparison of two keys - true if two keys are the same, false if they're different. - - - - - Returns the class ID that can identify this type of key Keys with different class ID always return false. - the keys' class ID - - - - - Returns a copy of the current key. Note that all members of the new keys should also been copied. You should not share pointers between keys because the life time of a key is managed by Max. The key's dispose time is unknown from the plug-in's perspective. - new copy of the current key - - - - - Same as Equals(), returns the comparison of two keys - true if the two keys are same, false if they're different. - - - - - This class defines a consolidation render item, which is used to improve rendering performance by batching similar render items together. - - - - - This function clears all render items held by the consolidation item. There are many situations that will cause Max call this function, such as adding or removing a render item for a node, moving an object, changing an object's data etc... - - - - - This class defines a strategy to consolidate one type of consolidation key. - - - - - Create a new consolidation item based on the key - a new consolidation render item - - - - - Returns whether this strategy supports immediate consolidation. Standard consolidation works on a 3-seconds-rule. This means a render item will be sent to a corresponding consolidation item after it doesn't change for 3 seconds. Immediate consolidation works on a frame-by-frame basis. It's useful for many small animated objects, such as bones. Rendering these objects is very slow due to poor batching performance. With immediate consolidation, items are sent to a consolidation item immediately after being added to the world. - true if the strategy supports immediate consolidation, otherwise false. - - - - - This class is used to customize the behavior of a render item. It can be set via CustormRenderItemHandle::SetImplementation. The main behavior of a render item is defined in 2 functions: Realize() and Display(). Realize() is called once per frame. It is used to prepare render data for the Display() function. To improve performance, it's recommended to build and store geometry data in this function. You should build vertex streams to at least meet material requirements in the pipeline context. Display() might be called more than once. You should follow material requirements in the pipeline context to draw the geometry. In some cases, the render item may looks different between viewports (for example, billboard). So you may build geometry dynamically in the Display() function. The vertex stream should always follow material requirements in the pipeline context. - - - - - Realize() might be called once per frame. However, if the render item is culled by Max, it won't call Realize() any more. Realize() is designed to build necessary data for the Display() function. Most of the requirement and pipeline states are stored in the PiplineContext. So you should at least build vertex buffers to meet the material requirements. Since this function may be called every frame, it's better to have some cache mechanism to avoid unnecessary geometry rebuilding. - - context of the pipeline. - - - - Display() might be called more than once per frame. Users can get a virtual device or legacy graphics window from the pipeline context. It's your job to activate a material (either from the pipeline context or using a custom material), loop all passes, set the vertex format, set the vertex stream, index and call VirtualDevice::Draw()/DrawInstanced() to render geometries. Always make sure the vertex format should be same as pipeline context's material requirement (if it exists). And the vertex stream layout should meet the format. - - context of the pipeline. - - - - Get the number of primitives in this render item. Sometimes a render item doesn't have an explicit primitive count (such as a procedure item). In these cases, returning a non-accurate count is acceptable. This primitive count is mainly used for BSP cell creation. - number of primitives in this render item. - - - - - This function is called in a hit test pass. All custom render items which use a different render code path need to implement this interface. Users can get hit test information from the and use the draw context to do a hardware hit test. Max uses occlusion query-based hit test. Each render node is associated with an occlusion query. So a typical approach in this HitTest() is call Display() to render the item. Max will get the render result to find out which nodes are hit. - - - - - This function will be called when the render item is hit. Some objects (like cameras) may need special operations rather than selection of the node when specific components are hit. For this scenario, write a separate render item and override the OnHit() function to do the those actions. - - - - - A callback used to render items using . - - - A developer would implement this interface to allow immediate mode drawing of primitives, text and markers. - The display system will query for this interface and the Display method will be called. - The pointer to the should not be stored as its life time is managed by the graphics driver - - - - - A wrapper of DoDisplay() function. This function additional checks if current object is disposed. - - - - - Prototype of user defined render procedure. User should implement this method, and this method is called when rendering. Note: this interface has reference counter, after creation you need to call AcquireInterface, when you want to release it, call ReleaseInterface. - - Current time - Instance of IPrimitiveRender. User can use this class to draw geometries, markers, and texts. - The display context. - - - - A core interface for accessing properties of the graphics library introduced in 3ds Max 2012. The graphics library allows plug-ins to draw into the viewports using a retained mode API. Methods of this class can be used to determine if the graphics driver is running in retained mode which is important when porting plugins that draw into the viewport. - - - - - Plug-ins that have a mesh representation and use Mesh::render() in their implementation of BaseObject::Display() will need to update their display logic in order to appear correctly in the viewport when the retained mode graphics driver is active. If a textured lit mesh is required and IsRetainedModeEnabled() returns true, the calls to Mesh::render() needs to be skipped. If the plugin explicitly sets GW_WIREFRAME or unsets GW_LIT and GW_TEXTURE then the call to mesh::render() can be kept in place. - True if the current viewport graphics driver runs in retained mode. - - - - - Queries whether the system is performing hardware hit testing for a specific viewport. The new viewport graphics system is capable of performing hardware hit testing by rendering all scene objects into a viewport-sized buffer using GPU. For performance sake, plug-ins that have a mesh representation and use Mesh::select() to perform hit testing in their implementation of BaseObject::HitTest need to skip the Mesh::select() call if they already implemented BaseObject::UpdateDisplay to render the mesh in retained mode and IsHardwareHitTesting() returns true. By doing this, plugins can avoid duplicated mesh drawings, and the mesh will be rendered in retained mode, which is significantly faster. - - The specific viewport in which we want to know whether we are performing hardware hit testing. - - - - Get current device caps /param caps reference of a structure /return true if success. Otherwise false. - - - - - Get if the viewport color pipeline is OpenColorIO based - true if the viewport color pipeline is OpenColorIO based, false otherwise - - - - - Get the rendering target format used in viewport color pipeline - one of ColorPipelineTargetFormat enumeration - - - - - This class provide some facility to add some extended behavior to the fixed render pipeline. For e.g., 3rd party developer may specify their own background fragment, shading fragment for the viewport. Also developer could add post-shading fragments and overlay fragments. Post-shading fragments(usually some screen space effects, for e.g., bloom effect or glow effect) are directly evaluated right after the evaluation of shaded fragments. Overlay fragments which are evaluated at last could be some viewport UI overlay or any other elements to be rendered topmost. - - - - - Get the count of post shading fragments added. - - - - - Delete the post-shading fragment with index 'i' - true if succeed or false otherwise. - - the index of the post shading fragment to be deleted - - - - Get the count of overlay fragments added. - - - - - Delete the post-shading fragment with index 'i' - true if succeed or false otherwise. - - the index of the overlay fragment to be deleted - - - - Restore the default background fragment - - - - - Restore the default shading fragment, if you use a ShadingFragment or a Viewport Shading fragment, we will remove it to restore what was originally in the viewport. - - - - - Facilitates translation of material parameter values to their shaders representation. Materials can use programmable shaders to describe their appearance when displayed in the Nitrous viewport and rendered with Quicksilver. Programmable shaders allow for a more realistic and complex visual appearance than does. Besides MetaSL shader ( See and IParameterTranslatorfor more details), 3ds Max 2014 starts to support HLSL shader. - give a proper chance in UpdateHLSLMaterial() to update parameters of - , such as parameter values, map channel values. See for more details. - Plug-ins derive from . They rather need to create instances of . 3ds Max will query the plug-in for its via a request for the interface identified by IHLSL_MATERIAL_TRANSLATOR_INTERFACE_ID. Then get via GetHLSLMaterialHandle() of . Typically a plug-in would implement GetHLSLMaterialHandle of in response to this request and its override of Animatable::GetInterface(Interface_ID) for - The following code snippet illustrates how a material plug-in may implement : - - - - - Update HLSLMaterial parameters - Returns true if successful, false otherwise. - - The time at which to update the plug-in's parameter value - The device's feature level - - - - Get - Returns the . - - The device's feature level - - - - Use this interface to query the per node related render items from a mesh or mnesh. One can directly query this interface from a mesh or mnmesh object. - - - - - This function is usually called by IObjectDisplay2::UpdatePerNodeItems() to get accurate render items specified by generateRenderItemsContext to match the accurate per-node requirements for the current node's specific render items - DO NOT modify any which are returned in targetRenderItemContainer. We cache all internally which could be shared by other render nodes. So modify them directly may cause unwanted behaviors. If you do have a request to modify any , please first manually clone them by using another or a . - true if successful or false otherwise - - contains all the information that is used to generate all the required render items. - which contains all infos required for adding per node relevant render items. - the target render item container. - - - - This interface manages the normal mapping modes that can affect how 3ds Max calculates/interprets the tangent/binormal(bitangent) in vertex/pixel shading level during baking/rendering. This interface is implemented by the system. Plug-ins can get/set the following values on the NormalMappingManager. - - - Usage: 3ds Max to use the mode compatible with Maya to calculate/interpret tangent/binormal(bitangent) 3ds Max to use the mode compatible with MikkT to calculate/interpret tangent/binormal(bitangent), and enable calculate bitangent per pixel flag. - - - - - Get the normal bump mode used by 3dsmax system - the normal bump mode - - - - - Get the tangent basis mode used by 3dsmax system - the normal bump mode - - - - - Get the parameter name of Orthogonalize Per Pixel flag - the name of Orthogonalize Per Pixel flag - - - - - Get the flag indicating if Orthogonalize Per Pixel is enabled or disabled - True if Orthogonalize Per Pixel is enabled, False otherwise. - - - - - Get the parameter name of Calculate Bitangent Per Pixel flag - the name of Calculate Bitangent Per Pixel flag - - - - - Get the flag indicating if Calculate Bitangent Per Pixel is enabled or disabled - True if Calculate Bitangent Per Pixel is enabled, False otherwise. - - - - - FileIO(Internal Use Only) - - - - - FileIO(Internal Use Only) - - - - - To give object plugins better control of display, now object plugins can expose interface. This interface allows object plugins to provide different RenderItem for different nodes and different views. - If an object plugin provides both and IObjectDisplay interface, only will be used. IObjectDisplay interface is still supported by Nitrous, however, we don't suggest plugins to use it anymore. In the future it will be obsoleted. - - - - - Return the object display requirement of this object. - - - - - An object could be referenced by multiple nodes at the same time, while different node may requires different display of the object (backface cull vs. non-backface cull, vertex color shading vs. material shading, etc.). IObjectDisplay2::PrepareDisplay gives object plugins a chance to prepare display data for all nodes, thus avoid duplicate display data generation for each node or each view. If an object contains a or and wants to display it, then Mesh::PrepareDisplay or MNMesh::PrepareDisplay must be called in this function. - true if prepare successfully, false otherwise. - - The display context, which contains all the requirements for plugin to generate render items. - - - - This function will be called for each owner nodes of a given object plugin. Plugins can follow the input node properties, and create appropriate RenderItem. For example, if an object wants to display high-resolution mesh when node is selected, and display low-resolution mesh when node is not selected, it can use this function to create different DisplayItem for different notes. - true if successful or false otherwise - - The display context, which contains all the requirements for plugin to generate render items. - which contains all information required for adding per node relevant render items. - the target render item container to which this plugin object will be added. - - - - This function will be called for each viewport and for each owner nodes of a given object plugin. If plugin wants to display / hide certain RenderItem for a given view property, plugin can override this function and update RenderItem based on the input view properties. - that this function is optional. If plugin doesn't have view-dependent RenderItems, it doesn't need to override this function. - true if the plugin has updated any render items for hTargetNode or false otherwise. We STRONGLY suggest return false for performance sake when no any render item has been actually updated. - - The display context, which contains all the requirements for plugin to generate render items. - which contains all information required for adding per node relevant render items. - the view for which render items will be updated - the target render item container to which this plugin object will be added. - - - - Facilitates translation of material and texture map parameter values to their shaders representation. Materials and texture maps can use programmable shaders to describe their appearance when displayed in the Nitrous viewport and rendered with Quicksilver. Programmable shaders allow for a more realistic and complex visual appearance than does. Note that 3ds Max 2012 only supports MetaSL shaders. See for more details. - The Nitrous graphics system handles automatic translation of Paramblock2 based material and texture map parameters given that their names and types match those of the shader. allows plug-ins to control this translation process. Nitrous queries the plug-in for the interface by passing IPARAMETER_TRANSLATOR_INTERFACE_ID to its overwrite of Animatable::GetInterface(Interface_ID), and uses it instead of its own automated translation. Nitrous automatically detects when a plug-in's parameters, reference structure or animatable structure changes, and will call the methods on this interface to re-translate the plug-in's parameters to the shader. - The following code snippet illustrates how a material plug-in may implement : - - - - - Retrieves the plug-in's parameter value that corresponds to a given shader parameter. - Returns true if the plug-in parameter value was retrieved successfully, false otherwise. - - The time at which to retrieve the plug-in's parameter value - The name of the shader parameter. The name is not case sensitive. - Pointer to a data structure that will store the plug-in's parameter value. This parameter will need to be cast to one of the supported types - see ShaderParameterType - The type of the shader parameter - - - - Retrieves the shader input parameter name for a given "sub" slot of the plug-in. The plug-in need to "compute" the name of the input shader parameter that corresponds to a given "sub" slot identified by its slot index and type. Nitrous will connect the shader corresponding to material or texture map at that "sub" slot with the shader input parameter that has the name this method generates. - true if the shader name was successfully generated, false otherwise. - - The type of plug-in's "sub" slot - The index of the "sub" slot within the plug-ins list of slots - The shader input parameter name - - - - One time setup before any parameter is translated. Called once before the parameter list is parsed. This could be used to make sure all parameters are valid before being translated. - If it returns false, the translation does not take place. - - - - - The interface for filtering per viewport. - - - The clients can access this interface to query if a node is filtered by a viewport. All methods of this class are implemented by the system. - - - - - This class is used to draw simple primitives, markers, text with given material and transformations. - - - Description - The class provides various ways to draw objects. Many functions are self contained and handle much of the code for you by using , whilst others give you complete control over how the primitive is drawn. For example DrawPrimitive() allows the developer to create vertex and index buffers and define the actual vertex format to be used by providing a StreamFormatHandle which provides formating information for vertex data like Position, UVs and Normals. - This class is running in graphic driver's thread. So sharing data between max thread and driver thread should be designed carefully ensuring thread safety. Users can get an instance of in IDisplayCallback::Display(). - - - - - This method gets current row-major world transform matrix - current world transform matrix - - - - - This method gets current row-major view transform matrix - current view transform matrix - - - - - This method gets current row-major projection transform matrix - current 4x4 projection matrix - - - - - This method gets current viewport rectangle - current viewport - - - - - This method gets current depth range - current depth range - - - - - This method sets current viewport rectangle and depth range - - viewport area - viewport depth range, x is near plane(default 0), y is far plane(default 1) - - - - This method clears screen - - the element to clear (Target | Stencil | ZBuffer) - the Target's clear color - the value of depth buffer after clear - the stencil value after clear - - - - This method clears sub-region of screen - - upper left of clear rect - bottom right of clear rect - the element to clear (Target | Stencil | ZBuffer) - the Target's clear color - the value of depth buffer after clear - the stencil value after clear - - - - This method draws indexed primitives to screen, warning : primitive restart is not supported, you will need several calls to handle this - - type of primitive (line, triangle) - the primitive data pointer. In system memory. - the number of primitives. - the vertices index array A index array stores a lot of integers. Which indicates how the primitive been constructed. For example, a triangle list index "0, 2, 5" means vertex v0, v2 and v5 consist one triangle. A line strip index "0, 3, 1" means vertex v0, v3, v1 consist two lines: one is v0-v3, the other is v3-v1. - size of the index buffer - - - - This method draws primitives to screen - - type of primitive (point, line, triangle) - the primitive data pointer. In system memory. - the number of primitives. - - - - This method draws primitives based on the current vertex and index buffers - - type of primitive (point, line, triangle) - the 1st primitives vertex position in vertex buffer - the number of primitives. - - - - This method draws multiple primitives instance from vertex buffer and index buffer. The instance data should be saved in one of the vertex streams. For example, the layout of transform instance stream should be: When drawing the primitives, each instance's matrix will apply to the primitive. So you can draw multiple instances in one call. - - type of primitive (point, line, triangle) - the 1st primitives vertex position in vertex buffer - the number of primitives. - the number of instances in the stream - - - - Draw a given render item. - - the current display context. - the render item to be draw. - - - - This method draws a quad covering the entire current target set - - z value of this quad - - - - This method draws a string at given world position - - world position of the string - the text - - - - This method draws a string at given screen position (upper left is the origin) - - screen position of the string - the text - - - - This method should be called before AddMarkers. It can be used to draw markers. The system will create the appropriate buffer which will be filled up with calls to AddMarker - True if successful. - - - - - This allows drawing batches of markers at a time. - - Only call this function between BeginMarker and EndMarker pair - True if successful. If false, then the buffer has potentially overflowed. Try using EndMarker and start another sequence - - Marker type - Pointer to a buffer which contains marker's position in world space - of markers - Marker's color - - - - This allows drawing batches of screen-space markers at a time. - needed to be drawn. - Only call this function between BeginMarker and EndMarker pair - True if successful. If false, then the buffer has potentially overflowed. Try using EndMarker and start another sequence - - Marker type - Pointer to a buffer which contains marker's position in screen space. z value's range is [0, 1]. "0" is front most and "1" is back most. It is used for comparing depth with other geometries. - of markers - Marker's color - - - - Ends the marker drawing sequence. This will draw and flush the internal buffers. - - - - - This method sets current material used by DrawPrimitive and DrawIndexedPrimitive - - the new materials' pointer - - - - This method gets current material - current material handle - - - - - This method sets vertex buffers used by DrawPrimitive - The number of steams is set by the StreamFormatHandle - - number of vertex buffers, range is 0 to max number of streams - 1 - vertex buffer array - - - - This method sets index buffer used by DrawPrimitive - - A pointer to the index buffer object - - - - This method retrieves current render states object. allows the developer to set various graphics states, whilst performing state management. - A reference of object - - - - - This method retrieves current virtual device object. allows the developer to set depth-stencil state,rasterizer state and blend state. - A reference of object - - - - - This class is similar to IUnknown in COM. - A class that implements interface means that an instance of that classes can be shared by multiple owners. Each owner holds a reference to that instance. Once an owner doesn't need that instance, Release() of that instance must be called by the owner and then the reference count of that instance will be decreased by one. - An instance of such class will be deleted automatically if its reference count is zero. - - - - - increase reference count of this object by one - increased count - - - - - decrease reference count of this object by one, if the decreased reference count equals zero, the object will be deleted. - decreased count - - - - - Get reference count of this object - count - - - - - Try query an interface from the ref object using a given interface id. - a pointer to the desired interface if this interface exists or NULL otherwise. - - the id of the interface type to query - - - - is a representation of a geometry. - - - - - This function might be called multiple times in a frame, such as when we use shadow maps. Inherited classes need to use in the pipeline context to render the geometry. It's recommend to prepare the geometry data in another function like the constructor, and only do rendering tasks in the Display() function. Furthermore, sub-classes are not allowed to change current material parameters. So for multiple material instance, you should use multiple render items to store them. Note: the vertex buffers' format must match current stream requirement in pipeline context. /param drawContext the context for display /param start start primitive to render /param count primitive count to render /param lod current lod value from adaptive degradation system - - - - - Get the type of primitives in the geometry. /return the geometry's primitive type - - - - - of primitives the mesh represents. /return geometry's primitive count - - - - - of vertices in the mesh. /return number of vertices in the mesh. - - - - - Get start primitive of this geometry. - The index of the start primitive. - - - - - Get the stream requirement of this render geometry. To optimize performance, it's better to create a requirement-geometry mapping. And make the render geometry read-only after created. - the stream requirement which this geometry built with. - - - - - Get index buffer of this geometry. - index buffer of this geometry. Might be invalid if the geometry doesn't need index buffer - - - - - A render item container, it provides various methods to access the contained render items. - - - - - Get the number of render items contained in this container. - the number of render items contained in this container. - - - - - Get the i-th render item in this container. - the i-th render item in this container. - - the index of the render item to be retrieved. - - - - Find a render item with the specified mesh element description. - the render item with the mesh element description. - - the unique ID associated with the specified mesh element description. - - - - Find all render items with the specified mesh element description. - the render item array with the mesh element description. - - the unique ID associated with the specified mesh element description. - - - - Add a render item into this container. - - the render item to add. - - - - Add all render items from the specified render item container into this container. - - the render item container that the render items in which would be added into this container. - - - - Remove the render item with the specified index from the container. - - the index of the render item to be removed. - - - - Remove all render items from this container. - - - - - controls primitive renderer's current render style. It defines set-up states for all kinds of vertex and pixel processing. Some render states set up vertex processing, and some set up pixel processing. This interface is acquired from IPrimitiveRenderer::GetRenderStates() - - - - - Get alpha blend status - - - - - Get source element - - - - - Get destination element - - - - - Get alpha blend method - - - - - Get source element - - - - - Get destination element - - - - - Get alpha blend method - - - - - Get blend factor - - - - - Get polygon cull method - - - - - Get current polygon fill method - - - - - Get current point size - - - - - Get current depth culling status. - - - - - Get compare function - - - - - Get current depth write status - - - - - Push all render states into internal stack. You can then change the states and restore them by calling PopRenderStates. If there's only a few states to change, it's better to manage them by yourself. - - - - - Restore render states to internal stack's topmost render states and pop it out of stack you can use this function to restore previous pushed states. - - - - - Apply current render states to real render device. - - - - - This class is a representation of a render view which provides some common functions to manipulate a viewport. For e.g., invalidate or render the view port, save or load the view fragment graph etc.,. To get access to a instance, please call ViewExp18::GetRenderView() - - - - - Load the view fragment graph from a specified xml file - true if succeed or false otherwise. - - the file name of the xml file - - - - Unload the view fragment graph - true if succeed or false otherwise. - - - - - Save the view fragment graph to a specified xml file - true if succeed or false otherwise. - - the file name of the xml file - - - - the render view's width and height - - the width of the view - the height of the view - - - - Get the render view's width - the width of the render view. - - - - - Get the render view's height - the height of the render view. - - - - - Get the render region of the render view. - the render region that includes the scales,clipping rectangle and offset of the original render target in the screen space of the render view. - - - - - provide the access to with which 3rd party developer can add some extended behavior to the fixed render pipeline. For e.g., - developer may specify their own background fragment, shading fragment for the viewport. Even developer can override the current view whole fragment graph with a customized fragment graph. To get access to a instance, please use ViewExp18::GetRenderView(). - - - - - the override view fragment graph for the current viewport. - true if a new override graph is assigned to the render view or the render view succeed to restore the default fragment graph. Or false otherwise. - the override graph must have at least one output(with output index 0) whose type id must be PresentableTargetHandle::ClassID(). Or false would be returned. - - when pGraph is a non-null-pointer, it will override the default fragment graph or an existing override graph of the render view. When pGraph is a null-pointer, the render view will restore the default fragment graph. - - - - Get the override view fragment graph for the current viewport. - - - - - Get the fixed viewport render pipeline instance for the current viewport. - use to add extended fragments to the current viewport render pipeline. - - - - - Represents the programmable shader associated with a material or texture map plug-in. Materials and texture maps can use programmable shaders to describe their appearance when displayed in the Nitrous viewport and rendered with Quicksilver. Programmable shaders allow for a more realistic and complex visual appearance than does. Note that 3ds Max 2012 only supports MetaSL shaders. - Plug-ins do not need to derive from . They rather need to create instances of it using IShaderManagerCreator::CreateShaderManager(), one for each shader they support. 3ds Max will query the plug-in for its via a request for the interface identified by ISHADER_MANAGER_INTERFACE_ID. Typically a plug-in would create an instance of in response to this request in its override of Animatable::GetInterface(Interface_ID) and delete it in its destructor by calling IShaderManagerCreator::DeleteShaderManager(). The following code snippet illustrates how a plug-in manages its instance: - The parameters of the shader need to be fed with values from the parameters of the material or texture map plug-in. This process is facilitated by class that plug-ins need to implement. - - - - - Retrieves the shader's type. - - - - - Retrieves the shader's class name. - - - - - Retrieves the fully qualified path of the shader file. - - - - - Factory class for objects. and texture map plug-ins based on programmable shaders need to create an for each of the shaders they use. The plug-in is responsible for destroying the instance. Call IShaderManagerCreator::GetInstance() to access the sole instance of . - - - - - Creates an object based on a programmable shader. Currently only MetaSL shaders are supported. A MetaSL shader's code is stored in a file. The shader itself has a type and a class name. The plug-in is responsible for the life-time management of the instance created by this method. - A valid instance, or NULL in case of an error such as when the specified shader file is not found. See for a code example of how to use this method. - - The type of the shader. Currently only MetaSL is supported. - The shader's class name. - Fully qualified file path of the file that stores the shader's code. For a MetaSL shader this must be an xmsl file. - A pointer to the material or texture map plug-in the is created for. - - - - Deletes an instance. and texture map plug-ins that created instances need to call this function in order to delete them properly. - - the instance of . - - - - provides any material or texture plugin the ability to display itself in the new Viewport Display system in 3ds Max 2012. supports fast efficient handling of a basic phong style shader. It supports all the usual surface elements like Diffuse, Specular with the added ability to support two input textures for diffuse and opacity. If a developer needs finer control over the visual appearance of the material then they should look to use the Advanced mode graphics API - A developer typically would not need to worry about many of the methods in the class as the viewport display system will translate the host material calling MtlBase::GetDiffuse() and then using ISimpleMaterial::SetDiffuse to update the display definition. - Every material and texture map will have an available as it is added as a property of the . To access the property use the following code The only aspect of the material setup that is not fully automatic is the allocation of textures. In general materials have a more complicated requirement for texture display. An example would be diffuse and opacity display with different mapping channels. Texture plugins on the other hand tend to be more simplistic. However, there are examples of a more complex setup as can be seen with the mix or composite maps. To support these more complex setups the developer must implement and implement SetupTextures. SetupTextures is called when ever a change in the material or texture is detected by the system. It is in this method the developer should assign the texture using SetTexture. This method also provides a chance to override the automatic translation of the material parameters, however, it is not a requirement. If is not implemented the translation code will use GetActiveTexHandle() to access the texture resource, this is how texture maps such as Checker work. - also allows the material to define a draw style such as whether it is a solid or wireframe. During translation the materials requirements will be checked. For example the standard material can be forced into wireframe mode. The translating code would look like this is used to provide quick and approximate representations of materials in the viewport. More realistic material representations can be created by writing custom real-time shader using the advanced mode graphics API - All of the methods of this interface are implemented by the graphics driver layer, it is not designed to be derived by plug-ins. - - - - - Clones the instance of . - a pointer of new cloned . - - - - - Returns the fill mode that the material is using. - the fill mode. - - - - - Returns ambient color that the material is using. - the ambient color. - - - - - Returns diffuse color that the material is using. - the diffuse color. - - - - - Returns specular color that the material is using. - the specular color. - - - - - Returns Emissive color that the material is using. - the Emissive color. - - - - - Returns specular power that the material is using. THe power value can be in the range of 0.0f and 1.0f - the specular power. - - - - - Returns specular level that the material is using. - the specular level. - - - - - Returns self illumination mode that the material is using. - the self illumination mode. If TRUE, the SelfIllumColor is on. - - - - - texture transform matrix - true if successful - - The texture usage - The transform matrix - - - - Get texture transform matrix - the texture transform matrix - - The texture usage - - - - texture with texture handle. - True if successful - - A texture handle. If pTexture is NULL it will clear the texture. This can give finer control than using - The texture usage - - - - Get texture handle - A pointer to texture handle - - The texture usage - - - - Clears all texture used by this material - - - - - Sets the border color as an RGBA value for the texture with the specified texture usage. - True if successful - - The texture usage - The border color - - - - Returns the border color of the texture with the specified texture usage. - the border color - - The texture usage - - - - extends to support more textures. To distinguish from a texture, a texture here is called a 'stage texture'. It is like D3D SetTextureStageState. To access the property, use the following code - - - - - Returns the maximum number of texture stages that 3dsmax system supports. As of 3ds Max 2016, a maximum of 8 textures stages is supported. - maximum number. - - - - - number of texture stages. - True if successful - - number of stage. - - - - Returns the number of texture stages. - the number of texture stages. - - - - - stage texture with texture handle. - True if successful - - The stage texture index. - A texture handle. If pTexture is NULL it will clear the texture. This can give finer control than using - - - - stage texture color operation. - True if successful - - The stage texture index. - color operation. - - - - This interface enables material and texture map plugins to display textures in the new viewport display system in 3ds Max 2012. Developers override the ITextureDisplay::SetupTextures() method to assign a texture resource to the managed by the material or texture map plug-in. - In general materials have a more complicated requirement for texture display. An example would be diffuse and opacity display with different mapping channels. Texture plugins on the other hand tend to be more simplistic. However, there are examples of a more complex setup as can be seen with the mix or composite maps. To support these complex setups a plugin must implement , otherwise during translation GetActiveTexHandle() will be called. - The texture resource is represented by the class and can be created using TexHandleMaker::CreateHandle(). - The instance lifetime is managed by the plugin. If the texture data managed by a plug-in (e.g. texture related parameters) becomes invalid then the plug-in must deleted the and to call ISimpleMaterial::ClearTextures(). It is possible to clear a single texture resource by calling SetTexture() with NULL and the appropriate map usage. - See Stdmtl2.cpp for an example implementation of SetupTextures() - - - - - Allows for setting up the textures of a . The automatic translation of material and texture map plug-ins can be complemented by implementing this method to setup the texture maps of a material or texture map plug-in by calling ISimpleMaterial::SetTexture(). This method can also override in its implementation the automatic translation of all material parameters (diffuse color, etc). - Texture map plug-ins should only setup their textures with ISimpleMaterial::SetTexture as they are displayed without lighting or other surface details. Texture maps assigned to a will be used by both the viewport and the hardware renderer. This method is called by 3ds Max when the parameters of a material or texture map change. - - The time at which the textures need to be setup - the helper object that needs to be used to update the display representation of the textures - - - - is a map structure that contains key/variable pairs. We use this class to store some built-in parameters for and Graph. Every built-in parameter is given with a name as the key. - - - - - Checks if the dictionary has the given key. - true if this variable is a dictionary and has that key, false otherwise. - - the key to check. - - - - Finds the value of the given key. - the variable that is associated with that key. Returns NULL is no matching variable is found. - - the key to check. - - - - Finds or creates a key-variable pair, and returns the reference to the given key. - reference to the variable that is associated with that key. If the key does not exist in the dictionary, this creates the key-variable association and returns the newly created variable. - - the key to find or create. - - - - Removes a key. - true if removed successfully, false otherwise. - - the name of the key to remove. - - - - Clear all key/variable pairs. - - - - - Gets the number of keys. - the count of all keys, 0 if no key. - - - - - Gets one key by using the index - one key, or empty string if no index matches. - - the index of this key in the container. - - - - Gets one variable by using the index - one variable, or one int type variable if no index matches. - - the index of this variable in the container. - - - - This class is a representation of a basic view. - - - - - is used to manage the view fragment graph for viewports. The developer can get access to this CORE interface by using - - - - - Get the ActiveShade fragment from the active viewport. - a pointer or nullptr is something failed for some reason, such as you are querying this ActiveShadeFragment on a viewport that is not a 3D viewport. - - - - - Get the ActiveShade fragment from a given viewport . - a pointer or nullptr is something failed for some reason, such as you are querying this ActiveShadeFragment on a viewport that is not a 3D viewport. - - - - - Get the default custom shading fragment class ID. - a classID which is not if the default custom shading fragment has been set. - - is true if the default fragment also handles wireframe views or false if it does not. - - - - a default custom shading fragment class ID that will replace the default illuminance/shading fragment in all viewports. This fragment gets blended with the others fragments automatically. The color target should contain an alpha layer, which can be opaque, but we use alpha blending so it should always contain an alpha layer. Your fragment must have 2 inputs which are in that order : the color target and the depth target, it must have 2 outputs in that order the color and the depth target. All inputs and output should be a TargetHandle::ClassID(). The color and depth input targets are empty, set at the good format for the viewport and need to be filled by your fragment. If you need call this via Maxscript, please use NitrousGraphicsManager.SetDefaultViewShadeFragment classIdPartA classIdPartB bUseSameFragmentForWireframeViews - true if succeed or false otherwise. - - the customized shading fragment class ID - should be true if your fragment also handles wireframe views or false if it does not and we will use the default wireframe fragment in that case. - - - - Remove any default custom shading fragment class ID previsouly set. If you need call this via Maxscript, please use NitrousGraphicsManager.ResetDefaultViewShadeFragment() - - - - - Viewport Setting For The Nitrous Graphics Viewport. - - - To access this interface from a object, please call ViewExp::GetInterface(IVIEWPORT_SETTINGS_INTERFACE_ID). - - - - - Get the enable state of progressive rendering - true if enabled or false otherwise - - - - - Get the state of showing edged faces - true if edged faces is on or false otherwise - - - - - Get the state of 'use texture' - true if use texture or false otherwise - - - - - Get the state of 'display selected with edged faces' - true if this option is on or false otherwise - - - - - Get the state of show selection brackets. - true if this option is on or false otherwise - - - - - Get the state of shade selected edged faces. - true if this option is on or false otherwise - - - - - Get the state of viewport disable - true if viewport is currently disabled or false otherwise - - - - - Get the state of viewport clipping - true if this option is on or false otherwise - - - - - Get the state of use environment background color - true if this option is on or false otherwise - - - - - Get the state of use viewport background - true if this option is on or false otherwise - - - - - Enable/Disable show highlight. - - - - - Get the state of show highlight - true if this option is on or false otherwise - - - - - Get the viewport visual style of current viewport - the visual style - - - - - Get the state of shade selected objects - true if this option is on or false otherwise - - - - - Get the state of auto display selected light - true if this option is on or false otherwise - - - - - Get the enabled state of ambient occlusion - true if ambient occlusion is enabled or false otherwise - - - - - Get the state of display shadow - true if shadow is on or false otherwise - - - - - Get the state of degrade to default lights - true if this option is on or false otherwise - - - - - Get the state of draw backfaces - true if this option is on or false otherwise - - - - - Get the state of never degrade geometry - true if this option is on or false otherwise - - - - - Viewport Setting For The Nitrous Graphics Viewport. - - - To access this interface from a object, please call ViewExp::GetInterface(IVIEWPORT_SETTINGS_2_INTERFACE_ID). - - - - - Get the enabled state of Bloom effect - true if Bloom is enabled or false otherwise - - - - - Get the Bloom tint color, using a instead of because we want float components for r,g,b - - - - - Get the Bloom tint contribution (multiplier applied on the tint color) - - - - - Get the Bloom Threshold - - - - - Get the Bloom ThresholdSmoothing, is the size of the window to smooth the threshold with a smoothstep function with float brightness = smoothstep(Threshold, Threshold + ThresholdSmoothing, pixelLuminance) - - - - - Get the Bloom Strength (multiplier on the Bloom effect) - - - - - Get the Bloom Radius, is the number of mipmaps (smaller sub-textures) used to create the blur effect, the more mipmaps there is, the larger and smoother is the effect - - - - - Get the Bloom quality as an enum - - - - - Get the enabled state of Bloom dirt map - true if Bloom dirt map is enabled or false otherwise - - - - - Get Bloom dirt map as an image filename This will return the string for the bitmap that was set from the UI or by Maxscript, which could be a relative or full path filename. We use the asset manager to try to resolve the path if it is relative. - - - - - Get Bloom dirt map as an image full path filename This will return the full path filename of the bitmap or "" if the bitmap doesn't exist on this machine or hasn't been set The result is cached in a local string so the resolution of any relative filename is not done for every call. - - - - - Get Bloom dirt map contribution (multiplier applied on the dirt map) - - - - - Get if Bloom is applied on the background or not - - - - - Get, if instead of the resulting color buffer with bloom applied, we want to display only the bloom pass (w/o the dirt map applied) If GetBloomShowFilterPass() is true or GetBloomShowRadiusPassNumber() is not -1 then SetBloomShowBloomPass is ignored, as the 2 previously mentioned parameters will overwrite GetBloomShowBloomPass - - - - - Get, if instead of the resulting color buffer with bloom applied, we want to display only the filtering pass If GetBloomShowRadiusPassNumber() is not -1 then SetBloomShowFilterPass is ignored, as the previously mentioned parameter will overwrite SetBloomShowFilterPass - - - - - Get, if instead of the resulting color buffer with bloom applied, we want to display only the n-th radius pass (mipmap sub-texture). A value of -1 means we show the result and not any of these radius passes, if the value is greater than GetBloomRadius() then this is ignored. - - - - - Get the enabled state of automatic mode in viewport color pipeline - true if automatic mode is enabled or false otherwise - - - - - Get if viewport color pipeline affects background or not - true if viewport color pipeline affects background or false otherwise - - - - - Get scene linear exposure value to be applied in viewport color pipeline - scene linear exposure value to be applied in viewport color pipeline - - - - - Get post display gamma value applied in viewport color pipeline - post display gamma value applied in viewport color pipeline - - - - - Get color view transform applied in viewport color pipeline - view color view transform applied in viewport color pipeline - - - - - Get display name applied in viewport color pipeline - display name applied in viewport color pipeline - - - - - Get rendering color space name applied in viewport color pipeline - rendering color space name applied in viewport color pipeline - - - - - This class provides low level access to the GPU device. It wraps the variable 3D API into an unified interface. This means you do not need to know whether the real device is actually Direct3D9, Direct3D11 or OpenGL. Similar to the device interface in Direct3D, this interface provides rendering functions such as Draw() and DrawInstanced(), and resource functions like SetVertexStreams(), SetIndexBuffer() and so on. You can also change render states via Get/SetBlendState(), Get/SetRasterizerState(), and Get/SetDepthStencilState(). For example, to change the Z-Bias of the next draw call, use RasterizerState::SetDepthBias() or RasterizerState::SetSlopeScaledDepthBias(). - For an example of code that implements this interface, see the sample project in howto/Graphiccs/GPUParticle. - Typical usage of stream-out data may look like this: - - - - - Returns the thread id of the virtual device. - Return 0 for DirectX9, the real thread id for DirectX11. - - - - - Gets the status of the device. Note: When IsValid is false, all device-related resources may be invalid. Sometimes plugins may attempt to dispose after Nitrous has already done so. At this time, any calls to device resources may cause a crash. Therefore, plugins should check this flag to make sure the device is valid before releasing the resources. - true if the device is valid. false if not. - - - - - Begins a frame draw. Should be paired with EndFrame(). Brackets sets of drawing calls, only 1 level deep allowed. - - - - - Ends a frame draw. Should be paired with BeginFrame(). - - - - - Begins a scene draw. Brackets sets of drawing calls. Only 1 level deep allowed. - - - - - Ends a scene draw. - - - - - Gets the current rasterizer state. - The rasterizer state handle. - - - - - Gets the current depth-stencil state. - The depth stencil state handle. - - - - - Gets the current blend state. - The current blend state handle. - - - - - Gets the pixel coordinate viewport for the drawing. - The viewport's {0,0,w,h}, or {0,0,0,0} if no target is defined. - - - - - Gets the depth range. - The depth range, normally between 0.0 to 1.0. - - - - - Gets scissor box in pixels. - The scissor box. The default value is the current render target size. - - - - - Gets the number of vertex buffer streams. - The current number of active streams. - - - - - Gets the specified vertex buffer stream. - The vertex buffer handle at nStream. - - The stream index of the vertex buffer. - - - - Gets the number of current output vertex buffer streams. - The number of current output vertex buffer streams. - - - - - Gets the specified output vertex buffer stream. Note: this function only works for DX11 devices. - The vertex buffer handle at output nStream. For dx9 devices (feature level < LEVEL_4_0), an invalid handle is returned. Use VertexBufferHandle::IsValid() to check the validity. - - The index of the stream. - - - - Sets the render target at index 0. - - A pointer for the render target handle. - A pointer for the z buffer handle. The size of zBuffer must be equal to or larger than the target. Can be . - - - - Gets the specified render target - The target handle. The handle might be invalid if the corresponding index doesn't exist. - - The index of the target. For DX9, the maximum number of the index is 4, for DX11, it's 8. - - - - Gets the current render target count. - The current target count. - - - - - Gets the current z buffer. - The current z buffer. The handle might be invalid if the z buffer doesn't exist. - - - - - Gets the current index buffer. - The current index buffer handle. - - - - - Draws part of a set of primitives. - - The primitive type. - The start vertex index in the current vertex buffer. - The number of primitives to draw. - - - - Draws part of a set of primitives with an instance. Note: you need call VertexBufferHandle::SetInstanceCount() to set the instance count of the instance data stream. - - The primitive type. - The number of instances. - The start vertex index in the current vertex buffer. - The number of primitives to draw. - - - - Performs a full clear: target( nTargets ) to a given color, z to a given z, stencil to a given stencil. The target (or MRT targets), instead of the viewport, is cleared. The clear operation is not affected by the scissor box. - - The components to clear. - The color after the clear. Available when or is set. - The z value after the clear. Available when or is set. - The stencil value after clear. Available when or is set. - - - - Performs a partial clear: a sub-region of the target/z/stencil is cleared. The region is clipped to the bounds of the viewport rectangle, and the clear operation is not affected by the scissor box. - - The region to clear. - The components to clear. - The color after the clear. Available when or is set. - The z value after the clear. Available when or is set. - The stencil value after the clear. Available when or is set. - - - - Clear a Unordered Access target with initial value. This API wraps DX11 API, it works on FLOAT, UNORM, and SNORM unordered access views (UAVs), with format conversion from FLOAT to *NORM where appropriate. - - uav buffer to clear - 4 unsigned int values to copy to corresponding UAV's RGBA channels. - - - - This class is used for describing the mesh stream requirements of a material. By default, 3ds Max automatically generates for all materials. However if a material plugin wants to provide customized hardware shaders, it must - provide a as well. Other plugins like the object plugin, will provide render items that suffice the requirement. - We create this class for two reasons: - First, a mesh contains a lot of channels however a material may be interested in a few channels of that mesh (eg. Position and the first texture coordinate channel). Converting a mesh channel to vertex buffer is a time and memory consuming job, therefore the material provide a to indicate which channel is used by the material to minimize the number of vertex buffers we created. - Second, after we converted mesh channels to vertex buffers, it is necessary to indicate details like how is the vertex buffers are organized in hardware streams and the usage index of the channels. The usage index is used by hardware shaders of the material to differentiate the channels with the same type and usage. For example, if a material wants uv map channel 99 be treated as TEX0 in hardware shaders and uv map channel 32 may be treated as TEX1. Then the following code may be necessary: - - - - - Remove all streams from this requirement. - - - - - Add a stream to this requirement. Simply return existing stream index if the stream to be added is already in the array. - the newly added stream index, or the existing stream index. - - the stream element to add. - - - - Find the index of a stream element - the index to the found element, if not found, returns (size_t)-1 - - the element to find - - - - Remove the stream element specified by the given index from this requirement. - - the index to the stream element. - - - - Get the number of streams of the requirement. - the number of streams. - - - - - Get the field of the i-th stream. - the field of the i-th stream. - - the index to the stream. - - - - Compare two . - 1 if this object is greater than rhs, -1 if this object is less than rhs, zero otherwise. - - the "right-hand-side" of the compare function. - - - - Get extra flags of this requirement. The extra flag should be a combination of MaterialRequirementFlags. - the extra flags. - - - - - Swap another with this one - - another . - - - - Get the max material ID of a multi-sub material. - the max material ID of a multi-sub material. Default value is 0. - - - - - Application can use this class to create a render target in memory which can be a target input/output for a fragment node. - - - - - This class describes a single mesh element(which corresponds to a render item) required to be generated by calling Mesh::GenerateRenderItems() or MNMesh::GenerateRenderItems() from the specified mesh(or mnmesh). - - - - - Get the type of this mesh element. - the mesh element type. - - - - - Get the part of this mesh element. - the mesh part. - - - - - Get whether to shade the mesh element in soft selection color. - true if shaded in soft selection color or false otherwise. - - - - - Get whether the mesh element requires its back faces to be culled. - whether to cull the back face. - - - - - Get the description bits of this element description. This value is a combination of all member values on bit base and corresponds to a specific type of mesh element description. Developers may use it to query a render item from an . - the description bits corresponding to this element description - - - - - Class that stores output information for a fragment. An output can be connected to multiple inputs. - - - - - Gets the number of connected inputs. - the number of connected inputs. - - - - - Gets the i-th connected input. - pointer to the i-th connected input. - - the index of the input connected to this output class. - - - - Gets the variable that stores in the output. - the variable that stores in the output. - - - - - Update the variable that stores in the output. - true if the type of the variable is compatible with the type of this output, false otherwise. - - - - - Evaluate the current output. If this output has an owner fragment, the owner fragment will also be evaluated. - true if succeed, false otherwise. - - context info for evaluation. - - - - This class is similar as . But instead of binding to a texture, application can use this class to present content to a specific window. - - - - - Present the content to specific window This method must called out of ImmediateFragment::Begin/End() block. Typically, after ImmediateFragment::End(). - - handle of the window - - - - is a query object used for submitting hardware queries. Typically use QueryType_Occlusion to query any pixels rendered, use QueryType_SO_Stats to query geometry shader output statistics etc. - - - - - Initialize this device query - true if successfully initialized, false otherwise. - - query type to issue. - - - - Issue the query Call this function before IVirtualDevice::Draw() to get information from the Draw call. - - - - - End the query Call this function after IVirtualDevice::Draw() to end the query - - - - - Get the query data's size - - - - - Get the query data - False if the data is not ready, and the client must keep waiting. True if the data is ready to use. - - A pointer to the returned data, which depends on the query type. Only filled if the function returns true. Must not be nullptr. - size of the data, query from - Whether to flush the device's command buffer when checking for data. If flushing is not performed, the client may have to wait indefinitely for a result. - - - - This class encapsulates a complete rasterizer state, like fill mode, cull mode, point size, etc. - - - - - Get the raster fill mode /return the fill mode - - - - - Get culling mode /return the culling mode - - - - - Gets whether color registers are interpolated between vertices. /return true if the color interpolation is enabled, false if disabled. - - - - - z buffer depth bias value by float /param value float depth bias - - - - - z buffer depth bias value by int /param value int depth bias - - - - - Get depth bias is float or int /return true if using float depth bias, false if it's int. - - - - - Get float depth bias /return depth bias - - - - - Get int depth bias /return depth bias - - - - - get the depth bias clamp value /return depth bias clamp - - - - - Get the slope scaled depth bias value /return slope scaled depth bias value - - - - - Get if depth clipping is enabled /return true if enabled, false if not. - - - - - Get scissor clipping state. /return true if scissor is enabled, false if not. - - - - - Get MultiSample State /return true if multi-sample enabled, false if not. - - - - - Get vertex point size. /return vertex point size - - - - - This is the base wrapper class for all viewport render items. A render item is the primary drawable element that holds the geometry. A plugin object that wants to be displayed in the viewport needs to create and maintain a set of concrete derived render items like TupleMeshRenderItem and expose those render items to max via the IObjectDisplay interface. - - - - - Get the visibility group of this render item. - the visibility group of this render item. - - - - - Get custom material for render item. - the custom material. - - - - - Get the description bits of this render item. The description bits correspond to a specific type of mesh element description. Developers may use it to query a render item from an . - the description bits - - - - - Get the transparent hint of the current render item. This hint could helper decide whether to place an render item in transparent pass or opaque pass. - the transparent hint of current render item. - - - - - Returns consolidation data of this render item - consolidation data of this render item - - - - - returns the item's z bias - item z bias - - - - - returns if the item will be be frustum culled before being drawn. - item frustum culling boolean value - - - - - returns the item local bounding box. - item bounding box in local coordinates. - - - - - This is a utility class. It is used for storing a set of render items. - - - - - This is a decorator class for . is mainly used when we want to create an additional instance of an existing , namely a decorator. The decorator will share the same render geometry of the original render item but it will have some different visual appearance. For e.g, it would have different material assigned, different world position or visibility group, etc. In such cases, there's no need to completely copy the original render item of which we can simply create a decorator. And we can specify the different visual appearance/behavior for the decorator. - - - - - Initialize the decorator. - true if itemToDecorate can be decorated or false otherwise. Note can't be decorated. - - the original render item to be decorated. - - - - Get the decorated render item. - the original render item to be decorated. - - - - - the offset matrix for the decorator. The world position of this decorator would be an offset from the world position of the node owning it. - Calling this function will simply override the inner state resulted from any previous call to SetAbsoluteMatrix() - - the offset matrix - - - - Get the offset matrix - true if an offset matrix has been assign to this decorator or false otherwise - - use this parameter to get the offset matrix - - - - the absolute matrix for the decorator. The world position of this decorator would be directly determined by absoluteMatrix. - Calling this function will simply override the inner state resulted from any previous call to SetOffsetMatrix() - - the absoluteMatrix matrix - - - - Get the absolute matrix - true if an absolute matrix has been assign to this decorator or false otherwise - - use this parameter to get the absolute matrix - - - - This class describes a graphics node. A graphics node is the container of render items. It also contains a material to shade all those render items. One render item could be added to multiple node to share the graphics data. - - - - - Initialize this graphics node. - true if successfully initialized, false otherwise. - - - - - Returns the world matrix of this node. - the world matrix. - - - - - the bounding box of this node in its own space. - - the bounding box of this node in its own space. - - - - Returns the max node. - the max node. - - - - - Returns whether this node would be visible to cameras in the scene. - true if this node is visible to cameras in the scene, false otherwise. - - - - - Returns whether this node would appear in rendered reflections and refractions. - true if this node would appear in rendered reflections and refractions, false otherwise. - - - - - Returns whether this node could receive shadows. - true if this node could receiver shadows, false otherwise. - - - - - Returns whether this node could case shadows. - true if this node could case shadows, false otherwise. - - - - - Returns whether this node should not be culled when rendering. - true if this node should not be culled when rendering, false otherwise. - - - - - Returns whether this node is selected. - true if this node is selected, false otherwise. - - - - - Returns whether this node is in bounding box mode. A node is in bounding box mode means that only the bounding box of this node would be shown in the view port. - true if this node is in bounding box mode, false otherwise. - - - - - Returns whether back face cull is enabled on this node. - true if back face cull is enabled on this node, false otherwise. - - - - - Returns the wire color of this node. - the wire color of this node. - - - - - Returns the opacity of this node. - the opacity of this node. - - - - - Get the number of render items that this node contains. - the number of render items that this node contains. - - - - - Get the i-th render item of this node. This function will not modify the reference count of the returned render item. - the i-th render item of this node. - - the index to the render item. - - - - Add a render item to this node. This function will add reference to the input render item. - - the render item to add. - - - - Remove the render item with the specified index from this node. - - the index of the render item to be removed. - - - - the default material for the given render item. The material for a render item could be determined by three parameters: - According to this priority, the "default" material will be used, if the render item doesn't have an override material. - Different render item could has different "default" material for the same node. For example: the default material for wireframe render item could be a solid white material. - - the index of the render item. - the default material of that render item. - - - - Get the solid material assigned to the current node. - A custom solid material could be specified when updating per node items. This material would be passed to the inner mesh whose solid mesh render item will be assign this material. - - - - - Get the wireframe material assigned to the current node. - - - - - Remove all render items from this node. Also release reference to those render items. - - - - - is the iterator class to iterate all render nodes in the current render world. - - - - - Advances the node iterator by one position. This function is similar as operator ++. - the iterator itself - - - - - Copy assignment of this iterator from anther iterator - the iterator itself - - the iterator to be copied - - - - Check if this iterator is equal with another one - true if both iterator are same or false otherwise - - the iterator to be compared against - - - - Dereferencing the iterator to a reference to the current render node - the reference to the current render node. - - - - - is the base wrapper class of the nitrous world. - - - - - Initialize this render world. - true if successfully initialized, false otherwise. - - - - - Call Reset() to clear all render nodes. - - - - - Add a render node to the world - true if successfully added, false otherwise. - - the render node to be added - - - - Remove a render node from the world - - the render node to be removed - - - - Synchronize changes to all render nodes from client side to server side. - - - - - Get count of all render nodes in the world. - the count of nodes - - - - - Returns an iterator referring to the first node in the render world. - an iterator referring to the first node in the render world. - - - - - Returns an iterator referring to the past-the-end node in the render world. - an iterator referring to the past-the-end node in the render world. - - - - - Get the bounding box of all render nodes in the world - the bounding box of all render nodes in the world - - - - - Get the bounding box of all render nodes casting shadows in the world - the bounding box of all render nodes casting shadows in the world - - - - - is used to get the shadow map data associated to an which is a light. - - - - - Retrieve the shadow maps data from the light node provided - false if something went wrong during the call so the returned parameters are not valid, true if everything is ok. - - - the which should be a light node only. - : the color of the shadow for this light. - : the depth bias of the shadow for this light. - : the slope bias of the shadow for this light. - : the depth range of the shadow map for this light. - : the shadow map resolution (is always a square texture). - : the matrix to convert from light space to Cube space for the shadow map. - : the 6 view and projection matrices combined together for each cubemap face to convert from light space to viewport clip space. If the shadow map is not a cubemap, there is only 1 view projection matrix in the array. - : the 6 view matrices to convert from world space to light space for each cube map face. If the shadow map is not a cubemap, there is only 1 view matrix in the array. - - - - - is a simple implementation of . just contains the vertex buffer array, the index buffer, the primitive type, the vertex count and the stream format. 3rd party developer can directly use this class for simple mesh whose geometry could be defined using vertex buffer and index buffer. - - - - - the number of primitives in the geometry. - - the number of primitives - - - - the stream requirement of this render geometry. - - the stream requirement which this geometry built with. - - - - index buffer of this geometry. - - index buffer of this geometry. - - - - Add a vertex buffer to this geometry. - - the vertex buffer to be added. - - - - Remove the index-th vertex buffer. - - the index of the vertex buffer to be removed - - - - Get the number of vertex buffers. - the number of vertex buffers. - - - - - Get the index-th vertex buffer. - the index-th vertex buffer. - - the index of the vertex buffer - - - - the start primitive offset for drawing. - - this offset will pass to function - - - - This is the base wrapper class for all graphics primitive classes in max viewport: worlds, nodes, render items, materials, etc. It contains internal graphics object pointer and holds a reference to that pointer. It will release its reference to graphics object in its destructor. - Note this is not for generic smart handle use. - - - - - Check if this handle is valid. User should never call member functions of an invalid handle. - - - - - Release the underlying graphics objects. After calling this function, any function of the same instance should not be used. - - - - - Get the underlying graphics object id. This function is internally used only. - - - - - Get the underlying graphics object pointer. This function is internally used only. - - - - - is a material class to support solid color. This class is used for viewport display and Quicksilver. It's used by RenderItemHandle::SetCustomMaterial() to describe the solid color surface. How to use: - - - - - Initialize the instance of solid color material. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - - - - Get the color for solid color material. - the color for solid color material. - - - - - is a material class to support phong style material . This class is used for viewport display and Quicksilver. It's used by RenderItemHandle::SetCustomMaterial() to describe the phong style surface. How to use: - - - - - Initialize the standard material instance. A must be initialized before it's used. - true if successfully initialized, false otherwise. - - - - - Returns the ambient color. - the ambient color. - - - - - Returns the diffuse color. - the diffuse color. - - - - - Returns the specular color. - the specular color. - - - - - Returns the specular level. - the specular level. - - - - - Returns the specular power. - the specular power. - - - - - Returns the emission color. - the emission color. - - - - - Returns the opacity value. - the opacity value. - - - - - Returns the two side flag. - the two side flag. - - - - - Returns the diffuse texture. - the diffuse texture. - - - - - Clear the diffuse texture. - - - - - Returns the opacity texture. - the opacity texture. - - - - - Clear the opacity texture. - - - - - This class encapsulates a complete set of stencil buffer operations for stencil test. - - - - - Get stencil fail operation /return stencil fail operation - - - - - Get stencil operation when stencil test passes and depth test fails. /return depth fail operation - - - - - Get stencil operation when stencil test and depth test all pass. /return stencil and depth pass operation - - - - - Get compare function for stencil test. /return compare function for stencil test. - - - - - This class holds the blend state for single render target. - - - - - Get the blending is enabled or not. /return true if enabled, false if not. - - - - - the blend factor for source color. /return current source blend factor - - - - - Get the blend factor for destination color /return current destination blend factor - - - - - Get the operation for color blending. /return the operation for color blending. - - - - - Get the blend factor for source alpha. /return the blend factor for source alpha - - - - - Get the blend factor for destination alpha. /return the blend factor for destination alpha. - - - - - Get the operation for alpha blending. /return the operation for alpha blending. - - - - - Get color write mask /return current mask - - - - - Application can use this class either as a render target or convert it to texture and assign to model. - - - - - This is texture class to support texture for material, such as . How to use: - - - - - Initialize the instance of specified type texture. A should be initialized before it's used - true if successfully initialized, false otherwise. - - type of the texture - the width of texture. - the height of texture. - the depth of texture. Used for volume texture. - number of sub textures. Used for texture array in DX11. For single texture, specify "1". DX9 ignores this parameter. - level number of texture. If this value is zero, a complete mipmap chain is created. - member of the TargetFormat enumerated type, describing the pixel format of the texture. - resource usage of the texture - - - - Initialize the instance of texture from file. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - filename of the texture. Supported format: .bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, and .tga. - - - - Unlocks a rectangle on a texture resource. - true if successful, otherwise false. - - - - - Get number of sub-targets - for CubeMap, returns 6. For volume map, returns depth in creation parameter. Otherwise, return 1 - - - - - Get sub target of the texture. For standard 1D, 2D, 3D texture, only "0" is valid. For cube texture, valid value is 0-5. For Volume texture, valid value depends on creation parameter. - sub-target handle. - - sub target index - - - - the size of the texture. - - the width of the texture - the height of the texture - the height of the texture - - - - Get whether auto-generate mipmaps. - true means system will handle mipmap generation. - - - - - This is utility class to create from . - - - - - This is material class to support material with texture. How to use: - - - - - Initialize an instance of texture material. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - - - - Returns the texture handle. - the texture handle. - - - - - Returns the texture map channel ID. - the texture map channel ID. - - - - - Specifies material filters. Sets material filter. - - description. - - - - This class contains all information that will be passed to IObjectDisplay::UpdateDisplay and will be used by plugin to update its display data. All the value of this class are set by system and plugin developers should build render items to satisfy those requirements. - - - - - Get component requirement flags. Component requirement flag is decided by current viewport configuration: visual style, edged faces, etc. and node display properties: backface cull, vertex ticks, etc. - A combination of RenderItemCategory - - - - - Clear the required stream of this class. - - - - - Get the required streams. Required streams is for generating mesh render items. - - - - - Add stream requirements, so that the new requirement of the contains both old requirement and the newly input requirement. - - the requirement to be added. - - - - Get the display time. - the current time. - - - - - Get the number of nodes that reference the plugin object. - the number of owner nodes. - - - - - Get the i-th owner node of the array. - the i-th owner node. - - the index of the node in this context. - - - - This class contains node dependent information for calling IObjectDisplay2::UpdatePerNodeItems(), and IObjectDisplay2::UpdatePerViewItems() - - - - - Get the current node to update render items. - - - - - This class contains view dependent information for calling IObjectDisplay2::UpdatePerViewItems() - - - - - Get the current view for updating per view items which would be used by IObjectDisplay2::UpdatePerViewItems(). And during the execution of IObjectDisplay2::UpdatePerNodeItems(), NULL would be returned for this function. - the current view for updating per view items. - - - - - is a simple class that stores certain data that a developer can decide at runtime. We use this class to transfer parameters from fragment to fragment. - - - - - Changes this variable to a certain type, and resets the value. For numbers, resets to zero. For string, resets to empty string. For RefObject, resets to NULL. - - The type that this variable will be changed to. - - - - Gets the type of this variable. - the type of this variable. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A char value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An unsigned char value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A wchar_t value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A short value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An unsigned short value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An int value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An unsigned int value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A long value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An unsigned long value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An __int64 value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - An unsigned __int64 value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A float value. - - - - - Tries to convert this variable to char and return the value. If this variable is not a number, an exception is thrown. - A double value. - - - - - Tries to get the multi-byte string value of this variable. If this variable is not a multi-byte string, an exception is thrown. - multi-byte string pointer. It's life time is controlled by the variable, you don't need to delete it. - - - - - Tries to get the Unicode string value of this variable. If this variable is not a Unicode string, an exception is thrown. - Unicode string pointer. It's life time is controlled by the variable, you don't need to delete it. - - - - - Tries to get the pointer that is referenced by this variable. If this variable is not an variable, an exception is thrown. - This function directly returns the pointer to the . It doesn't increase the reference count of that . - - - - - Tries to get the dictionary pointer that is referenced by this variable. If this variable is not a dictionary variable, an exception is thrown. - This function directly returns the pointer to the dictionary. It's life time is controlled by the variable, developer don't need to delete it. - - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is a multi-byte string and is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is an unicode string and is successfully updated, false otherwise. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is an pointer and is successfully updated, false otherwise. If it succeeds, this function tries to release the old that is referenced by the variable and increase the reference count of the input value. - - input value. - - - - Tries to update this variable's value, without changing this variable's type. If the input value cannot be converted to this variable's type, returns false. - true if the variable is successfully updated, false otherwise. - - input value. - - - - Converts this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type. Then assign the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - convert this variable to the input value type, then assigns the input value to this variable. - a reference to the variable itself. - - input value. - - - - is a memory buffer that contain vertex data. Vertex buffers can contain any vertex type - transformed or untransformed, lit or unlit - that can be rendered through the use of the rendering methods. - - - - - Initialize a vertex buffer with initial data - true if successfully initialized, false otherwise. - - The stride in bytes of each vertex of the newly created buffer. - number of vertices in this buffer - initial data, can be nullptr - usage of the buffer - access flag of the buffer - pool state of the buffer - if this buffer is used as "buffer" shader type, then it must specify data type. - - - - Clear all vertices in the buffer and set the size of the buffer to zero. - - - - - Get the size of each vertex of this buffer. Measured in bytes. - the size in bytes of each vertex. - - - - - Get the real number of vertices in the buffer - the number of vertices. - - - - - Get the capacity of the buffer - the capacity - - - - - This function is used for reading/writing data from/into the vertex buffer. - if the input parameter is invalid (eg. vertexIndex + numberOfVertices is greater than the total number of vertices of the buffer), the function returns NULL. - the buffer for developers to read/write vertex data. The size of the buffer is numberOfVertices * vertexStride. - - the vertex index that the lock operation starts - the number of vertices that this function will lock. - behavior of the locking. Default is write access. - - - - Unlock the buffer to update. This function must be called after Lock. Once this function is called, the buffer that returned by Lock become invalid and should not be used any more. - - - - - Gets the buffer usage type - the usage type - - - - - Gets the buffer pool type. - buffer pool type - - - - - Gets the buffer access type. - buffer access type - - - - - Clone the buffer - the cloned buffer handle - - - - - Copy data from another vertex buffer Note the source buffer format must match this buffer - - the source buffer to copy to this buffer - - - - Copy partial data from source buffer to specified location of this buffer Note both buffer should ensure they have enough space to copy the data - - the source buffer - offset of the source buffer - number of vertices to copy - start offset of this buffer - - - - Copy data from hardware buffer to system buffer - true if the data copy is success. Otherwise false. - - true to reserve hardware memory, false to release the memory. - - - - Copy data from system buffer to hardware buffer - true if the data copy is success. Otherwise false. - - true to reserve system memory, false to release the memory. - - - - is a material class to support vertex color. This class is used for viewport display and Quicksilver. It's used by RenderItemHandle::SetCustomMaterial() to describe the vertex color surface. How to use: - - - - - Initialize the instance of vertex color material. A should be initialized before it's used. - true if successfully initialized, false otherwise. - - - - - Base class of all viewport fragment. - - - - - Do evaluation. Perform necessary computation in this function, and set value to its output. Please note this function cannot be directly called, it can only be called indirectly by calling Fragment::Evaluate(). - true if succeeded, false otherwise. - - context info for evaluation. - - - - This class wrap up all viewport related parameters. For e.g., the width and height of render view render region,frame draw method etc.,. - - - - - Get the render view's - the of the render view. - - - - - Get the render view's width - the width of the render view. - - - - - Get the render view's height - the height of the render view. - - - - - the render view's width and height - - the rectangle size of the render view. - - - - Get the render region of the render view. - the render region that includes the scales,clipping rectangle and offset of the original render target in the screen space of the render view. - - - - - Indicate whether the render region intersection with the view after computation. - true if having intersection or false otherwise. - - - - - Get the intersection position in the view coordinate if having intersection. - the intersection position in the view coordinate. - - - - - Get the intersection position in the source coordinate if having intersection. - the intersection position in the source coordinate. - - - - - This a structure that holds parameters used for render item consolidation - - - - - Pointer to a instance. Plug-ins should manage the Strategy's life time. - - - - - Pointer to a instance Plug-ins should manage the Key's life time. - - - - - This struct is used to store some device related information. - - - - - The current viewport virtual device's feature level - - - - - This struct is a collection of elements that are necessary in a render view. - - - - - record the dirty flags of render view. See the enumeration RenderViewDirtyFlag in Enum.h file. - - - - - indicates the type of frame.See the enumeration FrameType in Enum.h file. - - - - - Message parameters. - - - - - Defines a rectangular region that has been locked by a call to TextureHandle::LockRect(). If a RECT was provided to the LockRect call, pBits will be appropriately offset from the start of the texture resource. - - - - - of bytes in one row of the texture resource. - - - - - Pointer to the locked bits. - - - - - This struct describes a single stream element that will be used by the hardware shader of a material. More specifically, it defines one input parameter of vertex shader. Based on the structure we know exactly how to bind a max mesh channel to a vertex shader input parameter. - - - - - Compare two . - 1 if this object is greater than rhs, -1 if this object is less than rhs, zero otherwise. - - the "right-hand-side" of the compare function. - - - - Get the max channel id which record where is the element come from. - this function is used for channels related to texture coordinates like uv, tangent and bitangent. Since a mesh may have multiple texture coordinates, this id is used to differentiate those coordinates. For other vertex buffers like position and normal, the channel id is zero. - the max channel id. - - - - - Get the vertex field type of the stream element. - the vertex field type. - - - - - Get the channel category of the stream element. - the vertex channel category. - - - - - Get the usage index of the stream element. - the usage index. - - - - - Get whether this stream contains instance data - true if it's a instance data stream - - - - - the struct that defines the width and height of one rectangle. - - - - - the width of one rectangle. - - - - - the height of one rectangle. - - - - - Note: The render region can set the clipping rectangle,offset and scale of render target in the screen space of render view. - - - - - the flag can indicate the order of scaling and clipping.The offset order does not affect the final result. - - - - - the scale value for the cropped render target after it is positioned in the screen space of the view. Its X and Y are radios that take the render target's width and height as base. The scaling operation take the center of the render target as reference point. - - - - - indicate the clipping rectangle of the render target. - - - - - the offset value of the render target in the screen space of the view. They are ratios that take the view's width and height as base. - - - - - This structure is used to define a simple vertex stream. - - - Used by DrawPrimitive and DrawIndexedPrimitive for vertex data. It is used for all types of primitive. The pointers should point to arrays in system memory. - The size of the arrays should be at least the same as "primitiveCount" passed in DrawPrimitive and DrawIndexedPrimitive. Simply set an array to NULL if it is not needed, however Positions should never be NULL, it must always have valid data. - - - - - Position array. - - - - - Normals array. - - - - - Vertex array. - - - - - Texture coordinate array. The number of TextureCoordStreams is defined by "MaximalTextureStreams". - - - - - This structure is used to define vertex's texture coordinate information. - - - - - of floats in a texture coordinate(from 0 to 4). "0" means no data. - - - - - Pointer of the texture coordinate array. Should be same size as vertices. - - - - - This class collects all marker items(both immediate and non-immediate), hardware build vertex buffer and index buffer in Realize() function and render them in Display() function. With this class, we can efficiently batch markers data and greatly reduce rendering API overheads. Ideally whole scene's marker objects can be rendered by a few consolidation items. - - - - - This class defines a marker item consolidation strategy. By default, marker item always support immediate consolidation. If user plugins have complex data that can't support immediate consolidation, they need to create own strategy with ImmediateConsolidationEnabled returns false. - - - - - This is a utility class for provide a key for marker consolidation item - - - - - Base class for marker render items. This class is also an alternate solution for marker functions in . Usually plugins needs to inherit this class and implement Realize() function to generate marker data unless the plugin has static data that never changes after creation. This class is designed for simple marker data that can be immediate consolidated. So it actually doesn't need to implement Display() fucntion because the display part is handled by . This item simply store data in system memory arrays, which has fast read performance. - If plugin's data like particle system is too complex and can't be generated in real time, we suggest the plugin to implements both Realize() and Display() functions. Then use a non-immediate consolidation strategy. So that the complex marker item won't slow down other marker items. A reference complexity of the marker item is if it has more than 1K markers, we suggest to disable immediate consolidation. - - - - - Return dirty status of this item - true if dirty, false if not - - - - - Sets dirty status of this item - - - - - Return whether this item contains marker data item will be skipped when consolidation - true if there's marker data. Otherwise false. - - - - - Add marker data by raw pointers with custom color. - - pointers of position data - pointers of color data. - Marker type - number of positions to add. - - - - Add marker data by raw pointers, with same color for all markers. - - pointers of position data - reference of color data. - Marker type - number of positions to add. - - - - Clear marker data - - - - - Get position array - position array - - - - - Get color array - color array - - - - - This class collects mesh edge render items and build hardware buffers for them. It also uses a shader to do hardware edge culling. With this shader, we can do efficient edge back-face cull. - - - - - This class defines an immediate mesh edge render item consolidation strategy. If user plugins have complex mesh data that can't support immediate consolidation, they need to create own strategy with ImmediateConsolidationEnabled returns false. - - - - - This is a utility class for provide a key for - - - - - Return if the mesh item is fixed size on screen - true if it's fixed size. Otherwise false. - - - - - true if the item needs back-face cull. Otherwise false. - - - - - This class is designed for small meshes that only renders edge element. This use case is typically used by gizmos like dummy, lights which originally uses mesh.render with GW_EDGES_ONLY flag to draw edges. The back-face cull calculation is done by software under DX9 and using hardware shader under DX11. - - - - - Return value of the flag - - specifies the flag to set - - - - the specified flag to 0 - - the flag to clear - - - - the specified flag to 1 - - the flag to set - - - - Get back-face cull status - back-face cull status of the item - - - - - Get mesh edge list - - edge list of the mesh - number of data in the array - - - - Get the color of edges - color of the edge - - - - - Get the mesh used by render item - pointer of the mesh - - - - - This class collects all spline items(both immediate and non-immediate), hardware build vertex buffer and index buffer in Realize() function and render them in Display() function. With this class, we can efficiently batch small line data and greatly reduce rendering API overheads. Ideally whole scene's line objects can be rendered by a few consolidation items. - - - - - This class defines a spline item consolidation strategy. By default, spline item always support immediate consolidation. If user plugins have complex data that can't support immediate consolidation, they need to create own strategy with ImmediateConsolidationEnabled returns false. - - - - - This is a utility class for provide a key for spline consolidation item - - - - - Base class for spline render items. This class is also an alternate solution for polyline functions in . Usually plugins needs to inherit this class and implement Realize() function to generate line data unless the plugin has static data that never changes after creation. This class is designed for simple line data that can be immediate consolidated. So it actually doesn't need to implement Display() fucntion because the display part is handled by . This item simply store data in system memory arrays, which has fast read performance. - If plugin's data is too complex and can't be generated in real time, we suggest the plugin to implements both Realize() and Display() functions. Then use a non-immediate consolidation strategy. So that the complex line item won't slow down other line items. A reference complexity of the line item is if it has more than 10K primitives, we suggest to disable immediate consolidation. - - - - - Return value of the flag - - specifies the flag to set - - - - the specified flag to 0 - - the flag to clear - - - - the specified flag to 1 - - the flag to set - - - - Return whether this item contains line data item will be skipped when consolidation - true if there's line data. Otherwise false. - - - - - Add line strip data by raw pointers with custom vertex color. Internally the function converts line strip to line list. And build index data for the strip. - - pointers of position data - pointers of color data. The function will automatically handle color shift in DX11 mode. - number of positions to add. - indicate whether this line strip is closed. The function will build index for closed strip. - indicate whether these primitives are also used for hit test. - - - - Add line strip data by raw pointers, with same color for all vertices. Internally the function converts line strip to line list. And build index data for the strip. - - pointers of position data - reference of color data. The function will automatically handle color shift in DX11 mode. - number of positions to add. - indicate whether this line strip is closed. The function will build index for closed strip. - indicate whether these primitives are also used for hit test. - - - - Clear line data - - - - - Get position array - position array - - - - - Get color array - color array - - - - - Get line list index array - line list index array - - - - - is an extension of dealing with instancing. - - - - - Destructor. - - - For the creation mode : creates the instances internal data on the GPU. The plugin should call this function with an Instancedata object populated with instance positions, orientations, materials etc... It can be called at any place in your plugin. This does a full rebuild of the instance data, erasing any existing data. You should call this again when the number of instances has changed or the original geometry instantiated has changed to rebuild the full internal data. - - : a const reference on which is populated with values such as instance positions, orientations, materials etc... /return true if it succeeded or false if it failed. The main reason why it could fail is because the GPU memory allocated by the instances would be too big for the GPU. You would see an assert in that case if asserts are enabled in your build. - - - - For the update mode : updates the instances internal data on the GPU. This function assumes that InstanceDisplayGeometry::CreateInstanceData(const InstanceData& data) has been already called once at least. As to update the data, it must have been created. Each time something changes on instances, say : the positions and colors have changed, you should call this method to update the instances internal data. In the data parameter of this method, only what needs to be updated should be non-null pointers and non zero for the number of elements. It can be called at any place in your plugin. Say you are updating only the positions, you should do : - - : a const reference on - - - - Get if the matrices / positions / orientations / scales on instances are in world space or relative to the node's transform matrix. - true if they are in world space, false if they are relative to the node's transform. - - - - - Generates the and adds it to the targetRenderItemContainer. This is an helper function when you are in the method from IObjectDisplay2::UpdatePerNodeItems(const UpdateDisplayContext& updateDisplayContext, UpdateNodeContext& nodeContext, IRenderItemContainer& targetRenderItemContainer) it creates and adds the instance render items to the container. - - is true to generate the render items for a wireframe display, false means for a solid mesh display. - is an which has to be passed from UpdatePerNodeItems. - is which has to be passed from UpdatePerNodeItems. - is an which has to be passed from UpdatePerNodeItems. - - - - Get the instance vertex buffer. - the instance vertex buffer handle. - - - - - Get the for the instance vertex buffer. is the class that describe the GPU vertex buffer data and the order in which it is defined. - the for the instance vertex buffer. - - - - - Get the geometry for the geometry vertex buffer. is the class that describes the GPU vertex buffer data and the order in which it is defined. This has to match the instance from the material for the display to be correct in the viewport. - the for the geometry vertex buffer. - - - - - the number of primitives in the geometry. This method is implemented by 3ds Max. - - the number of primitives - - - - the start primitive offset for drawing. This method is implemented by 3ds Max. - - this offset will pass to function - - - - the stream requirement of this geometry. This method is implemented by 3ds Max. - - the stream requirement which this geometry built with. - - - - index buffer of this geometry. This method is implemented by 3ds Max. - - index buffer of this geometry. - - - - Add a vertex buffer to this geometry. This method is implemented by 3ds Max. - - : the vertex buffer to be added. - - - - Remove the index-th geometry vertex buffer. This method is implemented by 3ds Max. - - the index of the geometry vertex buffer to be removed - - - - Get the number of geometry vertex buffers. This method is implemented by 3ds Max. - the number of geometry vertex buffers. - - - - - Get the index-th vertex buffer from the geometry. This method is implemented by 3ds Max. - the index-th geometry vertex buffer. - - the index of the geoemtry vertex buffer - - - - The struct is used to pass instance data to different methods of the class. It is shared by the creation and the update mode. It is used in the creation mode with InstanceDisplayGeometry::CreateInstanceData(const InstanceData& data) to create the instance vertex buffer. This has to be called once only unless you want to recreate all instance data when the number of instances has changed or the number of vertices has changed in the original instantiated geometry. It is also used in the update mode with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data) to update the instance data that has changed. - - - - - numInstances : this is the number of instances. In Creation mode : this parameter should be used with InstanceDisplayGeometry::CreateInstanceData(const InstanceData& data), it should be non zero. In update mode : with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data), this parameter can be ignored as the number of instances should not have changed. - - - - - If bTransformationsAreInWorldSpace is true, then all matrices/positions/orientation/scales used in are in world space, so moving the node will not move the instances. If bTransformationsAreInWorldSpace is false then all matrices/positions/orientation/scales are relative to the node's transfrom matrix, so moving the node will move all instances. In creation mode : this parameter should be set. In update mode : this parameter should not be used as this should not change in an update. - - - - - pMatrices is an array of with InstanceData::numInstances elements which are the transform matrix of each instance. This parameter can be null if you use the pPositions array instead but either pMatrices or pPositions should be non null if you want the instances to be at different positions. To set these matrices to world space or relative to the node's transform, please see InstanceData::bTransformationsAreInWorldSpace. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. - - - - - pPositions is an array of with InstanceData::numInstances elements which are the position of each instance. It can be a null pointer if you use the pMatrices array instead, but at least one of both pointers should be non null. To set these matrices to world space or relative to the node's transform, please see InstanceData::bTransformationsAreInWorldSpace. Internally, in the instance vertex buffer, this data is converted to a with pos/orientation/scale combined when added in the instance vertex buffer. In update mode, with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data), if you are not using InstanceData::pMatrices, but rather position/orientation/scale, always provide all three, as a missing value will be replaced by identity or null (for position) as we are combining the 3 into a matrix, even if only one of them is changing for a given frame. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. And please also provide orientation and scale in this mode even if not all of them have changes. - - - - - pOrientationsAsPoint4 is an array of which are quaternions. This parameter can be null if the orientation of instances is not overriden, it will be an identity orientation in that case. If you prefer to use the class to provide orientations, please see InstanceData::pOrientationsAsQuat. To set these orientations to world space or relative to the node's transform, please see InstanceData::bTransformationsAreInWorldSpace. Internally in the vertex buffer, this data will be converted to a with pos/rot/scale combined when put in the instance vertex buffer. In update mode, with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data), if you are not using InstanceData::pMatrices, but rather position/orientation/scale, always provide all three, as a missing value will be replaced by identity or null (for position) as we are combining the 3 into a matrix, even if only one of them is changing for a given frame. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. And please also provide position and scale in this mode even if not all of them have changes. - - - - - numOrientationsAsPoint4 is the number of elements in InstanceData::pOrientationsAsPoint4, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. This means you can only give one orientation if you want all instances to have the same orientation. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. - - - - - pOrientationsAsQuat is an array of which are quaternions. This parameter can be null if the orientation of instances is not overriden, it will be an identity orientation in that case. If you prefer to use the class to provide orientations instead of , please see InstanceData::pOrientationsAsPoint4. To set these orientations to world space or relative to the node's transform, please see InstanceData::bTransformationsAreInWorldSpace. Internally in the vertex buffer, this data will be converted to a with pos/rot/scale combined when put in the instance vertex buffer. In update mode, with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data), if you are not using InstanceData::pMatrices, but rather position/orientation/scale, always provide all three, as a missing value will be replaced by identity or null (for position) as we are combining the 3 into a matrix, even if only one of them is changing for a given frame. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. And please also provide position and scale in this mode even if not all of them have changes. - - - - - numOrientationsAsQuat is the number of elements in InstanceData::pOrientationsAsQuat, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. This means you can only give one orientation if you want all instances to have the same orientation. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. - - - - - pScales is an array of which is the scale of each instance. This parameter can be null if the scale of instances is not overriden, it will be an identity scale (1,1,1) used in that case. To set these orientations to world space or relative to the node's transform, please see InstanceData::bTransformationsAreInWorldSpace. Internally in the vertex buffer, this data will be converted to a with pos/rot/scale combined when put in the instance vertex buffer. In update mode, with InstanceDisplayGeometry::UpdateInstanceData(const InstanceData& data), if you are not using InstanceData::pMatrices, but rather position/orientation/scale, always provide all three, as a missing value will be replaced by identity or null (for position) as we are combining the 3 into a matrix, even if only one of them is changing for a given frame. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. And please also provide position and orientation in this mode even if not all of them have changes. - - - - - numScales is the number of elements in pScales, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can only be used if it was used in the creation mode previously. - - - - - pViewportMaterials is an array of which is the material of each instance. This parameter can be null if you want to use the original material from the node. If you need to convert from a 3ds Max class to a Nitrous , please see MaxSDK::Graphics::MaterialConversionHelper::ConvertMaxToNitrousMaterial. In creation mode : this parameter can be used. In update mode : this parameter should not be used. It is not compatible with the update mode since internally we sort the instances per material to batch render them for performance reasons which involves a reordering of the instance vertex buffer data. Internally, we will do a local copy of this array. - - - - - numViewportMaterials is the number of elements in pViewportMaterials, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter should not be used. Changing the number of materials is not possible in this mode. See InstanceData::pViewportMaterials for more info. - - - - - pUVWMapChannel1 is an array of which is the UVW value of each instance in map channel 1, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in map channel 1 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel1 is the number of elements in pUVWMapChannel1, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel2 is an array of which is the UVW value of each instance in map channel 2, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 2 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel2 is the number of elements in pUVWMapChannel2, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel3 is an array of which is the UVW value of each instance in map channel 3, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 3 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel3 is the number of elements in pUVWMapChannel3, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel4 is an array of which is the UVW value of each instance in map channel 4, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 4 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel4 is the number of elements in pUVWMapChannel4, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel5 is an array of which is the UVW value of each instance in map channel 5, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 5 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel5 is the number of elements in pUVWMapChannel5, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel6 is an array of which is the UVW value of each instance in map channel 6, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 6 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel6 is the number of elements in pUVWMapChannel6, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel7 is an array of which is the UVW value of each instance in map channel 7, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 7 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel7 is the number of elements in pUVWMapChannel7, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pUVWMapChannel8 is an array of which is the UVW value of each instance in map channel 8, we override the UVWs from the whole geometry with a single UVW value per instance (for all vertices of the geometry) on that map channel. That is how override UVWs per instance works on GPU. This parameter can be null if the UVWs in the map channel 8 of each instance are not overriden. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numUVWMapChannel8 is the number of elements in pUVWMapChannel8, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pColors is an array of which is the rgba color of each instance. This will result in the viewport as a flat shading color applied on each instance (no lighting effect added). has r,g,b,a components with values from 0.0 to 1.0, though we don't do any check on this. You can set a non zero alpha value to use transparency. This parameter can be null if you don't want to override the color per instance. Using a non-null InstanceData::pColors value with a non-null InstanceData::pViewportMaterials is not advised as we will use only either the material or the colors but not both. In creation mode : this parameter can be used. In update mode : this parameter can be used. Internally, we will do a local copy of this array. - - - - - numColors is the number of elements in pColors, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pVertexColorsAsColor is an array of , i.e : an rgb color with no alpha. With r,g,b with values from 0.0 to 1.0. There is no alpha on vertex colors in 3ds Max. We override the Vertex Colors from the whole geometry with a single Vertex value per instance, that is how it works on at the GPU level. There is a limitation : Vertex Colors override will work only on map channels which have not been overriden when you show both in the viewport. This parameter can be null if the Vertex Colors of each instance are not overriden. This data will be converted when written in the vertex buffer to DWORD R8G8B8X8 color as this is what 3ds Max uses internally for Vertex Colors in vertex buffers. If you prefer to use directly DWORD for Vertex Colors as it's faster, please see InstanceData::pVertexColorsAsDWORD. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numVertexColorsAsColor is the number of elements in pVertexColorsAsColor, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - pVertexColorsAsDWORD is an array of 32 bits DWORD R8G8B8X8, i.e : an rgb color with no alpha. With r,g,b with values from 0.0 to 1.0. There is no alpha on vertex colors in 3ds Max. We override the Vertex Colors from the whole geometry with a single Vertex value per instance, that is how it works at the GPU level. At this time, there is a limitation : Vertex Colors override will work only on map channels which have not been overriden when you show both in the viewport. This parameter can be null if the Vertex Colors of each instance are not overriden. If you prefer to use for Vertex Colors, please see pVertexColorsAsColor. This will be slower as DWORD is the format that 3ds Max uses natively for the Vertex in vertex buffers so we will convert from to DWORD. As an helper, to convert from r,g,b being values from 0 to 255 to 32 bits DWORD R8G8B8X8, please use the funcion declared above ConvertFromR8G8B8ToDWORD(int r, int g, int b). In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - numVertexColorsAsDWORD is the number of elements in pVertexColorsAsDWORD, it can be less than numInstances, in that case, we will loop through the data when filling the vertex buffer. In creation mode : this parameter can be used. In update mode : this parameter can be used. - - - - - The type of display for the volume. - - - - - The type of grid for this volume, there is one grid displayed per volume. - - - - - The type of algorithm used to set color on the volume grid. - - - - - We can normalize the volume grid data when providing a Float16 or Float32 grid. - - - - - Slice axis is used to display only a part of the volume, a slice of it on a given axis at a given position and thickness. - - - - - The parameters set for the display of the volume grid in the viewport - - - - - Example : Use INode::GetNodeTM(t)). - - - - - Example : Use INode::GetObjTMAfterWSM(t)). - - - - - Grid GPU compliant data computed by ComputeGridGPUParams. - - - - - The level set surface value in the grid. It is used only when GridParams::mbIsLevelSetGrid is true. - - - - - Used only when mRayMarchingStepType = RayMarchingStepType::Manual. It is the maximum iterations per pixel for sampling the volume during the ray marching, the higher it is, the higher is the quality but the slower is the rendering. This value must be positive but has no upper limit. - - - - - In the range 0.001 to 1.0, we will stop the ray marching when the accumulated opacity of the volume will reach that value per pixel. - - - - - A multiplier applied per voxel sample on the opacity, the lower it is, the less dense is the volume, this is to make your volume look more "cloudy". - - - - - this to true if you want the volume to take care of the camera being inside the volume, set it to false to ignore it (resulting in a faster display). - - - - - The type of display you want for the volume grid. - - - - - Optional : This is only used with fog volume grids. It is a 1D texture (a single line of pixels) to map the density of the voxels to the range [0.0, 1.0]. You can use a 2D texture but we will only consider the first line. A typical example of texture is an OSL Curve (float) map. If the texture map is RGB or RGBA, we will use only the R component to do the mapping. Use the function MaxSDK:Graphics::TextureHandle::Initialize(const MSTR& filename) defined in MaxSDK/include/Graphics/TextureHandle.h to create a from a bitmap fullpath filename and store it in your plugin, as it's a counted ref object. - - - - - Usually there are millions of voxels for a given volume, and displaying a part of them is enough to get an idea of the shape of it. So you can set the maximum voxels displayed. It is used only when DisplayParams::mDisplayType is DisplayType::Voxels. - - - - - Used only if DisplayParams::mDisplayType is DisplayType::Voxels, is the color accumulated per voxel sample. - - - - - Used only when DisplayParams::mDisplayType is DisplayType::Iterations, see DisplayType::Iterations for more information. - - - - - Use a color accumulated per voxel sample to display the grid. - - - - - Used only if DisplayParams::mGridColorType == GridColorType::Color, color to accumulate per voxel sample. - - - - - Used only if DisplayParams::mGridColorType == GridColorType::GradientMap, provide a 1D texture (a single line of pixels) or a 2D texture (we will only use the first line of pixels) to map from a volume grid value (either fog or level set) to a RGBA color. If the texture map provided doesn't have an alpha layer, we will use 1.0 for the alpha, if it has an alpha layer we will use it. If you want to use a separate map to handle the alpha, please see DisplayParams::mGridGradientMapAlpha. Use the function MaxSDK:Graphics::TextureHandle::Initialize(const MSTR& filename) defined in MaxSDK/include/Graphics/TextureHandle.h to create a from a bitmap fullpath filename. - - - - - Used only if DisplayParams::mGridColorType == GridColorType::GradientMap and DisplayParams::mGridGradientMap has been provided. This is a 1D texture (a single line of pixels) or a 2D texture (we will only use the first line of pixels) to map from a volume grid value to an alpha value in the range [0,0, 1.0]. If the texture map you use is RGB or RGBA, we will use only the R value as the alpha value. This works with fog and level set grids. Use the function MaxSDK:Graphics::TextureHandle::Initialize(const MSTR& filename) defined in MaxSDK/include/Graphics/TextureHandle.h to create a from a bitmap fullpath filename. - - - - - Used only if DisplayParams::mGridColorType == GridColorType::Blackbody and DisplayParams::mBlackbodyNormalize is false, is a factor applied to the black body temperature conversion, a factor of 1.0 makes it physically correct. - - - - - Used only if DisplayParams::mGridColorType == GridColorType::Blackbody, normalize the color with the luminance for the black body conversion. - - - - - Slice axis is used to display only a part of the volume, a slice of it on a given axis at a given position and thickness in a coordinates system. - - - - - Coordinates system in which the slice takes place, using the position, rotation and scale. - - - - - The thickness of the slice, is used only if mSliceAxis is different from SliceAxis::Off. The thickness is between 0.0 and 1.0 as it's relative to the the bounding box of the volume, a value of 0.5 meaning half of the bounding box size. - - - - - Call this when you have finished using this data, such as when the grid data has changed (displaying another grid) for example or in your plug-in destructor. - - - - - This structure contains the GPU data of the volume that lives as the DisplayParams::mGridGPUParams member so we don't recompute all of this each frame. You store locally a instance in your plug-in and use its DisplayParams::mGridGPUParams member to be filled by the call to ComputeGridGPUParams. You should not have to change anything in that structure, you can see it as the GPU compliant volume data. It is built using the helper function ComputeGridGPUParams(const GridParams& inGridParams, GridGPUParams& outGridGPUParams); - - - - - The volume grid information stored in a 3D texture. - - - - - The octree (spatial subdivision) stored in a 2D texture. - - - - - The voxels positions, this is the pointer you provided in GridParams::mpVoxelsPositions. This data is used when DisplayParams::mDisplayType = DisplayType::Voxels. - - - - - The number of voxels positions in mpVoxelPositions, this data is used when DisplayParams::mDisplayType = DisplayType::Voxels. - - - - - The size of voxels, is the same as GridParams::mVoxelsSize. - - - - - The local bounding box of the node your volume belongs to. - - - - - Same value as in GridParams::mbIsLevelSetGrid. - - - - - Is the same value as GridParams::mpBackgroundValue stored in a 32 bits float. - - - - - Call this when you have finished using the volume data, when the grid data has changed for example if you are loading an animation or in your plug-in destructor. After calling CleanUp() none of the volume data will be valid. - - - - - is where you define the parameters of the volume grid, independently from the display. You are going to pass this structure so that the helper function ComputeGridGPUParams will convert it to a structure which is GPU compliant. The structure is the in parameters of the helper function ComputeGridGPUParams and the structure is the out parameters. - - - - - Width of the grid. - - - - - Height of the grid. - - - - - Depth of the grid. - - - - - For example : is either a float* if GridParams::mGridType == GridType::Float32, or a half* if GridParams::mGridType == GridType::Float16. - - - - - A pointer on a background value which is either a float if GridParams::mGridType == GridType::Float32 or a half if GridParams::mGridType == GridType::Float16. - - - - - A boolean to tell if this grid is a level set or not. A level set grid is a grid created from a signed distance function (SDF). It contains negative and positive values that are the distance to the surface. Values for level sets grid go from -background to +background with negative values being the inside of the surface, 0.0 being the surface and positive values being the outside of the surface. - - - - - Type of data for each voxel, a voxel is a volume element. The resulting volume texture on the GPU will use the same format for its data. So using 16 bits will make a smaller GPU texture than using 32 bits voxel data. - - - - - Type of normalization for the grid data when the grid is a float grid. If this grid is a level set, GridParams::mbIsLevelSetGrid is true, then these parameters are ignored, we won't normalize the data. - - - - - Only used when GridParams::mNormalizationType = NormalizationType::ManualRange, is the minimum of the range. - - - - - Only used when GridParams::mNormalizationType = NormalizationType::ManualRange, is the maximum of the range. - - - - - The size of the array mpVoxelsPositions, is optional if you don't want to use the voxels positions as a display mode. If you are using openvdb to fill this data, it's : pGrid->activeVoxelCount() - - - - - Optional if you don't want to use the voxels positions as a display mode. If provided, you will still own this data, we will reuse your pointer and copy its value into GridGPUParams::mpVoxelPositions when you call ComputeGridGPUParams. Therefore this data must not be deleted while the volume is still in use. An example on how to provide mpVoxelsPositions data using openvdb : - - - - - The size of voxels, like the voxel size from openvdb. - - - - - Local bounding box of the node, will be copied to GridGPUParams::mNodeLocalBoundingBox. - - - - - This will create a mesh to be used in wireframe representation of the volume. The resulting mesh can be found in GridGPUParams::mpWireFrameMesh. In case you want to use your own wireframe representation for the volume, you can, by setting this to false, and initializing GridGPUParams::mpWireFrameMesh with a custom (we will use your pointer but never delete it). - - - - - Used only if mbComputeWireframeMesh is true. It is the number of subdivisions for the bounding box to create the wireframe mesh. We subdivide the bounding box of the volume by this wireFrameLevel and create a box mesh from each non empty cells which is concatenated into a single mesh. The smaller the value, the coarser the wireframe mesh. - - - - - This is parameter type of parameter. - - - - - This is parameter description of parameter. - - - - - type of parameter - - - - - unique name of parameter in shader - - - - - parameter types. - - - - - The type of plug-in's "sub" slot. - - - - - Supported shader types - - - - - This is the fill mode used in both SetFillMode and GetFillMode. - - - - - This enum type tells the viewport rendering system the usage of each texture. - - - - - Stage texture operation type. - - - - - The classes instances we receive when we are notified of a change: - - - The update types flags for nodes, you will receive a - - - - - The update types for materials, you will receive a . - - - - - The update types for materials, you will receive a . - - - - - The update types for materials, you will receive a . - - - - - The types of notifiers which may be registered, each corresponding to its own event class. - - - - - is a common class to all notifications events received: - - - - - Get the type of notifier: - - - - - Get the update type. - - - - - For debugging purpose you may use this to print the event to an existing file stream. - - - - - Immediate client is to get notifications as soon as they happen (by opposite to OnDemand client) - - - - - Monitor the active view whatever it is : a camera, a viewport or a light. This takes care of the lock/unlock view workflow for active shade. Also when the active view is changed to another view, you are called back and the new view is monitored automatically With this monitoring, you will events from notifierType : NotifierType_View and events - true if the active view is now monitored, false there was a problem - - The interface used to notify of new events. - An arbitrary pointer which is passed back, with the event, through . - - - - Stop monitoring active view - true if the active view is no longer monitored now, false if there was a problem - - The notification callback passed to the Monitor method. - The user data passed to the Monitor method. - - - - Immediate client is to get notifications as soon as they happen (by opposite to OnDemand client) - - - - - Destructor. - - - Monitor this node events - true if the node is now monitored, false there was a problem - - the INode* to monitor. - the NotifierType for this node. - : bit array flags, the events you want to monitor for that node, you'll get called only called for the selected events. Example for 2 events is : UpdateType_Node_WireColor | UpdateType_Node_Transform; - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor this material events - true if the material is now monitored, false if a problem occurred - - the Mtl* to monitor. - : bit array that is the events flags you want to monitor for that material, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor this events - true if the texmap is now monitored, false if a problem occurred - - the to monitor. - bit array : the events flags you want to monitor for that texmap, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor events on a generic reference target. This is used to monitor notifications an an arbitrary class for which there doesn't exist a more specialized monitoring function (as there are for , , , etc.). - true if the reference target is now monitored, false if a problem occurred - - The reference target to be monitored. - : bit array (see enum ReferenceTargetEventType) that is the events flags you want to monitor for that material, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor viewport events such as transform matrix changes (when you move the camera viewport while it's a viewport and not a Max camera) - true if the view is now monitored, false if a problem occurred - - the viewport ID to monitor. - bit array : the events flags you want to monitor for this viewport, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor render environment events (Tone operator for example) - true if we monitor these events now, false if there was a problem - - bit array : the events flags you want to monitor for render environment, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor render settings events (lock/unlock view for example) - true if we monitor these events now, false if there was a problem - - bit array : the events flags you want to monitor for render settings, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor scene events such as node added, file reset, file load, File import etc. - true if we monitor these scene events now, false if there was a problem - - bit array : the events flags you want to monitor for the scene, you'll get called only for the selected events - the interface used to notify of new events. - an arbitrary pointer which is passed back, with the event, through . - - - - Stop monitoring this node Unregisters a previously registered notification callback. - true if the node is not monitored now, false if the node was not in our arrays - - the INode* to stop monitoring for events. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring this material Unregisters a previously registered notification callback. - true if the material is not monitored now, false if the material was not in our arrays - - the Mtl* to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring this texmap Unregisters a previously registered notification callback. - true if the is not monitored now, false if the was not in our arrays - - the Texmap* to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring a reference target Unregisters a previously registered notification callback. - true if the reference target is not monitored now, false if the was not in our arrays - - The reference target to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring this viewport Unregisters a previously registered notification callback. - true if the view is not monitored now, false if the pView was not in our arrays - - the viewID of the viewport to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring render environment Unregisters a previously registered notification callback. - true if it is not monitored now, false if it was not monitored - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring render settings Unregisters a previously registered notification callback. - true if it is not monitored now, false if it was not monitored - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - Stop monitoring scene Unregisters a previously registered notification callback. - true if these scene events are no longer monitored now, false if there was a problem - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the notification callback passed to the Monitor method. - the user data passed to the Monitor method. - - - - InteractiveRenderingCallback is the the class to derive from to create a callback to receive events from InteractiveRendering. - - - - - Called to process an event. - - the event in question - the user data passed to the Monitor*() call on notification client. - - - - Base class for Interactive Rendering clients - - - - - returns the version number of the notification client - - - - - Print what's monitored inside the client (debugging purpose) - - a FILE you use to print out the data in it (can't be NULL) - - - - class is the entry point of the Interactive Rendering API, you can create or remove a Interactive Rendering Client Interactive rendering API is a middle API that makes the link between the low level NotificationAPI and the customer. It takes care of the lock/unlock workflow for active shade viewports It is dedicated for interactive rendering.If the user switches to another viewport, the new viewport is automatically monitored, you don't have to deal with all this. - - - - - < - - - Use this function to create an immediate client and get notified as soon as a change happens We use the Immediate Notification client you pass as a parameter. - a pointer on - - : a Notification client used to get notifications - : may pass the version of Interactive Rendering client you want to use, -1 = latest. - - - - < - - - Use this function to create an on demand client and ask for the changes when you need to update We are using an ImmediateNotification client to get notifications from NotificationAPI and we sort and store the events until you ask for them - a pointer on - - : may pass the version of Interactive Rendering client you want to use, -1 = latest. - - - - < - - - RemoveClient function, to stop monitoring. Cleaning is done by the manager which means your client gets deleted by the manager. - true if succeeded, false if the client was not found - - : the Interactive Rendering client you want to unregister. - - - - < - - - NumClients function - the number of Interactive Rendering clients connected - - - - - < - - - GetClient function - a pointer on a or NULL if index is out of range - - : the index of the Interactive Rendering clients to retrieve - - - - < - - - DebugPrintToFile function - - : a valid FILE pointer to print debug information to - - - - Events monitored : all related to materials. - - - You receive a instance when something is changed in a : - - - - - Retrieve the Mtl*. - - - - - Base class for all events associated with notifier types: NotifierType_Node_*. - - - - - Retrieve the INode*. - - - - - Event related to a parameter block change in a node's object. - - - - - Event related to a change in a node's object GI properties. - - - - - The PartID refers to the node property which has changed. values are depend on the even type: - - - - - The notification callback used to process all events from the notification API. - - - - - Called to process an event. Note that it is possible to monitor and stop monitoring events from within this notification callback. The notification system is specifically built to handle that. - - the event in question - the user data passed to the Monitor*() call on notification client. - - - - Base class for a notification client, is used to subscribe to notification events by monitoring 3ds Max data. - - - - - Destructor. - - - returns the version number of the notification client - - - - - Enable notifications - - : boolean to tell if we should receive notifications or not. - - - - Check if notifications are enabled or disabled - true if they are enabled - - - - - Print what's monitored inside the client (debugging purpose) - - a FILE you use to print out the data in it (can't be NULL) - - - - class is the entry point of the Notification API, you can create or remove a Notification Client. - - - - - < - - - Use this function to create a client which is the way to monitor notifications on nodes, materials, texmaps etc. and get notified immediately as soon as a change happens - a pointer on - - : may pass the version of notification client you want to use, -1 = latest. - - - - < - - - Use this function to create a client which is the way to monitor notifications on nodes, materials, texmaps etc with on demand mode changes. - a pointer on - - : may pass the version of notification client you want to use, -1 = latest. - - - - < - - - RemoveClient function, to stop monitoring. Cleaning is done by the manager. - true if succeeded, false if the client was not found - - : the notification client you want to unregister. - - - - < - - - NumNotificationClients function - the number of notification clients connected - - - - - < - - - GetNotificationClient function - a pointer on a or NULL if index is out of range - - : the index of the Notification clients to retrieve - - - - < - - - DebugPrintToFile function - - : a valid FILE pointer to print debug information to : all the notifiers, listeners and what they monitor - - - - Notifies the system of a render settings event. This method is used internally by the the application to broadcast a change in the scene's render settings. The notification system relies on this method to catch such events because there are no other, pre-existing methods (such as through BroadcastNotification()) for broadcasting such events. - - The type of event to be broadcast. - - - - Notifies the system of a render environment event. This method is used internally by the the application to broadcast a change in the scene's render environment. The notification system relies on this method to catch such events because there are no other, pre-existing methods (such as through BroadcastNotification()) for broadcasting such events. - - The type of event to be broadcast. - - - - Extends . - - - - - Notifies the system of a viewport event. This method is used internally by the the application to broadcast a change in the viewport. The notification system relies on this method to catch such events because there are no other, pre-existing methods (such as through BroadcastNotification()) for broadcasting such events. - - The type of event to be broadcast. - The id of viewport with the change - - - - Is a client where you get the notifications on demand, they are stored until you ask for them. - - - - - Returns the number of events currently waiting to be processed. - - - - - This function processes all events currently waiting in the queue. The queue is emptied in the process. - - The callback through which the events are processed, one by one. - - - - Monitor the active view whatever it is : a camera, a viewport or a light. This takes care of the lock/unlock view workflow for active shade. Also when the active view is changed to another view, the event is stored until you ask for the updates and the new view is monitored automatically - true if the active view is now monitored, false there was a problem - - an arbitrary pointer which is passed back, with the event, through . - - - - Stop monitoring active view - true if the active view is no longer monitored now, false if there was a problem - - the user data passed to the Monitor method. - - - - Is a notification client where you get the notifications on demand, they are stored until you ask for them. - - - - - Destructor. - - - Returns the number of events currently waiting to be processed. - - - - - This function processes all events currently waiting in the queue. The queue is emptied in the process. - - The callback through which the events are processed, one by one. - - - - Monitor this node events - true if the node is now monitored, false there was a problem - - the INode* to monitor. - the NotifierType for this node. - : bit array flags, the events you want to monitor for that node, you'll get called only called for the selected events. Example for 2 events is : UpdateType_Node_WireColor | UpdateType_Node_Transform; - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor this material events - true if the material is now monitored, false if a problem occurred - - the Mtl* to monitor. - : bit array that is the events flags you want to monitor for that material, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor this events - true if the texmap is now monitored, false if a problem occurred - - the to monitor. - bit array : the events flags you want to monitor for that texmap, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor events on a generic reference target. This is used to monitor notifications an an arbitrary class for which there doesn't exist a more specialized monitoring function (as there are for , , , etc.). - true if the reference target is now monitored, false if a problem occurred - - The reference target to be monitored. - : bit array (see enum ReferenceTargetEventType) that is the events flags you want to monitor for that material, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor viewport events such as transform matrix changes (when you move the camera viewport while it's a viewport and not a Max camera) - true if the view is now monitored, false if a problem occurred - - the viewport ID to monitor. - bit array : the events flags you want to monitor for this viewport, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor render environment events (Tone operator for example) - true if we monitor these events now, false if there was a problem - - bit array : the events flags you want to monitor for render environment, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor render environment events (Tone operator for example) - true if we monitor these events now, false if there was a problem - - bit array : the events flags you want to monitor for render settings, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Monitor scene events such as node added, file reset, file load, File import etc. - true if we monitor these scene events now, false if there was a problem - - bit array : the events flags you want to monitor for the scene, you'll get called only for the selected events - an arbitrary pointer which is passed back, with the event, through . - - - - Stop monitoring this node - true if the node is not monitored now, false if the node was not in our arrays - - the INode* to stop monitoring for events. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring this material - true if the material is not monitored now, false if the material was not in our arrays - - the Mtl* to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring this texmap - true if the is not monitored now, false if the was not in our arrays - - the Texmap* to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring a reference target Unregisters a previously registered notification callback. - true if the reference target is not monitored now, false if the was not in our arrays - - The reference target to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring this viewport - true if the view is not monitored now, false if the pView was not in our arrays - - the viewID of the viewport to stop monitoring. - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring render environment - true if it is not monitored now, false if it was not monitored - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring render settings - true if it is not monitored now, false if it was not monitored - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - Stop monitoring scene - true if these scene events are no longer monitored now, false if there was a problem - - : bit array flags, the events you want to stop monitoring, if you remove all the events we had recorded, we'll delete our internal data - the user data passed to the Monitor method. - - - - You receive a instance when something is changed in a : Events monitored : all related to reference targetss - - - - - Retrieve the ReferenceTarget*. - - - - - You receive a instance when some nodes have been added/removed to/from the scene Event monitored: EventType_Scene_Node_Added/EventType_Scene_Node_Removed - - - - - Events monitored : all related to texmaps. - - - You receive a instance when something is changed in a : - - - - - Retrieve the Texmap*. - - - - - You receive a instance when something dealing with the view has changed: Events received with that class : EventType_View_Transform or EventType_View_Active - - - - - Returns true if the active view is a camera or a light node, false if it's a viewport. - - - - - Returns the INode* of the new active view if it is a camera or a light node, NULL if it's a viewport. - - - - - Returns the newly active viewport. The pointer will not normally be null, but could be so in the case of an internal error. - - - - - Returns the 'view undo ID' associated with the active viewport, for internal use. - - - - - Is a data structure for parameter blocks updates, used with events such as : EventType_Material_ParamBlock, EventType_Node_ParamBlock, ... All related to paramblocks updates. - - - - - Retrieve the parameter block type (can be or or..) - - - - - Retrieve all the parameters updated in the parameter block. - - - - - Retrieve all the parameters names that were updated in the parameter block (whereever they come from references/custom attributes etc.) - - - - - Is a data structure for parameter blocks container information. - - - Retrieve the parameter block that was updated in the references or custom attributes or whatever of the Object* from the INode* or Mtl* or Texmap* etc... Example is a parameter from the shadow generator of a light node has been updated : m_ParamBlockType is the type of the param block such as PB1 or PB2 m_ParamBlockIndexPath contains the path to retrieve which parameter block was udpated. Example : if m_ParamBlockIndexPath contains 2 elements like : m_ParamBlockIndexPath[0].m_Type = CUSTOM_ATTRIBUTES; m_ParamBlockIndexPath[0].m_Index = 3; m_ParamBlockIndexPath[1].m_Type = REFERENCES; m_ParamBlockIndexPath[1].m_Index = 4; So to retrieve which paramblock was updated you have to use : Say, it's a node : INode* pNode = initialized somewhere; //Using minimal code checking for clarity ICustAttribContainer* custAttribCont = pNode->GetCustAttribContainer(); const int indexInCustAttr = m_ParamBlockIndexPath[0].m_Index; CustAttrib* custAttrib = custAttribCont->GetCustAttrib(indexInCustAttr); //Now get i-th reference from that custom attrib. using the index from m_ParamBlockIndexPath[1].m_Index const int indexInReferences = m_ParamBlockIndexPath[1].m_Index; RefTargetHandle pSubRefTarg = custAttrib->GetReference(indexInReferences); //And what we get now should be a paramblock of type PB_ONe or PB_TWO switch (m_Type){ case PB_ONE:{ IParamBlock* pblock1 = dynamic_cast<IParamBlock*>(pSubRefTarg); }break; case PB_TWO:{ IParamBlock2* pblock2 = dynamic_cast<IParamBlock2*>(pSubRefTarg); }break; } m_ParametersIDsUpdatedInThatParamBlock contains the ParamIDs(in case of type PB_TWO or the Param indices in case of type PB_ONE) which were updated m_ParametersNames contains all the parameters names that were updated wherever they come from so you can use only the names if you want. - - - - - is the parameter block container type - - - - - is the index in the array of container type (as an example say m_Type = REFERENCES, then m_Index should be used with Object* pObj; IParamBlock* pbock = pObj->GetReference(m_Index); - - - - - The class manages properties that OSL is interested in. - - - This class manages properties attached to 's (also known as "object properties" although they are actually on the object instance - i.e. ). This contains both the 'standard' properties like 'nodeHandle' and 'wireColor' but also any user-properties the user has added in the Property dialog. The latter has names prepended by the string "usr_". - Pass in an and get the class back, which contains the mapping of properties. There are two options: - The is retrieved from the pointer, and the values are then directly looked up in the INodeProperty's value member (pseudocode, example lacks error checking): - A slightly more optimized version could do this: - - - - - Get the properties for a particular - - - - - Check if the property manager is "enabled" from 3dsmax.ini. This flag is informational, and might be deprecated. - For the Scanline renderer implementation this being false means that it will not use the property manager. It doesn't in any way deactivate the use of these classes. - - - - - Invalidates the cache for a particular , or if NULL is passed, the cache for everything. The cache will be automagically rebuilt on the fly upon access. - - - - - The class handles object properties as used by OSL. - - - This is an to a particular value held by the . - - - - - Get the type of the parameter - - - - - Get the value, if the type is TypeInt - - - - - Get the value, if the type is TypeFloat - - - - - Get the value, if the type is TypeColor. Also used for points, vectors and normals - - - - - Get the value, if the type is TypeString. The value will be an ustring pointer. - - - - - for the 3ds MaxOSL global interface. This interface exposes methods that are not related to a particular OSL Map. - - - To retrieve the interface, use GetCOREInterface(id): This points to a global static singleton, so it only needs to be retrieved once. - - - - - Get the . - - - Returns the . - This points to a global static singleton, so it only needs to be retrieved once. - - - - - Returns the OSLMap instance and (optionally) its output name. - - - 3ds Max shading system does not inherently understand shaders with multiple outputs, and injects a hidden "Map Output Selector" behind every multi-output shader. This is hidden by the SME as a blue connection wire. But to be able to easily untangle this when connecting back inputs to a given output of an "OSL Map", this helper function allows one to get the map, and its output, based on a pointer. - Pointer to an OSL Map, or NULL if not an OSL Map - When the incoming is either a pointer to a "OSL Map" or a "Map Output Selector", the returned value will be the actual "OSL Map" plus (optionally, if output is non-NULL) the name of the output the is connected to on that "OSL Map". - The return value is NULL if the map pointed to by tex is not an "OSL Map", or the texture found behind the "Map Output Selector" is not an "OSL Map". - This function is useful when building an OSL tree representation in a 3rd party renderer. You walk the connected texmaps of a object, and use this function to know if this input is connected to an OSL Map, and if so, which output it is connected to. - The NULL return will indicate that the connection does not terminate in an "OSL Map", and will have to be treated differently (or rejected). - When a renderer wants to use its own OSL implementation, this function is used in conjunction with IOSLMapInterface::GetParameters to achieve this. - - - - - Returns the ustring token version of a string. - - - OSL code internally uses ustrings, which is a unique string class. The beauty of ustring is that once a given string been turned into a ustring, the same string will always return the same pointer. - Pass a string to this function, and get back the ustring version of that string, converted to a const char pointer (so as not to have to expose the ustring class to the interface). - This pointer is guaranteed to be the same for the same string, and hence string-compares can be relegated to pointer compares. - - - - - The for the 3ds MaxOSL Map interface. This interface exposes methods that relate to properties of a particular OSL Map. - - - To retrieve the interface, use GetInterface on the map: - - - - - Get the name of output x - - - - - Get the name of shader (not guaranteed to be unique in any way, just informational) - - - - - Get the OSL source code for this OSL Map - - - - - Get the OSO compiled byte-code for this OSL Map - - - - - Experimental, and of limited practical use: Get the converted HLSL of this OSL Map in the form of an HLSL function body. - - - - - Gets the HLSL conversion quality in percent. 100 doesn't mean the conversion is "perfect", it simply means that every operator in the OSO bytecode had some implementation that in itself didn't emit a warning in the conversion step. - - - - - Gets the pointer to the actual parameters of the OSL shader. - - - This will contain all the parameters as exposed by the OSL shaders. Note the following: - For renderers using their own OSL implementation, the work flow is as follows: - - - - - If a given parameter in the list returned by GetParameters() has TYPE_FILENAME, one uses this function to ask for the fully qualified path name. The function resolves the path also for UDIM filenames ("c:\foo\bar<UDIM>.exr"), something the regular 3ds Max resolver cannot do. The function is meaningless if the parameter is not of TYPE_FILENAME; in such case it will simply return an empty string. - - - - - for the 3ds MaxOSL Raytracing features, allowing OSL to use a 3rd party renderer's raytracing engine. - - - This interface should be exposed by the renderer on the it passes to the OSL Map's EvalColor/Mono/NormalPerturb() methods. The OSL Map rendering service callback for the OSL trace() call will get the interface with and call its IOSLRaytracingInterface::TraceRay method to perform raytracing. - - - - - The TraceRay call - to be implemented by the . - - - The OSL language contains a trace() call, and the renderer being used to render the OSL Map can choose to implement the trace() call in its own interal raytracing functionality. If this is not done, a fall back functionality is used, which is not very optimized (effectively, RenderGlobalContext::IntersectWorld is used!!). The needs to accept a GetInterface(MAXOSL_RAYTRACE_INTERFACE) on the it provides, and implement the and this function. - The function returns ReturnFlags and the HitSomething bit defines if the ray hits something or not. - If the OSL trace call has the "shade" value set, the TraceFlags::Shade bit is set. The other bits in the TraceFlags are currently unused and are reserved for future expansion. - In the Scanline renderer implementation, if TraceFlags::Shade=0, only hit_dist is filled in. However, if TraceFlags::Shade=1, the hit, hitCol and hitNormal are also filled in. These can be retrieved in the OSL code by doing respectively. - Note that getting "P" and "N" are part of the OSL specification, but the ability to get the "color" is an extension made by 3ds Max. - The function returns a TraceFlags bitmask of which currently only the HitSomething bit is defined, and means that the ray hit something. - - - - - The class is a container for properties that OSL is interested in. - - - This class is returned by the INodePropertyManager::GetProperties() for a particular , and allows querying which properties are available, and what values they have. - This contains both the 'standard' properties like 'nodeHandle' and 'wireColor' but also any user-properties the user has added in the Property dialog. The latter has names prepended by the string "usr_". - The lifetime of any 's returned are only guaranteed while the object itself is referenced. When it goes out of scope, the pointers may become invalid. - For more information and sample code, see - - - - - Returns a pointer for a given property name, or NULL if that property does not exist. If you know the name is already matching a UString pointer (which you can obtain from IOSLGlobalInterface::GetUString()) you can pass is_ustring = true. This removes a string hashing step, and is a good performance optimization if you choose to do these lookups at render time. - - - - - Returns the list of properties attached to this . These can be iterated through a GetValue() called for each. These pointers are ustrings, so is_ustring can be true in the GetValue() call, and they can be compared against previously stored ustring values. - - - - - Enum for the only four datatypes we support: Int, , (or any other three-valued OSL type like point/vector/normal) and - - - - - Bit values for the return value of TraceRay. - - - - - Bit values for the flags parameter of TraceRay. - - - - - is a simple wrapper class that holds an internal pointer to a particle flow slate model. Public particle flow actions/operators need to derive from this class when they want to show up in the new slate particle view. The memory management of the internal model is done by the wrapper. This wrapper class has been introduced temporarily in order to keep the MaxSDK clean from any appearances of the currently non public SlateSDK. When the SlateSDK is final this wrapper class can be replaced again, with it's according slate model class. - - - - - Sets the connection direction of the wrapped slate model. In case of a test operator it is Direction_Out for simple action operators its just Direction_None. - - The connection of the wrapped model. - - - - Helpers for the public maxsdk sample class PFOperatorDisplay. Notify slate model listeners like the ui controller about the color change, so that it can update the color of the slate color swatch. - - - - - Helpers for the public maxsdk sample class PFOperatorDisplay. Defines the display operator should use a slate color swatch for its UI edit control. - - - - - Helpers for the public maxsdk sample class PFOperatorDisplay. Updates visibility state of Swatch UI - - - - - Need to be called by NotifyTarget( int message, ReferenceMaker* hMaker ) in the object that derives from . It is internally used by slate to detect if the according for a particle flow action gets deleted. - - - - - This class lets control the amount of threading in different parts of Max */. - - - - - This method returns the actual number of threads to be used for a particular task depending on the number of elements. - - - This method returns the actual number of threads to be used for a particular task depending on the number of elements - - this is which part of you want to get the multi-thread level - is the number of elements in the loop to thread - - - - Just a helper class to record how long a task takes. Just call this at the start and EndTimer at the end will return the amount of time that has passed in milliseconds. - - - - - This methods let you start a local timer. Use these 2 methods if you are just timing a local block once. - - - - - This methods returns the amount of time in milliseconds that has passed since StartTimer. - - - - - Just a helper class to record how long a block of code. it starts a timer when constructed and stops when destructed. Useful for code block with lots of breaks and/or returns. - - - - - The interface for interacting with point cloud objects. - - - This interface provides methods for interacting with point cloud objects. For example, it provides a method to perform hit tests on point cloud objects and a method to get information about all visible point cloud vertices from a specified view. Users can get this interface by calling the GetInterface(IID_POINT_CLOUD) method for classes that implement this interface. - - - - - Return the total point count of the current point cloud file. - - - - - Return the visible point count in a specified viewport. - - - - - Block until all points are loaded. Pointclouds are loaded asynchronously. This function blocks until all the data is loaded. - - - - - Return the visible point count in the active viewport. - - - - - The interface for interacting with point cloud voxel nodes. The local space of a point cloud scan data is divided into many parts based on the distribution of point data, and each part is represented as a voxel node. This interface provides methods to get information about the point cloud vertices contained by the voxel node. This interface can be retrieved by calling the IPointCloud::CreateIPointCloudVisibleVoxelNodes method. - - - - - Get the node's bounding box in the point cloud object's local space. - - - - - A structure that contains the basic information about a point cloud vertex. - - - - - The vertex position in the point cloud local space. - - - - - The vertex color in RGBA. - - - - - The vertex normal in point cloud local space. - - - - - This is the interface class to Populate. It is a singleton class which is created upon 3dsMax start up. It manages all of the Populate operations. - - The following code sets some Populate parameters and simulates. It then selects all the simulated characters and sets them to high resolution. This code will only do something if Populate objects exist in the scene. Code to create Populate objects can be found in the , and documentation. - Example - - - - - A flow must be added to Populate in order for simulation to take place on it. The node won't be added if it is not a flow or it is already in Populate. - - - true if the flow was added, false if not - - - The flow node to be added - - - - Adds an idle area to Populate. - - - An idle area must be added to Populate in order for simulation to take place on it. The node won't be added if it is not an idle area or it is already in Populate. - - - true if the idle area was added, false if not - - - The idle area node to be added - - - - Adds a seat to Populate. - - - A seat must be added to Populate in order for simulation to take place on it. The node won't be added if it is not a seat or it is already in Populate. - - - true if the seat was added, false if not - - - The seat node to be added - - - - Updates the marks drawn on an idle area. - - - This will force the marks on an idle area to be recomputed. The node won't be updated if it is not an idle area or it is not in Populate. - - - true if the idle area was updated, false if not - - - The idle area node to be updated - - - - Shows or hides idle areas, flows, and seats. - - - - - true to show idle areas, flows and seats, false to hide them - - - - Returns whether or not the idle areas, flows, and seats are displayed. - - - - - Shows or hides marks on idle areas, flows, and seats. - - - - - true to show marks, false to hide them - - - - Returns whether or not marks on idle areas, flows, and seats are displayed. - - - - - a value between 0.0 and 1.0 indicating the probability the next seat created will be for a female - - - - - Sets the gender of the selected seats. - - - Uses the value of Seat Female Percent to set the gender - - - - - - - - - Returns the maximum angle at which seated people will talk to each other. - - - The angle is in degrees. - - - - - Returns the number of seated idlers. - - - - - Returns the number of pedestrians. - - - - - Returns a node from a standing idler, if there is one, NULL if not. - - - - - Returns a node from a seated idler, if there is one, NULL if not. - - - - - Returns a node from a pedestrian, if there is one, NULL if not. - - - - - - - - - Sets the display type of the characters. - - - - - - - - Shows or hides characters. - - - - - true to show characters, false to hide them - - - - Returns whether or not the characters are displayed. - - - - - Generates new meshes and texture maps for the selected characters. - - - If a pedestrian appears more than once, then only its appearance during time t will be changed. - - - time - - - - Swaps the appearance of the selected characters. - - - Only two characters of the same gender can be swapped. If a pedestrian appears more than once, all of its appearances will be changed. - True if successful, false if not. - - - - - Switches the mesh resolution for the selected characters. - - - High resolution characters will switch to low, and low resolution characters will switch to high. - - - - - Deletes all the characters. - - - - - Returns the number of frames to simulate. - - - - - Returns the turn optimization type - - - - - Computes a simulation. - - - Characters of the specified display type will appear on all the marks of the idle areas and flows, and on all the chairs. They will be animated for the specified number of frames. New characters will be spawned at the ends of the flows over time. Pedestrian spawning, speeds and genders will conform to flow parameters. - - - - - Resimulates all the selected standing or seated idle characters. - - - - - Returns the real world scale. - - - - - Returns the custom material for custom skinned characters. - - - - - Sets the Save Texture Maps flag. - - - - - true to save the texture maps, false to regenerate the texture maps on load - - - - Returns the value of the Save Texture Maps flag. - - - - - Shows the Appearance Dialog. - - - - - is the interface class to Populate flow objects. - Example - The following code creates a Populate flow, sets some if its parameters, and adds it to Populate. - - - - - Returns the path width. - - - - - Sets the path width. - - - - - the path width - - - - Returns the lane width. - - - - - Sets the lane width. - - - If the width is too large or small, it will be clipped to the allowable limits. - true if the width was successfully set, false if not - - - the lane width - - - - Returns whether or not the portals are unified (or linked) - - - If the portals are unified, portal 1 parameters apply to both portals, and portal 2 parameters are ignored. If the portals are not unified, portal 1 parameters apply to portal 1, and portal 2 parameters apply to portal 2. - - - - - Returns the lane weave type. - - - - - - - Sets the lane weave type. - - - true if the weave was successfully set, false if not - - - the lane weave type - - - - Returns the position randomization seed. - - - - - Sets the position randomization seed. - - - true if the seed was successfully set, false if not - - - the position seed - - - - Returns the gender randomization seed. - - - - - Sets the gender randomization seed. - - - true if the seed was successfully set, false if not - - - the gender seed - - - - Density is a value between 0.0 and 1.0, 0 meaning the portal releases no characters, and 1 meaning the portal releases the maximum allowable number of characters - - - time at which the density is retrieved - - - - Sets the flow density at the specified time. - - - Density is a value between 0.0 and 1.0, 0 meaning the portal releases no characters, and 1 meaning the portal releases the maximum allowable number of characters - true if the density was successfully set, false if not - - - time at which the density is set - - density of the flow at time t - - - - Returns the flow speed at the specified time. - - - Speed is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - - - time at which the speed is retrieved - - - - Sets the flow speed at the specified time. - - - Speed is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - true if the speed was successfully set, false if not - - - time at which the speed is set - - speed of the pedestrians at time t - - - - Returns the percent of runners at the specified time. - - - Running percent is a value between 0.0 and 1.0, 0 meaning the portal releases no running pedestrians, and 1 meaning the portal releases all running pedestrians. - - - time at which the running percent is retrieved - - - - Sets the percent of runners at the specified time. - - - Running percent is a value between 0.0 and 1.0, 0 meaning the portal releases no running pedestrians, and 1 meaning the portal releases all running pedestrians. - true if the run percent was successfully set, false if not - - - time at which the running percent is set - - percent of running pedestrians at time t - - - - Returns the percent of females at the specified time. - - - Gender percent is a value between 0.0 and 1.0, 0 meaning the portal releases all males, and 1 meaning the portal releases all females. - - - time at which the gender percent is retrieved - - - - Sets the percent of females at the specified time. - - - Gender percent is a value between 0.0 and 1.0, 0 meaning the portal releases all males, and 1 meaning the portal releases all females. - true if the gender percent was successfully set, false if not - - - time at which the gender percent is set - - percent of females at time t - - - - Density is a value between 0.0 and 1.0, 0 meaning the portal releases no characters, and 1 meaning the portal releases the maximum allowable number of characters - - - time at which the density is retrieved - - - - Sets the flow density of portal 2 at the specified time. - - - Density is a value between 0.0 and 1.0, 0 meaning the portal releases no characters, and 1 meaning the portal releases the maximum allowable number of characters - true if the density was successfully set, false if not - - - time at which the density is set - - density of the flow at time t - - - - Returns the flow speed of portal 2 at the specified time. - - - Speed is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - - - time at which the speed is retrieved - - - - Sets the flow speed of portal 2 at the specified time. - - - Speed is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - true if the speed was successfully set, false if not - - - time at which the speed is set - - speed of the pedestrians at time t - - - - Returns the percent of runners released from portal 2 at the specified time. - - - Running percent is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - - - time at which the running percent is retrieved - - - - Sets the percent of runners released from portal 2 at the specified time. - - - Running percent is a value between 0.0 and 1.0, 0 meaning the portal releases slow pedestrians, and 1 meaning the portal releases fast pedestrians. - true if the run percent was successfully set, false if not - - - time at which the running percent is set - - percent of running pedestrians at time t - - - - Returns the percent of females released from portal 2 at the specified time. - - - Gender percent is a value between 0.0 and 1.0, 0 meaning the portal releases all males, and 1 meaning the portal releases all females. - - - time at which the gender percent is retrieved - - - - Sets the percent of females released from portal 2 at the specified time. - - - Gender percent is a value between 0.0 and 1.0, 0 meaning the portal releases all males, and 1 meaning the portal releases all females. - true if the gender percent was successfully set, false if not - - - time at which the gender percent is set - - percent of females at time t - - - - Returns the number of points in the center line of the flow. - - - - - Returns the specified point. - - - - - the index of the retrieved point - - - - Returns true if a valid flow will result from the point being appended to the flow and false if not. - - - - - the point to be potentially added - - - - Appends a point to the flow. - - - - - the point to be added - - - - Returns true if a valid flow will result from the point being inserted at the specified index, and false if not. - - - index == 0 will insert at the start of the flow, and index == numpts will append past the end of the path. - - - the index at which the point will be inserted - - the point to be potentially inserted - - - - Inserts a point in the flow. - - - index == 0 will insert at the start of the flow, and index == numpts will append past the end of the path. - true if the point was successfully inserted, false if not - - - the index at which the point will be inserted - - the point to be inserted - - - - Sets a point in the flow. - - - A point at the start or end of a ramp cannot be set with this method. - true if the point was successfully set, false if not - - - the index of the point to be set - - the point to be set - - - - Deletes a point in the flow. - - - Points at ramp creases cannot be deleted with this function. - true if the point was successfully deleted, false if not - - - the index of the point to be deleted - - - - Selects or deselects a point in the flow. - - - true if the operation was successful - - - the index of the point to be selected - - the value to set the point's selected property to. to true to select, false to de-select. - - - - Creates a ramp. - - - The ramp will be created flat inside the segment, adding two new points inside the specified segment, with the ramp in between the two new points and the landing segments on either side. If it's impossible to create a ramp in the specified segment, it will not be created. - true if the ramp was successfully created, false if it is not possible to create a ramp in this segment - - - the index of the segment in which the ramp will be created - - - - Deletes a ramp. - - - The ramp whose starting crease is at the specified index will be deleted. Both ramp crease points will be deleted. - - If the resulting flow is on two levels, it will be broken up into two flows. - true if the ramp was successfully deleted, false if it is not possible to delete the ramp - - - the index of the starting crease of the ramp to be deleted - - - - Returns whether or not the specified index is at the starting crease of a ramp. - - - - - the index to check - - - - Returns whether or not the specified index is at the start of a ramp landing segment. - - - A ramp landing is the segment before or after a ramp. - - - the index to check - - - - Returns the crease percent. - - - The crease percent is a value between 0.0 and 1.0, indicating how far the crease is between the start of the first landing and the end of the second landing. - - - the index of the crease - - - - Sets the crease percent. - - - The crease percent is a value between 0.0 and 1.0, indicating how far the crease is between the start of the first landing and the end of the second landing. - - The first crease percent must have a lower value than the second crease percent. - true if the crease percent was successfully set, false if it was not possible to set the percent to the specified value - - - the index of the crease - - a value between 0.0 and 1.0 - - - - Sets points to be creases. - - - For internal use only. This is very dangerous because it doesn't check ramp validity when it creates creases. - - - - - When you add, insert, set, or delete points, or add, delete or change a ramp, an internal flag is set indicating that the flow has changed and the sides need to be recomputed. You can call this function to recompute them, or they will be recomputed when the flow is displayed. Computation causes the internal flag to be reset. - true if the flow is usable, false if not - - - if true, the sides will be computed, if false, the sides will only be computed if the flow has changed since the last side computation - - - - Returns whether or not the flow is usable. - - - An unusable flow displays without lanes or marks, and with orange edges in the viewport, and no simulation will take place on it. - - - - - Returns the default path width. - - - - - Returns the color of the edges of an unusable flow. - - - - - Temporarily stores the flow points. - - - You can store the points before changing them, check the flow validity, and if they are invalid, restore them. However, since the functions which edit the flow are undoable, this function is not terribly useful and is only used internally in special cases. - - - - - Restores the temporarily stored points. - - - You can store the points before changing them, check the flow validity, and if they are invalid, restore them. However, since the functions which edit the flow are undoable, this function is not terribly useful and is only used internally in special cases. - - - - - is the interface class to Populate idle area objects. - The idle area object is a scripted plugin that can be found in: stdplugs\stdscripts\IdleAreaObject.ms. Because it is a scripted plugin, the interface to it is different than a standard class interface. - Also, Idle Areas inherit from class. To create or edit their geometry, you have to access the base edit poly object. - Example - The following code creates a rectangular Populate idle area, sets some if its parameters, and adds it to Populate. - - - - - Sets the internal reference to the idle area object. - - - This function must be called, and must return true, in order to use any of the other functions. - - - an object of class - - - - Returns the area density, a value between 0.0 and 1.0. - - - - - Sets the area density. - - - - - a value between 0.0 and 1.0 - - - - Returns the percent of groups in the area, a value between 0.0 and 1.0. - - - - - Sets the percent of groups in the area. - - - - - a value between 0.0 and 1.0 - - - - Returns the percent of pairs in the area, a value between 0.0 and 1.0. - - - - - Sets the percent of pairs in the area. - - - - - a value between 0.0 and 1.0 - - - - Returns the percent of females in the area, a value between 0.0 and 1.0. - - - - - Sets the percent of females in the area. - - - - - a value between 0.0 and 1.0 - - - - Returns the base orientation of single characters, an angle in degrees. - - - - - Sets the base orientation of single characters. - - - - - an angle in degrees - - - - Returns the maximum random variation from the base orientation of single characters, an angle in degrees. - - - - - Sets the maximum random variation from the base orientation of single characters. - - - - - an angle in degrees - - - - Returns whether or not the single characters on the area are facing the look at object. - - - - - Sets whether or not the single characters on the area are facing the look at object. - - - - - - - - Returns the area look at object. - - - - - Sets the area look at object. - - - - - - - - Returns the position randomization seed. - - - - - Sets the position randomization seed. - - - - - - - - Returns the singles randomization seed. - - - This seeds the random placement of singles characters. - - - - - Sets the singles randomization seed. - - - This seeds the random placement of singles characters. - - - - - - Returns the orientation spread randomization seed. - - - - - Sets the orientation spread randomization seed. - - - - - - - - Returns the gender randomization seed. - - - - - Sets the gender randomization seed. - - - - - - - - Returns the motion randomization seed. - - - - - Sets the motion randomization seed. - - - - - - - - is the interface class to Populate seat objects. - Example - The following code creates a Populate seat, sets a seat parameter, and adds it to Populate. - - - - - Returns the seat gender. - - - - - - - Returns whether or not the person on the seat will be single. - - - If single, the person on the seat will be simulated not interacting with anyone else, not talking or listening to another seated character. Otherwise, the simulation will decide if the person should interact or not, and with whom. - - - - - Returns the seat height. - - - - - Figure Display Types. - - - - - Turn Optimization Types. - - - Each of these options specifies an algorithm used to decide which way a character will turn when it reaches an intersection. - - - - - Lane Weave Types. - - - - - Seat Gender Types. - - - - - Base class for translating the scene camera. This base class provides basic, common functionality related to translating the scene camera. It handles: - - - - - Base class for translating an environment. This base class provides basic, common functionality related to translating an environment. It handles: - - - - - Base class for translating an . This base class provides basic, common functionality related to translating an . It handles: - - - - - Resolves the given material by discarding any "wrapper" materials that should be ignored by the renderer. For example, in the case of a Shell material, this returns the Shell's sub-material that is flagged for rendering. This method may be overridden if necessary, to add support for renderer-specific behaviour. - The resolved material, free of wrappers which the renderer may not understand directly. - - The material to be resolved (or un-wrapped). - - - - Enables the implementation to override what notification messages it wants to invalidate this translator. - True if the event needs to evaluate this translator, false otherwise - in which case the event is ignored. - - The event type to potentially filter. - - - - Enables the implementation to specify to determine whether it cares about a specific node property changing. This method covers the properties PART_REND_PROP_*. - - - - - Enables the implementation to specify to determine whether it cares about a specific node property changing. This method covers the properties PART_DISP_PROP_*. - - - - - Enables the implementation to specify to determine whether it cares about a specific node property changing. This method covers the properties PART_GI_*. - - - - - Returns whether this translator translates a mesh for which we need to care if UVW channels are required by the material but missing on the mesh. These missing UVW channels will be automatically reported by the system. - - - - - Returns the UVW channel IDs which are used by the mesh that this node references. This is used to determine whether the node's material is dependent on any missing channels, for error reporting purposes. This is called in PostTranslate(), so it's recommended tha the list of UVW channels IDs be cached during the translation of the object. - This is only called if CareAboutMissingUVWChannels() returns true. - - - - - Returns the set of material IDs referenced by this mesh. This is used to determine whether the node's material is dependent on any missing channels, for error reporting purposes. - This is only called if CareAboutMissingUVWChannels() returns true. - - - - - Notifies that the object, being instanced by the pool, has changed and needs to be re-translated. For example, would be called if the mesh of the instanced object were to change. - - The pool which is sending the notification. - The type of event that triggered this notification. - - - - Base class for translating a material. This base class provides basic, common functionality related to translating a material. It handles: - - - - - Base class for translating a . This base class provides basic, common functionality related to translating a . It handles: - - - - - Base class for translating the object referenced by a node instancing pool. This base class provides basic, common functionality related to translating the object referenced by an . It handles: - - - - - Returns whether this translator takes into account displacement properties from the material. That is, whether a change in the material's displacement properties should cause this translator to be invalidated. - - - - - Notifies that the object, being instanced by the pool, has changed and needs to be re-translated. For example, would be called if the mesh of the instanced object were to change. - - The pool which is sending the notification. - The type of event that triggered this notification. - - - - Base class for translating an arbitrary . This base class provides basic, common functionality related to translating a . It handles: - - - - - Base class for translating a . This base class provides basic, common functionality related to translating a . It handles: - - - - - Abstracts the common properties of the camera to be rendered. - This container wraps and abstracts the camera to be rendered, whether it be a Standard, Physical, or viewport camera. The logic for interpreting a camera , , and are conveniently hidden away by this class. Additionally, This class provides a unified mechanism for notifying of changes in the camera properties. - - - - - Returns the physical camera being used, if one is being used at all - or null otherwise. The physical camera exposes additional, advanced parameters which are not generic enough to be exposed directly by . - - The time value at which the camera node is evaluated to extract the physical camera. - - - - Evaluate the motion transform for the camera. - - The time at which to evaluate the transform. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - The optional motion blur settings to used when evaluating the transform. If null is passed, then the camera's and node's motion blur settings are used, just as . - - - - Returns the projection type used by the camera. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the field-of-view of the camera, in radians. - Only valid for perspective cameras. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the width of the orthographic aperture, in system units. - Only valid for orthographic cameras. - The ratio between the aperture width and height is image aspect ratio. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the height of the orthographic aperture, in system units. - Only valid for orthographic cameras. - The ratio between the aperture width and height is image aspect ratio. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns whether Depth-of-Field is enable on the camera. - Only valid for perspective cameras. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the focal length of the lends, in system units. - Only valid for perspective cameras. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the distance to the focus plane, in system units. This is the distance at which the lens is focused, not to be confused with the lens focal length. - Only valid for perspective cameras. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the lens' aperture radius, in system units. This is the absolute radius, not the f-stop. - Only valid for perspective cameras. - Returns 0 if the camera does not specify the lens aperture size (not all cameras do). - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the clipping planes are enabled - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the distance to the near clipping plane, in system units. - returns 0 if clipping planes are disabled. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the distance to the far clipping plane, in system units. - returns std::numeric_limits<float>::max() if clipping planes are disabled. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the resolution of the image to be rendered. - This is identical to the resolution of the returned by GetBitmap(). - - - - - Returns the pixel aspect ratio of the image to be rendered. - The image aspect ratio is: pixel_aspect_ratio * resolution.x / resolution.y - - - - - Returns the bitmap to which the image is to be rendered. - Progressive renderers should generally not render into this directly, as this may cause artifacts when saving the image while it is being rendered. Instead, they should render to an internal frame buffer and using IRenderSessionContext::GetMainFrameBufferProcessor() to copy the buffer to the bitmap. - - - - - Returns the region to be rendered. The renderer should only render pixels within this region; pixels outside the region should generally not not be overwritten in the . - The region covers the entire image if region rendering is not being used; the region is thus guaranteed to be clipped to the current resolution and to be at least one pixel in size. - The box is relative to the upper-left corner of the image (i.e. upper-left is (0,0)). - The region is inclusive: the last row/column of the region must be rendered. - - - - - Returns the X-Y offset of the canvas to be rendered, in the image planes, as number of pixels. The offset is expressed as floating-points as it may include fractions of a pixel. - The offset is relative to the upper-left corner of the image (i.e. upper-left is (0,0)). - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns a structure that may be passed GeomObject::GetRenderMesh(). - The that is returned does not implement View::CheckForRenderAbort(), as this method is not supported by the RenderingAPI in general. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns a structure, initialize with the camera's properties. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the scene motion blur settings specified by the camera. - These are the settings to be used for the scene, not the settings for the camera's own motion blur. - - The time value at which to evaluate the camera. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Unregisters a notification callback, previously registered with RegisterChangeNotifier(). - - - - - Aggregates the properties related to environment and background mapping. - This container aggreates the properties of the environment and background maps associated with a scene. The exact source from which these are collected is abstracted, thus conveniently hiding any future evolution in 3ds Max's support for environment, background, and backplate mapping. - - - - - Returns the mode in which the background should operate. - - - - - Returns the background texture, to be used if and only if the background mode is set to BackgroundMode::Texture. - - - - - Returns the background color, to be used if and only if the background mode is set to BackgroundMode::Color. - - The time value at which to evaluate the color, which may be animated. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Returns the mode in which the environment should operate. - - - - - Returns the environment texture, to be used if and only if the environment mode is set to EnvironmentMode::Texture. - - - - - Returns the environment color, to be used if and only if the environment mode is set to EnvironmentMode::Color. - - The time value at which to evaluate the color, which may be animated. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - interface for processing the contents of an frame buffer. - This interface abstracts functionality for processing the contents of a frame buffer - typically for storing a frame buffer into an output representation. The most common use case should be to transfer the contents of a renderer's internal frame buffer into a 3ds Max, in a thread-safe and efficient manner. - - - - - Processes the given frame buffer. The exact behaviour of this method is defined by the particular implementation of this interface. For example, class IRenderSessionContext returns a frame buffer processor which transfers the data to the output . But other implementations could, for example, store the result in a render element , or to an entirely different output device. - True on success. False on error, generally if IFrameBufferReader::GetPixelLine() has returned false. - - Whether the active should be applied to the contents of the frame buffer. - The time at which the will be evaluated. - The interface, implemented by the caller, from which the frame buffer data is extracted. The implementation would typically fetch the pixels from the renderer's internal frame buffer. - - - - An interface which encapsulates a render session for interactive rendering. - This render session is allocated for the duration of an ActiveShade session. It is created when the user initiates the ActiveShade render, and destroyed when the user terminates the ActiveShade process; these correspond roughly to calls to IInteractiveRenderer::BeginSession and IInteractiveRenderer::EndSession. - - - - - Initializes the interactive rendering session. This method is called once, from the main thread, just after the is instantiated. The implementation should perform initial setup of the renderer, for example the initial translation of the scene. If any dialogs or pop-ups need to be shown to the user in case of scene errors, missing files, etc. - this is the place to do it. Modal interruptions of the interactive workflow should not occur beyond this initialization phase. - This method may start the renderer, but should neither block nor wait for any reason. It should not perform frame buffer updates. - True on success. False if initialize fails, causing the render session to be aborted and destroyed. - - The time at which the scene is to be translated. - - - - Updates the interactive session at regular intervals. This method is polled continuously to update the render session. This update normally consists of: - This method is called from a dedicated thread - not from the main thread. It's therefore unsafe to access the 3ds Max scene in any way. To perform tasks which require the main thread, use IRenderingProcess::RunJobFromMainThread(). - This method is polled continuously, without any explicit wait between calls. It's the implementation's responsibility to wait for some milliseconds if it has nothing to do. Failing to do so will cause the thread to run at 100% usage and will impact rendering performance. - True on success. False on error of any kind, causing the render session to be aborted. - - The time at which the scene should be updated. This could differ from either that passed to the last call to this method, or to InitializeInteractiveSession(). A time change should be interpreted as the user moving the time slider. The render session must then update any scene element which is invalid at the new time. - A boolean which must be set to , by this method's implementation, if rendering has finished. The state of being is reversible: this method will continue to be called after the renderer is done, and the renderer is allowed to react to scene changes and restart rendering (at which point it will stop reporting itself as ). There are mechanisms that rely on interactive renderers correctly reporting when they are done - for example a script that would save the image once it's fully rendered. - - - - Requests that the rendering process be aborted as the session is being terminated. This method is called when the session needs to be terminated, just before the is destroyed. - UpdateInteractiveSession() is guaranteed never to be called either during or after this call. - This method is called from the main thread. - - - - - Returns whether there are interactive changes which have not yet been taken into account by the renderer This state may be used, for example, by scripts which wish to wait until rendering is done (see UpdateInteractiveSession()) and all pending scene changes have been processed, before they save the rendered image. - This is called from the main thread, and as such may be called concurrently with UpdateInteractiveSession(). It should therefore be thread safe. - - The time at which to check for scene validity. If the scene was updated/translated at a different time value, then it might not be valid for this one. - - - - An interface which encapsulates a render session for offline (non-interactive) rendering. - This render session is allocated for the duration of an offline rendering session, which consists of rendering one or more animation frames, without the possibility of the user interacting (modifying) with the scene while the renderer is active. This interactive is created when the user initiates an offline render, and destroyed when the rendering operation is completed; this corresponds roughly to calls to Renderer::Open() and Renderer::Close(). - - - - - Translates or updates the scene at the given time. This method is called once per frame to translate (on first frame) or update (on further frames) the scene, in preparation for the frame about to be rendered. It's important that the scene translation be handled by this method (and not by RenderOfflineFrame()), because there are certain system events that must occur between translation and rendering. These system events are handled by the system. - True on success. False on failure, for any reason - in which case the rendering process will be aborted. - - The time at which the scene is to be translated. - - - - Renders a single frame of an animation sequence. This is called to render a single frame of an animation sequence, following a call to TranslateScene (not quite immediately, a few things occur in between). Before returning, this method is expected to update the frame buffer with the rendered result (see ICameraContainer::Bitmap()). - True on success. False on failure, for any reason - in which case the rendering process will be aborted. - - The time at which the frame is being rendered (same value passed to the previous call to ). - - - - Processes render elements, one by one, after a frame has been rendered. Following a successful call to RenderOfflineFrame(), the system iterates over all active render elements and calls this method for each. The implementation is expected to store the result, for each element is supports, using the provided frame buffer processor. Any unsupported render elements should simply be skipped, in which case the renderer may output an error message if it so desires. - The render session may skip this mechanism and process its render elements results in the call to RenderOfflineFrame(), if it wishes. It should, then, simply return true from this method. The render elements should then be fetched using IRenderSessionContext::GetRenderElements(). - True on success. False on failure, for any reason - in which case the rendering process will be aborted. - - The time at which the frame is being rendered (same value passed to the previous call to ). - The render element to be processed. - The interface through which the frame buffer is to be stored. This is optional: the renderer may store the the result directly into the render element's , if it wishes so. - - - - Stops the progressive rendering process at the next possible iteration. See Renderer::StopRendering(), from which this call is forwarded. - - - - - Pauses the rendering process. See Renderer::PauseRendering(), from which this call is forwarded. - - - - - Resumes the rendering process, following a pause. See Renderer::ResumeRendering(), from which this call is forwarded. - - - - - The Rendering API's interface for logging messages against 3ds Max build-in mechanisms. - This interface abstracts 3ds Max's internal message logging interfaces for the needs of a renderer. Internally, it logs the messages to the render message window, as well as to file, as necessary. - - - - - Logs a message. - - The type/category of the message. - The actual message. - - - - Logs a message which should only reported once per render session. Certain errors or events may be encountered numerous times during a translation or rendering process, and it may be undesirable to spam the user with identical, duplicate (error) messages. This method keeps a record of all the messages it has processed, ignoring all duplicates. - To reset the state of the logger, i.e. enable reporting duplicate messages again, this interface must be destroyed and re-created. - - The type/category of the message. - The actual message. - - - - The Rendering API's interface for managing the render process. - This interface abstracts various tasks related to the rendering process: The interface's implementation of these tasks is specialized for the rendering API, and should be used rather than existing (more general) 3ds Max SDK equivalents (such as ). - - - - - Sets the progress title, displayed in the render progress dialog. - It's a good idea to reset the progress title (to an empty string) once a task is done - to avoid lingering, invalid titles. - The title string is also passed to the message logging system. - This method may safe be called from any thread, but not concurrently as it contains no locking. - This method must not be used for reporting while scene translation is in progress. Instead, use class . - - The string to display as the progress title. - - - - Sets the numerical progress to be displayed in the progress dialog. - The progress is not reported to the logging system, so it is a good idea for the render session to also report progress messages. - This method may safe be called from any thread, but not concurrently as it contains no locking. - This method must not be used for reporting while scene translation is in progress. Instead, use class . - - The number of units of work which are done. Current progress is expressed as: . - The number of units of work in total. Current progress is expressed as: . - The type of progress being reported. The system may report both types of progress differently. - - - - Reports progress for an infinite render. This method is used to report the number of work units performed, when there is no set limit - i.e. the renderer will progress indefinitely, until explicitly stopped by the user. The progress dialog will set itself up with an infinite/ongoing progress bar. - This method must not be used for reporting while scene translation is in progress. Instead, use class . - - The number of units of work which are done. - The type of progress being reported. The system may report both types of progress differently. - - - - Sets the scene statistics which get displayed in the render progress dialog. See RendProgressCallback::SetSceneStats(). - - - - - Reports a UVW channel is required but missing on the given geometric object. A translator may determine that it requires a certain UVW channel to be present (because a texture may be dependent on it). If the channel is not present on the mesh, then it should report it using this method. The system will automatically report the error using the standard mechanisms - though only for offline rendering (MEdit and ActiveShade do not report an error). - - The node which references the mesh for which a UVW channel is missing. - The ID for the UVW channel which is missing. - - - - Returns whether the user has requested that the renderer abort. This method is to be polled at regular intervals by the renderer to determine whether the user has requested that the renderer abort. If it returns true, then the renderer should terminate as soon as possible, regardless of how far the rendering process has progressed. It is perfectly fine to have a partial or otherwise invalid frame buffer when aborting. - Once a render session has been aborted, that session will no longer be used for rendering: it is destroyed. It is therefore OK for the render session to assume it will no longer be used. - If the renderer has been paused, then this method may block until the renderer is resumed. This is the legacy, passive method for pausing a renderer. - True if the an abort has been requested. False otherwise. - - - - - To be called when the render session starts translating the scene. This method reports a progress message and starts a timer. - - - - - To be called when the render session finishes translating the scene. This method reports a progress message and the total time used for translating the scene. - - - - - To be called when the render session starts rendering the scene. This method reports a progress message and starts a timer. - This method should also be called if the renderer is restarted, such as following a scene update. - - - - - To be called by the render session when it effectively pauses the renderer. This method reports a progress message and pauses the rendering timer. - This method does nothing if the renderer is already paused. - - - - - To be called by the render session when it effectively resumes the renderer, following a pause. This method reports a progress message and resumes the rendering timer. - This method does nothing if the renderer is not already paused. - - - - - To be called when the render session finishes, aborts, or stops rendering the scene. This method reports a progress message and the total time used for rendering. - This method does nothing if the render was not currently running (paused is considered running). - - - - - Returns the elapsed translation time, as delimited by calls to TranslationStarted() and TranslationFinished(). - May be called while tranlsation is active (i.e. before TranslationFinished() has been called). - The elapsed translation time, in seconds. - - - - - Returns the elapsed rendering time, as delimited by calls to RenderingStarted() and RenderingFinished(). - May be called while rendering is active (i.e. before RenderingFinished() has been called). - The elapsed rendering time, in seconds. - - - - - Creates a new timer with the given name, and starts that timer. If a timer with that name already exists, then it is resumed (un-paused). - The timer may be sopped/paused by calling StopTimer() with the same timer name. - Consider using class to more easily start and stop timers. - - The name of the timer, which will be reported to the user (through the log system) at the end of the rendering operation. An empty name causes the call to no-op. - - - - Stops the timer with the given name. - - - Stops the existing timer with the given name. - The time is actually paused, and may be re-started by calling StartTimer() again with the same timer name. - - The name of the timer, which will be reported to the user (through the log system) at the end of the rendering operation. An empty name causes the call to no-op. - - - - Returns the total time accumulated for the timer with the given name. - - - Calling this method on a timer which is currently running is perfectly valid; the current running time will be correctly queried. - - The name of the timer for which to retrieve the running timer. - - - - Cancels all pending main thread jobs, preventing further jobs from running. This must be called by an offline renderer when it cancels its render in order to avoid deadlocks. When a render is aborted, some render threads may be waiting on a main thread job to finish executing - for example through logging, progress reporting call, or bitmap update. To avoid a deadlock, where the main thread would be waiting for the renderer to abort which would in turn be waiting for main thread jobs to finish, it's crucial that the offline render session call this method before it starts waiting for the renderer to finish. Calling this method causes all calls to RunJobFromMainThread() to return false. - This method is only to be called from the main thread. - - - - - Runs a job from the main thread. The 3ds Max SDK is generally not thread safe. Most SDK operations, such as scene translation/update, must therefore be done from the main thread. Because the render session will not necessarily operate from the main thread (e.g. IInteractiveRenderSession::UpdateInteractiveSession()), this method provides a simple mechanism for execute an arbitrary job from the main thread. - This call is synchronous: it returns once the job has completed or has been aborted. - If the render session is aborted, then pending jobs are cancelled and this method returns false. - If this method is called from the main thread, then the job is immediately executed with no synchronization overhead. - Consider calling CancelMainThreadJobs(), when aborting an offline render, to avoid deadlocks. - True if the job executed successfully, false if the job didn't execute because the render session was aborted. - - - - - Common base class for and - A render session is a temporary object which manages the render processing for renderer plugin. Whereas the renderer plugin manages the user-visible parameters and file I/O, the session manages the act of rendering. A session is created when a user starts rendering, and then destroyed when rendering is finished - enabling simple lifetime control for the contents of the renderer. - Multiple render sessions may exist, in parallel, for a single renderer plugin. This enables, for example, the material editor to render previews while an interactive (ActiveShade) session is active. - - - - - Abstracts the set of settings and parameters which may affect rendering. - This interface exposes commonly used render settings in a way that abstracts the differences between offline and interactive rendering. For offline rendering, most of these parameters are internally extracted from class . For interactive rendering, they are queried from the appropriate source. - Note that many of the classical 3ds Max rendering settings, from the common render settings panel, are not exposed here. Those parameters are, for the most part, considered specific to the legacy scanline renderer and are generally ignored by the Rendering API. - - - - - Returns the (a.k.a. exposure control) plugin to be used by the render session. - Consider letting the system process the , via IRenderSessionContext::GetMainFrameBufferProcessor(). - The to be used by the render session, or null if none. - - - - - Returns the physical scale to be used. - The physical scale is used to convert non-physical lighting quantities to physical ones, mainly textures used for environment lighting and self-illumination. For a self-illumination texture, the default physical scale of 1500 would map a white texel (RGB 1,1,1) to 1500 cd/m2 (477 cdm2). - Note that the physical scale works in a backwards manner: rather than multiply non-physical values by the scale, physical values must be divide by the scale. This brings all values into generic, non-physical space. Following rendering, the internally multiplies all values by the physical scale, thus bringing all values values back to physical space. This backward implementation is meant to ensure compatibility with legacy, non-physical plugins which do not know about the physical scale. A simple alternative is to divide the frame buffer values, by the physical scale, before they are passed to the . - The physical scale to be used for converting non-physical lighting values to physical ones. - - The time at which to evaluate the physical scale. - [in, out] The validity of the returned value is intersected into the input value of this parameter. - - - - Unregisters a notification callback, previously registered with RegisterChangeNotifier(). - - - - - Returns whether only selected objects should be rendered. - This options is, internally, taken into account by ISceneContainer::GetGeometricNodes(). - - - - - Returns the duration, in time ticks, of a single animation frame. This value is mostly useful for motion blur: it may be used to determine the time values for the shutter open and close times. - Consider using ICameraContainer::GetGlobalMotionBlurSettings() to get shutter time values for motion blur. - - - - - Returns whether the session is rendering a preview for he material editor or browser. - - - - - Returns the render target type for which the render session was created: offline, interactive, material editor, etc. - - - - - Returns the renderer from which the render session was created. - - - - - Manages the translation graph for a scene. - The translation manager is responsible for maintaining the translation graph for a scene. It should be created by the render session that wishes to use the translation component of the Rendering API. Once created, this interface enables the creation of the root of the translation graph - the scene translator, which then serves as the anchor point for the translation of the whole scene. - This interface is implemented by the system. An instance of the interface can be obtained from IRenderSessionContext::GetTranslationManager(). - - - - - Updates the translation graph anchored at the given root. This method traverses the translation graph, starting at the given root, and updates (re-translates) every node which is not valid at the given time value. - This method may be called from any thread. Internally, the work will be performed from the main thread. - The result (success or failure) of the update. - - The root translator node at which to start the traversal. This has to be a root translator, as returned by . - The time at which to update the scene translation graph. - - - - Checks whether any part of the translation graph is invalid at the given time. - True if any node, in the translation graph, is invalid at the given time. False otherwise. - This method performs no acccess to the 3ds Max scene; it merely traverses the translation graph and checks for its validity. Consequently, it's safe to call it from any thread. But there is no locking in place, so the translation manager should not be accessed in parallel by another thread. - - The root of the translation graph to be checked. - The time value at which to check for validity. - - - - Releases a reference to a root translator. Root translators are reference counted. Acquiring one through TranslateScene() increments its reference count, which must then be decremented using this method. - The released root translator should no longer be accessed following this call. - This call may result in the deletion (garbage collection) of parts or all of the translation graph, depending on whether the reference count of the root node goes to 0. - - The root translator to be released. - - - - used for progress reporting by translators. - Translators must use this interface to report progress; they shouldn't use directly. This is to ensure stability when translating for an interactive render session. When updating the UI tho show the new progress status, window messages get processed; these messages may represent user input which will in turn be processed into scene modifications. The modifications may interfere with the translation process. For example, if the user hits the delete key, and that command gets processed while updating the progress bar, then a scene object may get deleted while it's still being accessed by the translator. This interface includes special checks to warn the translator of such situations, through the abort_immediately parameter of the method it exposes. - - - - - This method is equivalent to IRenderingProcess::SetRenderingProgressTitle(), but contains additional handling to abort translation if a scene change occurs while processing the UI messages. - - The string to display as the progress title. - [out] If set to true (by the system), the caller the translation that is currently in progress: no further access to the 3ds must be performed, under risk of crash (e.g. if a scene element was deleted); Translate() must immediately return . Failure to abide by this will result in race conditions, random and hard to reproduce crashes. - - - - This method is equivalent to IRenderingProcess::SetRenderingProgress(), but contains additional handling to abort translation if a scene change occurs while processing the UI messages. - - The number of units of work which are done. Current progress is expressed as: . - The number of units of work in total. Current progress is expressed as: . - [out] If set to true (by the system), the caller the translation that is currently in progress: no further access to the 3ds must be performed, under risk of crash (e.g. if a scene element was deleted); Translate() must immediately return . Failure to abide by this will result in race conditions, random and hard to reproduce crashes. - - - - Base class for all translator outputs. - As the base class for translator outputs, this class is used to safely perform dynamic casts. It contains no public methods. - - - - - Encapsulates all of the possible result states for a translation operation. - For simplicity, implementations of Translator::Translate() can return a result value by directly referencing the enum, e.g.: - - - - - Base class for a translator. - Translators are responsible for translating a set of inputs (classes and IRenderSessionContext) into one or more outputs (class TranslatorOutput). Together, the translators form a translation graph that is anchored around the scene's root translator. Each is entirely self-contained, such that it may be garbage collected once no longer used by the scene's translation graph. - - - - - Performs translation for a single keyframe. This method is designed to optimize the translation of keyframe data for use with motion blur. If an object must be evaluated at various time values (keyframes) in order to generate motion blur data (i.e. motion transforms, motion vectors, etc.), then it may be problematic to generate all that data within the implementation of Translate(). Evaluating an object at various time values, within each call to Translate(), can cause a ping-pong effect if various scene objects were dependent on each other: the object being depended on would be re-evaluated for every keyframe of every dependent object - for example, if three objects were dependent on a fourth, and each had to be evaluated at 4 keyframes for purposes of motion blur, then the fourth object would be fully evaluated a total of 16 times during scene translation. To avoid this problem, it makes sense to serialize the evaluation of keyframes, such that all objects are first evaluate at the first keyframe, then the second, and so on. This way, the fourth object ends up being evaluated only five times (once at time t, then once for each keyframe). When dependencies exist on complex objects, this can have a major impact on overall translation time. - AcquireChildTranslator() may not be called from this method (it will always return null). Child translators must be acquired in Translate(), and cached locally if needed by TranslateKeyframe(). - It is possible for this method to set translator outputs; if this happens, then the parent translators would be invalidated, and re-translated once all keyframes have been processed. This allows parent translators to have dependencies on outputs that are created as a result of translating the keyframes. But in such a case, of course, the parent translator would have to understand that, the first time gets translated, the outputs of its child translator will not exist yet... and it should not fail in that case, but simply knowlingly wait for the second translation to be successful. - The (success) state of the translation process. - - The time value at which the scene is being translated - equal to the 't' argument passed to . - The time value at which the current keyframe is to be evaluated. This is one of the values returned through the keyframesNeeded argument of ; will be called once for each keyframe returned through keyframesNeeded, in ascending order. - The interface through which translation progress is to be reported (optionally). - - - - Called just before Translate() to enable pre-processing of any kind. This method is to be used to perform per-processing that needs to happen before Translate() is called. A separate method is needed in case the class hierarchy results in a sub-classes Translate() being called before this class. Example uses of this method include calling IRenderSessionContext::CallRenderBegin() or MtlBase::Update(). - - The time at which is about to be called. - The validity of the translator, to be intersected with the input value. The translator will be re-translated whenever the current time value falls outside of this validity. - - - - Called just after Translate() to enable post-processing of any kind. The principle is identical to that of PreTranslate(), except that this method is called immediately after the call to Translate(). - This method is called regardless of the return value of Translate(). - - The time at which was just called. - The validity of the translator, to be intersected with the input value. The translator will be re-translated whenever the current time value falls outside of this validity. - - - - Called by the system to accumulate statistics on the translated scene. The implementation may add to the statistics, if this translator outputs anything that is relevant to them. - - The interface with which statistics may be recorded. - - - - Accumulates statistics on the whole translate graph, starting at this translation node. Included in the traversal are this translator, and all descendant translators. This method would normally be called on a scene root translator. - - The interface with which statistics are recorded. - - - - Deferred checks whether this translator should be invalidated. Used in combination with a call to Invalidate(true), this method is called when checking the scene validity to see if this translator should be deferred invalidated. Deferred invalidation is necessary if the translator requires access to the scene to determine if it is in fact invalid. Accessing the scene within notification callbacks is generally unsafe, as some notifications are sent while the scene is in an intermediate state. - The new validity interval of the translator; empty if the translator is to be invalidated outright. Return previous_validity to leave the translator's validity as-is. - - The time at which the validity check is performed. - The current validity interval interval of the translator. - - - - Returns the string label to be used by the time reporting mechanism. The translation system automatically times every translator for reporting, to the log, a categorized table that shows where translation time is spent. This method returns the label under which this translator's time is reported. Multiple translator classes can use the same label, resulting in their time being added up to a common total. Returning an empty string causes this translator's time to be reported under a "miscellaneous" category. - - - - - Unique identifier for a translator in the scene's translation graph. - The plays three roles: This class should rarely be implemented directly by the plugin developer. Instead, consider using one of the built-in implementations of translator keys, which greatly simplify the task: - - - - - Returns whether the given key is identical to this one. The comparison should typically consider, both, the set of values stored in the key, and the type of the key, such that two keys that store identical values (e.g. the same INode*) but which create different types of translators (e.g. Instance versus InstanceAttributes) would be deemed to be different. Such comparison will typically be performed using a dynamic_cast. - - - - - Returns the hash value passed to the constructor. - - - - - Container for translation statistics. - Simple container with which translation statistics are accumulated. - - - - - The total number of lights. - - - - - The total number of geometric objects. - - - - - The total number of faces. - The exact meaning of faces is defined by the renderer. It could triangles, quads, lollipops, or else. - - - - - Adds the given number of lights to the statistics. - - - - - Adds the given number of geometric objects to the statistics. - - - - - Adds the given number of faces to the statistics. - The exact meaning of faces is defined by the renderer. It could triangles, quads, lollipops, or else. - - - - - Encapsulates the camera shutter settings used with motion blur. - - - - - The shutter duration, 0 if and only if motion blur is disabled. - - - - - The offset, to be applied to the time value for the current frame, to calculate the shutter open time. - shutter_open_time = current_frame_time + shutter_offset - shutter_close_time = currrent_frame_time + shutter_offset + shutter_duration - - - - - Returns whether motion blur is enabled, e.e. whether shutter_duration is not 0. - - - - - Encapsulates motion transforms for an object. - - - - - The transform at shutter open time (t + offset) - - - - - The transform at shutter close time (t + offset + duration) - - - - - The settings used to evaluate the transforms. - - - - - Abstracts a set of nodes that all point to the the same object instance. - This interface represents a set of nodes which, for rendering purposes, can be treated as all being instances of the same object. As such, the pool has a front-facing representative node which may be used to evaluate that shared/instanced object. - - - - - Returns the pool's representative node. The representative node is the front-facing node that may be used to evaluate the object that is instanced by the pool. In theory, any node in the pool may be used for this purpose; this method simply chooses one of them. - - - - - Registers a change notification callback, which gets called whenever the pool, or the instanced object, changes. - - The notification callback to be registered. - - - - Unregisteres a notification callback previously registered with MonitorNodePool(). - - The notification callback to be unregistered. - - - - Extends class with additional functionality. - - - - - Returns the number of nodes in the pool. - In most cases, users of should only care about the representative node, returned by GetRepresentativeNode(). In some cases, however, they may care about the set of of nodes contained by the pool. Note, however, that nodes are only incorporated into their respective pool on calling INodeInstancingPool::IManager::GetPoolForNode(), and may be ejected at any time, e.g. when scene changes are detected. Querying the list of nodes contained by a pool is therefore only truly valid right after calling INodeInstancingPool::IManager::GetPoolForNode() for every node in the scene. - - - - - Returns the node, at the given index, contained in the pool. - In most cases, users of should only care about the representative node, returned by GetRepresentativeNode(). In some cases, however, they may care about the set of of nodes contained by the pool. Note, however, that nodes are only incorporated into their respective pool on calling INodeInstancingPool::IManager::GetPoolForNode(), and may be ejected at any time, e.g. when scene changes are detected. Querying the list of nodes contained by a pool is therefore only truly valid right after calling INodeInstancingPool::IManager::GetPoolForNode() for every node in the scene. - - The index of the node to query; see . - - - - Manages the creation and existence of node instancing pools. - This manager is the interface through which new node pools are created. It also handles the addition of new nodes to existing pools. - - - - - Notification callback for monitoring changes in a node instancing pool. - - - - - Notifies that the object, being instanced by the pool, has changed and needs to be re-translated. For example, would be called if the mesh of the instanced object were to change. - - The pool which is sending the notification. - The type of event that triggered this notification. - - - - Notifies that the set of nodes, contained in the pool, may have changed. This method notifies that some nodes may have been added or removed to/from the pool. We say may have changed, because it's impossible to know for sure at this point due to node evaluations being disallowed (unsafe) in notification callbacks. The listener should use a deferred validity check (i.e. call Translator::Invalidte(true)) and later re-acquire the pool for the node being cared for. This re-acquisition of the pool will cause the nodes to be re-evaluated and the pools to be re-built accordingly. - - The pool which is sending the notification. - - - - projection types - - - - - Notification callback interface for - When registered with an , this interface will be called whenever a relevant change occurs in the parameters of the camera. - - - - - Notifies that something has changed in the camera. - - - - - The modes in which the background/backplate may operate. - - - - - The modes in which the environment may operate. - - - - - interface for reading frame buffer data. - This is the interface, used by , for extracting the frame buffer data from the renderer's internal representation. - - - - - Reads a subset of a single line of the frame buffer. - Pixels are to be written to target_pixels starting at index 0, without any offset. x_start is not to be used as an offset in the target buffer. - True on success, false on failure to read to frame buffer for any reason. - - The index of the frame buffer line to be read. - The first pixel to be read, within the line. - The number of pixels to be read, guaranteed to be within the bounds of the line. - The buffer into which the pixels are to be written, allocated to store pixels. - - - - Returns the resolution of the frame buffer being abstracted by this class. This resolution bounds the range of valid pixel indices that may be accessed with GetPixelLine(). - Internally, the caller is responsible for supporting arbitrary resolutions - and thus to resize the frame buffer if necessary. - - - - - Returns the region, within the frame buffer, which can be read. This is the region which has been rendered, which contains meaningful value. The caller should limit its frame buffer access to the pixel indices within the region returned here. - - - - - The message type is used to categorize and filter messages, according to user preferences. - - - - - to a job which gets executed from the main thread. - Main thread jobs are run using IRenderingProcess::RunJobFromMainThread(). - - - - - Runs the job, guaranteed to be called from the main thread. - - - - - Guard class for starting and stopping a timer automatically. - - - This class calls IRenderingProcess::StartTimer() in the constructor, and IRenderProcess::StopTimer() in the destructor when in standard mode. But the behaviour may be reversed to instead call StopTimer() in the constructor and StartTimer() in the destructor, effectively pausing the timer for the lifetime of the guard. - - - - - The type of target for which the render session was created. - - - - - Notification callback interface for . - When registered with an , this interface will be called whenever a relevant change occurs. - - - - - Notifies that the plugin was replaced by a different one (i.e. IRenderSettingsContainer::GetToneOperator() will return a different value). - - - - - Notifies that a parameter of the has changed, potentially meaning that the needs to be re-processed on the image being rendered. - - - - - Notifies that the physical scale has changed. - - - - - - - The possible values that a may take. - - - - - Defines what the RenderInstanceSource::GetData() method returns and how to treat it. - - - - - Information about a given source, to be instanced multiple times. - - - - - Get the number of instances of this source. - - - - - Get the nth instance of this source. - - - - - Get the flags that define the type of data stored. Defines the type returned by the GetData() method, and any other relevant information, like whether the plugin must delete the pointer once it's finished using it. - - - - - Get the data pointer for the object that should be instanced. - - - Currently, it is either a Mesh* or an INode*, and the flags returned by the GetFlags() method can be queried to find out which class type it is. The variable should only have one class type flag set, but may have other relevant information flagged as well, so one should not test for the class type with the equality ('==') operator, but instead with the bitwise AND operator ('&'). For example: - If the "pluginMustDelete" flag is set, the pointer should be deleted after use. Be sure to cast to relevant class before deletion so the proper destructor is called. - - - - - Get the velocity map channel, or -1 if none. This method returns the map channel where per-vertex velocity data (stored in units/frame) might be found, inside any meshes returned by the . A value of -1 means that the mesh contains no per-vertex velocity data. - - - Not all meshes are guaranteed to contain velocity data. It is your duty to check that this map channel is initialized on a given mesh and that its face count is equal to the mesh's face count. If both face counts are equal, you can retrieve vertex velocities by iterating over each face's vertices, and applying the corresponding map face vertex value to the vertex velocity array you are constructing. Vertex velocities must be indirectly retrieved by iterating through the faces like this, because even if the map vertex count is identical to the mesh vertex count, the map/mesh vertex indices may not correspond to each other. Here is an example of how vertex velocities could be retrieved from the velocity map channel, through a : - - - - - Information about a given instance of a . - - - - - Return a raw custom data pointer. If the ID is invalid, returns nullptr. - - - - - Return an integer value. If the ID is invalid, returns 0. - - - - - Return a float value. If the ID is invalid, returns 0.0. - - - - - Return a vector value. If the ID is invalid, returns (0.0,0.0,0.0). - - - - - Return a color value. If the ID is invalid, returns (0.0,0.0,0.0). - - - - - Return a TM value. If the ID is invalid, returns Matrix(). - - - - - Get unique instance ID. This method returns the unique birth ID of an instance (i.e. the birth ID of a particle or scattered item). This value should be unique for each instance in the set. It can be negative or zero. - - - - - Get user-defined Instance ID. This method returns the arbitrary, user-defined ID of an instance. Texmaps can make use of this value at render-time. It can be negative or zero. - - - - - Get age and lifespan (if available). Certain objects like particle systems will have "age" information. This method returns true if the object has these values and assigns the age and lifespan to the referenced parameters. The age value starts at zero at this instance's "birth" and increases up to a value of lifespan at the "death" of this instance. To get normalized age, divide age by lifespan. - - - - - Get material override. This method returns an instance's material override. A return value of nullptr means no override is set on the instance and thus the default node material should be used. - - - - - Get the transformation matrix (or matrices). - - - This method returns the instance's transform(s) spread evenly over the motion blur interval (the interval specified by the argument passed to the UpdateInstanceData method), in temporal order. - If the array returned has a single element, it represents a static instance that is not moving. If it has two elements, it contains the transforms at the start and end of the interval. If it has three elements, it contains the transforms at the start, center, and end of the interval. And so on. - A vector with more than two elements allows a renderer to compute more accurate multi-sample motion blur. - - - - - Get the transformation matrix at shutter open only. This method returns the instance's transform. This can be more efficient if the object is actually internally using a single transform and a velocity and spin, saving it the effort of computing the additional matrices. If a renderer does not plan to use multiple matrices, or if it computes motion blur using the GetVelocity() and GetSpin() methods, it can call this method instead of using GetTMs()[0], which while equivalent, might be slightly less efficient. - - - - - Get instance velocity. - - - Returns the instance velocity of the instance in world space, measured in units per tick. - - - - - Get instance rotational velocity. - - - Returns the spin of the instance, as an in units per tick. - - - - - The allows a renderer to access an object's instancing information so that it can do efficient instancing at render-time. This interface is implemented by an object and called by a renderer. - - - It is legal for a renderer to iterate over the RenderInstanceSources and RenderInstanceTargets from multiple threads. However, the same thread should not concurrently access multiple RenderInstanceTargets at the same time. This makes it legal for the object plugin to actually reuse the memory returned by the RenderInstanceSource::GetRenderInstanceTarget() method to improve performance, as long as that memory block is kept separate per thread. - A renderer should not call GetRenderMesh() for an object that supports this interface. However, even if an object implements this interface, it should ideally still implement GetRenderMesh() to return an aggregate mesh of all instances, so that a renderer that does not support this interface will at least render something. - An instance may have custom data channels. The data channel names used by an instancer can be retrieved using the RenderTimeInstancingInterface::GetChannels() method. Each data channel has a name, a type, and a ChannelID, which is used to retrieve the actual values for each instance using the RenderInstanceTarget::GetXXX() methods. - Usage example by a renderer: - - - - - Make sure that the instancing data is up-to-date. This method needs to be called by the renderer to make sure that the instancing data is up-to-date and ready to be retrieved. - - - - The time of the evaluation. Most often same as the shutter open time, if motion blur is used. - Returns the validity of the returned data. For example, if FOREVER is returned it indicates to the renderer that the instances are not moving or changing at all, and could in principle be retained over multiple frames. - An initialized , which upon return will contain info on how the motion data is returned. If the object will return values for velocity and spin, it should set the mb_velocityspin flag. - The view. This allows the object to do level-of-detail computations or camera frustum culling. - The plugin argument of this method takes the name of the plugin querying this interface, in lowercase letters. For example: _T("arnold"), _T("octane"), _T("redshift"), _T("vray"), etc. This is a somewhat arbitrary value, but by having renderers identify themselves during a query, the object can internally determine if any renderer-specific edge cases need to be processed. - - - - Release the instancing data. When a renderer is done with the data returned by this interface, it can call this method. If the generating plugin allocated some information, it can release it in this method. - - - - - Get the number of sources. - - - - - Get the nth source. - - - - - The name of the data channel. - - - - - The type of data channel. - - - - - The data channel's ID. An opaque integer token representing the data channel. Used to actually retrieve the channel's data. - - - - - For typeCustom only - the size of the data, in case the renderer needs to make a copy of it. - - - - - ID overrides. Allows mapping an existing material ID to another on an instance. If srcID is equal to -1, it will override all existing material IDs. - - - - - The material ID to override. If srcID is equal to -1, the override applies to all the material IDs of the mesh. - - - - - The material ID that will be used to replace srcID. - - - - - Equals operator. - - - - - Not equals operator. - - - - - UVW channel override data. This will override all the UVW coordinates of a given map channel on a mesh with a single value. - - - - - The map channel to override. - - - - - The UVW value to override it with. - - - - - Equals operator. - - - - - Not equals operator. - - - - - Motion blur information struct. This communicates information about shutter intervals and motion blur behavior between the object and the renderer. It is filled in and passed to the RenderTimeInstancingInterface::UpdateInstanceData() method by the renderer and the object may modify it to communicate back to it. - - - - - Defines information about what motion blur info is available for a source. - - - - - - - Defines the open and closing time of the shutter. If set to NEVER, motion blur is not used. - - - - - The number of TMs that the RenderInstanceTarget::GetTMs() method should return, or -1 for a variable number of TMs. - - - The renderer can use the numberOfTMs variable to specify the number of TMs that the RenderInstanceTarget::GetTMs() method should return, which is useful if the renderer only supports a fixed set. - When this is passed into the RenderTimeInstancingInterface::UpdateInstanceData() method from the renderer, the meaning is as follows: - Upon returning from the RenderTimeInstancingInterface::UpdateInstanceData() method, the object can fill in the response value: - Note that the object is only allowed to modify the numberOfTMs value when: - - - - - Type of the data channel. - - - - - Defines what MotionBlurInfo::flags means. - - - - - A class to help control the setting of the worker thread. Create an instance of this class, and when it is destructed the worker thread is set to its original value. - - - - - The property name resolution context where localized \ English string translation lookup is occurring. - - - - - Enum describing file open mode options - - - - - encodings used in the class. In addition to the standard Windows constants like CP_ACP, CP_UTF8, etc... The following constants can also be used as encoding. - - - - - A wrapper around the underlying IBailOutProcessManager instance. Ensures proper cleanup of the state of the instance even if we happen to throw out of the function in which it is used. - - - - - To detect whether the bail-out should jump out the busy process or not. - If true bail-out should jump out the busy process. If false bail-out should not jump out the busy process. - - - - - To detect whether the bail-out is done or not. - If true bail-out is done. If false bail-out is missed. - - - - - To detect whether the bail-out is embed or not. - If true bail-out is embed. If false bail-out is not embed. - - - - - Represent an abstract binary stream of data. - - - - - Returns the last error encountered using the stream. - If no error occurred during the uses of this class, this function will returns null. If for any reason, any call to this interface, this member will returns a user-readable error code that explain why the operation failed. - - - - - Returns true when at end of file. - - - - - Returns true if a call to Write(void*, size_t) would succeed. - - - - - Read a specified number bytes from this stream and stores it in the data parameter. - Returns the number of bytes read. Or 0 if the end of file was reached. - - - Buffer to store the bytes taken out of this stream. - - of bytes available in "data" to store the content of this stream. - - - - Write a number of bytes from the data parameter to this stream - Returns the number of bytes written. - - - The byte source to copy from - - The number of bytes to copy from the data parameter. - - - - Move the pointer inside this stream to a specified position. - - - The amount to offset the file pointer by. - - Can be either SEEK_SET, SEEK_CUR, SEEK_END. - - - - Make sure that all the buffer are synced with the OS native objects. - - - - - Erase all the data after the current position. - - - - - Holds binary data in memory only. The Reader class uses this as a buffer for reading data. - - - - - Reduce the memory used by this object. - - - - - Reset this object, _len = 0 - - - - - Loose the information the beginning of this buffer up to the current position. - - Keep the X last bytes of the memory buffer - - - - Loose the information from the specified position up to the end of this buffer. - - - - - Quick-read. This function will returns you a direct-pointer to the memory of this buffer and move the stream position. - - - - - Quick-write. This function will returns you a direct-pointer to the memory of this buffer where you should write and move the stream position. - - - - - Opens a file and sets its buffer size. - This class is designed as a helper when dealing with reading/writing potentially large files. When opening a file, a default buffer size of 4KB is used. When reading or writing the file, the operations occur in 4KB chunks. For large files, such as bitmap files, this will result in a very large number of file operations. If the file operations have a high latency, such as dealing with a slow network or operating in a cloud environment, this can result in very poor performance. - The file is closed in the destructor. - Files opened using this class will have a buffer size of, depending on options used, an environment variable value, an ini file file value, or a specified value that defaults to 256KB. - - - - - Open a file - Returns true if file was opened - - The name of the file to open - The mode to open the file in. This is the same mode specifier as win32 api fopen. - Whether to set buffer size. If false, the default win32 4KB buffer is used - - whether to potentially override defaultBufferSize value with environment variable / ini file setting - The default buffer size in bytes - - - - Close the file - - - - - Represents a single Unicode character. - The main advantage of this class is the ability of representing them without allocating external memory. - This class was designed to be able to cast "unsigned int*" array to a "Char*" array. This class doesn't have any destructor or virtual functions. - - - - - Convert this character to a . - - - - - Convert this character to UTF16. - number of characters converted. - - string buffer to put the converted characters - the buffer size of param string in number characters - - - - Convert this character to the active code page. - - number of characters converted. - - - string buffer to put the converted characters - - the buffer size of param string in number characters - - - - Convert this character to the specified code page. - number of characters converted. - - The specified code page - string buffer to put the converted characters - the buffer size of param string in number characters - - - - Convert this character to an MCHAR (Active Code Page or UTF16). - number of characters converted. - - string buffer to put the converted characters - the buffer size of param s in number characters - - - - Compare this character to an active code page character. - - - - - Compare this character to a UTF16 character. - - - - - Compare this character to a UTF16 character. - - - - - Not equal operator for an active code page character. - - - - - Not equal operator for a UTF16 character. - - - - - Not equal operator for a UTF16 character. - - - - - Assignment operator for a UTF16 character. - - - - - Assignment operator for an active code page character. - - - - - Assignment operator for a . - - - - - Assignment operator for a constant UTF16 character. - - - - - Assignment operator for a constant active code page character. - - - - - Change this character to represents the first character of the string specified, based on the code page specified. - - - The specified code page - - The string to use as a copy source - - - - Returns true if this character represents a NULL character. - - - - - Returns true if this character represents a non-NULL character. - - - - - Returns the character as UTF32 - - - - - Determine if this character is found inside a particular character set. - This function slightly differs from strrchr or wcsrchr, because it can search DBCS or UTF16 character accurately inside a string without partially matching it. - - - - - Character accumulator - Concatenate "Char" object to form a character string. - - - - - Get the string pointer. - - - - - Add a character at the end of this string. - - - - - Reset this accumulator - - - - - Obtain the last character in this accumulator - - - - - Remove the last character of this accumulator - - - - - Return the number of MCHAR already in the accumulator - - - - - Iterate intelligently inside a string. - This class should be used to iterate through characters of a string. It guarantees that the string pointer never points to the end of a character. The template parameter should be either char, wchar_t, const wchar_t etc. - - - - - Assignment operator. Copies an existing character iterator. - - - - - Assignment operator. Copies another character as the templated type as this iterator. - - - - - Return the nth character from the iterator. - - - The index of the character to retrieve from the string - - - - Determine if the iterator has reached the end of the string. - - - - - Obtain the current string pointer. - - - - - Return the nth character from the iterator. - - - The index of the character to retrieve from the string - - - - Base exception class for 3ds Max. - - - This serves as a base class for other exception classes. Instances of this class own and make their own copies of the error message. - - - - - Assignment operator. - - - - - Returns the message of the exception. - - - - - This class creates and attempts to acquire a named Mutex based on a file name in its constructor, and releases and closes the Mutex in its destructor. Instances of this class are typically used to control access to a file across multiple 3ds Max sessions. - - - - - Returns true if the Mutex was acquired. - - - - - Releases the lock if the Mutex was acquired. - - - - - An interface of bailing out the busy processing functions by pressing the 'Esc' key. - - - - - At the beginning of the busy process, a bail-out can be embed, so that you can trigger the bail-out in the busy process to jump out the busy process. For example, you can embed bail-out at the front of long time loop. - - - - - After bail-out operation is done, you need to end the bail-out. - - - - - To detect whether the bail-out should jump out the busy process or not. - If true bail-out should jump out the busy process. If false bail-out should not jump out the busy process. - - - - - To detect whether the bail-out is done or not. - If true bail-out is done. If false bail-out is missed. - - - - - To detect whether the bail-out is embed or not. - If true bail-out is embed. If false bail-out is not embed. - - - - - A pure virtual interface for Poly 's UI as dialog Showing Status. - - - class If the Poly Objects' UI setting is used as dialog, dialog will replace caddy to show the parameters of the Poly Objects. If the dialog is showing right now, users change the Poly Objects' UI setting as caddy, a tip dialog at the bottom-center of the panel in Max will pop up and remind users that the caddy controls will now be used. - - - - - To get whether the Poly 's UI as dialog is currently showing or not. - true if the dialog is currently showing, false otherwise. - - - - - To set the showing status of Poly 's UI as dialog. - - if bShowing is true, the showing status of Poly 's as dialog is on. false otherwise. - - - - To get whether the Poly 's UI as dialog is set as on or off. - true if the dialog is set as on, false otherwise. - - - - - An interface of giving users a tip . - - - - - Give users a tip. - - - - - Stores all the strings inside CStr and WStr. CStr and WStr use this class to perform their internal operations and hold different encodings for a string. It has several goals: - - - - - Create a new string that is the concatenation of this string and another. - - - - - Appends a string at the end of this string. - - - - - Check if the strings are equal. A common code page is determined for the 2 MaxStrings, strings with those encodings are created if necessary, and then strcmp / wcscmp is used to compare those strings. - Values are -1, 0, or 1. - - - - - Compare this string with another while ignoring the case. - - - - - Equality operator. - true if the strings are equal; otherwise false. - - - - - Determine if this string is null. Note: an empty string is not null. - - - - - Clears the data of this object. - - - - - Allocate a new string inside this object and returns a modifiable pointer to it. You can modify this string as long as you don't perform any other operation with this object's instance. - - - - - - - - - - - - - - - - - - - - - Reinitializes the instance with the specified string and code page - - - The encoding of the string passed in. - - The new text to replace this string with - - Length in characters of the string parameter. Use this only when you already know the size of the string getting passed in. Otherwise leave the parameter out, and by default the function will compute the length for you. - - - - Reinitializes the instance with the specified Active Code Page (ACP) string. - - - The new text to replace this string with - - Length in characters of the string parameter. Use this only when you already know the size of the string getting passed in. Otherwise leave the parameter out, and by default the function will compute the length for you. - - - - Reinitializes the instance with the specified UTF8 string. - - - The new text to replace this string with - - Length in characters of the string parameter. Use this only when you already know the size of the string getting passed in. Otherwise leave the parameter out, and by default the function will compute the length for you. - - - - Reinitializes the instance with the specified UTF16 string. - - - The new text to replace this string with - - Length in characters of the string parameter. Use this only when you already know the size of the string getting passed in. Otherwise leave the parameter out, and by default the function will compute the length for you. - - - - Returns a which in turn enables casting to a char array encoded with a specific code page. The char array held by the instance is valid as long as the instance is valid. - - A instance that can be used to cast to a char* array. - - - The code page to convert to - [out] - If length is not null, the size of the resulting string is stored to the length pointer. - - - - Cast this object to a char array using Active Code Page encoding - A instance that can be used to cast to a char* array. - - [out] - If length is not null, the size of the resulting string is stored to the length pointer. - - - - Cast this object to a UTF8 encoded string. - A instance that can be used to cast to a char* array. - - [out] - If length is not null, the size of the resulting string is stored to the length pointer. - - - - Cast this object to a UTF16 or UNICODE encoded string. - A MaxStringCast<wchar_t> instance that can be used to cast to a wchar_t* array. - - [out] - If length is not null, the size of the resulting string is stored to the length pointer. - - - - Cast this object to a UTF32 encoded string. - A MaxStringCast<unsigned int> instance that can be used to cast to an unsigned int* array. - - [out] - If length is not null, the size of the resulting string is stored to the length pointer. - - - - Get the number of characters in the string, based on the encoding. - - - - - Returns the number of times this string has been converted to other encodings. - - - - - Returns the number of characters allocated in memory, in which the string is stored. (Including the NULL character). This is different from the number of characters actually stored for the string. Thus this can be bigger than the length of the string. It might actually be a little bit bigger than the length of the string if this object was manipulated with AllocBufferCP() or AllocBufferUTF16(). - - - - - Gets a common code page. Determine the ideal intermediate codepage between this and another one. - - - - - - - - - - - - - Return a BSTR of this string. The string is allocated with SysAllocString, and the caller is responsible to free it using SysFreeString. - - - - - Construct a OLE string. - A MaxStringCast<wchar_t> which can be cast to a wchar_t for converting to an OLESTR - - - - - A is used when casting a to a type. It holds - So, the string pointer is guaranteed to be valid as along as the instance is alive. Warning: If you cast directly to a, for example, char*, then something else could operate on the causing it to delete the string buffer in the MaxStringData, and you would be left holding a dangling pointer. - Note, data held by this class should be treated as read only and not modifiable. Thus its operator methods only convert to constant types. For instance if used with a char type, its operators will only return a const char*. If you want a char* type need to create a copy instead. Therefore do not use const_cast<> with this class. - - - - - Returns a const pointer to the string. If the string is NULL, a pointer to 0 is returned. - - - - - Returns a const pointer pointer to 0. - - - - - returns true if this string is null or empty, false otherwise - - - - - Cast this object to a MCHAR. The string returned is valid as long as the exists. - - - - - Cast this object to a wchar_t. The string returned is valid as long as the exists. - - - - - Returns a const ref to the owning . - - - - - A Utility class for helping to convert to a specified code page. - - - - - A Utility class for helping to convert to UTF8. - - - - - is a handy utility mix-in base class that makes any class derived from it non-copyable. - - - Rather than explicitly disabling the copy constructor and assignment operator for a class by declaring them private and leaving them unimplemented, deriving from this class has the same effect. The compiler cannot generate a copy constructor or assignment operator for a class derived from because 's are private and unimplemented. - - - - - Thrown when a null pointer is dereferenced. - - - - - Thrown when an out of bounds index is detected. - - - Used when bounds checking indexes passed into arrays. For instance if an array has 10 items, valid indexes would be 0 thru 9. Therefore an instance of this class could be thrown if an index of -1 or 10 was passed into an array. - - - - - type - adds path-operation richness over symbol strings. - - - The interface provides operations for path composition (Path::Append and Path::Prepend ) and decomposition (Path::StripToTopParent, Path::StripToLeaf, Path::RemoveTopParent, Path::RemoveLeaf), query methods for determining information about a , such as whether it's absolute, relative, a root or a UNC, and finally, quick conversions from relative to absolute or absolute to relative. - Note paths are automatically kept in a standard form, where: - Normalization is a separate, explicit method that must be called by the client. Normalization removes null directories \\.\\ and adds in any missing backslash after the drive letter. Wherever possible, normalization will resolve out any ".." path components so: "r:\\dirA\\dirB\\..\\dirC" becomes "r:\\dirA\\dirC." If these hit the root, they just get stripped off, so "r:\\.." normalizes to "r:\\" If the path is relative, and there are more ".."s than preceding directories, the extra sets are kept at the start of the path: "b\\..\\..\\c" becomes "..\\c" Any trailing backslash is kept on the path for compatibility with many win32 API functions. If a uniform trailing-backslash format is desired, for example, for display in the UI, it is up to client-level code to implement this policy. Unresolved symbols are left intact during normalization. Resolving the symbols in a string normalizes automatically. - To reiterate, normalization as performed by the Normalize() method is different from the basic standard form maintained by all members of . The client must call Normalize() explicitly (or ResolveSymbols() which is the only method that calls Normalize() automatically). The reason that these are kept separate is to keep from radically modifying a path in a way that may be surprising to a user. If the user wishes to construct a path with many '..\'s in it, the user will expect to see this result. Normalize() may then be called subsequently when it is deemed appropriate. - To illustrate the difference: - - - - - this from another. - - - Equivalent to the assignment operator, but more verbose. - - - path to copy. - - - - this 's internal string from a null terminated character string. - - - Equivalent to the assignment operator, but more verbose. - - null-terminated character string to copy into this path. - - - - this from a MSTR. - - - Equivalent to the assignment operator, but more verbose. - - MSTR to copy into this path. - - - - Assignment operator. - - - - - path to copy - - - - Assignment operator taking a null terminated character string. - - - - null-terminated character string to copy into this path. - - - - Assignment operator. - - - - MSTR to copy into this path. - - - - Get whether this is an absolutely specified path. - - - An absolute path is rooted from a starting backslash (\), drive letter or UNC hostname. - Returns true if this is an absolute path. - - - - - Get whether this is an empty path. - - - An empty path has a backing string representation of "". - true if this is an empty path. Returns false otherwise. - - - - - Query whether this path doesn't have any illegal characters according to the Windows platform rules. - - - Illegal characters are ':' for any character but the second and any occurrence of * ? " < > or |. - true if the path appears to be legal, false if an illegal character was found. - - - - - Check if this path is just a root. - - - Possible roots are: Note that all roots are absolute paths, but not all absolute paths are roots. - The host or drive letter does not have to exist. This path just has to fit the pattern. - true if this path fits one of the patterns for a root outlined above, false other wise. - - - - - Query whether this path is a UNC path. - - - A UNC path fits "\\\\host" or "\\\\host\\share" or "\\\\host\\share\\subdirectory\\". The host doesn't necessarily have to exist. - true if this path is a UNC, false otherwise. - - - - - Query whether this path fits the pattern for a UNC share. - - - The UNC share pattern is \\host\share. - true if this path is a UNC share. False, otherwise. - - - - - Query whether this path is rooted at backslash, that is at the current drive with no drive letter. - - - e.g. "\\abc\\def" is rooted at backslash. - - - - - Query whether this path is rooted at a drive letter. - - - true if this path is rooted at a drive letter like "c:\\dir\\dir" - - - - - Query with this path, when normalized, starts with "..". - - - true if normalizing the path causes it to be relative to an ancestor path - ie, it starts with ".." False, otherwise. - - - - - Query whether this and the passed-in path are exactly the same. - - - This does not perform any path resolution to try to determine if the paths point to the same file. To be equal, the two paths must have exactly the same current representation. - true if both paths are exactly the same. - - a path to check for equality with this one. - - - - Query whether this and the passed-in path are exactly the same. - - - This is a convenience operator overload. It calls IsEqual() under the hood. - true if both paths are exactly the same. - - a path to check for equality with this one. - - - - Query whether this and the passed-in path currently point to the same location. - - - This may not remain true (or false) if the paths contain symbols that may resolve differently later on. - true if both paths resolve out to pointing to the same location, false otherwise. - - a path to check for equivalence with this one - - - - Query whether this path has a trailing backslash. - - - true if this path has a trailing backslash. - - - - - Add a backslash to the end of this path if there isn't one already. - - - A reference to this . (This allows for operation chaining.) - - - - - Remove any trailing backslash from this path. Does nothing if there is no trailing backslash. - - - A reference to this . (This allows for operation chaining.) - - - - - Add a new parent path to the start of this path. - - - While the usual cleaning up is done, Normalization is not performed. No checking is performed to verify that the resulting path will be legal. Generally, this should be relative while the new parent path may be absolute or relative. - Examples: To convert a relative path to an absolute path with an arbitrary base, simply Prepend that base to this relative path. - A reference to this . (This allows for operation chaining.) - - The new parent path to place at the start of this path. - - - - Add a new child path at the end of this path. - - - While the usual cleaning up is done, Normalization is not performed. No checking is performed to verify that the resulting path will be legal. Generally, the new child should be relative should be relative, while this base path may be absolute or relative. - Examples: - A reference to this . (This allows for operation chaining.) - - the new relative child component for this path. - - - - all but the topmost parent from this path. - - - Examples: - A reference to this . (This allows for operation chaining.) - - - - - Remove the topmost parent from this path. - - - Examples: - A reference to this . (This allows for operation chaining.) - - - - - all but the very last child from this path. - - - Examples: - A reference to this . (This allows for operation chaining.) - - - - - Remove the very last child from this path. - - - Examples: - A reference to this . (This allows for operation chaining.) - - - - - Resolve out any symbols in the path string. - - - After resolving the symbols, normalization is performed automatically. At the moment, this is an internal feature to 3ds Max, but is exposed to the SDK to support future functionality. - A reference to this . (This allows for operation chaining.) - - - - - Transform this path into its normal form. - - - This will clean up pieces not following the backslash rules outlined in the class documentation, and will convert ".."s as much as possible. "r:\\dirA\\dirB\\..\\dirC" becomes "r:\\dirA\\dirC." If these hit the root, they just get stripped off, so "r:\\.." normalizes to "r:\\" If the path is relative, and there are more ".."s than preceding directories, the extra sets are kept at the start of the path: "b\\..\\..\\c" becomes "..\\c" - Any symbols in the path will be maintained since a symbol may resolve out to more than one directory. - A reference to this . (This allows for operation chaining.) - - - - - Convert all the characters in this path to lower case. - - - A reference to this . (This allows for operation chaining.) - - - - - Convert this absolute so that it points to the same location, but relative to the new base path. - - - The following attempted conversions are invalid and will leave the path unchanged: Example: ("c:\\a\\b\\c").ConvertToRelativeTo(("c:\\a\\b\\d") produces ("..\\c") - A reference to this . (This allows for operation chaining.) - - absolute base path from which this must later be rooted to point to its current location again. - - - - Convert this mapped drive to a UNC path with a host and share name. - - - This operation only modifies the path if it is rooted at a valid mapped drive. - - - - - Convert this relative path to absolute rooted at the current 3ds Max Project Folder. - - - This will automatically resolve any symbols and normalize this path. If this already resolves to an absolute , it will ignore the current working directory. This does not resolve the path using the 3ds Max file search mechanism. - If conversion to an arbitrarily-rooted absolute path is desired, Prepend should be used instead. - A reference to this . (This allows for operation chaining.) - - - - - Get the fully-resolved, lower case, path converted to absolute rooted at the current 3ds Max Project Folder. - - - This is a performance-oriented convenience method for clients that wish to hold on to the original, unresolved, relative path yet often need to access the absolute path. - This path after it's been fully resolved, converted to absolute (rooted at the Project Folder), and converted to lower case. - - - - - Converts an absolute path into a path that is relative to the current Project Folder. - - - Converts an absolute path into a path that is relative to the current Project Folder. If the path cannot be made relative (if it is rooted on a different drive, for instance), then it is left untouched. If the path is already relative, it is also left untouched. - A reference to this . (This allows for operation chaining.) - - - - - Queries whether the file or directory exists. This works on both files and directories. - - - - true if the path exists and false otherwise - - - - - Queries whether the file or directory is rooted to the specified folder. This works on both files and directories. - - - - true if the file or directory is rooted to the specified folder and false otherwise - - - - - Get the current string representation of this path. - - - Note that this does not perform any symbol resolution or normalization. - A copy of this 's current string representation. - - - - - Get the internal c-string formatted data representation for this path. - - - Note that this c-string is not guaranteed to be consistent after any modifications are made to the object. If the data is needed persistently, consider either copying the contents of this pointer, or calling GetString() instead. - A null-terminated c-string representation of the internals of this object. - - - - - Creates base file to support incremental upload of Autodesk 360 files if applicable. - - - This function should be called before a file which is in sync is overwritten with a new version (typically during save operation). This is necessary to support incremental upload of the file. It must be called every time the file is overwritten (i.e. on every save). This function creates a base file using the current version which will be used by the sync engine to upload only the changes. If the file specified by this path is not an Autodesk 360 sync'ed file, no action occurs as a result of this call. - True if a base file was created - - - - - General multi-purpose exception for runtime errors. - - - - - A diagnostic class used for tracing. This class prints a message to the debug output window in visual studio. It ensures that a message is automatically printed when the execution leaves the scope. Using the macro's below, this class can be used to trace when a function starts and when a function exits. For example: Will print Scope: foo - START Scope: foo - END - So no matter what, whenever the function returns, the destructor will guarantee that a ending statement will be printed. - - - - - A basic timer tool. - - - A is a light-weight timer tool that tests the time consumption.This timer tool uses high performance counter(QueryPerformanceCounter) to record the time comsumption and the time tested is at the milliseconds level.The workflow of is like this: Start -> ( Pause ->(Resume)*n)*n -> Stop. Between Start and Stop, numbers of Pause -> (Resume)*n operations can be done. And also Stop operation can be done directly after Pause operation. For example: - - - - - This method lets you start to trace the time and changes the current state to PLAYING. - - - - - This method lets you start in a PAUSED state. - - - - - This method lets you pause to trace the time and changes the current state to PAUSED. - - - - - This method lets you resume to trace the time and changes the current state to PLAYING. - - - - - This method lets you stop to trace the time and changes the current state to STOPPED. - - - - - This method lets you clear the time traced and changes the current state to STOPPED. - - - - - This method lets you know whether the timer is running. - - - - - This method lets you know whether the timer is paused. - - - - - This method lets you know whether the timer is stopped. - - - - - This method lets you know what the current timer state is. - - - - - This method lets you get the elapsed time(milliseconds) traced. - - - Note that each paired call of Start/Stop and Resume/Pause imposes some overhead, mainly the time associated with 2 calls to QueryPerformanceCounter. If client code is making many Resume/Pause calls and/or the code executing between the Start/Stop and Resume/Pause calls runs very fast, the reported elapsed time may be significantly impacted by this overhead. - - - - - Thrown when an invalid index is passed into Tab::operator[] or Tab::Addr. - - - For instance with a with 10 items, an index of -1 and 10 is out of bounds since valid index are 0 thru 9. - - - - - struct . A hash functor for plain old data. - - - - - - - Computes a Fowler-Noll-Vo FNV-1A hash on the input data, suitable for noncryptographic uses. - Returns an FNV-1A hash of size size_t. - - Constant reference to an object of the template class _Kty. - - - - When a 3ds Max session starts up, immediately after creating the main HWND a named file mapping object is created that contains the data associated with an instance of struct . This functionality was added in 3ds Max 2018 as the class of the main HWND is now a Qt-based class rather than "3DSMAX". This new mechanism also allows the version of 3ds Max to be determined and is extendable in the future. - - - The structure definition of the data stored to the named file mapping object. - - - - - LineEndMode is used to control how text file end of line characters are handled. - - - - - This class is the base for all text file readers. It declare a common interface to all implementation - - - - - Reads a single char and returns it's UTF32 representation. UTF-32 (or UCS-4) is a protocol to encode Unicode characters that uses exactly 32 bits per Unicode code point. All other Unicode transformation formats use variable-length encodings. The UTF-32 form of a character is a direct representation of its codepoint. - UTF32 character read - - - Read a char but does not move the internal pointer to next char. - - - - Reads characters from the file - Characters read. - - Stop reading after 'nchars' characters or when end of file reached. - - - - Reads a line from the file (or nchars, depending on which one comes first.) - Line read. - - Stop reading after 'nchars' characters even if the EOL was not found. - By default, this function will returns the line including it's end-of-line character(s) unless you set "dontReturnEOL" to true. - - - - Get the number of characters read so far. - - - - - Get the current line number. - - - - - Read a character from the file - Character read. - - Read a char but does not move the internal pointer to next char. - - - - Unread a character - Put back a character inside the buffer. The data will be re-read next time you call read. This is used internally when parsing max scripts. - of character written. - - to put back in the buffer - - - - Seek inside the stream. - Returns the absolute position of the text file. (in chars) - - The seeks operations are done in number of characters (not bytes). - The direction to move. Origin can be one of the following - - - - Returns true if file is open - - - - - Returns true if file at the end - - - - - This class is the base for all text file writers. It declare a common interface to all implementations and expose a number of services to output formatted strings to a file. - - - - - Write a string - of characters written - - to write - of character to write. Default is size of string in characters - - - - Write an UTF-16 string - of characters written - - to write - of character to write. Default is size of string in characters - - - - Write an - of characters written - - to write - - - - Returns true if we can write to file. - - - - - Returns true if file is open - - - - - Make sure that all the buffer are synced with the OS native objects. - - - - - Returns true if file at the end - - - - - Get the current position in the file. - - - - - Seek inside the stream. - Returns the absolute position of the text file. (in chars) - - The seeks operations are done in number of characters (not bytes). - The direction to move. Origin can be one of the following - - - - Write a formatted string using current locale. Writes the format string, filled in by the optional arguments. See the ISO C++ documentation for more information on printf and format strings. - - - format is not null. - There are the correct number of optional arguments to fill the format string. - The number of characters written. - - The format specification. - optional arguments to format. - - - - Reads and interprets text files. - This class was designed to perform file and stream I/O in a code page neutral way. - It was designed to perform resolve the following problems: - Plugin developer should consider using this class to perform File I/O to ensure that the files they generate remain compatible to previous version of Max. - - - - - Wrap a Win32 file handle - In addition to that, you can also specify FAVOR_UTF8. It can be used to cascade the detection of the codepage. For example, if you specify "CP_ACP | FAVOR_UTF8", the detection algorithm will treat any non-UTF8 data as ACP. - true if successful, false otherwise - - File Handle - This parameter can contains hint to the detection algorithm. Acceptable values are all codepages numbers that are recognized by Windows. - - - - Open a file using a file name - In addition to that, you can also specify FAVOR_UTF8. It can be used to cascade the detection of the codepage. For example, if you specify "CP_ACP | FAVOR_UTF8", the detection algorithm will treat any non-UTF8 data as ACP. - true if successful, false otherwise - - File name to open. If file does not exist, it will be created. - This parameter can contains hint to the detection algorithm. Acceptable values are all codepages numbers that are recognized by Windows. - - - - Open a file using a file name - In addition to that, you can also specify FAVOR_UTF8. It can be used to cascade the detection of the codepage. For example, if you specify "CP_ACP | FAVOR_UTF8", the detection algorithm will treat any non-UTF8 data as ACP. - true if successful, false otherwise - - File name to open. If file does not exist, it will be created. - This parameter can contains hint to the detection algorithm. Acceptable values are all codepages numbers that are recognized by Windows. - - - - Close the underlying stream and free any intermediate data. - - - - - Returns the last error return by the - Error string - - - - - Returns the current encoding of this file. - Returns the actual encoding found - - - - - Determine how this reader handles line ending. - LineEndMode - - - - - Returns the read buffer size - - - - - Returns the detect buffer size - - - - - Return the number of characters in the file - The total number of chars. - - - - - Calculate the total number of line feeds in the file - The total number of lines. - - - - - Get the EOF character handling method. - - - - - Reads up to "len" bytes from the file and convert it to a unicode-compliant string. - - of bytes to take out of the underlying stream. - Determine if this function will trim the last EOL sequence. - - - - Reads the file in a single operation and returns it in a single string object. - The full stream content - - - - - Get the number of bytes read so far. - - - - - This class is used to access text file with both reader and writer functionality. - - - - - Unread the passed string - size in nb of characters that has been written - - The string that will be put back into the buffer - - - - Open a file using a file name - In addition to that, you can also specify FAVOR_UTF8. It can be used to cascade the detection of the codepage. For example, if you specify "CP_ACP | FAVOR_UTF8", the detection algorithm will treat any non-UTF8 data as ACP. - true if successful, false otherwise - - File name to open. If file does not exist, it will be created. - Streaming mode - - - - Open a file using a file name - In addition to that, you can also specify FAVOR_UTF8. It can be used to cascade the detection of the codepage. For example, if you specify "CP_ACP | FAVOR_UTF8", the detection algorithm will treat any non-UTF8 data as ACP. - true if successful, false otherwise - - File name to open. If file does not exist, it will be created. - Streaming mode - - - - Close the opened file - - - - - Write Text files. - This class was intended to be used to write text file. It differ from the ANSI fopen, fprintf, et al, because it's smarter when it's to modify existing files. It detect the underlying file format and match it intelligently. - It was designed to resolve the following problems: - - - - - Bind on a file File handle This service is used to allow a developer to access a file open with fopen but with the advantage to use the SDK API. Using this service allows the developer to now worry about character encoding The developer is responsible to close the file once he is done. - true if successful, false otherwize - - File handle to use User is responsible for closing the file. - Append to file or truncate file - If the stream actually contains any data and append is true, it will detect it's format and match it. You can hint the detection algorithm by using FAVOR_UTF8. If the stream is empty, it will use the code page specified here. You can mix it with "WRITE_BOM" and/or "FLIPPED" bits. - - - - Open a file - true if successful, false otherwize - - File name to open - Append to file or truncate file - If the stream actually contains any data and append is true, it will detect it's format and match it. You can hint the detection algorithm by using FAVOR_UTF8. If the stream is empty, it will use the code page specified here. You can mix it with "WRITE_BOM" and/or "FLIPPED" bits. - - - - Open a file - true if successful, false otherwize - - File name to open - Append to file or truncate file - If the stream actually contains any data and append is true, it will detect it's format and match it. You can hint the detection algorithm by using FAVOR_UTF8. If the stream is empty, it will use the code page specified here. You can mix it with "WRITE_BOM" and/or "FLIPPED" bits. - - - - Close the file - - - - - Returns the last error return by the . - - - - - Returns the actual encoding used. - The encoding - - - - - Write an ASCII char - of characters written. - -1 if error - - The character to write - - - - Write an ASCII char - of bytes written. - -1 if error - - The character to write - - - - Text file reading encoding - - - - - EOF character handling - - - - - Three timer states are defined. - - - - - Defines the standard set of shading parameters for hair strands. - - - - - The material to be used for shading this hair. If null, then the shading parameters below should be used instead. - - - - - The ambient diffuse term. - - - - - Glossiness. - - - - - Specularity. - - - - - Specular color. - - - - - Specular color for secondary highlights. - - - - - Possible 3ds Max product help locations. - - - - - Shape of the aperture used to render bokeh with the depth of field effect. - - - - - Type of lens distortion. - - - - - A guard class which enables a physical camera to evaluate itself for ray-traced rendering (as opposed to viewport rendering). - - - In order to render viewports (more or less) correctly, the physical camera overrides Object::Eval() to return a object-space transform matrix which approximates the lens tilt/shift effect. Because this approximation fails in some cases, a ray-traced renderer should implement its own version of the tilt/shift effect. To do this, the renderer must disable the tilt/shift approximation from the evaluation of the transform matrix; it does so by instantiating this guard class wherever a camera is evaluated (e.g. through INode::EvalWorldState() or INode::GetObjTMAfterWSM()). - This class follows the guard implementation pattern, which performs all required work in the constructor and destructor. - - - - - The set of parameters used by the Physical Exposure . - - - - - The white point of the rendered image. - - - - - The aperture size, as an f-number. - - - - - The shutter duration, in seconds. - - - - - The ISO sensitivity. - - - - - The exposure value derived from: f-number, shutter, and iso. - - - - - The amount of vignetting. - - - - - Strength of highlights. - - - - - Gamma curve for the rendered image (incorporates the mid tones parameters). - - - - - Strength of dark values. - - - - - saturation. - - - - - used to provide generic access to the bitmap aperture. - - - This class abstracts the access mechanism to the bitmap aperture, such that we have no direct dependency to class . If the client is implementing this interface from a Max SDK plugin, then it may provide direct access to the contents of the , baked using Texmap::RenderBitmap. But if the client is calling the sampler from a shader that doesn't have access to the Max SDK, then it should access the texmap using whatever facilities are exposed by the shading API. - - - - - Returns the resolution of the bitmap aperture in X. - - - - - Returns the resolution of the bitmap aperture in Y. - - - - - Returns the contents of the pixel in the bitmap aperture, at the given X and Y coordinates. - - - - - A simple RGB color value. the Max SDK's class couldn't be used since we want to remain independent from the rest of the Max SDK. - - - - - The features that can be enabled/disabled when executing scene embedded scripts in safe scene script execution mode. - - - - - Encapsulates weather measurements provided by a weather data file. - - - - - The illuminance measurement on a horizontal plane, excluding the solar disc area. - - - - - The illuminance measured while facing the sun directly. - - - - - The dew point temperature in celsius. Only to be used if dew_point_temperature_valid is true. - - - - - Whether a valid dew_point_temperature was provided. - - - - - PluginPackage component types. PluginPackages contain components that need to be installed together on a system to provide a usable function to the user. - - - - - Type of an environment variable. - - - - - This enum type specifies a function. - - - - - Icon size parameter. - - - - - IDs for function published (Fps) methods and properties. - - - - - A callback class for enumerating animatables. - - - This class is a callback object for the Animatable::EnumerateAllAnimatables() method. The proc() method is called by the system. The Animatables are enumerated in order of creation - - - - - This is the method called by system from Animatable::EnumerateAllAnimatables(). - - - Return true to continue the enumeration, false to stop the enumeration. - - - A pointer to the - - - - A callback class for acquiring/releasing a FlagBit. - - - This class is a RAII object for acquiring/releasing a FlagBit - - - - - Possible return values for callback method (CAssertCB::AssertEx) invoked when an assertion fails. - - - - - Compares this class instance to another one - - - - - Symbolic name for the enum. - - - - - Equivalent integer code. - - - - - This class is used to temporarily disable global reference makers. - - - Implements the guard pattern to disable global reference makers. While disabled, none of the reference messages are sent to the global reference makers that were registered through RegisterGlobalReference(). - The class correctly handles nested disables by using a counter which is incremented in the constructor and decremented in the destructor. - An example of a case where it is useful to disable global reference makers is an operation which creates a lot of temporary references, such as temporary materials. The global reference makers may not need to be aware of the existence of these temporary references, so they may be disabled for performance reasons. - - - - - The type of the underlying object against which the hit testing occurred; triObject for , polyObject for , and patchObject for . The empty type indicates that no hit testing has been performed yet - - - - - Scene redraw guard class. - - - Instantiating an object of this type suspends (disables) scene redraw. When the object is destroyed, scene redraw is enabled automatically. - - - - - Suspends scene redraw. - - - - - Resumes scene redraw. - - - - - List of node properties. Interface10::FindNodes accepts a combination of these values and uses them to match nodes in the current scene. - - - - - Pivot modes the system can be in. - - - - - Flags for LoadFromFile method. - - - - - - - IDs for function published (Fps) methods and properties. - - - - - Enum for where to create the individual layer controllers when calling EnableAnimLayers. - - - - - - - Enum for specifying what type of controller you want a non keyable controller to collapse to when you collapse onto it. - - - - - - - The options used when calculating the vertex colors. - - - - - face colors is false, or mixed vertex colors if true - - - - - The options used when calculating the vertex colors. - - - - - Reuse Illumination or render direct lights. - - - - - The auto-tangent algorithms supported by 3ds Max. - - - - - The label and icon that make up each individual option for Type::eCombo grip item. - - - - - The string label for the radio option. - - - - - The icon file. - - - - - The grip value that's used by the grip item when it's value is retrieved via GetValue or set via SetValue. - - - - - The value is an integer. - - - - - The value is a float. - - - - - The value is a distinct combination set. - - - - - The value is a . - - - - - Reserved. Currently not in use. - - - - - Access possibilities for when a container is inherited. - - - - - Possibilities for items that may get locked when the AccessType is eAnythingUnlocked. - - - - - Possible values for global container status display. - - - - - of parameters that may be fed by the daylight system to the controlled light. - - - - - The DaylightControlType enumeration is for specifying how the daylight system is controlled,manually, from a specified date and time or via a weather file. - - - - - Describes the effect in use - - - - - Describes what the current pass is doing, standard rendering to the viewport, or for example creating textures for use later in the render process - - - - - Various 3ds Max Constraints. - - - These are the constraints supported by IGame - - - - - Various 3ds Max controller types. - - - - - Euler Orderings. - - - These are the rotation orders for an Euler Controller - - - - - The supported Coordinate Systems. - - - These are used to tell IGame how to format the data - - - - - Knot types. - - - - - Knot data. - - - - - Various types used by 3ds Max. - - - - - IGame modifier types. - - - These are the modifiers known to IGame - - - - - A morph type. - - - This provides details about the type of morph operator being accessed - - - - - Various IGame types. - - - These are the objects supported by IGame - - - - - Various 3ds Max types. - - - These are 3ds Max object - Developers can use this to cast the pointer to one of the relevent 3ds Max classes - - - - - Skinning Types. - - - These are the Skin modifiers known to IGame - - - - - Vertex types. - - - These are the types used by the modifiers - - - - - Enums of return types that the geometry checker may return. eFail means the check has failed for some reason, the other return types specify what type of geometric entity is returned. - - - - - The returned output of the checker. Currently the output is just a list of indices. What the indices are is specifed by the ReturnVal enum. - - - - - The PostDisplayCB method of the class is called after an image is displayed in the image viewer. Developers can use this to do any post-display related work. - Parameters: - HWND hWnd - - The handle of the image viewer window. - - - - - This method provides a way to extend the class with interfaces. - Parameters: - id - - The interface ID. - Default Implementation: - { return NULL; } - - - - - The EventHanderCB method of the class allows you to intercept window events prior to them being passed through. - Parameters: - HWND hWnd - - The handle of the image viewer window. - - UINT message - - The message identifier. - - WPARAM wParam - - The WPARAM value. - - LPARAM lParam - - The LPARAM value. - - bool &propagate - - TRUE if the message and event are to be propagated, otherwise FALSE. - - - - - This method provides a way to extend the class with interfaces. - Parameters: - id - - The interface ID. - Default Implementation: - { return NULL; } - - - - - This class represent a callback object which can be used with an interactive renderer. Information set via RendProgressCallback::SetCurField() or RendProgressCallback::SetSceneStats() will be ignored. If a title is set via the inherited method SetTitle(), it will appear in the main status bar, but will be replaced by the 'IRenderTitle' when necessary. An interactive renderer should abort if RendProgressCallback::Progress() returns RENDPROG_ABORT. - - - - - - - This method allows you to retrieve the orientation of the progress line shown during rendering. - The line orientation which is one of the following; LO_Horizontal or LO_Vertical. - - - - - This method returns the color of the progress line shown during rendering. - - - - - This method returns the current title. - - - - - The enum type for the space with regard to which the IK goal is interpreted. - - - - - Property ID enumeration. - - - - - Enumerates the available unit system for displaying lighting quantities. - - - - - Encapsulates the information related to a unit system. - - - - - The unit system being represented. - - - - - The unit suffix for luminance values. - - - - - The unit suffix for illuminance values. - - - - - Enum for the type of node mapping to due when creating a map file using CreateMapFile. - - - - - - - Enum for different flags to pass in when calling ILoadSaveAnimation::SaveAnimation and ILoadSaveAnimation10::SetUpAnimsForSaveExt. - - - If eAnimatedTracks is set, then a track needs to be animated. If eIncludeConstraints is set, and if eAnimatedTracks is set, constraints will also be considered to be animated. If eKeyable is set, then keyable tracks will be saved if eSaveSeg is set, then a segment of time will be saved. if eSegPerFrame is set then a key per frame will be saved over a saved segment. - - - - - Enum for different flags to pass in when calling ILoadSaveAnimation::LoadAnimation and ILoadSaveAnimation10::SetUpAnimsForLoadExt. - - - If eRelative is set, then nodes who are children of the scene root will keep their original position and orientation and the animation will be loaded relatively to that, otherwise the animation will be loaded in absolutely. If eInsert is set, then the animation will be inserted at the specified time and the existing animation will be moved over, otherwise the animation will replaced the existing animation at that time. If eStripLayers is set, then the active layer name will be stripped out from the current node controllers that have layers. If eIncludePB2s is set then we will include ParamBlock2 tracks when loading into the animation. Note that the eIncludePB2s flags is currently only used by ILoadSaveAnimation10::SetUpAnimsForLoadExt - - - - - Enum for different flags to pass in when calling ILoadSaveAnimation::CreateMapFile and ILoadSaveAnimation10::SetUpAnimsForMapExt. - - - If eMapControllerExactName is set then the controllers will try to be matched based upon their exact names, otherwise, they will try to match off of their subanim order. If eMapControllerType is set then the controller need to be the same of the same class, otherwise they won't map. If eStripLayersInMap is set, then the active layer name will be removed from the current node controllers that have layers. - - - - - This enumeration defines how the material is behaving in viewport. - - - - - A description for a parameter to be used in a meta-data, and its UI in an eventual rollout. - - - There are reasonable defaults for most of the fields. The ones that have to be filled are: - - - - - Enumeration defining versions of the face extrude operation. - - - - - User Property key. - - - - - User Property value. - - - - - IDs used by function publishing. - - - - - IDs of enumeration types used by function published methods. - - - - - Data structure for storing the ABCDE coefficients of the Perez sky model. - - - - - Types of requirement. - - - - - Different sources for renderer message. - - - - - Type of a message. - - - - - Definition of scene state parts. - - - Each part is represented by a bit in a - - - - - Function-publish IDs for the SimpleFaceData Channel functions. - - - - - Function-publish IDs for the SimpleFaceData Manager functions. - - - - - < Stores a color for each vertex of a triangle face. - - - - - Please refer to for more details. - - - - - Enum for our 3 floating view panels - - - - - List of xref item types or categories of xref-able scene entities. - - - Use the following values when retrieving xref items from xref records. - - - - - Types for the lights. These values are used in SetType and returned by Type. - - - - - Types for the distributions. These values are used in SetDistribution and returned by GetDistribution. - - - - - IDs for the references kept by this object. - - - - - IDs for the parameters blocks for Lightscape lights. - - - - - This enum is used to hold the General parameter IDs. - - - - - This enum is used to hold the Extended parameter IDs. - - - - - This enum is used to hold the Shadow parameter IDs. - - - - - This enum is used to hold the Spotlight parameter IDs. - - - - - This enum is used to hold the Photometric Web parameter IDs. - - - - - This enum is used to hold the intensity types. These are valid values for the Intensity Type parameter. - - - - - Shadow types for MAX. - - - - - Preset light colors. - - - - - Area Lights sampling custom attribute. - - - This class holds the sampling information and additional information for area lights. - - - - - Returns the number of samples to be used. - - - The number of samples should be a power of 2 - The number of samples - - - The time at which the number of samples is retrieved. - - If this argument is not NULL, the validity of this number of samples is intersected with the interval pointed to by this argument. - - - - Sets the number of samples to be used. - - - The number of samples should be a power of 2 - - - The time at which the number of samples is set. - - The number of sample to use. - - - - Returns whether the area light computation is enabled. - - - always the value kDefault_EnableAreaLight - - - The time at which the value is retrieved - - If this argument is not NULL, the validity of this value is intersected with the interval pointed to by this argument. - - - - Returns whether the light's shape is rendered. - - - TRUE if the light shape is rendered - - - The time at which the value is retrieved - - If this argument is not NULL, the validity of this value is intersected with the interval pointed to by this argument. - - - - whether the light's shape is rendered. - - - - - The time at which the value is retrieved - - Render or not the light shape in mental ray - - - - Default number of samples. - - - - - Helper class for disabling macroscript compiles in an exception-safe manner. - - - - - Explicitly enable macroscript compiles. - - - - - Class for easily & safely disabling the macro recorder. This class disables the macro recorder in its constructor and re-enables it in its destructor. It is therefore a fool-proof (and exception safe) way of temporarily disabling the macro recorder - - - - - Disables the macro recorder. - - - - - Enables the macro recorder. - - - - - interface ID. - - - - - interface ID. - - - - - A helper class for aquiring and releasing channel locks. Create an instance of this class to lock the channels, when it is destructed the locks are released. - - - - - helper class for disabling c++ callstack capture if a system exception is thrown. useful in code where exceptions are not unexpected, and the exception is 'eaten'. for example: - - - - - helper class for disabling mxs callstack capture if an exception is thrown. useful in code where exceptions are not unexpected, and the exception is 'eaten'. for example: - - - - - A helper class for aquiring and releasing channel locks. Create an instance of this class to lock the channels, when it is destructed the locks are released. - - - - - The type of the underlying object, triObject for , polyObject for , and patchObject for . - - - - - Selection enum values. - - - - - These enums describe how the geometry will be subdivided by OpenSubdiv. They are offset by -1 from the parameter values OpenSubdiv uses internally. - - - - - These enums describe how the varying data ie UV maps etc. will be subdivided by OpenSubdiv. They match the parameter values OpenSubdiv uses internally. - - - - - These enums describe how creases are handled by OpenSubdiv. They match the parameter values OpenSubdiv uses internally. - - - - - These enums tell whether to use CPU or GPU computation for OpenSubdiv - - - - - published properties for real-world map size. - - - - - Used to tear down a save reference hierarchy. - - - Before accessing the save reference hierarchy for a , the may need to prepare the save reference hierarchy. This is done by calling SpecifySaveReferences on the and all of its save references. An instance of the class passed to the SaveEnum method will perform this preparation. After the actions are complete, an instance of the class are passed to the SaveEnum method to tear down the save reference hierarchy. An example of this can be seen in the code example for . - - - - - Used to prepare a save reference hierarchy. - - - Before accessing the save reference hierarchy for a , the may need to prepare the save reference hierarchy. This is done by calling SpecifySaveReferences on the and all of its save references. An instance of the class passed to the SaveEnum method will perform this preparation. Plugins will not normally need to perform these actions to prepare the save reference hierarchy for a as the system will have already done so at the beginning of the save process. The only time a plugin would need to do this is if it is initiating a call to SaveEnum on the reference maker (i.e., the SaveEnum call is not in a SaveEnum implementation). For example: - /code this code is not within a SaveEnum implementation, so the save ref hierarchy has not already been created initialize: build save ref hierarchy preSaveEnumProc; maker->SaveEnum(preSaveEnumProc, FALSE); - SimpleSaveEnumerator saver; maker->SaveEnum(saver); - finalize: clear save ref hierarchy postSaveEnumProc; maker->SaveEnum(preSaveEnumProc, FALSE); /endcode - As seen in the code example, after completing the SaveEnum calls, you will also need to perform an additional SaveEnum passing a . This proc tears down the save reference hierarchy. - - - - - Returns whether pause is supported by this renderer. - - - - - List of commands that can be passed to Execute() - - - - - Indicates the pointer (stylus) type in use. Returned by the GetPointerType method. - - - - - Enables processing a tone operator independently of class , for example in a multi-threaded manner. - - - As class derives from , it may only safely be used from the main thread. But tone operators can be expensive to process, making it desirable to process them from non-UI threads (or even from multiple threads). This interface encapsulates everything a tone operator needs to process itself, but doesn't derive from so may safely be used from arbitrary threads. The implementation of this interface must allow for concurrent calls from arbitrary threads. - - - - - See virtual void ToneOperator::ScaledToRGB(float energy[3], const Point2& xyCoord) - This method is thread-safe, it may be called from multiple threads concurrently. - - - - - See virtual float ToneOperator::ScaledToRGB(float energy, const Point2& xyCoord) - This method is thread-safe, it may be called from multiple threads concurrently. - - - - - See virtual float ToneOperator::CanInvert() - This method is thread-safe, it may be called from multiple threads concurrently. - - - - - See virtual float ToneOperator::InverseMap(float energy[3], const Point2& xyCoord) - This method is thread-safe, it may be called from multiple threads concurrently. - - - - - See virtual float ToneOperator::InverseMap(float energy, const Point2& xyCoord) - This method is thread-safe, it may be called from multiple threads concurrently. - - - - - Enum of type that a controllery can be, e.g position track, rotation y track, note track etc.. - - - Enum of type that they can be, The can be more than one type. eNone means it has no type, eTransform means that the track is a transform controller or a child of one, eBaseObject means that the track is under an object, eModObject means the track is under a modifier, eNoteTracks means the track is a , eVisTracks means the track is a visibility track, eMatMaps means the track is under a material map, eMatParams means the track is under a material parameter, eCustomAttributes means the track is under a custom attribute, eIK means the track is under an IK controller, ePos means that track is position controller or one of it's children, eRot means the track is a rotation controller or one of it's children, eScale means the track is a scaleController or one of it's children, ePosX means the track is a position x controller, ePosY means the track is a position y controller, ePosZ means the track is a position z controller, eList means the track is a list controller or one of it's children, eRotX means the track is a rotation x controller, eRotY means the track is a rotation y controller, eRotZ means the track is a rotation z controller, eKeyable means the track is keyable,eScaleX means the track is a scale controller, eScaleY means the track is a scale y controller, eScaleZ means the track is a scale z controller, eExposeWorldTransform means the track is the world TM of a node,eLayer means that the track is a layer controller or a child of one - - - - - The types of object definition redefinition. - - - - - Used as the parameter in NOTIFY_NODE_RENAMED event - - - - - Used as the parameter in NOTIFY_NODE_NAME_SET event - - - - - Used as the parameter in NOTIFY_LAYER_DELETED event - - - NewLayer and OldLayer can be null when switching between layers, during create, and when loading files Layers may not be present in layer manager when sent during file load/merge - - - - - Used as the parameter in NOTIFY_POST_NODES_CLONED event - - - - - Gets the plugin manager - - - - - The single instance of the class. - - - - - The Primary Manager . - - - - - The MXS debugger interface. A Singleton. - - - - - Class ID of general deformable object. - - - - - Class ID of general texture-mappable object. - - - - - A modifier specifying this Class ID as its input type takes any object type as input. - - - - - an array of channel masks for all the channels "within" the . - - - - - Global object that contains the new object. - - - - - The unique instance of the real worls map size interface. - - - - - Wrapper around the windows function GetSystemMetrics. In Vista+ when running Aero, the value returned for SM_CXFRAME and SM_CYFRAME is incorrect in order to provide backwards compatibility with NT. To get the correct value, also need to add the value from SM_CXPADDEDBORDER. The implementation of this method automatically corrects the values returned for SM_CXFRAME and SM_CYFRAME. Note that SM_CXSIZEFRAME is the same index as SM_CXFRAME, and SM_CYSIZEFRAME as SM_CYFRAME; - - - The system metric or configuration setting to be retrieved. - - - - Multiplies each component of an by a float. - An with each component multiplied by a float. - - - - - Multiplies each component of an by a float. - An with each component multiplied by a float. - - - - - Composite fg over bg, assuming associated alpha, i.e. pre-multiplied alpha for both fg and bg - - This is: fg + (1.0f-fg.a)*bg - Parameters: - &fg - - Specifies the foreground color to composite. - - & bg - - Specifies the background color to composite over. - The resulting . - - - - - This global function creates a new instance for reading chunks out of buf: - Parameters: - BYTE *buf - - The buffer to read. - - int bufSize - - Specifies the nuymber of bytes that are valid in buf. - - - - - This global function create a new instance. - Parameters: - int initBufSize - - Specifies the initial size the internal buffer is allocated to. It will be enlarged if necessary. - - - - - This global function is provided by 3ds Max and is used to create the arcball dialog box. Then the methods of your callback class are called based on the user's use of the dialog. - Parameters: - *cb - - The callback whose methods are called based on the user's interaction with the dialog controls. - - HWND hwndOwner - - The window handle of the dialog owner. - - MCHAR* title=NULL - - The title string to be displayed in the dialog. - A new instance of the class. The instance is deleted when the dialog is closed. - - - - - Method to be called to signal a violation of some assumption in the code. - - - This method should not be called directly, but rather via the various assertion macros such as DbgAssert, MaxAssert, DbgVerify, etc. - Currently, this method either returns TRUE or it triggers the shutdown of 3ds Max - - - the line number where the assertion occurred - - the file path and name where the assertion occurred - - the non-decorated name of the function in which the assertion occurred - - the expression that was asserted - - - - Sets a callback object that allows for performing a custom action when an assertion fails (is triggered). - - - A plugin can supply an object that allows for executing a custom action when an assertion fails in 3ds Max. For details on the extent of possible customization see class . Currently, only one callback object can be active at any given time. This means that the callback installed by a plugin can be de-installed by another plugin. Thus, plugins should keep their callbacks active for as short of a time period as possible, and restore the previous callback object when they de-activate their own. - The old callback object or NULL if there's none set - - - The new callback object to use - - - - Returns the Proxy Manager singleton object. - - - - - Declare a bitmap asset accessor to the specified callback. - - - Decorates the specified asset accessor as a bitmap enabled asset accessor before declaring it to the specified enumeration callback. - - The EnumAuxFiles callback to declare the asset to. - The original asset accessor to decorate with proxy settings. - The bitmap info of the bitmap. If NULL, the declared bitmap will always be treated as a single frame, no pi-data bitmap. - Specify flags that define how the specified callback will declare the decorated accessor. Also controls how the accessor will be decorated. - - - - This global function will create a new instance of the specified storage type and return a pointer to it. - Parameters: - *manager - - The bitmap manager used for this storage. - - UINT type - - The type of storage to create. One of the following values: - - BMM_LINE_ART - BMM_PALETTED - BMM_GRAY_8 - BMM_GRAY_16 - BMM_TRUE_16 - BMM_TRUE_32 - BMM_TRUE_64 - The bitmap storage instance created or NULL if the specified type could not be created. - Data Members: - protected: - - int openMode; - - The mode the storage was opened in. See Bitmap Open Mode TypesUINT usageCount; - - The number of bitmaps using this storage. - - *manager; - - The bitmap manager associated with this storage. - - int flags; - - See Bitmap Flagsint type; - - See Bitmap Types palette[256]; - - The palette entries (256 max). See Structure . - - int paletteSlots; - - The number of palette slots used. - - UWORD *gammaTable; - - The gamma correction table. - - *rendInfo; - - A pointer to an instance of . See Class . - - bi - - Describes the properties of the bitmap associated with this storage. - - - - - A global function in bitmap.h - - Returns a localized string that describes one of the (BMM_TRUE_32, BMM_TRUE_64, etc.) bitmap types. The string is loaded into a static buffer and therefore should be used or copied immediately. The bitmap flags (from BitmapInfo::Flags()) are also used. - Parameters: - - - - - Create a filename appended by the specified frame number. This function will pad the filename with zeros. - - - For example, an input filename of sampleKitchen.bmp and frame 4 results in sampleKitchen0004.bmp - Zero if an error occurred, non-zero for success. - - A pointer to the buffer containing the base filename from which to create a numbered filename. - The frame number to append. Can be BMM_SINGLEFRAME for convenience, which results in the original filename. - A pointer to the buffer in which to store the created filename. This buffer must be large enough to accommodate the original filename, the digits of the framenumber, any zero-padding, and the file extension. - - - - Retrieve a list of existing files in a sequence that matches the base filename and numbering of the specified filename. - - - For example, a filename of sampleKitchen0001.bmp will return all existing files that match sampleKitchenxxxx.bmp, such as all files from sampleKitchen0000.bmp to sampleKitchen0060.bmp. This is similar to the sequence detection used in the Image File List (IFL) image format. - The number of matching files found. Zero if none found or an error occurred. - - The filename to match. - The list of matching files found. This list is cleared by the function. - - - - Resolves the filename in the given (bi->) - - - These functions search the system for a bitmap. The input parameter contains the name of the bitmap that is searched for (bi-> or namein). If the filename from the input is incorrect, and the bitmap is found somewhere else, these functions set the output (bi-> or nameout) with the correct path. When using the second version, you must specify the size in characters of the nameout buffer using nameoutSize. If the buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - The order of the search is as follows: - - - - - Resolves the given input name (namein) into the given output (nameout) - - - - - Splits up a file path into three strings, the directory name, file name, and file extension. - - - The three out parameters are allowed to be NULL. For non-NULL parameters you must specify the size in characters of the buffer. If the buffer is not big enough to hold the output (including a null terminator), the result is truncated. - - The full path to the file to be split - A string containing the directory portion of the file path - The size in characters of the directory buffer - A string containing the file name portion of the file path - The size in characters of the filename buffer - A string containing the file extension portion of the file path - The size in characters of the extension buffer - - - - This function appends a slash character to the end of the path passed unless one already exists. - - - - The path name to append. If NULL, no operation. - - - - This function removes the slash character from the end of the path passed if present. - - - - The path name to append. If NULL, no operation. - - - - This function appends a slash character to the end of the path passed unless one already exists. - - - - The path name to append. - - - - This function removes the slash character from the end of the path passed if present. - - - - The path name to append. If NULL, no operation. - - - - Rearranges the palette pal (which has colors 0..ncols-1 occupied, in descending order of frequency), into newpal so that the colors 10-245 are populated first, then 0-9, then 246-255. Sets the optional array remap to map the old palette index values to the new ones. - Parameters: - *pal - - The palette to rearrange. - - *newpal - - The rearranged palette. - - int ncols - - The number of colors in the palette. - - BYTE *remap=NULL - - An array that maps the old palette index values to the new ones. - - - - - Returns the Pager singleton object. - - - - - Returns the index of the component with the maximum absolute value. - Parameters: - & - - The color to check. - The index of the component with the maximum absolute value. r=0, g=1, b=2. - - - - - Returns the index of the component with the minimum absolute value - Parameters: - & - - The color to check. - The index of the component with the minimum absolute value. r=0, g=1, b=2. - - - - - Returns the value of the component with the maximum absolute value. - Parameters: - & - - The color to check. - The value of the component with the maximum absolute value. - - - - - The value of the component with the minimum absolute value. - Parameters: - & - - The color to check. - - - - - Returns the 'length' of the color, i.e. - - return (float)sqrt(v.r*v.r+v.g*v.g+v.b*v.b); - Parameters: - & v - - The color to return the length of. - The length of the color. - Operators: - - - - - From a super class id determine which default control to use. Use the other GetDefaultController when a ParamType is available. - - - - - From a super class id and ParamType, determine which default control to use. Ex: A boolean parameter will have a ParamType2 of TYPE_BOOL with a super class CTRL_FLOAT_CLASS_ID. In this case we would expect the default boolean control over the default float control. - - - - - Returns the sum of two ScaleValues. This still multiplies since scale values are multiplicative not additive. - - - - - Returns the difference of two ScaleValues. - - - - - Multiplication of a and a float. - - - - - Multiplication of a and a float. - - - - - Returns the sum of a and a float. This adds f to s.x, s.y, and s.z. - - - - - Returns the sum of a and a float. - - - - - Returns a TimeValue that is the specified time mod of the interval length. The returned time is somewhere within the interval passed. This cycles the time so that it appears within the interval. - - - - - Returns the number of times the TimeValue cycles through the interval. - - - - - Takes an interval and checks the flags and modifies the interval based on the state of the flags. - - - - - Returns a quaternion scaled by the specified factor. This scales the 'angle' of the quaternion. - - - - - Return the fixed font used by 3ds Max. - - - HFONT object representing the font - - - - - Return the fixed font used by 3ds Max, based on the 3ds Max's language and character set. For internal use only. - - - HFONT object representing the font - - - - - Return the fixed bold font used by 3ds Max. - - - HFONT object representing the font - - - - - Return the fixed bold font used by 3ds Max, based on the 3ds Max's language and character set. For internal use only. - - - HFONT object representing the font - - - - - Returns the height of the fixed font used by 3ds Max. - - - Font height (14 for English & European languages, 12 for Asian languages) - - - - - Returns the height of the small fixed font used by 3ds Max. - - - Font height (8 for English & European languages, 9 for Asian languages) - - - - - Returns the fixed font character set for the language currently used by 3ds Max. - - - character set for the current language - - - - - Returns the font face string for the fixed font used by 3ds Max. - - - Font face string for the fixed font. - - - - - Return the standard font used in 3ds Max's user interface. - - - HFONT object representing the font - - - - - Return the standard font used in 3ds Max's user interface, depending on the language and charset. For internal use only. - - - HFONT object representing the font - - - - - Return the standard bold font used in 3ds Max's user interface. - - - HFONT object representing the font - - - - - Return the standard bold font used in 3ds Max's user interface, depending on the language and charset. For internal use only. - - - HFONT object representing the font - - - - - Returns the height of standard font which used in 3ds Max's user interface. - - - Font height (14 for English & European languages, 12 for Asian languages) - - - - - Returns the height of small font which used in 3ds Max's user interface. - - - Font height (8 for English & European languages, 9 for Asian languages) - - - - - Returns character set for the current language used in 3ds Max's user interface. - - - character set for the current language - - - - - Returns the font face string for the standard font used in 3ds Max's user interface. - - - Font face string for the standard font. - - - - - Return the standard small font 6 points used in 3ds Max's user interface. - - - HFONT object representing the font - - - - - Return the standard light font used in 3ds Max's user interface, weight = FW_LIGHT(300). - - - HFONT object representing the font - - - - - Return the standard italic font used in 3ds Max's user interface. - - - HFONT object representing the font - - - - - Returns a pointer to the which controls the overall operation of CUI Frames (the windows which contain toolbars, menus, the command panel, etc). - - - - - Used to initialize and return a pointer to the spinner control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Returns the global spinner snap setting; TRUE if on; FALSE if off. - - - - - Returns the global spinner snap increment or decrement value. - - - - - Returns the number of decimal places displayed in the edit box linked to a spinner control. Note that this function also affects slider controls. See Class . - - Spinner controls have a global snap setting. This is set in 3ds Max using File/Preferences... in the General page by changing the Spinner Snap setting. When enabled this specifies an increment that is applied to the current spinner value each time the UP or DOWN buttons are pressed on the spinner control. - - - - - Used to initialize and return a pointer to the slider control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - This global function is used for setting up integer sliders. It performs the equivalent of the GetISlider(), SetLimits(), SetValue(), and LinkToEdit(). - Parameters: - HWND hwnd - - The handle of the dialog box in which the slider appears. - - int idSlider - - The ID of the slider. - - int idEdit - - The ID of the edit control. - - int min - - The minimum allowable value. - - int max - - The maximum allowable value. - - int val - - The initial value for the spinner. - - int numSegs - - The number of segments to use for the control. - A pointer to the slider control. - - - - - This global function is used for setting up floating point sliders. It performs the equivalent of the GetISlider(), SetLimits(), SetValue(), and LinkToEdit(). - Parameters: - HWND hwnd - - The handle of the dialog box in which the slider appears. - - int idSlider - - The ID of the slider. - - int idEdit - - The ID of the edit control. - - float min - - The minimum allowable value. - - float max - - The maximum allowable value. - - float val - - The initial value for the spinner. - - int numSegs - - The number of segments to use for the control. - A pointer to the slider control. - - - - - This global function is used for setting up 'universal' value sliders (EDITTYPE_UNIVERSE - these display world space units). It performs the equivalent of the GetISlider(), SetLimits(), SetValue(), and LinkToEdit(). - Parameters: - HWND hwnd - - The handle of the dialog box in which the slider appears. - - int idSlider - - The ID of the slider. - - int idEdit - - The ID of the edit control. - - float min - - The minimum allowable value. - - float max - - The maximum allowable value. - - float val - - The initial value for the spinner. - - int numSegs - - The number of segments to use for the control. - A pointer to the slider control. - - - - - Returns TRUE if CC_SLIDER_CHANGE notifications are sent by sliders while the user adjusts them with the mouse; FALSE if they are not sent. - - - - - This function returns TRUE if a particular rollup panel is open given a handle to the dialog window in the panel. - Parameters: - HWND hDlg - - Handle to the dialog window in the panel. - - - - - Used to initialize and return a pointer to the rollup window control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the custom edit control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the custom status edit control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the button control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the custom status control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the separator control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the toolbar control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the vertical toolbar control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the image control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Used to initialize and return a pointer to the color swatch control. - - window handle of the control. - sets the initial color selected. - sets the text string displayed in the title bar of the selection dialog. - - - - Used to initialize and return a pointer to the color swatch control. - - window handle of the control. - sets the initial color selected. - sets the text string displayed in the title bar of the selection dialog. - - - - Used to initialize and return a pointer to the color swatch control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Refresh all color swatches. - - - - - Used to initialize and return a pointer to the D&D window control. - - window handle of the control. - - - - Used to release the control when finished. - - Points to the control to release. - - - - Handy routines for setting up Spinners. This global function (not part of class ) is used for setting up Spinners. It performs the equivalent of GetISpinner(), SetLimits(), SetValue(), and LinkToEdit(). WARNING: To prevent a Memory Leak, be sure to call ReleaseISpinner on the pointer that this function returns, or use AutoPtr and . - - - - A pointer to the spinner control. - - - The handle of the dialog box in which the spinner appears. - - The ID of the spinner. - - The ID of the edit control. - - The minimum allowable value. - - The maximum allowable value. - - The initial value for the spinner. - - - - Handy routines for setting up Floating Point and Universe Spinners. This global function (not part of class ) is used for setting up Spinners. Internally it calls the GetISpinner(), SetLimits(), SetValue() and LinkToEdit() functions. WARNING: To prevent a Memory Leak, be sure to call ReleaseISpinner on the pointer that this function returns, or use AutoPtr and . - - - - A pointer to the spinner control. - Sample Code: - Sample code to initialize a spinner / edit control. The above code could be replaced with the following simplified code: - - - The handle of the dialog box in which the spinner appears. - - The ID of the spinner. - - The ID of the edit control. - - The minimum allowable value. - - The maximum allowable value. - - The initial value for the spinner. - = 0.1f - The initial scale value for the spinner. - - - - Returns TRUE if CC_SPINNER_CHANGE notifications are sent by spinners while the user adjusts them with the mouse; FALSE if they are not sent. - - - - - Explicitly marks the scene as "dirty". - - - Similar to SetSaveRequiredFlag(BOOL), but with finer control over both "save" and "autobackup" flags. This is used when flags need to be reset after an operation. - - - If TRUE, the scene will be flagged as requiring a save. - - If TRUE, the scene will be flagged as requiring an autobackup. - - - - Retrieves the internal save required flag. - - - The value of the "save-required" flag as last set by the SetSaveRequiredFlag method. - - - - - Retrieves the internal autobackup save required flag. - - - The value of the "autobackup-save-required" flag as last set by the SetSaveRequiredFlag method. - - - - - This tells if the scene needs to be saved. - - - Whenever an undoable operation is executed (by the user or otherwise), or SetSaveRequiredFlag is called with TRUE as its first parameter, the scene is considered different than its most recently saved version. - TRUE if the scene needs to be saved; FALSE otherwise. - - - - - This tells if the current scene needs to be backed up. - - - An autosave is required when (a) something has changed in the scene (a save is required) and (b) no autosave has been performed since the last scene change. The second condition (b) guarantees that the scene is backed up only once when a 3ds Max session is left unattended for a time that spans several autosave (autobackup) time intervals. - TRUE if an autosave should occur; FALSE otherwise. - - - - - This is another way to decompose a matrix into the scale and rotation parts (the position part can be retrieved from the bottom row of the matrix). This does not return correct results for off axis scale. - Parameters: - m - The input matrix to decompose. - - &s - The scale from the matrix. - - & q - The rotation of the matrix. - - - - - This will decompose a matrix into the translation, rotation and scale components and store the results in the structure passed. This will return correct results for off axis scale. This is a fairly computationally intensive iterative solution operation. - Parameters: - A - The input matrix to decompose. - - *parts - The result. See above. - - - Sample Code: - Note: If you want to rebuild a from the decomposed parts you get back from decomp_affine() the important thing is the order the parts are combined. - - Consider the following matrices constructed from the various affine parts: - ptm = position component (t) - rtm = "essential" rotation (q) - srtm = "stretch" rotation (u) - stm = scale component (k) - ftm = the flip tm -> ScaleMatrix((ap.f,ap.f,ap.f)); - - Here's the correct way of reassembling the decomposed matrix: - - - - - - This is used to take the and inverts them. This gives you the equivalent parts for the inverse matrix. - Parameters: - *parts - The input pointer. - - *inverse - The inverse of parts. - - - - - This will recompose a matrix into a . - Parameters: - & ap - The input parts to compose. - mat - Result of the composition. - - - - - - Builds a new matrix for use as a X rotation transformation. - A new X rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a Y rotation transformation. - A new Y rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a Z rotation transformation. - A new Z rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a translation transformation. - A new translation . - - Specifies the translation values. - - - - Builds a new matrix for use as a rotation transformation by specifying yaw, pitch and roll angles. - - This definition will depend on what our coordinate system is. This one is equivalent to: Which presupposes Y is vertical, X is sideways, Z is forward - A new rotation . - - Specifies the yaw angle in radians. - Specifies the pitch angle in radians. - Specifies the roll angle in radians. - - - - Builds a new matrix for use as a rotation transformation by specifying an angle and axis. - A new rotation . - - Specifies the axis of rotation. Note that this angle is expected to be normalized. - Specifies the angle of rotation. Note: The direction of the angle in this method is opposite of that in . - - - - Return the inverse of the matrix - - The matrix to compute the inverse of. - - - - These transform a with a . These two versions of transforming a point with a matrix do the same thing, regardless of the order of operands (linear algebra rules notwithstanding). - The transformed . - - The matrix to transform the point with. - The point to transform. - - - - These transform a with a . These two versions of transforming a point with a matrix do the same thing, regardless of the order of operands (linear algebra rules notwithstanding). - The transformed . - - The point to transform. - The matrix to transform the point with. - - - - Transform the vector () with the specified matrix. - The transformed vector (as a ). - - The matrix to transform the vector with. - The vector to transform. - - - - transform a plane. - this only works if M is orthogonal - - The transformation to apply to the plain - the plane to be transformed - - - - This method is used to build a matrix that constructs a transformation in a particular space. For example, say you have a rotation you want to apply, but you want to perform the rotation in another coordinate system. To do this, you typically transform into the space of the coordinate system, then apply the transformation, and then transform out of that coordinate system. This method constructs a matrix that does just this. It transforms matrix m so it is applied in the space of matrix xm. It returns a that is xm*m*Inverse(xm). - Returns a that is xm*m*Inverse(xm). - - Specifies the coordinate system you want to work in. - Specifies the transformation matrix. - - - - Mirrors the input matrix against the X, Y, or Z axis. This function mirrors the input matrix such that if it transformed a p, the transform applied by the mirrored transform would place p in an equivalent position relative but with one of it's elements negated. - - The Matrix to mirror - The world plane to mirror around. The axis will be reflected against the plane formed by the point (0, 0, 0) and the normal where normal[axis] = 1; - The matrix can be mirrored either by pure rotation, or by pure scaling. If true, the matrix is mirrored by flipping one of its axis, changing the handedness of the matrix. This had the advantage that the mirroring will be passed onto all it's children. This is preferential when the system can handle it, but can cause issues in systems that do not compensate for scale, eg game pipelines and skinning. if false, the mirroring will be achieved using rotation only and will not affect child local positions. It is better to use non-scaling mirroring when dealing with tools or processes that do not well support scale, or when the matrix will be blended with non-scaled matrices. (eg, Point/Quat based pipelines and skinning) - - - - Same as Maxtrix3::operator[]. Perform matrix multiplication without additional matrix copy - - The result of matrixA * matrixB - First matrix to multiply - Second matrix to multiply - - - - Same as Maxtrix3::Inverse. Compute the inverse of the matrix without additional matrix copy - - The inversed matrix. - The matrix to compute the inverse of. - - - - Returns the 'Length' of the point. This is sqrt(v.x*v.x+v.y*v.y) - the length value - - the to test - - - - Returns the component with the maximum absolute value. - the maximum component (0=x, 1=y). - - the to test - - - - Returns the component with the minimum absolute value. 0=x, 1=y. - the minimum component (0=x, 1=y). - - the to test - - - - Returns a unit vector. This is a with each component divided by the point Length(). - the unit vector for the specified - - the to test - - - - Divide a by a scalar - the resulting - - the - the divisor - - - - Double-Precision Line Segment Intersection test. Determines if two line segments intersect. - Intersection determination (0: No intersection, 1: Lines intersect (intersection location in 'intersectPoint'), 2: Lines parallel (no intersection)) - - endpoint 1 for the first line segment - endpoint 2 for the first line segment - endpoint 1 for the second line segment - endpoint 2 for the second line segment - if the lines intersect, this will return the intersection point. - - - - Double-Precision Line Intersection test. Determines if two infinite lines cross, and if so, where. - Intersection determination (0: Lines parallel, 1: Lines intersect (intersection location in 'intersectPoint')) - - point 1 on the first line - point 2 on the first line - point 1 on the second line - point 2 on the second line - if the lines intersect, this will return the intersection point. - - - - Returns the component with the maximum abs value. 0=x, 1=y, 2=z. - - - - - Returns the component with the minimum abs value. 0=x, 1=y, 2=z. - - - - - Returns the length of the - - - - - Returns a whose members are divided by a scalar. - - - - - Normalizes p using double precision - - - - - These methods centralize the handling of maxscript exceptions in c++ code. Typical usage looks like: - scopedMaxScriptEvaluationContext; MAXScript_TLS* _tls = scopedMaxScriptEvaluationContext.Get_TLS(); two_value_locals_tls( thingValue, propNameValue ); try { scopedSaveCurrentFrames(_tls); vl.thingValue = InterfaceFunction::FPValue_to_val( thing ); vl.propNameValue = Name::intern( propName ); vl.thingValue = vl.thingValue->get_property( &vl.propNameValue, 1 ); vl.thingValue->to_fpvalue( retVal ); } catch (& e) { ProcessMAXScriptException(e, _T("GetScriptedProperty"), false, false, true); } catch (...) { ProcessUnknownMAXScriptException(_T("GetScriptedProperty"), false, false, true); } - - The maxscript exception to process - The string to be used in the title bar of the error message box, and is used as part of the verbose description of the exception. Can be null. - If true, an error message box is displayed (unless max is in quiet mode). - If true, source position of error is shown in Scripting editor. - If true, terminal handling of the exception is occurring. If false, the catch will be rethrowing the exception. - If true, error information is not written to , a brief description of the exception and its source location is written to the log file. - - - - From in file VC2015Samples/_Hash_seq/fnv1a.hpp The internal hash function std::_Hash_seq(const unsigned char *), used to implement std::hash on some string types, was visible in recent versions of the Standard Library is not anymore visible (VC2017 15.3) - To remove this dependency, add the header (fnv1a.hpp) to any affected code, and then find and replace _Hash_seq by fnv1a_hash_bytes. You'll get identical behavior to the internal implementation in _Hash_seq. - - - - - This function will wrap a in a and/or a if the value is a , the code is currently in a structure or plugin context, and the 's owner is the associated with the structure or the MSPluginClass associated with the plugin. - Parameters: - Value* val - - The to potentially wrap. - - MAXScript_TLS* _tls - - The current MAXScript thread local storage pointer if known. - If val is a , either a wrapper for the , the , or if not a , the val. - Description: - This function is used when storing a for later use in a callback. The needs to be wrapped in a and/or a if the is defined by a and/or MSPluginClass so that the proper context is set when later calling the . This context allows plugin and structure locals to be properly resolved to the instance of the plugin and/or structure the was acquired from. - - - - - Determines the number of parameters defined by a . - Parameters: - Value* val - - A potentially wrapped . - - int& parameterCount - - The number of parameters defined by a . - True if val is a or a wrapped , and the parameterCount arg was set. Otherwise, false. - - - - - Determines if 2 values point to the same in the same context. - Parameters: - Value* fn1 - - The first potentially wrapped . - - Value* fn2 - - The second potentially wrapped . - - - True if both vals point to the same , and if they are wrapped MAXScriptFunctions, whether there contexts are the same. Otherwise, false. - - - - - Return the wrapped . may be wrapped in a and/or a - Parameters: - Value* val - - A potentially wrapped . - - - The wrapped . If val is not a , , or , val is returned - - - - - Gamma corrects the value passed using the specified gamma setting. - Parameters: - float v - - The value to gamma correct. - - float gamma - - The gamma setting. - The gamma corrected value. - - - - - De-gamma corrects the value passed using the specified gamma setting. - Parameters: - float v - - The value to de-gamma correct. - - float gamma - - The gamma setting. - - - - - Gamma corrects the value passed using the specified gamma setting. - Parameters: - UWORD c - - The value to gamma correct. - - float gamma - - The gamma setting. - The gamma corrected value. - - - - - De-gamma corrects the value passed using the specified gamma setting. - Parameters: - UWORD c - - The value to de-gamma correct. - - float gamma - - The gamma setting. - - - - - Returns the number of bytes per pixel for the specified channel. - Parameters: - int i - - The index of the channel. See G-Buffer Channel Indices. - - - - - Returns the name of the specified channel. - Parameters: - int i - - The index of the channel. See G-Buffer Channel Indices. - The name returned for the specified index: - - GB_Z (0): "Z" - - GB_MTL_ID (1): "Material Effects" - - GB_NODE_ID (2): "Object" - - GB_UV (3): "UV Coordinates" - - GB_NORMAL (4): "Normal" - - GB_REALPIX (5): "Non-Clamped Color" - - GB_COVERAGE (6): "Coverage" - - GB_BG (7): "Coverage Background" - - GB_NODE_RENDER_ID (8): "Node Render ID" - - GB_COLOR (9): "Color" - - GB_TRANSP10): "Transparency" - - GB_VELOC (11): "Velocity" - - GB_WEIGHT (12): "Sub-Pixel Weight" - - GB_MASK (2): "Sub-Pixel Coverage Mask" - - - - - Returns the maximum layer depth. - - - - - Creates and returns a pointer to a new default G-Buffer. The buffer is essentially created empty. - - A 'default' G-Buffer is one that 3ds Max itself creates. See GBuffer::IsDefaultGBuffer() below. - - - - - Returns both the sine and cosine of the specified angle as floats. - - - - - Returns the sine of the specified angle as a float. - - - - - Returns the cosine of the specified angle as a float. - - - - - Returns the square root of the specified argument as a float. - - - - - Returns a non-zero value if crossing mode is used for selections, or zero if windowing mode is used instead. - - - - - Sets the type of crossing mechanism used in crossing mode of selections. This is either AC_DIR_RL_CROSS or AC_DIR_LR_CROSS. - - - - - Retrieves the current value of the specified custom color - The current value of the color, as an RGB value - - The identifier of the custom color to retrieve. See - - - - Sets the current value of the specified custom color. - - The identifier of the custom color to retrieve. See - Pointer to the new color value object - - - - Retrieves the default value of the specified custom color. - The default value of the color, as an RGB value - - The identifier of the custom color to retrieve. See - - - - Returns the absolute value of an integer. - - - - - Given three points in a windows coordinate system (where the upper-left of the window is origin) returns TRUE if the face is facing backwards, FALSE otherwise - - - - - Given three points in a coordinate system where the lower-left of the window is origin returns TRUE if the face is facing backwards, FALSE otherwise - - - - - Returns the facing of a given triangle relative to the screen. Returns whether a given triangle is front-facing, side-facing, or back-facing relative to the screen. The triangle is passed as three points in screen space. This function is used for "w" format device coordinates. - - The 1st triangle vertex - The 2nd triangle vertex - The 3rd triangle vertex - If true, flip the triangle (so backfacing would return frontfacing) - - - - Returns the facing of a given triangle relative to the screen. The methods wFacingType() and hFacingType() will return whether a given triangle is front-facing, side-facing, or back-facing relative to the screen. The triangle is passed as three points in screen space. This function is used for "h" format device coordinates. - - The 1st triangle vertex - The 2nd triangle vertex - The 3rd triangle vertex - If true, flip the triangle (so backfacing would return frontfacing) - - - - Returns a bounding rectangle that encloses the entire hit region. For example if the hit regions was a fence region, this method would return the smallest rectangle that included the entire set of fence region points. - - The hit region to check - Points to the returned bounding rectangle. - - - - Returns the signed distance from x, y to the line defined by p1->p2. - - - - - Returns the unsigned distance from the 2D point x, y to the 2D line segment defined by p1->p2. - - The x coordinate of the 2D point. - The y coordinate of the 2D point. - The first end point of the 2D line segment. - The second end point of the 2D line segment. A line segment is the finite segment between two end points , different from the infinite line used in distToLine. Notice that this routine returns unsigned distance, which means not matter on which side of the line the point is, the returned value is always non-negative. - - - - Returns z depth at closest point in the line defined by p1->p2 to x,y v = the vector from p1 to p2 w = the vector from p1 to q=(x,y) t = (w dot v) / (v dot v) p1[2] + (p2[2] - p1[2]) * t - - - - - Returns z depth at closest point in the segment defined by p1->p2 to x,y v = the vector from p1 to p2 w = the vector from p1 to q=(x,y) t = (w dot v) / (v dot v) t = clamp(t, 0.0, 1.0) p1[2] + (p2[2] - p1[2]) * t - - - - - Returns nonzero if the line defined by p1->p2 crosses into the RECT and 0 otherwise. - - - - - Returns nonzero if the line-segment defined by p1->p2 crosses into the RECT and 0 otherwise. - - - - - Returns nonzero if the line-segment defined by p1->p2 crosses the circle center at (cx, cy) with a radius of r 0 otherwise. - - - - - Returns TRUE if the point passed is inside the specified triangle. - Returns TRUE if the point passed is inside the specified triangle; otherwise FALSE. - - The first point of the triangle - The second point of the triangle - The third point of the triangle. - The point to check. - - - - Returns the z value of where the projected screen point q would intersect the triangle defined by (p0, p1, p2). - Returns TRUE if the point passed is inside the specified triangle; otherwise FALSE. - - The first point of the triangle - The second point of the triangle - The third point of the triangle. - The screen point to check. - - - - Given an integer returns another integer which is the closest power of 2 - - - - - There is only a single global instance of this class, and this method returns a pointer to it. A developer may use this pointer to call the methods of . - - - - - Calculates the barycentric coordinates of the point p in 3-dimensional space according to a reference triangle indicated by its three vertices p0, p1 and p2. - Barycentric coordinates of point p. - - The three vertices of the reference triangle in 3-dimensional space. - The point for which the barycentric coordinates should be calculated. - - - - Calculates the barycentric coordinates of the point p in 2-dimensional space according to a reference triangle indicated by its three vertices p0, p1 and p2. - Barycentric coordinates of point p. - - The three vertices of the reference triangle in 2-dimensional space. - The point for which the barycentric coordinates should be calculated. - - - - Checks if the given ray intersects a three-dimensional box. - true if the ray intersects the box, false otherwise. - - The ray - The box - - - - Calculates the distance of a given point from a line in two dimensions. - The distance of the point from the line. - - Pointers to the two 2-dimensional points with which the line is defined. - Pointer to the 2-dimensional point whose distance from the line should be calculated. - - - - Calculates the distance of a given point from a line in three dimensions. - The distance of the point from the line. - - Pointers to the two 3-dimensional points with which the line is defined. - Pointer to the 3-dimensional point whose distance from the line should be calculated. - - - - Computes the bump basis vector in MikkT way for the U texture channel (called the tangent), and the cross product of the surface normal with the tangent (called the binormal). These along with the surface normal are used as the basis vectors for normal mapping. - - The callback will be called during the computation to fill all required data and receive the results of computation. - - - - Computes the bump basis vectors for the U and V components of the texture coordinates channel (also called the tangent and bitangent). - This function differs from ComputeTangentAndBinormal() as the latter computes the binormal - the cross product of U tangent vector and normal - rather than the V tangent (or bitangent). The binormal and bitangent will differ if the U and V coordinates are not perpendicular to each other. - Two unit vectors in XYZ space, tangent to the surface of the given triangle, aligned with the U and V directions of the given texture coordinates. - - The XYZ coordinate of the first triangle vertex. - The XYZ coordinate of the second triangle vertex. - The XYZ coordinate of the third triangle vertex. - The UV coordinate of the first triangle vertex. - The UV coordinate of the second triangle vertex. - The UV coordinate of the third triangle vertex. - - - - Low precision compression of a vector from 12 bytes to 4 bytes. Only accurate to 1 part in 512. This is commonly used to compress normals. The vector has to be <= 1.0 in length. - The 4-byte long compressed value of p - - The decompressed vector. - - - - Creates an arbitrary axis system given an up vector that conforms to the AutoCAD algorithm. - - The up vector. - The new axis system. - - - - This method is called to perform the video color check for each pixel. This function can be used to correct a pixel with RGB values that will give "unsafe" values of chrominance signal or composite signal amplitude when encoded into an NTSC or PAL color signal. This happens for certain high-intensity high-saturation colors that are rare in real scenes, but can be present in computer generated images. - A non-zero value if the color is corrected. Otherwise, zero. - - The pixel to check and correct if necessary. - One of these values: - - - - This method puts up the modal HSV color picker dialog box. This dialog appears below: - - - Parameters: - HWND hwndOwner - - Owner window handle. - - DWORD *lpc - - Pointer to color to be edited. See . - - *spos - - The starting position of the upper left corner of the dialog window. This is set to the ending position when the user is done. You may pass NULL to get the default location. - - *callBack - - Callback object whose procs are called when the color changes. See Class . - - MCHAR *name - - The name of color being edited to appear in the title bar. - Returns TRUE if the user exists the dialog with OK, otherwise returns FALSE. - - - - - This method puts up the modal HSV color picker dialog box. - Parameters: - HWND hwndOwner - - Owner window handle. - - *lpc - - Pointer to color to be edited. - - *spos - - The starting position of the upper left corner of the dialog window. This is set to the ending position when the user is done. You may pass NULL to get the default location. - - *callBack - - Callback object whose procs are called when the color changes. See Class . - - MCHAR *name - - The name of color being edited to appear in the title bar. - Returns TRUE if the user exists the dialog with OK, otherwise returns FALSE. - - - - - Converts the specified color in the RGB (red, green, blue) format to the HSV (hue, saturation, value) format. - - - - - Converts the specified color in the HSV (hue, saturation, value) format to the RGB (red, green, blue) format. - - - - - Converts the specified color in the HSV (hue, saturation, value) format to the HWBt (hue, whiteness, blackness) format. - - - - - Converts the specified color in the HWBt (hue, whiteness, blackness) format to the HSV (hue, saturation, value) format. - - - - - Converts the specified color in the RGB (red, green, blue) format to the HSV (hue, saturation, value) format. - - - - - Converts the specified color in the HSV (hue, saturation, value) format to the RGB (red, green, blue) format. - - - - - Call this function to bring up the modeless color picker. - Parameters: - HWND hwndOwner - - - The owner window handle. - - - DWORD initColor - - - The initial color for the color picker. - - - IPoint2* spos - - - The initial screen position of the upper left corner. NULL may be passed for the default location. - - - *pcallback - - - The callback object to respond to color change events. - - - MCHAR *name - - - The title string in the dialog. - - - int objClr=0 - - - A BOOLEAN used to indicate that the is being used to set the object color from the control panel. In all other cases, the default value of 0 should be used. - - A pointer to a object. Returned object is owned by the system and pointer may become dangling after the HSVCallback::BeingDestroyed() called on the passed pcallback object. - - - - - Retrieves the color picker initial screen position. - The screen coordinates of the color picker. This is the coordinate of the upper left corner. - - - - - This function is available in release 3.0 and later only. - - This global function is used internally to establish the current color picker used. - Parameters: - *colpick - - Points to the color picker to use. - A pointer to the current color picker. - - - - - This function is available in release 3.0 and later only. - - Returns a pointer to the current color picker. - - - - - This global function is available in release 4.0 and later only. - - Returns a pointer to the color manager with which you can call the methods of this class. - - Note the following #define which may be used to simplify coding a bit: - - - - - - - This function, which is not part of the class, allows you to retrieve a pointer to the Drag and Drop Manager interface. This will return a pointer to the drag and drop manager interface from the core interface. - - - - - This function allows you to create a new bitmap viewer as either a floating window or docked in a viewport. - Parameters: - Bitmap* pBitmap - - The bitmap to use with the viewer. This should not be NULL. - - IImageViewer::DisplayStyle displayStyle - - The display style for the viewer, which is either IV_FLOATING or IV_DOCKED. - A pointer to a new or NULL if the viewer could not be created. - - - - - This method will delete and release the specified bitmap viewer. This method should not be used while the viewer is being displayed. Use UnDisplay() or Hide() before calling this method. - Parameters: - * - - A pointer to the viewer. - - - - - This global function creates a new IK driver controller. - - - - - This global function creates and returns a pointer to a new IK driven controller by specifying the driver controller and a node to which the driven controller is assigned. - Parameters: - IKDriverControl* driver - - Points to the driver controller to use. - - INode* drivenNode - - Points to the driven node to use. - - - - - This global function is available in release 3.0 and later only. - - Returns a reference to the macro script directory. - - - - - This global function is available in release 3.0 and later only. - - This is an internal only function used by 3ds Max during startup to get the macroScript system initialized. - - - - - Deletes the passed. - Parameters: - *n - - The to delete. - - - - - Creates an on the heap. - Parameters: - *n - - The original pointer. - - tm - - The additional transformation matrix. - - BOOL dm=TRUE - - If TRUE this item will be deleted; otherwise it is left alone. - A pointer to the created. - - - - - get base type ignoring flag - - - - - get base type ignoring flag - - - - - This method is used to create a parameter block2. - Parameters: - *pdesc - - This is an array of parameter block descriptors. - - ReferenceMaker* iowner - - Points to the owner of the parameter block. - A pointer to the created parameter block. On error NULL is returned. - - - - - This function for internal use only. - - - - - This function updates or creates a new ParamBlock2, based on an existing ParamBlock of an earlier version. The new parameter block inherits any parameters from the old parameter block whose parameter IDs match. This may also be used to partially update an existing ParamBlock2. The parameter type of the ParamBlock and ParamBlock2 entries must match, with a special case that if the ParamBlock parameter type is TYPE_RGBA, the ParamBlock2 parameter type can be either TYPE_RGBA or TYPE_FRGBA - Parameters: - *pdescOld - - The array of parameter block descriptors which describes each parameter in the old parameter block. - - int oldCount - - The number of elements in the array above. - - *oldPB - - The old parameter block. - - ParamBlockDesc2* pdescNew - - Points to the new parameter block 2 descriptor. - - IParamBlock2* newPB=NULL - - Points to an existing indicating that this paramblock should be filled in from the old ParamBlock, rather than creating a new one. - The new parameter block2. - - - - - This function updates a ParamBlock based on an existing ParamBlock2. The ParamBlock inherits any parameters from the ParamBlock2 whose parameter IDs match. The parameter type of the ParamBlock and ParamBlock2 entries must match, with a special case that if the ParamBlock parameter type is TYPE_RGBA, the ParamBlock2 parameter type can be either TYPE_RGBA or TYPE_FRGBA This is mainly intended for use in Save To Previous, where the current version is ParamBlock2 based, and the old version is ParamBlock based. Note that if a ParamBlock2 parameter is animated, the ParamBlock2 will hold a reference to a controller for that parameter. This function does not clone the controller and have the ParamBlock hold a reference to that clone, rather the ParamBlock will hold a reference to the original controller. This is normally ok, since the ParamBlock will be deleted at the end of the save process. If the ParamBlock is being created other than for Save To Previous, you should consider replacing any references held by the ParamBlock with a clone of that reference. - Parameters: - IParamBlock2* pb2 - - Points to source . IParamBlock* pb1 - - Points to destination . *pdescPB1 - - The array of parameter block descriptors which describes each parameter in the ParamBlock. - - int pb1Count - - The number of elements in the array of parameter block descriptors. - - - The number of parameters copied from the to the . - - - - - Helper function for handling Save To Previous for a ParamBlock to ParamBlock2 migration. - - - This method does all the required handling to support the Save To Previous handling of a ParamBlock to ParamBlock2 migration. The code creates a ParamBlock from a ParamBlock2 and registers the ParamBlock to be saved instead of the ParamBlock2. - - The owner of the ParamBlock2 instance. - The ParamBlock2 instance to process. - The owner's reference number of the ParamBlock2 instance. - An array of parameter block descriptors. - The number of parameter block descriptors in the array. - The version number of the parameter block The following is an example usage, where all references to the ParamBlock2 instance are replaced with a ParamBlock instance. /code bool BoxObject::SpecifySaveReferences(ReferenceSaveManager& referenceSaveManager) { if saving to previous version that used pb1 instead of pb2... DWORD saveVersion = ; if (saveVersion != 0 && saveVersion <= MAX_RELEASE_R19) { ProcessPB2ToPB1SaveToPrevious(this, pblock2, PBLOCK_REF_NO, descVer1, PBLOCK_LENGTH, CURRENT_VERSION); } return __super::SpecifySaveReferences(referenceSaveManager); } /endcode - - - - This function determines whether a param type is animatable. - - - - - Implemented by the System. - - This method is used to create a parameter block. - Parameters: - *pdesc - - This is an array of parameter block descriptors. - - int count - - This is the number in the array. - A pointer to the created parameter block. On error NULL is returned. - - - - - Implemented by the System. - - This method is used to create a parameter block with a version number to aide in backwards compatibility. - Parameters: - *pdesc - - This is an array of parameter block descriptors. - - int count - - This is the number in the array. - - DWORD version - - This is used to indicate a version of the parameter block. This is used for backwards compatibility when loading 3ds Max files that were saved with a previous version of the parameter block structure. There is a mechanism which allows the older format to be converted to the newer format so the older files may still be loaded and used. See the Advanced Topics section on ~{ Parameter Maps }~ for more information. - A pointer to the created parameter block. On error NULL is returned. - - - - - Implemented by the System. - - This creates a new parameter block, based on an existing parameter block of a later version. The new parameter block inherits any parameters from the old parameter block whose parameter IDs match. - Parameters: - *pdescOld - - The existing parameter block descriptor. - - int oldCount - - The number of old parameters. - - *oldPB - - The old parameter block. - - *pdescNew - - The new parameter block descriptor. - - int newCount - - The number of new parameters. - - DWORD newVersion - - The version of the new parameter block. - The new parameter block. - - - - - Creates a parameter map that will handle a parameter block in a modeless dialog where time does not change and the viewports are not redrawn. This overload of CreateModalParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function creates a parameter map that will handle a parameter block in a modeless dialog where time does not change and the viewports are not redrawn. Note that there is no need to destroy it. It executes the dialog and then destroys itself. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateModalParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - TimeValue t - - The time at which the dialog is launched. - - HINSTANCE hInst - - The plug-ins instance handle. - - MCHAR *dlgTemplate - - The dialog template. - - HWND hParent - - The parent window. - - *proc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - Returns TRUE if the user selected OK, FALSE otherwise. - - - - - Creates a parameter map to handle the display of parameters in the command panel. This overload of CreateCPParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function creates a parameter map to handle the display of parameters in the command panel. This will add a rollup page to the command panel (or optionally replace an existing one). - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateCPParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins interface pointer. - - HINSTANCE hInst - - The plug-ins instance handle. - - MCHAR *dlgTemplate - - The dialog template. - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A flag to control the settings of the rollup page: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - ParamMap2UserDlgProc* dlgProc=NULL, - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - - HWND hOldRollup=NULL - - If non-NULL specifies an existing rollup window in the current UI context that should be replaced with the newly created rollup for this map. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Although it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - Returns a pointer to the parameter map2. - - - - - This function destroys a parameter map created by CreateCParamMap2(). The rollup page is removed and the parameter map is deleted. - Parameters: - *m - - A pointer to the parameter map2 to delete. - - - - - Create a child dialog of the given parent command panel parammap (for tabbed dialogs, etc.) This overload of CreateChildCPParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function creates a child dialog of the given parent parammap (for tabbed dialogs, etc.). This version takes an extra parent IParamMap2* and creates a child dialog window in the parent parammap's window (rather than a new rollup) that is mapped by the new parammap. Developers need to call this explicitly once the parent parammap has been created as child parammaps are not created automatically by the P_AUTO_UI mechanisms. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateChildCPParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins rendering parameters interface pointer. - - HINSTANCE hInst - - The plug-ins instance handle. - - IParamMap2* parent - - The parent parameter map. - - MCHAR *dlgTemplate - - The dialog template. - - MCHAR *title - - The title displayed. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - Returns a pointer to the parameter map2. - - - - - This function destroys a parameter map created by CreateChildCPParamMap2(). - Parameters: - *m - - Points to the parameter map2 to destroy. - - - - - Creates a parameter map to handle the display of render parameters or atmospheric plug-in parameters. This overload of CreateRParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - Creates a parameter map to handle the display of render parameters or atmospheric plug-in parameters. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateRParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins rendering parameters interface pointer. See Class . - - HINSTANCE hInst - - The plug-ins instance handle. - - MCHAR *dlgTemplate - - The dialog template. - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A flag to control the settings of the rollup page: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Allthough it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - Returns a pointer to the parameter map2. - - - - - This function destroys a parameter map created by CreateRParamMap2(). The rollup page is removed and the parameter map is deleted. - Parameters: - *m - - Points to the parameter map2 to destroy. - - - - - Creates a parameter map for render or atmospheric parameters in a child dialog window of the given parent parammap. This overload of CreateChildRParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function create a parameter map for render or atmospheric parameters in a child dialog window of the given parent parammap, used typically to create tab child windows in a tabbed rollout. This version takes an extra parent IParamMap2* and creates a child dialog window in the parent parammap's window (rather than a new rollup) that is mapped by the new parammap. Developers need to call this explicitly once the parent parammap has been created as child parammaps are not created automatically by the P_AUTO_UI mechanisms. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateChildRParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins material parameters interface pointer. See Class . - - HINSTANCE hInst - - The plug-ins instance handle. - - IParamMap2* parent - - The parent parameter map. - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the dialog. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - Returns a pointer to the parameter map2 created. - - - - - This function destroys a parameter map created by CreateChildRParamMap2(). - Parameters: - *m - - Points to the parameter map2 to destroy. - - - - - Creates a parameter map to handle the display of texture map or material parameters in the material editor. This overload of CreateMParamMap2() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - Creates a parameter map to handle the display of texture map or material parameters in the material editor. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateMParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins material parameters interface pointer. See Class . - - HINSTANCE hInst - - The plug-ins instance handle. - - HWND hmedit - - The window handle to the materials editor. - - TexDADMgr* dad - - Points to the manager used to handle drag and drop of textures. See Class . - - MtlDADMgr* mdad - - Points to the manager used to handle drag and drop of materials. See Class . - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A flag to control the settings of the rollup page: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - - HWND hOldRollup=NULL - - If non-NULL specifies an existing rollup window in the current UI context that should be replaced with the newly created rollup for this map. - - int category = ROLLUP_CAT_STANDARD - - The category parameter provides flexibility with regard to where a particular rollup should be displayed in the UI. RollupPanels with lower category fields will be displayed before RollupPanels with higher category fields. For RollupPanels with equal category value the one that was added first will be displayed first. Allthough it is possible to pass any int value as category there exist currently 5 different category defines: ROLLUP_CAT_SYSTEM, ROLLUP_CAT_STANDARD, and ROLLUP_CAT_CUSTATTRIB. - - When using ROLLUP_SAVECAT, the rollup page will make the provided category sticky, meaning it will not read the category from the RollupOrder.cfg file, but rather save the category field that was passed as argument in the CatRegistry and in the RollupOrder.cfg file. - - The method will take the category of the replaced rollup in case the flags argument contains ROLLUP_USEREPLACEDCAT. This is mainly done, so that this system works with param maps as well. - Returns a pointer to the parameter map2 created. - - - - - This function destroys a parameter map created by CreateMParamMap2(). The rollup page is removed and the parameter map is deleted. - Parameters: - *m - - Points to the parameter map2 to destroy. - - - - - This function creates a child dialog of the given modal parent parammap (for tabbed dialogs, etc.). Unlike modal parent parammap, you do need to destroy it. This version takes an extra parent IParamMap2* and creates a child dialog window in the parent parammap's window (rather than a new rollup) that is mapped by the new parammap. Developers need to call this explicitly once the parent parammap has been created as child parammaps are not created automatically by the P_AUTO_UI mechanisms. - Parameters: - MapID map_id - - Specifies the ID of the parameter map/rollup to be created for this particular parameter block. - - *pb - - Points to the parameter block2. - - HINSTANCE hInst - - The plug-ins instance handle. - - IParamMap2* parent - - The parent parameter map. - - MCHAR *dlgTemplate - - The dialog template. - - MCHAR *title - - The title displayed in the dialog. - - *proc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - Returns TRUE if the user selected OK, FALSE otherwise. - - - - - This function creates and returns a child dialog of the given parent parammap (for tabbed dialogs, etc.). This version takes an extra parent IParamMap2* and create a child dialog window in the parent parammap's window (rather than a new rollup) that is mapped by the new parammap. Developers need to call this explicitly once the parent parammap has been created as child parammaps are not created automatically by the P_AUTO_UI mechanisms. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateChildMParamMap2() with default map ID of 0. - Parameters: - *pb - - Points to the parameter block2. - - *ip - - Pass in the plug-ins material parameters interface pointer. See Class . - - HINSTANCE hInst - - The plug-ins instance handle. - - IParamMap2* parent - - The parent parameter map. - - TexDADMgr* tdad - - Points to the manager used to handle drag and drop of textures. See Class . - - MtlDADMgr* mdad - - Points to the manager used to handle drag and drop of materials. See Class MtlDADMgr_. - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the dialog. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - Returns a pointer to the parameter map2 created. - - - - - This function destroys a parameter map created by CreateChildMParamMap2(). - Parameters: - *m - - Points to the parameter map2 to destroy. - - - - - This function may be called to create a parameter map2 for use in the material editor dialog. This overload of CreateAutoMParamDlg() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function may be called to create a parameter map2 for use in the material editor dialog. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateAutoMParamDlg() with default map ID of 0. - Parameters: - HWND hMedit - - The window handle of the materials editor. - - *i - - The interface pointer for materials. See Class . - - MtlBase* mtl - - Points to the material calling this function. - - IParamBlock2* pb - - Points to the parameter block instance associated with the parameter map. - - ClassDesc2* cd - - The class descriptor2 for the plug-in creating the parameter map. - - HINSTANCE inst - - The plug-ins DLL instance handle. - - MCHAR* dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR* title - - The title displayed in the rollup page title bar. - - int rollFlags - - A set of flags to control settings of the rollup page. - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - - HWND hOldRollup=NULL - - An optional window handle to allow supplying an existing rollup that will be replaced by the newly cerated one. - A pointer to an interface for managing the parameter map2. - - - - - This function creates an AutoEParamDlg for render effects. This overload of CreateAutoEParamDlg() has a new parameter, map_id, that specifies the ID of the parameter map/rollup to be created for this particular parameter block. See original function for the rest of the description. - - - - - This function creates an AutoEParamDlg for render effects. - - Note, in version 4.0 and later, this actually maps to a call on the explicit map ID overload of CreateAutoEParamDlg() with default map ID of 0. - Parameters: - *i - - An interface pointer for rendering effects. - - SpecialFX* e - - Points to the rendering effect calling this function. - - IParamBlock2* pb - - Points to the parameter block instance associated with the parameter map. - - ClassDesc2* cd - - The class descriptor2 for the plug-in creating the parameter map. - - HINSTANCE inst - - The plug-ins DLL instance handle. - - MCHAR* dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR* title - - The title displayed in the rollup page title bar. - - int rollFlags - - A set of flags to control settings of the rollup page. - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - - ParamMap2UserDlgProc* dlgProc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. - A pointer to an interface for managing the parameter map2. - - - - - Creates a Win32-based , for use in the render settings panel, which automatically manages the creation and lifetime of the underlying parameter map. - In most cases, this method shouldn't be used directly by plugin developers. Instead, the plugin should call ClassDesc2::CreateParamDlgs() to automatically create the for all dialogs flagged with P_AUTO_UI or P_AUTO_UI_QT. But if the plugin needs to manage (perhaps conditionally) the creation of its dialogs, then it may call this function directly for individual parameter maps. - The which was created. - - The ID of the parameter map for which to create the dialog. - The interface passed to . - The object for which the dialog is being created. - The parameter block to which the parameter map is associated. - The class descriptor of the object for which the dialog is being created. - The HINSTANCE for the DLL that hosts the resources for the dialog template. - The dialog template to be used, specified as MAKEINTRESOURCE(resource_id). - The title of the rollup window to be created. - flags, such as APPENDROLL_CLOSED. - An optional dialog procedure to do custom processing of window messages. - A value controlling the order in which rollouts are positioned. - - - - This function creates a parameter map that will handle a parameter block in a modal dialog where time does not change and the viewport is not redrawn. Note that there is no need to destroy it. It executes the dialog and then destroys itself. - Parameters: - *desc - - The array of ParamUIDescs, one element for each control to be managed. - - int count - - The number of items in the array above. - - *pb - - Pointer to an instance of the class . This is the pointer to the virtual array of parameters. - - TimeValue t - - This is just the current time when the user is bringing up the dialog. - - HINSTANCE hInst - - The DLL instance handle of the plug-in - - MCHAR *dlgTemplate - - Dialog template for the dialog box. - - HWND hParent - - The parent window handle. - - *proc=NULL - - If there is some custom handling required by a particular control, the client can derive a class from and set it as the parameter map's user callback. See Class . - TRUE if the user selected OK; otherwise FALSE. - - - - - Creates a parameter map to handle the display of parameters in the command panel. This will add the rollup page to the command panel. - Parameters: - *desc - - The array of ParamUIDescs, one element for each control to be managed. - - int count - - The number of items in the array above. - - *pb - - Pointer to an instance of the class . This is the pointer to the virtual array of parameters. - - *ip - - The interface pointer passed into the BeginEditParams() method. - - HINSTANCE hInst - - The DLL instance handle of the plug-in - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A set of flags to control settings of the rollup page. - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - A pointer to the parameter map that is created. - - - - - This method allows one to switch rollups in the command panel. It creates the new parameter map and calls :: ReplaceRollupPage(). - Parameters: - HWND oldhw - - The window handle of the old rollup. - - *desc - - The array of ParamUIDescs, one element for each control to be managed. - - int count - - The number of items in the array above. - - *pb - - Pointer to an instance of the class . This is the pointer to the virtual array of parameters. - - *ip - - The interface pointer passed into the BeginEditParams() method. - - HINSTANCE hInst - - The DLL instance handle of the plug-in - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A set of flags to control settings of the rollup page. - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - A pointer to the parameter map that is created. - - - - - This function destroys a command panel parameter map. The rollup page from the command panel is removed and the parameter map is deleted. - Parameters: - *m - - A pointer to the parameter map to destroy. - - - - - This function creates a parameter map to handle the display of render parameters or atmospheric plug-in parameters. - Parameters: - *desc - - The array of ParamUIDescs, one element for each control to be managed. - - int count - - The number of items in the array above. - - *pb - - Pointer to an instance of the class . This is the pointer to the array of parameters. - - *ip - - The interface pointer passed into CreateParamDlg(). - - HINSTANCE hInst - - The DLL instance handle of the plug-in - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A flag to control the settings of the rollup page: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - A pointer to the parameter map that is created. - - - - - This function destroys a parameter map created by CreateRParamMap(). The rollup page is removed and the parameter map is deleted. - Parameters: - *m - - A pointer to the parameter map to destroy. - - - - - This function is available in release 2.0 and later only. - - This function creates a parameter map to handle the display of texture map or material parameters in the material editor. - Parameters: - *desc - - The array of ParamUIDescs, one element for each control to be managed. - - int count - - The number of items in the array above. - - *pb - - Pointer to an instance of the class . This is the pointer to the array of parameters. - - *ip - - The interface pointer. See Class . - - HINSTANCE hInst - - The DLL instance handle of the plug-in - - MCHAR *dlgTemplate - - Dialog template for the rollup page (created using the resource editor) - - MCHAR *title - - The title displayed in the rollup page title bar. - - DWORD flags - - A flag to control the settings of the rollup page: - - APPENDROLL_CLOSED - - Starts the page in the rolled up state. - A pointer to the parameter map that is created. - - - - - This function is available in release 2.0 and later only. - - This function destroys a parameter map created by CreateMParamMap(). The rollup page is removed and the parameter map is deleted. - Parameters: - *m - - A pointer to the parameter map to destroy. - - - - - Returns the component with the maximum abs value. 0=x, 1=y. - - - - - Returns the component with the minimum abs value. 0=x, 1=y. - - - - - Returns the length of the - - - - - Returns the component with the maximum abs value. 0=x, 1=y, 2=z. - - - - - Returns the component with the minimum abs value. 0=x, 1=y, 2=z. - - - - - Returns the length of the - - - - - Returns an whose members are divided by a scalar. - - - - - Sets the default tangent types for the Bezier controller. - - - - - Retrieves the default tangent types for the Bezier controller. - - - - - Sets the parameters for the default TCB controller. - - - - - Retrieves the parameters for the default TCB controller. - - - - - Implemented by the System. - - This method allows a plug-in to register a callback that will be called when reading a 3DS file that has a particular appdata chunk. The plug-in callback is given an opportunity to read the chunk and create an object other than a based on the contents of the chunk and the original object. - Parameters: - *cb - - The callback to read the chunk and create an object. - - - - - This function is used internally by the 3DS Import plug-in. - - Note the following about 3DS App Data. If app data is encountered and no plug-in has registered to convert it, then it is just hung off the object (or in the case of KXP app data). For object app data, 's super class and class ID are used to identify the chunk and the sub ID is set to 0. For node app data, 's super class and class ID are used to identify the chunk and the sub ID is set to 0. - - This single 3ds Max app data chunk will contain the entire 3DS app data chunk, which may have sub chunks (see the IPAS SDK). The following routines will aid in parsing 3DS app data. - - - - - This function gets the ID string out of an XDATA_ENTRY chunk and null terminates it. - Parameters: - char *chunk - - A pointer to the chunk. - - char *idstring - - The ID string. - - - - - Returns the offset into appd of the specified chunk or -1 if it is not found. - Parameters: - void *appd - - The is the entire app data chunk containing all the sub-chunks. - - DWORD len - - This is the length of the entire app data chunk. - - char *idstring - - The ID of the chunk to find. - The offset into appd of the specified chunk or -1 if it is not found. - - - - - This function is similar to FindAppDataChunk() above, but returns a pointer to the chunk or NULL if it is not found. - Parameters: - void *appd - - The is the entire app data chunk containing all the sub-chunks. - - DWORD len - - This is the length of the entire app data chunk. - - char *idstring - - The ID of the chunk to find. - A pointer to the chunk or NULL if it is not found. - - - - - This function adds the chunk to the appdata chunk, preserving existing chunks. chunk should point to the new chunk header followed by its data. - Parameters: - void **pappd - - The is the entire app data chunk containing all the sub-chunks. - - DWORD &len - - This is the length of the entire app data chunk. - - void *chunk - - A pointer to the new chunk header. - Nonzero if the chunk was added; otherwise zero. - - - - - Deletes a chunk from the appdata while preserving other chunks. - Parameters: - void **pappd - - The is the entire app data chunk containing all the sub-chunks. - - DWORD &len - - This is the length of the entire app data chunk. - - char *idstring - - The ID of the chunk to delete. - Nonzero if the chunk was deleted; otherwise zero. - - - - - Gets the IAutobackup interface pointer. - - - - - Attempts to delete keys that lie within the given time range. - - The controller whose keys are to be reduced. - The time range within which to delete keys. - After the key reduction, the controller's values at each step are guaranteed to be within this distance from their original values. - The controller will be sampled in steps of this time increment. - The callback object used to report the key reduction status and control continued processing. - - - - Interpolates between two points. Specialization to handle rounding of integer type - - - - - Returns TRUE if the application is running under a trial license, as opposed to a full, authorized license; otherwise FALSE. - - - - - Returns true if the application is running under a network license. - - - - - This global function is available in release 4.0 and later only. - - Creates a new mesh sphere at the given center position with the specified radius and segments count. - Parameters: - & pos - - The center point for the sphere in object space. - - float radius - - The radius for the sphere. - - int segments - - The number of segments for the sphere mesh. - A pointer to the sphere mesh. Developers are responsible for deleting this mesh when done. - - - - - This global function is available in release 4.0 and later only. - - Create a mesh torus with the given center point, outer radius, inner radius, and segment counts along the two circular dimensions of the torus. - Parameters: - & pos - - The center point in object space. - - float radius - - The first radius. - - float radius2 - - The second radius. - - int segs - - The segment count along the vertical circular dimension. - - int sides - - The segment count along the horizontal circular dimension. - A pointer to the torus mesh created. Developers are responsible for deleting this mesh when done with it. - - - - - This global function is available in release 4.0 and later only. - - Creates a mesh box with the given center point, length, width and height as well as segment parameters. - Parameters: - & pos - - The box is built from this position in size along +X, +Y and +Z. This coordinate is in object space. - - float l - - The length of the box. - - float w - - The width of the box. - - float h - - The height of the box. - - int lsegs - - The number of segments in the length dimension. - - int wsegs - - The number of segments in the width dimension. - - int hsegs - - The number of segments in the height dimension. - A pointer to the box mesh. Developers are responsible for deleting this mesh when done. - - - - - This global function is available in release 4.0 and later only. - - Creates a new series of lines in the form of a cube and adds it to the specified with the given position and side length size. - Parameters: - & shape - - The to add the box shape to. - - & pos - - The position for the center of the cube shape in object space. - - float size - - The size of one side of the cube in object space. - Data Members: - protected: - - int mDispSelectedIndex; - - The Index of manipulator that the mouse is over, for display. - - MSTR mToolTip; - - The tooltip text. - - float mGizmoScale; - - The scaling factor of the gizmo. - - *mpPblock; - - The Parameter Block 2 for the manipulator. - - RefTargetHandle mhTarget; - - The handle to the manipulator reference target. - - MouseState mState; - - The state of the mouse, which is one of the following: - - kMouseIdle - - The mouse is idle, manipulator not active and the mouse is not over it. - - kMouseDragging - - The mouse is currently dragging the manipulator. - - kMouseOverManip - - The mouse is over the manipulator, but it is not being dragged. - - BOOL mActiveViewOnly; - - This flag defines whether the manipulator is shown in the active viewport only. - - mValid; - - The validity interval of the reference. - - - - - Get a filename that is in the current set. - - - If the file doesn't exist in the set and does exits in the factoryDefaults for the set it is copied to the MarketDefault set. - The full path of the market defaults file requested. - - The filename (without) path of the file whose read location is requested. - - - - Get the appropriate write location for a market defaults file. - - - Get the appropriate write location for a market defaults file This value will depend on whether the application is configured to work with User Profile directories. - The path to which market default files should be written. - - - - - Builds an identity matrix and sets the rotation components based on the specified angle. - Parameters: - float angle - - Specifies the angle of rotation. - A new object with the specified rotation angle. - - - - - Builds an identity matrix and sets the specified translation components. - Parameters: - & p - - Specifies the translation. - A new object with the specified translation. - - - - - Returns the inverse of the specified . - Parameters: - & M - - Specifies the matrix to return the inverse of. - The inverse of the specified . - - - - - Transforms the specified with the specified . - Parameters: - & A - - The matrix to transform the point with. - - & V - - The point to transform. - The transformed . - - - - - Transforms the specified with the specified . - Parameters: - & V - - The point to transform. & A - - The matrix to transform the point with. - - - The transformed . - - - - - This method transforms a 2D point by a 2x3 matrix. This is analogous to the 3D case. - Parameters: - & M - - The matrix to transform the point with. - - & V - - The point to transform. - The transformed . - - - - - Builds a new matrix for use as a X rotation transformation. - A new X rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a Y rotation transformation. - A new Y rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a Z rotation transformation. - A new Z rotation . - - Specifies the angle of rotation in radians. - - - - Builds a new matrix for use as a translation transformation. - A new translation . - - Specifies the translation values. - - - - Builds a new matrix for use as a rotation transformation by specifying yaw, pitch and roll angles. - - This definition will depend on what our coordinate system is. This one is equivalent to: - - M.IdentityMatrix(); - - M.RotateZ(roll); - - M.RotateX(pitch); - - M.RotateY(yaw); - - Which presupposes Y is vertical, X is sideways, Z is forward - A new rotation . - - Specifies the yaw angle in radians. - Specifies the pitch angle in radians. - Specifies the roll angle in radians. - - - - Builds a new matrix for use as a rotation transformation by specifying an angle and axis. - A new rotation . - - Specifies the axis of rotation. Note that this angle is expected to be normalized. - Specifies the angle of rotation. Note: The direction of the angle in this method is opposite of that in . - - - - Return the inverse of the matrix - - The matrix to compute the inverse of. - - - - Return the inverse of the matrix using doubles for the intermediary results - - The matrix to compute the inverse of. - - - - Return the pseudoinverse of an affine symmetric matrix, meaning that if the matrix is degenerate (projects into a plane, line or point; eg. has both row 1 and column 1 zero) this will still produce a matrix that inverts the nonzero parts of the transform. - - The matrix to compute the pseudoinverse of. - - - - Transposes the affine portion of the matrix. Since does not have a 4th column you cannot transpose the entire 4x4 matrix, so this method only transposes the 3x3 matrix representing rotations, scale and skew. - - The matrix to compute the affine transpose of. - - - - These transform a with a . These two versions of transforming a point with a matrix do the same thing, regardless of the order of operands (linear algebra rules notwithstanding). - The transformed . - - The matrix to transform the point with. - The point to transform. - - - - These transform a with a . These two versions of transforming a point with a matrix do the same thing, regardless of the order of operands (linear algebra rules notwithstanding). - The transformed . - - The point to transform. - The matrix to transform the point with. - - - - Transform the vector () with the specified matrix. - The transformed vector (as a ). - - The matrix to transform the vector with. - The vector to transform. - - - - transform a plane. - this only works if M is orthogonal - - The transformation to apply to the plain - the plane to be transformed - - - - This method is used to build a matrix that constructs a transformation in a particular space. For example, say you have a rotation you want to apply, but you want to perform the rotation in another coordinate system. To do this, you typically transform into the space of the coordinate system, then apply the transformation, and then transform out of that coordinate system. This method constructs a matrix that does just this. It transforms matrix m so it is applied in the space of matrix xm. It returns a that is xm*m*Inverse(xm). - Returns a that is xm*m*Inverse(xm). - - Specifies the coordinate system you want to work in. - Specifies the transformation matrix. - - - - Mirrors the input matrix against the X, Y, or Z axis. This function mirrors the input matrix such that if it transformed a p, the transform applied by the mirrored transform would place p in an equivalent position relative but with one of it's elements negated. - - The Matrix to mirror - The world plane to mirror around. The axis will be reflected against the plane formed by the point (0, 0, 0) and the normal where normal[axis] = 1; - The matrix can be mirrored either by pure rotation, or by pure scaling. If true, the matrix is mirrored by flipping one of its axis, changing the handedness of the matrix. This had the advantage that the mirroring will be passed onto all it's children. This is preferential when the system can handle it, but can cause issues in systems that do not compensate for scale, eg game pipelines and skinning. if false, the mirroring will be achieved using rotation only and will not affect child local positions. It is better to use non-scaling mirroring when dealing with tools or processes that do not well support scale, or when the matrix will be blended with non-scaled matrices. (eg, Point/Quat based pipelines and skinning) - - - - Same as Maxtrix3::operator[]. Perform matrix multiplication without additional matrix copy - - The result of matrixA * matrixB - First matrix to multiply - Second matrix to multiply - - - - Same as Maxtrix3::Inverse. Compute the inverse of the matrix without additional matrix copy - - The inversed matrix. - The matrix to compute the inverse of. - - - - Same as Matrix3::AffineTranspose. Computes the affine transpose without additional matrix copy - - The inversed matrix. - The matrix to compute the affine transpose of. - - - - Create a rotational matrix oriented to the provided normal. - - The normal vector, must be normalized. - The output orientation matrix. - - - - Methods that control an internal optimization related to reference message propagation. The optimization consists of preventing the same ref message from being sent repeatedly to the same refmaker. This optimization improves the performance of interactive manipulation of complex IK rigs, but it is not completely reliable in the presence of some objects such as VIZWalls. - Call this method to turn the optimization On (value = true) or Off (value = false) at runtime. When 'commitToInit' is true, 'value' is saved to the current market default file as 'DontRepeatRefMsg=<value>' - - - - - Call this method to find out if the optimization is active or not. - - - - - In order to apply the optimization to a notification session, the Pre/PostRefNotifyDependents methods have to bracket it. IMPORTANT: The notification session should not contain GetValue calls. - - - - - Methods that control optimization for evaluating the transforms of complex rigs, especially of those with the expose transform helper. Note that this optimization may not work completely reliable with all objects and controllers - - - - - Methods that control optimization for not sending duplicate notifications. Note that this optimization may not work completely reliable with all objects and controllers - - - - - and get the controller validity interval optimization flag for the base controllers. When this flag is active, all Linear and Bezier controllers will express validity intervals that take into account flat sections in the animation curves that drive them. This allows for a performance improvement during scene evaluation because work can be skipped when dependencies don't actually change. - - - By default, ControllerIntervalOptimization is true. - - - Whether or not to enable this optimization - - Whether or not to write this setting into the defaults ini file. - - - - Get whether the listener is displayed in a viewport. Returns true if listener displayed in viewport. - - - - - compiles and evaluates the specified string. - - - If the string is successfully compiled and evaluated, and a pointer to an is provided, the return value is converted to an and returned through the referenced . If the string is not successfully compiled and evaluated: Error messages are by default logged to if net rendering. If not net rendering, error messages are written to or by default logged to if in quiet mode. If a pointer to an is provided, the error message is stored in the as a TYPE_TSTR. Note: This must be called from the main max thread (That contains UI Controls). This is due to the possibility that results from the Maxscript actions can cause the UI to be updated. And since Much of the UI contains WPF Elements which will throw an exception if NOT updated from the main thread. - Returns TRUE if script was executed successfully. - As of 3ds Max 2016, if the result of the script evaluation cannot be converted to an , the is set to TYPE_VALUE and the Value* is stored in it. The Value* is guaranteed to be protected from garbage collection only until a new Value* is created or a new expression is evaluated in the calling thread. So the calling code must protect the Value* from garbage collection as soon as possible. Typically this is done via value local storage (for example, one_value_local), a , or a . For example: In the above example, a scriptSource value of Dynamic was specified. This will cause the file contents to be executed with restricted security rights, regardless of Safe Scene Execution settings. This would protect against a scene embedded malicious script modifying the file contents, adding malicious commands. - - - Points to a null-terminated string that specifies the commands to compile and evaluate. This expects a string containing Maxscript expressions, NOT a file path. - - the source of the script string. - - If TRUE, or net rendering, errors are by default logged to . If FALSE and not net rendering, errors are logged to . - - Optionally points to an . If not NULL, the result of the script evaluation is converted to an and stored in the specified . If an error occurs, the error message is stored in the as a TYPE_TSTR. - - If TRUE and quietErrors is TRUE, errors are logged to . If FALSE and quietErrors is TRUE, errors are not logged to . - - - - that compiles and evaluates a Maxscript expression. - - - Returns Value* resulting from evaluating source. Evaluation is within a try/catch, so this function will not throw. - - - Contains the script to compile and evaluate. The method will protect this value from garbage collection. - - If res is non-NULL, will contain TRUE on return if script was executed successfully, FALSE if not. - - the source of the script string. - - - - that compiles and evaluates a Maxscript expression string. - - - Returns Value* resulting from evaluating source. Evaluation is within a try/catch, so this function will not throw. - - - Contains the script to compile and evaluate. If null, returns 'undefined'. - - If res is non-NULL, will contain TRUE on return if script was executed successfully, FALSE if not. - - the source of the script string. - - - - Executes the given script file. - - - Internally this calls filein_script_ex. - - - If filename is NULL, this will open a dialog prompting the user to choose a file path to an existing script. If the parameter is non-null, then the given file will be evaluated and compiled. - - - - Executes the given script file. - - - - TRUE if the script was successfully executed, FALSE if not. Note that this does not reflect the result of the script. - - if captured_error_message is specified and an error occurs, no error dialog is displayed. If captured_error_message is not specified and an error occurs, whether an error dialog is displayed depends on current quiet mode state. - - - The fully qualified path to the existing file. This can be maxscript files (*.ms, .mxs), maxscript zip files (*.mzp), encrypted maxscript files (*.mse), or python files (*.py, *.pyc, *.pyw). - - for capturing error message, can be nullptr. - - If true, if thread's scriptSource is Embedded and Safe Scene Execution Mode is enabled validate script file extension is valid to run and run script as embedded. - - - - Executes the given script file using given ScriptSource. - - - - TRUE if the script was successfully executed, FALSE if not. Note that this does not reflect the result of the script. - - if captured_error_message is specified and an error occurs, no error dialog is displayed. If captured_error_message is not specified and an error occurs, whether an error dialog is displayed depends on current quiet mode state. - - - The fully qualified path to the existing file. This can be maxscript files (*.ms, .mxs), maxscript zip files (*.mzp), encrypted maxscript files (*.mse), or python files (*.py, *.pyc, *.pyw). - - The ScriptSource value to use when executing the script - - for capturing error message, can be nullptr. - - - - Executes the given script file specified as an AssetUser. This function should be used for executing script files whose name is stored in the scene file. - - - - true if the script was successfully executed, false otherwise. Note that this does not reflect the result of the script. - - If MaxSDK::ISceneScriptSecurityManager::IsSafeSceneScriptExecutionEnabled(SettingType) returns true, the script file's extension is validated to run as embedded and the script is run as embedded. - - if captured_error_message is specified and an error occurs, no error dialog is displayed. If captured_error_message is not specified and an error occurs, whether an error dialog is displayed depends on current quiet mode state. - - - The AssetUser specifying the script file. This can be maxscript files (*.ms, .mxs), maxscript zip files (*.mzp), encrypted maxscript files (*.mse), or python files (*.py, *.pyc, *.pyw). The AssetType would typically be kPreRenderScript, kPostRenderScript, or kOtherAsset. - - for capturing error message, can be nullptr. - - - - Opens the specified file in the Scripting editor. - - - - - If filename is NULL, this will open a dialog prompting the user to choose a file path to an existing script. If the filename is not found, and empty script is opened in the script editor with the specified filename. If the parameter is non-null, then the given file will be opened in the Scripting editor. - - - - This function is available in release 3.0 and later only. - - This is the standard affect region function, based on a distance and the three affect region parameters (same as the editable mesh). - - This function is a cubic curve which returns 1 at distance 0, 0 if distance is greater than falloff, and other values for distance between 0 and falloff. To "see" this function graphed, look at the curve in the Soft Selection parameters in Edit , Editable , Select, or Volume Select. This function currently is constructed as follows: - - - Parameters: - float dist - - The distance to the selection. The method for computing this distance is up to the developer; for example in Select, it's the distance to the nearest selected vertex, while in Volume Select (with a box or sphere selection region) it's the distance to the selection volume. - - float falloff - - The limit distance of the effect. If distance > falloff, the function will always return 0. - - float pinch - - Use this to affect the tangency of the curve near distance=0. Positive values produce a pointed tip, with a negative slope at 0, while negative values produce a dimple, with positive slope. - - float bubble - - Use this to change the curvature of the function. A value of 1.0 produces a half-dome. As you reduce this value, the sides of the dome slope more steeply. Negative values lower the base of the curve below 0. - Returns the strength of the Affect Region function at the given distance. (In selection modifiers, this is the "soft selection" amount, the amount it's considered selected. A vertex at a distance with a return value of .25, for instance, will be affected 1/4 as strongly in a deformation as a fully selected vertex.) - - - - - This function is available in release 3.0 and later only. - - This function creates a matrix with the normal as a Z-axis. The X and Y axes are chosen arbitrarily. - Parameters: - & normal - - The input normal is specified here. - - & mat - - The output matrix. - - - - - This function is available in release 3.0 and later only. - - This function creates vertex normals that are weighted averages of faces using each vertexSmoothing groups are not used in these computations - the normals are those you would expect with a totally smooth mesh. - Parameters: - & mesh - - The mesh whose average vertex normals are computed. - - > & vnormals - - The output vertex normals. . This will be set to size mesh.numVerts. - - - - - This function is available in release 3.0 and later only. - - This function computes and returns the average normal of a group of selected vertices. - Parameters: - & mesh - - The mesh to check. The function uses mesh.VertSel() to check for selected verts. - - - - - This function is available in release 3.0 and later only. - - This function computes and returns the average center of a group of selected vertices. - Parameters: - & mesh - - The mesh to check. The function uses mesh.VertSel() to check for selected verts. - - - - - This function is available in release 3.0 and later only. - - Removes hidden faces from the mesh.FaceSel() selection array. - Parameters: - & mesh - - The mesh to check. - - - - - This function is available in release 3.0 and later only. - - This function removes edges on hidden faces from the mesh.EdgeSel() selection array. - Parameters: - & mesh - - The mesh to check. - - - - - This function is available in release 3.0 and later only. - - This function hides vertices that are only used by hidden faces. If alsoHide has size mesh.numVerts, it is used to indicate other vertices that should also be hidden. Note that passing mesh.VertHide() as alsoHide will NOT WORK, as mesh.vertHide is overwritten before alsoHide is read. - Parameters: - &mesh - - The mesh to check. - - &alsoHide - - If specified, this is used to indicates other vertices that should also be hidden. - - - - - This function is available in release 3.0 and later only. - - This function computes distances from selected vertices (as indicated by selMask) to non-selected ones. - - NOTE: This function leverages interal space accelerating structure to compute the nearest distance to the selected vertices. Under the worst condition the algorithm complexity is log(n)*n, in practice the algoirthm is nearly linear complexity. - Parameters: - const Point3* & vertArray - - The pointer to the first vertex to check. - - int & *vertStep - - The vertex memory step in bytes when stepping to next vertex. & & selMask - - This is the mask indicating the selected vertices, usually it is computed from mesh.VertexTempSel(). float *selDist - - This is assumed to be a float array of size mesh.numVerts. It is set to -1 for all verts if there is no selection. Otherwise, selected vertices have a value of 0, and nonselected vertices have the distance to the nearest selected vertex. - - - - - This function is available in release 3.0 and later only. - - This function computes distances from selected vertices (as indicated by mesh.VertexTempSel()) to non-selected ones along edge paths. selDist is assumed to be a float array of size mesh.numVerts. selDist is set to -1 for all verts if there is no selection. Otherwise, selected vertices have selDist value 0; non-selected vertices that are "iters" or fewer edges away from a selected vertex are assigned the shortest edge-path distance to a selected vertex; and non-selected vertices that are more than iters edges away are set to -1. The is computed by the algorithm if the one passed is NULL; otherwise you can save time by passing a cached one in. - - This is NOT an n-squared algorithm like the one above. It's more a sort of order-of-n-times-(iters-squared). - Parameters: - & mesh - - The mesh to check. - - float *selDist - - An array of floats of size mesh.numVerts. - - int iters - - If 0, Selection Distance is computed from each vertex to the nearest selected vertex, regardless of topology. This is a VERY EXPENSIVE ALGORITHM, which takes almost 4 times as long for twice as many vertices. If iters is non-zero, it represents the number of edges one should "travel" in trying to find the nearest selected vertex - this means that it only takes twice as long for twice as many verts. (This is like the Distance parameter in EMesh's Soft Selection dialog.) If iters is 0, ae is irrelevant and may be left as NULL. If iters is nonzero, an Adjacent List is required, and will be computed internally from the mesh if ae is NULL. (If you've got an for this mesh handy, pass it in, otherwise don't worry about it.) - - Note also that if iters is nonzero, the distance is computed along the edges, not directly through space. If there is no selected vertex within an iters-length path, a vertex is assigned a 0 selection value. - - *ae=NULL - - The optional adjacent edge list. - - - - - This function is available in release 3.0 and later only. - - Computes distances from nonselected vertices in the mesh to each of the vertex clusters. This is a VERY EXPENSIVE ALGORITHM, which takes almost 4 times as long for twice as many vertices. - - Preparation for this method would typically look like: - - fclust: - - <DWORD> vclust; - - fclust.MakeVertCluster (msh, vclust); - - <float> ** clustDist; - - <float> *)[fclust.count]; - - <float>; - - ClustDistances (mesh, fclust.count, vclust.Addr(0), clustDist); - - Then (*clustDist[c])[v] would give the distance from vertex v in the mesh to the vertices of cluster c. - Parameters: - &mesh - - The mesh the clusters are based on. - - DWORD numClusts - - The number of clusters in this mesh. - - DWORD *vclust - - A pointer to an array of vertex cluster IDs. Typically this is a pointer to the data in the table created by EdgeClusterList::GetVertClusters or FaceClusterList::GetVertClusters. - - <float> **clustDist - - This is an array of <numClusts> pointers to tables that will be used to store distances from various clusters. Each table will be set to the ize of mesh.numVerts and filled with distances to the cluster that table represents. - - - - - This function is available in release 3.0 and later only. - - Computes distances from nonselected vertices in the mesh to each of the vertex clusters. Unlike the other version which doesn't have an iters or ae parameter, this is a linear algorithm which computes distance along a finite number of edges. - - Preparation for this method would typically look like: - - fclust: - - <DWORD> vclust; - - fclust.MakeVertCluster (msh, vclust); - - <float> ** clustDist; - - <float> *)[fclust.count]; - - <float>; - - ClustDistances(mesh, fclust.count, vclust.Addr(0), clustDist); - - Then (*clustDist[c])[v] would give the distance from vertex v in the mesh to the vertices of cluster c. - Parameters: - & mesh - - The mesh the clusters are based on. - - DWORD numClusts - - The number of clusters in this mesh. - - DWORD *vclust - - A pointer to an array of vertex cluster IDs. Typically this is a pointer to the data in the table created by EdgeClusterList::GetVertClusters or FaceClusterList::GetVertClusters. - - <float> **clustDist - - This is an array of <numClusts> pointers to tables that will be used to store distances from various clusters. Each table will be set to the ize of mesh.numVerts and filled with distances to the cluster that table represents. - - int iters - - The maximum number of edges to travel along looking for a vertex in the given cluster. - - *ae=NULL - - length computations require an adjacent edge list. If you don't pass one in this parameter, it'll have to construct its own from the mesh. - - - - - This global function is available in release 3.0 and later only. Finds a triangulation of an n-sided polygon using vertices in the specified mesh. As long as the vertices are coplanar, this algorithm will find a proper triangulation, even for nonconvex polygons. - Parameters: - &m The mesh containing the vertices used in the polygon. int deg The size of the polygon. int *vv The vertex indices of the polygon, in order around the perimeter. For instance, if deg is 5 and w points to an array containing (3, 6, 8, 0, 7), the polygon is presumed to have the outline described by m.verts[3], m.verts[6], m.verts[8], m.verts[0], and m.verts[7]. int *tri This is where the output is placed. Note that this should point to an array of size at least (deg-2)*3, to hold all the triangles. The values placed in this array are indices into the w array - that is, given a 5-sided polygon, one triangle in this list might be (0,2,3), indicating you should use the 0th, 2nd, and 3rd elements of w to form the triangle. Put another way, to make a face from the n'th triangle given by this array, you would set: f.v[0] = w[tri[n*3+0]];f.v[1] = w[tri[n*3+1]];f.v[2] = w[tri[n*3+2]]; - - - - - Returns the Channel ID of the map channel. if mp>=1, this always returns TEXMAP_CHANNEL. For mp<1, including the hidden map channels, this is currently always VERTCOLOR_CHANNEL. In the future it may include map channels that are actually part of GEOM_CHANNEL or something. - - The map channel. - - - - Similar to MapChannelID, but this returns the CHAN_NUM version:TEXMAP_CHAN_NUM, VERTCOLOR_CHAN_NUM, etc. - - The map channel. - - - - Return the data type of the specified vertex data channel - The data type of the specified channel (see Data Types for Mesh Vertices, above). - - - One of the values from - - - - Returns a pointer to a default value for the specified channel. - - One of the values from - - - - *tm2 = NULL, int whichInv = 0, int weld = TRUE); Note: This method is still in the SDK, but it is now obsolete. Calls to CalcBoolOp() should be replaced with calls to the new form of . Please see the method MNMesh::MakeBoolean in Class for details. This function stores the result of a boolean operation between mesh1 and mesh2 into mesh. This operation may be a union, intersection or difference. If tm1 or tm2 are non-NULL, the points of the corresponding mesh will be transformed by these matrices before the boolean operation. The mesh will be transformed back by either Inverse(tm1) or Inverse(tm2) depending on whichInv (a value of 0 will use tm1, a value of 1 will use tm2, unless whichInv is -1 in which case it will not be transformed back). - Nonzero if the operation completed successfully; otherwise zero. - - The result of the boolean operation is stored here. mesh = mesh1 op mesh2. - The first operand. - The second operand. - The boolean operation. One of the values from - = NULL A callback to display a progress. See Class . - = NULL If non-NULL then the points of mesh1 will transformed by this matrix before the boolean operation. - = NULL If non-NULL then the points of mesh2 will transformed by this matrix before the boolean operation. - = 0 If 0, the resulting mesh will be transformed by Inverse(tm1). If 1, the resulting mesh will be transformed by Inverse(tm2). If -1, the mesh will not be transformed back. - = TRUE If TRUE, the vertices of the resulting mesh are welded. - - - - This function is available in release 2.0 and later only. This function may be used to simply combine two meshes into one. - - The result of the combine operation is stored here. mesh = mesh1+mesh2. - The first operand. - The second operand. - If non-NULL then the points of mesh1 will transformed by this matrix before the boolean operation. - If non-NULL then the points of mesh2 will transformed by this matrix before the boolean operation. - If 0, the resulting mesh will be transformed by Inverse(tm1). If 1, the resulting mesh will be transformed by Inverse(tm2). If -1, the mesh will not be transformed back. - - - - Slices a single mesh. The N and the float offset define a slicing plane (by DotProd (N,X) = offset). Default behavior is to split faces that cross the plane, producing 1-2 new faces on each side and a new vert in the middle of each edge crossing the plane. split means to add 2 different but coincident points to the top and bottom sets of faces, splitting the mesh into two meshes. - TRUE if slice operation resulted in a change in the mesh. - - The mesh to slice - The slicing plane - The offset on the slicing plane - Indicates that mesh should be split into two along the plane, otherwise faces are created with shared vertices. Ignored is remove is TRUE - Indicates that the faces below the plane should be removed - Contains a pointer to the for the mesh if precomputed. Providing this will aid in calculation speeds if pre-computed. The contents are not updated after the slice operation. - - - - This function computes the current distance of each vertex from the current selection, along paths of edges. NOTE: This is an n-log-n algorithm: it compares every non-selected vertex with every selected one. - Parameters: - & mesh - - The mesh we're computing distances in. - - float *selDist - - A pointer to an array of floats of size mesh.VNum(). This array is filled in with one float value per vertex. If this value is 0, the vertex is either selected or "on top of" a selected vertex. Otherwise it represents the distance to the closest selected vertex. Values of -1 are used to indicate vertices that are more that iters edges away from any selected vertex. - - int iters - - This indicates the maximum number of edges the algorithm may travel along in finding the distance between vertices. (Maximum path length.). - - DWORD selFlags - - Indicates what flag defines the hard selection we're basing this soft selection on. (MN_SEL is generally best.) - - - - - Computes the current distance of each vertex from the specified cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - - NOTE: This is an n-log-n algorithm for each cluster: it compares every vertex not in the cluster with every vertex in it. - Parameters: - & mesh - - The these cluster distances are based on. - - int numClusts - - The number of clusters available. - - int *vclust - - A pointer into the vertex cluster table. - - <float> **clustDist - - An array of pointers to tables which will be filled with one float value per vertex. The table pointed to by clustDist[i] contains the cluster distances for cluster i. Note that clustDist must be allocated, for instance by <float>*)[numClusts], and must have its members allocated, for instance by <float>, by the calling routine. If a value in a table is 0, the vertex is either selected or on top of a vertex in the cluster. Otherwise it represents the distance to the closest selected vertex. If useEdgeDist is TRUE, values of -1.0 are returned for vertices with no edgeIts-length path to a vertex in the cluster. - - - - - Computes the current distance of each vertex from the specified cluster. If cached, the cache is returned. Otherwise a cache is allocated and computed from the current mesh and the parameters. - - NOTE: This algorithm takes time proportional to the number of verts in each cluster times iters times the number of clusters. - Parameters: - & mesh - - The these cluster distances are based on. - - int numClusts - - The number of clusters available. - - int *vclust - - A pointer into the vertex cluster table. - - <float> **clustDist - - An array of pointers to tables which will be filled with one float value per vertex. The table pointed to by clustDist[i] contains the cluster distances for cluster i. Note that clustDist must be allocated, for instance by <float> *)[numClusts], and must have its members allocated, for instance by <float>, by the calling routine. If a value in a table is 0, the vertex is either selected or on top of a vertex in the cluster. Otherwise it represents the distance to the closest selected vertex. Values of -1.0 are returned for vertices with no iters-length path to a vertex in the cluster. - - int iters - - The maximum edge path length to compute distance along (in number of edges). - - - - - This method creates a world space derived object. - Parameters: - *pob=NULL - - If non-NULL then the WS derived object will be set up to reference this object. - A pointer to the derived object. - - - - - This method creates an object space derived object. - Parameters: - *pob=NULL - - If non-NULL then the derived object will be set up to reference this object. - A pointer to the derived object. - - - - - The global function begins an enumeration of the geometry pipeline using the specified node. - Parameters: - *gpep - - Points to the callback object to process the enumeration. - - *start - - Points to the node to start the enumeration. - - bool includeEmptyDOs = false - - In case the flag includeEmptyDOs is declared as true, the proc will be called even for DerivedObjects, that don't contain any modifiers. In that case the object pointer will be NULL, the derObj pointer will contain the DerivedObject and the index will be -1. - One of the following values: - - PIPE_ENUM_CONTINUE - - PIPE_ENUM_STOP - - - - - The global function begins an enumeration of the geometry pipeline using the specified object. - Parameters: - *gpep - - Points to the callback object to process the enumeration. - - *start - - Points to the object to start the enumeration. - - bool includeEmptyDOs = false - - In case the flag includeEmptyDOs is declared as true, the proc will be called even for DerivedObjects, that don't contain any modifiers. In that case the object pointer will be NULL, the derObj pointer will contain the DerivedObject and the index will be -1. - One of the following values: - - PIPE_ENUM_CONTINUE - - PIPE_ENUM_STOP - - - - - The global function begins an enumeration of the geometry pipeline using the specified derived object and modifier index. The caller of this method has to provide the IDerviedObject the is applied to and the index of the in the . Developers can use the method Modifier::GetIDerivedObject() in order to get the IDerviedObject and the index, given a modifier and a . - Parameters: - *gpep - - Points to the callback object to process the enumeration. - - *start - - Points to the derived object to start the enumeration. - - int modIndex = 0 - - The zero based index of the modifier in the derived object to start with. - - bool includeEmptyDOs = false - - In case the flag includeEmptyDOs is declared as true, the proc will be called even for DerivedObjects, that don't contain any modifiers. In that case the object pointer will be NULL, the derObj pointer will contain the DerivedObject and the index will be -1. - One of the following values: - - PIPE_ENUM_CONTINUE - - PIPE_ENUM_STOP - - - - - Indicates if any mouse proc is currently in the process of aborting a mouse proc. This function is not part of this class but is available for use. It returns TRUE if any mouse proc is currently in the process of aborting a mouse proc, FALSE otherwise. For instance, a developer may be using the Animatable::MouseCycleCompleted() method to put up a dialog box, but needs to not put it up if the mouse proc was aborted. This method provides a way to know if indeed the mouse proc is aborting so the dialog won't be displayed inside MouseCycleCompleted(). - TRUE if aborting, FALSE otherwise. - - - - - Converts a "human readable" 3ds Max version to Version Macros. - - - A value in Version Macros (such as MAX_RELEASE), or MAX_RELEASE_UNSUPPORTED if a non-supported 3ds Max version is specified. - - 3ds version as it occurs in the product name - - - - Converts a given 3ds Max version number to a EMxsMaxFileVersion. - - - The version number as it occurs in the product name , or kMxsMaxFileVersion_Unsuported if a non-supported 3ds Max version is specified. - - 3ds version number - - - - This global function creates and returns a pointer to a new Note Track. - - - - - This global function is called to establish the connection between the event and the callback. - Nonzero if the event was registered; otherwise zero. - - The callback function called when the event occurs - A pointer to a parameter which will be passed to the callback function - Specifies which notification to register. See . - - - - This global function is called to break the connection between the event and the callback. After this function executes the callback is no longer invoked when the event occurs. - Nonzero if the event was unregistered; otherwise zero. - - The callback function called when the event occurs. - This parameter must be identical to the param sent into . This function will only unregister a callback if this parameter equals the param sent in to the function. - Specifies which notification to unregister. See - - - - This global function unregisters the callback from all codes - Nonzero if the events were unregistered; otherwise zero. - - The callback function called when the event occurs. - A pointer to a parameter which will be passed to the callback function. - - - - It is not recommended to use this function directly. Consider using the templated version of this function for improved type safety - - Specifies which notification to broadcast. See - - - - It is not recommended to use this function directly. Consider using the templated version of this function for improved type safety - - Specifies which notification to broadcast. See - This parameter is passed to the callback. - - - - This global function sets the specified named selection clipboard. - Parameters: - *clip - - Points to the named selection clipboard to set. - - int which - - Specifies which clipboard to set. One of the following values: - - CLIP_VERT - - CLIP_FACE - - CLIP_EDGE - - - - - This global function returns a pointer to the specified named selection clipboard. - Parameters: - int which - - Specifies which clipboard to get. One of the following values: - - CLIP_VERT - - CLIP_FACE - - CLIP_EDGE - - - - - This global function sets the specified named selection clipboard. - Parameters: - *clip - - Points to the named selection clipboard to set. - - int which - - Specifies which clipboard to set. One of the following values: - - CLIP_P_VERT - - CLIP_P_PATCH - - CLIP_P_EDGE - - - - - This global function returns a pointer to the specified named selection clipboard. - Parameters: - int which - - Specifies which clipboard to get. One of the following values: - - CLIP_P_VERT - - CLIP_P_PATCH - - CLIP_P_EDGE - - - - - This global function returns the vertex named selection clipboard. - - - - - This global function returns a pointer to the named selection clipboard. - - - - - This global function returns a pointer to the named selection clipboard. - - - - - Returns whether when you attach new map faces to a mesh/mnmesh those faces should be cleared or planar mapping applied - - - - - This global function (not part of class ) may be used to count the number of faces and vertices in an object. It uses Object::PolygonCount() if it is supported, and converts to and counts faces and vertices otherwise. - - time at which to compute the number of faces and vertices. - to the object to check. - number of faces is returned here. - number of vertices is returned here. - - - - This function is to count trifaces of a mesh It works similar to GetPolygonCount(), where GetPolygonCount will count EditablePoly object's Polys as 1 Poly, instead of several trifaces. It also will not count splines unless their renderable property is true - - - - - Creates a new empty derived object, sets it to point at the given object and returns a pointer to the derived object. - A pointer to the derived object. - - object reference of the derived object will point at this object. - - - - Registers an object converter with the system. - Returns true if the converter could be added; false if not. - - to the instance to register. - - - - Indicates if a can convert to the specified class ID. Note: this actually checks if an Editable object can convert to the specified type, since an Editable is what you get when you call CreateNewTriObject (). - - This method may be used in an object's CanConvertToType() and ConvertToType() methods. If your object supports conversion to a , but doesn't support conversion to the given class ID, you can use this method to find out if TriObjects can be used as an "intermediary". If so, you can construct a temporary , convert it to the given class ID, and call the temporary 's DeleteThis() method. - Nonzero if the can be converted to the specified objec type; otherwise zero. - - Class ID to convert to. - - - - Indicates if a can convert to the specified class ID. - Nonzero if the can be converted to the specified objec type; otherwise zero. - - Class ID to convert to. - - - - Indicates if a SplineObject can convert to the specified class ID. - Nonzero if the SplineObject can be converted to the specified objec type; otherwise zero. - - Class ID to convert to. - - - - This method will register the object passed as the editable tri object. - - object to register as the editable tri object. - - - - Registers a class ID of an object that the user can collapse other objects to. The type will only appear if the current object returns nonzero from CanConvertTo(cid). - - class ID the object will collapse to. - name of the collapse-to object type (such as "Editable Poly"). - whether an object should be allowed to collapse to itself. (false is generally preferred, so that the collapse-to menu only has relevant entries.) - - - - This global function is not part of class but is available for use. - - Returns the mouse speed value used in perspective viewports. This value corresponds to the value that the user may set using the 3ds Max command in the File / Preferences . . . Move / Rotate Transform area. - - - - - This global function is not part of class but is available for use. - - Returns the mouse move mode. This value corresponds to the value that the user may set using the 3ds Max command in the File / Preferences . . . Move / Rotate Transform area. - One of the following values: - - MOVE_INTERSECTION - - MOVE_PROJECTION - - - - - This is called to create an instance of a . When done, be sure to call ColorPacker::DeleteThis(). - Parameters: - int w - - The width of bitmap to be packed. - - *pal - - The palette to use. - - int npal - - The number of entries in the palette. - - BYTE* remap=NULL - - This is a 256 byte table that maps the numbers into another number. This is used so the palette may be rearranged in Windows order. To make palettes for Windows, the best thing to do is to put the colors in so that colors that Windows uses are either left alone, or they are occupied by the colors that are least important in the image. This is because Windows will come along and alter these colors. This is the first 10 colors and the last 10 colors. - - The quantizer creates a palette from 0-239, where 0 is the most used color and 239 is the least used. The color packer uses 0-239 as well, and it operates most efficiently when the colors are sorted as the quantizer orders them. - - What can be done is to use FixPaletteForWindows() to rearrange the colors for the Windows palette. This creates the remap table passed to this method. Then as a last step the remap table is used to reorganize the palette. Below is the documentation for the global function FixPaletteForWindows(). Sample code that uses these APIs is in /MAXSDK/SAMPLES/IO/FLIC/FLIC.CPP. - - - - - Converts a mesh to a patch mesh. - - - - - Converts a patch mesh to a mesh. - - - - - This method converts a to Trimesh, similarly to the method ConvertPatchToMesh(). - - - However, the new method also stores the mapping from the 's faces to the 's patches in the 'mapping' parameter. - - - The patch to convert - - The mesh object we set our converted TriMesh onto. - - After conversion, this array will be filled a mapping from the 's faces to the PatchMeshs faces. - - One of the ConversionFlags - - - - Returns true if the current Max version is newer than maxRelease or the same but an extension equal or newer than the one specified as maxExt is present. - - the version of max from the Version Macros to check against - the extension version to check against - - - - Returns the 3ds Max extension number. It returns 0 if there's no extension installed. - - - - - Creates an instance of a class specified by superclass ID and class ID. This can be useful when there is no convenience method for creating the desired class. - Many classes have named IDs defined in plugapi.h. You can also obtain the numeric class ID of a class using the MaxScript ShowClass() function, or from an object in a scene using $obj.ClassID(). Here's an example of output for a selected skylight object: - Example: - This example creates a skylight instance. - - - - - Returns the length of the point. This is sqrt(v.x*v.x+v.y*v.y); - - - - - Returns the component with the maximum absolute value. 0=x, 1=y. - - - - - Returns the component with the minimum absolute value. 0=x, 1=y. - - - - - Returns a unit vector. This is a with each component divided by the point Length(). - - - - - Returns a whose x and y members are divided by a scalar. - - - - - Returns the component with the maximum abs value. 0=x, 1=y, 2=z. - - - - - Returns the component with the minimum abs value. 0=x, 1=y, 2=z. - - - - - Returns the length of the - - - - - Returns the length of the - - - - - Returns an whose members are divided by a scalar. - - - - - Normalizes p using float precision - - - - - Normalizes p using double precision - - - - - Returns a that is the specified divided by the specified float. - - - - - Gets the class descriptor for the . - - - - - Allows a plugin to register an Editable Poly object. (This is done by epoly.dlo in the standard 3ds Max distribution.) This is the object which is collapsed to when the stack is collapsed. The default if no such object is registered is to simply collapse to a (which has no UI parameters). - Parameters: - ClassDesc* desc - - A pointer to the class descriptor. - - - - - Gets the class descriptor for the currently registered Editable Poly object. - - - - - Returns an Editable Poly object from the currently registered descriptor, cast as a . - - - - - Converts a poly object to a patch mesh. - - - - - Converts a patch object to a poly object. - - - - - Multiplies the quaternion by a scalar. - - - - - Multiplies the quaternion by a scalar. - - - - - Divides the quaternion by a scalar. - - - - - Returns the inverse of the quaternion (1/q). - - - - - Returns the conjugate of a quaternion. - - - - - Returns the natural logarithm of UNIT quaternion. - - - - - Exponentiate quaternion (where q.w==0). - - - - - Spherical linear interpolation of UNIT quaternions. - - As t goes from 0 to 1, qt goes from p to q. - - slerp(p,q,t) = (p*sin((1-t)*omega) + q*sin(t*omega)) / sin(omega) - - - - - Computes the "log difference" of two quaternions, p and q, as ln(qinv(p)*q). - - - - - Compute a, the term used in Boehm-type interpolation. - - a[n] = q[n]* qexp(-(1/4)*( ln(qinv(q[n])*q[n+1]) +ln( qinv(q[n])*q[n-1] ))) - - - - - Squad(p,a,b,q; t) = Slerp(Slerp(p,q;t), Slerp(a,b;t); 2(1-t)t). - - - - - Rotate p by 90 degrees (quaternion space metric) about the specified axis. - - - - - Quaternion interpolation for angles > 2PI. - Parameters: - float angle - - Angle of rotation - - & axis - - The axis of rotation - - & p - - Start quaternion - - & a - - Start tangent quaternion - - & b - - End tangent quaternion - - & q - - End quaternion - - float t - - Parameter, in range [0.0,1.0] - - - - - Converts the quaternion to a matrix and multiples it by the specified matrix. The result is returned in mat. - - - - - Converts the quaternion to a matrix and multiples it on the left by the specified matrix. . The result is returned in mat. - - - - - Converts the [angle,axis] representation to the equivalent quaternion. - - - - - Converts the quaternion to the equivalent [angle,axis] representation. - - - - - Compute the [angle,axis] corresponding to the rotation from p to q. Returns angle, sets axis. - - - - - Decomposes a matrix into a rotation, scale, and translation (to be applied in that order). This only will work correctly for scaling which was applied in the rotated axis system. For more general decomposition see the function decomp_affine(). See Structure . - - - - - Returns the transformation of the specified quaternion by the specified matrix. - - - - - Returns the identity quaternion ((0.0,0.0,0.0,1.0)). - - - - - Converts the quaternion to Euler angles. When converting a quaternion to Euler angles using this method, the correct order of application of the resulting three rotations is X, then Y, then Z. The angles are returned as ang[0]=x, ang[1]=y, ang[2]=z. - - - - - Converts Euler angles to a quaternion. The angles are specified as ang[0]=x, ang[1]=y, ang[2]=z. This method is implemented as: - - - - - - - Returns true if this RefMessage can have redundant notifications optimized (inhibited). - - - true if the message can be optimized; false if it cannot. - - - Specifies the level of optimization currently in use. - - Type of notification message that may be sent. - - Returns the level of optimization dependents should request. - - - - Gets a pointer to a default version of a . - - - First clear the A_WORK2 flag on all objects being cloned. - Flag is set on all entries in remap directory. - - - used to set this flag on all entries in the remap directory. - - - - This function is used to clone a single . - - - you should say: - If you are cloning multiple ReferenceTargets, you should be creating a and cloning the ReferenceTargets using RemapDir::CloneRef. Otherwise, any common under the ReferenceTargets being cloned would be cloned as separate ReferenceTargets, rather than a single that is shared. So, for example: - A pointer to the new reference target - - - A pointer to the reference target to clone. - - - - Registers an instance of this class whose NotifyRefChanged() method will receive the messages. - - - - - Points to an instance of this class whose NotifyRefChanged() method will receive the messages - - - - Unregisters the class so it won't be called anymore. - - - - - Points to an instance of this class whose NotifyRefChanged() method will no longer receive the messages - - - - Clears the specified Flag bits in a reference hierarchy. - - - This method calls ClearAFlag on the and all references from it, recursively, with the specified mask - - - The handle to the root to enumerate from - The bits to turn off in the flags - - - - Clears the specified Flag bits on all Animatables. - - - This method calls ClearAFlag on all Animatables with the specified mask - - The bits to turn off in the flags - - - - Checks if there is a path of references from a to a . - - - TRUE if there is a path of references from the to targ. This returns TRUE if mkr==targ) - - - The handle to the - - The handle to the - - - - to find out if we are saving an old version of a .MAX file. - - - - - - - used internally to maintain the SavingVersion number, which should not be called by plugins. - - - - - Disable reference messages globally. - - - The references messages are enabled by default. - Important: It is not recommended that 3rd party plugins disable reference messages. For 3ds Max to function correctly, every call to DisableRefMsgs() needs to be matched with a call to EnableRefMsgs(). - Note: the following reference messages are not disabled even when reference messages are globally disabled: - Note: DisableRefMsgs() can be overriden by EnableDisableRefMsgsOverride() - - - - - Enable reference messages globally. - - - The references messages are enabled by default. - Important: For 3ds Max to function correctly, every call to DisableRefMsgs() needs to be matched with a call to EnableRefMsgs(). Occasionally, when a plugin needs to re-enable reference messages while in a context in which they have been disabled (very likely by the plugin itself), it is important that it calls EnableRefMsgs() as many times as DisableRefMsgs() has been called. When the plugin finished its task, it should restore the reference message propagation to the previous state. The correct way to achieve this is as follows: - - - - - Returns the number of times reference messages have been marked as disabled. 0 means reference messages are enabled. - - - - - Force override of reference messages disabled globally. - - - In some cases, a component may use the messaging system to set/query information on a different part of the component. In order for the component to operate properly, it needs the reference messages to be processed even when reference messages are disabled globally. Important: For 3ds Max to function correctly, every call to EnableDisableRefMsgsOverride() needs to be matched with a call to DisableDisableRefMsgsOverride(). For example: - - - - - Turn off force override of reference messages disabled globally. - - - - - Returns the number of times Force DisableAllMsgs Override has been performed. - - - - - This returns the interface for a given render element. - - - This method checks for element being NULL and return directly NULL if its the case. - - the interface for this element or NULL if element is NULL. - - - The render element for which the interface is wanted. - - - - Locates the resource file for the specified script file name. The filename portion of the resource file name is the script file name plus a ".res" extension ([script.res] = <scriptname>.res). The resource file is looked for in the following locations, in the order given: - - - True if the resource file name was located. - - - The fully qualified script file name - - The resource file name if found - - - - Loads the specified resource file. Each line in the resource file consists of the resource id and the resource value. This creates and returns a where the resource id is the key and the resource value is the value. If the resource file does not exist, NULL will be returned. - - - Pointer to containing the resource id/resource value pairs, or NULL if the resource file doesn't exist. Note: this function will throw a if an error occurs while processing the resource file - - - The fully qualified resource file name - - - - Returns the system's localization language and country name. The system's localization language and country name are determined by querying the system for its ISO languange and country locale names. - - - The system's 2-letter localization language and country names in the form <language>-<country>, for example, 'en-US'. - - - If true, default locale for the user is returned. If false, default locale for the system is returned. - - - - This global function creates and returns a pointer to a new default shadow buffer renderer. - - - - - This global function returns a new default shadow-map shadow generator. - - - - - This global function returns a new default ray-trace shadow generator. - - - - - Find an endpoint weld target in a shape. - - - This is designed to work with the 3ds Max insert/create mechanism when it's working with the last knot in the shape being edited. It will use one of two threshold values depending on whether automatic endpoint welding is enabled. Caller has the option to allow the spline being edited to weld to itself (this will always be the knot being edited ('knotToCompare') welding to the first knot in the spline). - - If any knots in the shape have endpoints that are appropriate for welding, the function will fill in the 'weldToPolyOut' poly and 'weldToKnotOut' knot indices with non-negative indices of the candidate knot. - - - true if a weld candidate was found; false otherwise. - - Pointer to the for the viewport being used. This viewport will be used to compute the distance between endpoint knots in screen space, which is used with the auto-weld distance threshold value. - Transform of the object. - Pointer to the containing the spline being edited and the weld target candidate splines. - The index of the spline being edited. - The index of the knot that will be compared to candidate weld-target knots. - True if the caller wants to allow the spline being edited to weld 'knotToCompare' to its own first knot. - true if End Point Auto-Welding is to be used. - The index of the spline being welded to or -1 if no weld found. - The index of the knot in the spline being welded to or -1 if no weld found. - - - - Weld the last knot of a spline to the first knot in the same spline. - - - This function performs last-to-first knot welding in a spline. It shifts the position of the last knot to align with the first knot, including the Bezier vectors, if any, sets the first knot type as needed to preserve the spline's shape and closes the spline. - - - - Pointer to the containing the spline being welded. - The index of the spline being welded. - - - - This function retrieves the "Use Fixed Renderable End Cap Material ID" option - true if the "Use Fixed Renderable End Cap Material ID" option is enabled - - - - - This function retrieves the "Fixed Renderable End Cap Material ID" value - The zero-based material ID to use for end caps - - - - - This function sets the "Fixed Renderable End Cap Material ID" value - true if the value was successfully set; false otherwise. - - The zero-based material ID. - - - - Implemented by the System. - - Returns a new default sound object. This is the standard one provided by 3ds Max. - - - - - This function checks to see if a given segment of a spline is effectively linear. If the segment itself is LTYPE_LINEAR, both knots of the segment are KTYPE_CORNER, have zero-length Bezier vectors, or the Bezier vectors of both segment knots point directly at the other knot (or any combination of the above), the segment is considered to be effectively linear. 'linearTolerance' is a tolerance value that is used to determine if the Bezier vectors point directly at the other knot. Given a knot point K1 with its bezier vector KV and another knot point K2, if the value: Length(Normalize(KV-K1) - Normalize(K2-K1)) < linearTolerance, the vector is considered to be effectively linear. - true if the segment is effectively linear; false otherwise. - - The spline to check. - The segment index to check. - A tolerance value that is used to determine if the Bezier vectors point directly at the other knot. Given a knot point K1 with its Bezier vector KV and another knot point K2, if the value: Length(Normalize(KV-K1) - Normalize(K2-K1)) < linearTolerance, the vector is considered to be effectively linear. - - - - This function provides access to the "Shape Angle Constraint" display information This function is used internally to display Shape Angle Constraint angle values while editing a spline. - true if the angle is to be displayed; false otherwise. - - (out) The angle to be displayed, in degrees. - (out) The coordinates where the angle text is to appear. - - - - Get the master override switch that allows spline editing to ignore the Auto-Weld switch and always prompt for closure. - - - true if the override switch is set; false otherwise. - - - - - Create a Physical (or, optionally, a legacy StdMtl2) - - - Create new instances of the Physical , optionally depending on a 3dsmax.ini configuration key. If no config key is passed, the creation is unconditional. If a key name is passed, that key is searched in 3dsmax.ini's [LegacyMaterial] section, and if existing and set to 1, a legacy standard material is returned instead. This allows restoring legacy behaviour inside 3ds Max if that is necessary for some particular users reason. - The optional legacy parameter can point to a bool that will be set to true if the legacy fallback is used, meaning a StdMtl2 is returned. - This returns EITHER a Physical OR a Legacy Standard material. No other types of materials are ever returned. - - - - - Create a material of the type defined in the "market defaults" (or optionally, a StdMtl2 as a fallback) - - - Create new instances the configured "market default" mtl, optionally depending on a 3dsmax.ini configuration key. If no config key is passed, the creation is unconditional. If a key name is passed, that key is searched in 3dsmax.ini's [LegacyMaterial] section, and if existing and set to 1, a legacy standard material is returned instead. This allows restoring legacy behaviour inside 3ds Max if that is necessary for some particular users reason. - This can return ANY material, whatever is configured in the market defaults. - - - - - Return the primary texture slot for a material. - - - returns the primary texture slot ID for a material, generally the diffuse slot or similar. If the material derives from StdMtl2, this is equivalent to calling mtl->StdIDtoChannel(ID_DI). - - - - - SplitFilename (CStr* version) - - - - - SplitFilename (WStr* version) - - - - - SplitFilenameOld (char* version) - - - - - SplitFilenameOld (WStr* version) - - - - - Check to see if the string matches the pattern in pattern. - - - - - This global function is available in release 3.0 and later only. - - To use this function you need to create an instance of setting at least the ParameterRange and Eval procedures. The others can be NULL unless you have fast versions of them. This call then fills in a with the surface that is defined by the procedures and the tolerence. - Parameters: - *pSurf - - Points to the to generate CV surfaces from. - - double tolerence - - The tolerance is the allowable deviation of the approximating NURBS surface to the surface defined by the procs. - - & surf - - The generated is returned here. - See NURBS Results. - - - - - This global function is available in release 3.0 and later only. - - To use this API you need to create an instance of setting at least the ParameterRange and Eval procedures. The others can be NULL unless you have fast versions of them. The call tothis function then fills in a with the curve that is defined by the proceedures and the tolerence. - Parameters: - *pCrv - - Points to the object used to generate the curve procedurally. - - double tolerence - - The tolerance is the allowable deviation of the approximating NURBS surface to the surface defined by the procs. - - & crv - - The generated curve is returned here. - See NURBS Results. - - - - - Validates a NURBSId for a NURBS object. - - - - - Returns true if 3ds Max is running under a debugger. - - - - - Returns the number of processors in the system. - - - - - Returns the width of the screen (including multiple monitors) - - - - - Returns the height of the screen (including multiple monitors) - - - - - Returns a value indicating whether the application is configured to use User Profiles or not. - - - The application can be configured to use User Profiles. - true if the application uses User Profile directories - - - - - Returns a value indicating whether the application is configured to use romaing User Profiles or not. - - - The application can be configured to use roaming User Profiles. This value is dependent on whether the application uses User Profiles at all. Even if this returns true, if IsUsingProfileDirectories() returns false, then the application will default to the legacy path configuration locations under the application root install directory. - true if the application uses User Profile directories - - - - - This function is used to convert a path relative to the 3ds max install to an absolute path. - - - This function is used to convert a path relative to the 3ds max install to an absolute path. For instance, this will yield the absolute path of the downloads directory: - - - The ID of the directory to return. This value should be one of . - - The subdirectory to look for - - The resolved absolute path, or null string on failure. - - - - This is a helper for creating standard windows CSIDL directories. - - - This function is a helper for creating standard windows CSIDL directories The list of possible root directories is shown in the windows header SHLOBJ.h. In particular, the TryCSIDLDir() function can be used to create CSIDL_LOCAL_APPDATA paths, where you can put application-specific data tailored to the current windows user. - - - The ID of the directory to return. Should be one of the windows CSIDL defines. - - specifies the relative pathname. - - The absolute path to the created CSIDL directory, or null string on failure. - - - - Access to core interfaces from maxutil - no need to link against core.dll. - - - - - This function performs a mapping across the unit interval [0, 1] where the result is within the unit interval. If b is within the interval 0 to 1, the result of bias() is within the interval 0 to 1. This function is defined such that bias(a, 0.5)=a. The function is defined as follows: - - - - - - - This function performs a mapping across the unit interval [0, 1] where the result is within the unit interval. If b is within the interval 0 to 1, the result of gain() is within the interval 0 to 1. This function is defined such that gain(a, 0.5)=a. Above and below 0.5, this function consists of two scaled down bias() curves forming an S-shaped curve. The function is defined as follows: - - - - - - - This function is a smoother version of step() using a linear ramp. The boxstep() function is defined as follows: - - - - For comparison, note that step() returns values of 0 when x is less than a and 1 when x is greater than or equal to a. This function is not a part of the SDK, but step() is defined as follows: - - - - - 0 if "x" is less than "a", a linear interpolation between 0 and 1 if "x" is greater than or equal to "a" and less than or equal to "b", and 1 if "x" is greater than "b". - - The limit for the x value where the function will return 0. - The limit for the x value where the function will return 1. - A floating point value. - - - - This function is similar to step(), but instead of a sharp transition from 0 to 1 at a specified threshold, it makes a gradual transition from 0 to 1 beginning at threshold a and ending at threshold b. To do this, this function uses a cubic function whose slope is 0 at "a" and "b", and whose value is 0 at "a" and 1 at "b". This function provides a still smoother version of step() using a cubic spline. The smoothstep() function is used (instead of step()) in many procedural textures because sharp transitions often result in artifacts. - - The limit for the x value where the function will return 0. - The limit for the x value where the function will return 1. - A floating point value. - - - - This function returns the mathematical modulo operation and handles negatives correctly. The standard math functions fmod() and fmodf() as well as the operator % return negative results if the first operand is negative. This function always returns a positive remainder. - - - - - This function returns the mathematical modulo operation and handles negatives correctly. The standard math functions fmod() and fmodf() as well as the operator % return negative results if the first operand is negative. This function always returns a positive remainder. - - - - - This function makes a type of straight-segment S curve. The parameters are x, a, b, and d. The algorithm is as follows: - - for a+d < x < b-d sramp(x) = x - - for a-d < x < a+d sramp() makes a smooth transition (parabolic) from sramp' = 0 to sramp' = 1 - - for b-d < x < b+d sramp() makes a smooth transition (parabolic) from sramp' = 1 to sramp' = 0 - - - - - - - Returns 0 if "x" is less than "a", 1 if "x" is greater than "b", otherwise it returns "x". - - - - - An approximation of white noise blurred to dampen frequencies beyond some value. - - - - - An approximation of white noise blurred to dampen frequencies beyond some value in two dimensions. - - - - - A noise function in three dimensions implemented by a pseudo-random tricubic spline. This function is an approximation of white noise blurred to dampen frequencies beyond some value. - - - - - This function is an approximation of white noise blurred to dampen frequencies beyond some value in three dimensions, and time. - - - - - A noise function in three dimensions implemented by a pseudo-random tricubic spline. This is the same as noise3() scaled up by factor of 1.65 and clamped to -1,+1. The macro NOISE can be used to map the value returned from the noise3DS() function into interval [0,1]. - - - - - This turbulence function is a simple fractal generating loop built on top of the noise function. It is used to make marble, clouds, explosions, and so on. It returns a value in the range [0, 1]. - - - - - Takes the low 9 bits of an input value and returns a number in that range (0-512). - - - - - A fractional Brownian motion fractal (or fBm for short) that returns a floating point value. This version of the fBm is said to be "homogeneous" (the same everywhere) and "isotropic" (the same in all directions). There are versions of this function that accept an input floating point, , and value. - - - - - A one-dimensional Catmull-Rom interpolating spline through a set of knot values. The spline() function used to map a number into another number. The parameter of the spline is a floating point value. If x is 0, the result is the second knot value. If x is 1, the result is the final knot value. For values between 0 and 1, the value interpolates smoothly between the values of the knots from the second knot to the second to last knot. The first and last knot values determine the derivatives of the spline at the endpoint. - - - - - A variant of the spline() function for mapping colors. - - - - - A fast version of the standard C function floor(). It returns a floating-point value representing the largest integer that is less than or equal to x. - - - - - Returns the fraction (non-integer) part of the value passed. This is defined as x - (float)FLOOR(x). - - - - - Returns the larger of two values (returns the second value in the case of equality). - - - - - Returns x if it is less than y. Otherwise, y. - - - - - Performs an alpha-composite of one color (ctop) on top of another (cbot), assuming pre-multiplied alpha. - - - - - This is the noise function used by the 3ds Max Cellular texture. The idea is that there is a set of cells randomly distributed through space. This function returns the distances to the closest cells. Developers using this function can refer to: A Cellular Basis by Steven Worley, and published in the SIGGRAPH 1996 Conference Procedings. - - - - - A fractal version of CellFunction(). It has additional parameters for iterations and lacunariy. - - - - - Returns a random number in the range 0.0 to 1.0 based on a cell identifier. - - - - - Returns a pointer to the class descriptor for the regular, standard . - - - - - A new descriptor can be registered to replace the default descriptor. This new descriptor will then be used to create TriObjects. - Parameters: - ClassDesc* desc - - The class descriptor to replace the default descriptor. - - - - - Returns a pointer to the class descriptor for the editable . It returns the default if none has been registered. See below. - - - - - This method is used to create a new . Use this instead of new . It will use the registered descriptor if one is registered, otherwise you'll get a default . - - - - - This method is used to add a track view node. - Parameters: - BOOL hidden=FALSE - - If FALSE the node is hidden; otherwise it is visible in the viewports. - - - - - Retrieves the System Unit scale in terms of the specified unit type. For example, GetSystemUnitScale(UNITS_INCHES) returns the number of inches per unit. Returns -1.0 if an invalid unit type is supplied. - - - - - Computes a scaling factor for going from given units to others. - - - - The scale factor that is needed to scale from given units to others. - - - type of units from which we start (a value going from UNITS_INCHES to UNITS_KILOMETERS). - - scale of units from which we start. - - type of units into which we want to rescale (a value going from UNITS_INCHES to UNITS_KILOMETERS). - - scale of units into which we want to rescale. - - - - Retrieves the System Unit settings in effect. These are the System Unit type (Inches, Feet, Meters, and so on) and the System Unit scale settings. These are the values that users enter in the "1 Unit = XXX field" of the System Unit Setup dialog box. - - - - - Sets the System Unit settings. These are the System Unit type (Inches, Feet, Meters, and so on) and the System Unit scale settings. - - - - - Retrieves the current unit display information. - - - - - Sets the unit display information used by 3ds Max. - - - - - Returns the current unit display type to one of the following values: - - - - - Sets the current unit display type to one of the following values: - - - - - Converts the specified value to an ASCII representation according to the current unit scale. Note that this can cause a string overflow, especially when the units are set to miles or kilometers. If an overflow occurs the function returns a null string (_T("")). So, developers can check for this condition using something like if (buf[0] == '\0') to see if an overflow occurred. - - - - - Parses the specified string using the current unit settings and converts it to a floating point value. If an error occurs in the parsing then valid is set to FALSE. - - - - - Registers a default value for a distance value. The default has separate values for both Imperial and Metric systems. The Imperial default is given in inches and the Metric default is given in Meters. - - - - - Restores the original default value for a distance value. - - - - - Gets the default for the given section and key in the defaults file. The system returns the default relative to the current system units. If the units are Imperial (inches, feet, and so on) it returns the Imperial version of the default, otherwise it returns the Metric version. In either case the default value is returned in the current system units. - - - - - Sets the defaults for the given section and key in the defaults file. The system sets the default relative to the current system units. If the units are Imperial (inches, feet, and so on) it sets the Imperial version of the default, otherwise it sets the Metric version. - - - - - Returns a floating point value parsed from the specified windows control. - - - - - Returns a floating point value parsed using formatted with user locale input. - - - - - Returns an integer value parsed from the specified windows control. - - - - - Converts an integer value to a string for display in a windows control. - - - - - Converts a floating point value to a string for display in a control. The precision parameter is used to determine the number of values to display to the right of the decimal point. - - - - - Converts a floating point value to a string in the user locale. The precision parameter is used to determine the number of values appearing to the right of the decimal point. - - - - - Sets the dialog box control to display the passed floating point value. Trailing zeros are removed. - - - - - Returns a floating point value parsed from the specified dialog box control. - - - - - Moves the window to the specified coordinates. - - - - - Stretches the window to the specified size. - - - - - Centers the specified child window in the parent window. - - - - - This function is the same as the Win32 function GetClientRect() except that it returns the coordinates relative to the window's parent's client window. - - - - - Draws a button that has a bitmap icon. - - - - - Returns the height of a list box dropdown list. - - - - - Draws a shaded vertical line at the specified x coordinate between the two given y coordinates. The in parameter indicates whether the shading that appears to the right is light or dark. - - - - - Draws a shaded horizontal line at the specified y coordinate between the two given x coordinates. The in parameter indicates whether the shading that appears below the line is light or dark. - - - - - Draws a shaded rectangle. - - - - - Draws a rectangle with a 3D appearance. - - - - - Draws a rectangle with a white background and a 3D appearance. - - - - - Draws a toolbar button using the given rectangle and the in or out state. - - - - - Displays a string in an HWND (typically an edit control), trimming beginning characters with an ellipses if the string is too long. - - The string to be displayed. - The hWnd to display the string in - uses existing font - Reserved space in pixels that reduces string display area in hWnd - - - - Updates the width of a combo-box drop-down window to make all its items fit. - - - Call this function if some strings in your combo-box are longer than the actual combo-box control's width. This function will update the width of the combo-box to make the widest combo-box item fit. - -1 if the combo-box could not be updated successfully, the new width of the combo-box drop down otherwise. - - The handle of the combobox to update - true if the width of a vertical scroll bar should be taken into account - - - - Draws a rectangle in XOR mode using a specified border width. - - - - - Vista Aero related method. - - - This method will tell whether the Vista Aero is turned on or not. - TRUE if Vista Aero is turned on, otherwize FALSE. On Window XP or previous Windows, it will always return FALSE. - - - - - If the mouse cursor is currently hovering over a window. - - - This method will not differentiate whether the cursor is actually hovering over a window, or it's blocked by some other window. It only does a point-rectangle containment test. - TRUE if the mouse cursor is currently hovering the window, otherwise FALSE. - - The handle of the window. - - - - If the cursor position specified is currently confined in a window's rectangle. - - - This method will not differentiate whether the cursor is actually hovering over a window, or it's blocked by some other window. It only does a point-rectangle containment test. - TRUE if the mouse cursor is currently hovering the window, otherwise FALSE. - - The handle of the window. - The x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area. - The y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area. - - - - This sets the control whose window handle is passed to include the BS_AUTOCHECKBOX bit set. This creates a control which is same as a check box, except that a check mark appears in the check box when the user selects the box. The check mark disappears when the user selects the box next time. - - - - - This sets the control whose window handle is passed to include the BS_AUTO3STATE bit set. This creates a control which is the same as a three-state check box, except that the box changes its state when the user selects it. - - - - - Returns the checked state of the given control. - - - - - the check state of a radio button or check box to checked or unchecked. - - - - - Detects whether the file specified by the full, absolute filename exists, considering the missing file cache. - - - Detects whether specified file exists, optionally excluding files that are directories. Note that if the filename is a guid string, the guid string is converted to a AssetUser, and then the AssetUser's filename is tested to see if it exists. - TRUE if the file exists. - - The null-terminated filename or guid string - If true, returns TRUE if the filename is found and is either a file or a directory. If false, returns TRUE if the filename is found and is a file but not a directory. - - - - Detects whether the file specified by the full, absolute filename exists, potentially considering the missing file cache. - - - Detects whether specified file exists, optionally excluding files that are directories. Note that if the filename is a guid string, the guid string is converted to a AssetUser, and then the AssetUser's filename is tested to see if it exists. - TRUE if the file exists. - - The null-terminated filename or guid string - If true, returns TRUE if the filename is found and is either a file or a directory. If false, returns TRUE if the filename is found and is a file but not a directory. - If true, testing does not consider whether the file's path may be in the missing path cache. - - - - Detects whether the directory specified by the full, absolute filename exists, considering the missing file cache. - - - Detects whether specified directory exists. Note that if the filename is a guid string, the guid string is converted to a AssetUser, and then the AssetUser's filename is tested to see if it exists. - TRUE if the directory exists. - - The null-terminated directory or guid string - - - - Detects whether the directory specified by the full, absolute filename exists, potentially considering the missing file cache. - - - Detects whether specified directory exists. Note that if the filename is a guid string, the guid string is converted to a AssetUser, and then the AssetUser's filename is tested to see if it exists. - TRUE if the directory exists. - - The null-terminated directory or guid string - If true, testing does not consider whether the file's path may be in the missing path cache. - - - - Returns the number of adjacent color bits for each pixel in use by the desktop. - - - - - Delete superfluous zeroes from a string representing a floating point value. For example, "1.2300000" becomes "1.23". - - - - - Safely casts double to float. Valid flag will indicate overflow. - - - - - Safely casts double to int. Valid flag will indicate overflow. - - - - - Provides an extended message box functionality, This is used to support message dialogs with a '' or a 'Help' button and/or a 'Do not show this message again' check box. - - - See "https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messagebox" for a description of the Win32 MessageBox method parameters. - The MaxMessageBox methods provide a more complete extended message box functionality that better matches the Win32 MessageBox functionality, and should be used instead of MaxMsgBox. The MaxMsgBox method will be deprecated in the future. - - - The parent window handle - - The main message - - The caption or title for the message window - - The type of message box. The supported types are: - - Used for adding additional elements. The supported bit field values are: - - Used for specifying the help file topic id and for returning extra info: - - - - Returns a suggested color to use when drawing XOR lines over a viewport. The color is suggested based on the background color settings. - - - - - Returns a Listbox item's string as a MSTR. - the Listbox item's string - If the ListBox is not found, an empty string is returned - - The hWnd of the Dialog the Listbox is in - The id of the Listbox in the dialog. - The index of the Listbox item - - - - Returns a Listbox item's string as a MSTR. - If the ListBox is not found, an empty string is returned - - The hWnd of the Dialog the Listbox is in - The id of the Listbox in the dialog. - The index of the Listbox item - The Listbox item's string - - - - Returns a Listbox item's string as a MSTR. - the Listbox item's string - If the ListBox is not found, an empty string is returned - - Window handle of ListBox - The index of the Listbox item - - - - Returns a Listbox item's string as a MSTR. - If the ListBox is not found, an empty string is returned - - Window handle of ListBox - The index of the Listbox item - The Listbox item's string - - - - Returns a Combobox item's string as a MSTR. - the Combobox item's string - If the Combobox is not found, an empty string is returned - - The hWnd of the Dialog the Combobox is in - The id of the Combobox in the dialog. - The index of the Combobox item - - - - Returns a Combobox item's string as a MSTR. - If the Combobox is not found, an empty string is returned - - The hWnd of the Dialog the Combobox is in - The id of the Combobox in the dialog. - The index of the Combobox item - The Combobox item's string - - - - Returns a Combobox item's string as a MSTR. - the Combobox item's string - If the Combobox is not found, an empty string is returned - - Window handle of ComboBox - The index of the Combobox item - - - - Returns a Combobox item's string as a MSTR. - If the Combobox is not found, an empty string is returned - - Window handle of ComboBox - The index of the Combobox item - The Combobox item's string - - - - This global function is available in release 3.0 and later only. - - This displays the dialog that you currently get in Edit(able) mesh when you attach objects to each other. It gives options for how to deal with combining materials, and whether or not to condense materials which have excess material slots. - Parameters: - *ip - - The interface pointer. - - *user - - Points to the object. - TRUE if the user OKed the dialog; FALSE if the user Cancelled. - - - - - To get a object (see above), call this core function. It will return a pointer to the interface, which you can then use to perform functions related to bevel profile curve editing. - An example of the use of the bevel profile curves may be found in the Bevel Profile modifier. - A object containing the bevel profile curve - - - - - To use 3ds Max's standard bevel profile curves, make your plugin class a subclass of , then call this function, providing a pointer to your object as the 'user' parameter. The system will create and return a pointer to a standard bevel profile curve, which you should then make a reference to, as these curves can be animated. - An example of the use of the bevel profile curves may be found in the Bevel Profile modifier. - A object containing the bevel profile curve - - - Pointer to your BevelProfileUser object (your plugin) - - - - For the macro-recorder to establish itself with CORE. - - - - - To set the CUI macro scrit directory ref in CORE. - - - - - Get a pointer to the system Crease Manager. Plugins that work as Crease Containers will use this pointer to register/unregister themselves with the system so that the crease sets they contain will appear in the Crease Explorer when appropriate. Crease Containers will also use this pointer to notify the system when their crease sets have changed in any way, or when the number of crease sets they contain has changed. See , above. - A pointer to the system Crease Manager. - - - - - This global function returns a pointer to the BitmapCarrier. Note that there is only two of these: one for the source, and one for the destination. Developers should not delete these. Sample code using this class is available in /MAXSDK/SAMPLES/MATERIALS/BMTEX.CPP. - - - - - Registers a "core" interface with 3ds Max. Plug-ins can register their own "core" interfaces identified by a unique value. In order to register a "core" interface with 3ds Max, it's enough to declare an instance of a , i.e. plug-ins do not need to call RegisterCOREInterface(FPInterface* fpi). For more details see class . - - - pointer to the "core" interface object or its descriptor - - - - Retrieves a "core" interface based on a unique id - - Pointer to the corresponding "core" interface - - - Unique interface id - - - - Returns the count of "core" interfaces registered with 3ds Max. - - - - - Retrieves a "core" interface based on an index value Note that the order of "core" interfaces is not guaranteed. This means that the index of a "core" interface may not be given by NumCOREInterfaces()-1 right after the interface has been registered. - - Pointer to the corresponding "core" interface - - - index of the interface to retrieve. This is a zero based index. - - - - Unregisters a "core" interface previously registered with 3ds Max. Note that "Core" interfaces derived from class or a subclass of it are automatically unregistered when the C++ object that implements them is destroyed. - - - Pointer to the interface to unregister - - - - Get ID'd interface from for given class/sclass - - - - - Gets the interface pointer. - - - - - Returns the interface to the Batch Render Manager singleton object. - - - - - Helper macro returning the brush preset manager singleton object. - - - - - Returns the container manager interface. - - - - - Returns the container preferences interface. - - - - - External access to the conversion manager. - - - - - A global function to , the main starting point in IGame. - - - A Pointer to - - - - - Provides a way to query for the version of IGame the DLL has been built against. - - - A float value with the IGame Version - - - - - Provides a way to query for the version of 3ds Max that the IGame DLL is compatible with. - - - A float value with the 3ds max version. This currently can either be 4.2, 5.1 or 6.0. If it is 6.0 or higher then it will be compiled with the VC7.0 compiler - - - - - Retrieve the last error set by the system - The error code - - - - - Get the detailed description of the last error set by the system - The error text - - - - - the callback for the error logging - - A pointer the the IGameErrorCallback object created by the developer - - - - Reset the last error stored by the system. The global error will only change when IGame sets the last error. Using this method will override it. - - - - - Get the main interface pointer. - - - - - Multiply a with a . - - - - - Convenience method to retrieve the HeightManager interface. - - - - - Returns the interface to a sub-transform controller. - - - The interface. Returns NULL if either the control ptr is NULL, or it does not support the I_LINKTMCTRL2 interface. - - Sub-transform controller to fetch the interface from - - - - Returns whether the given Mtl/Texmap plugin is compatible with the given plugin. Always use this function to determine compatibility. - - - - - ParticleFlow relays on presence of specific interfaces in PF objects. Sometimes the objects are hidden behind layers of XRef objects and WSM modifiers. To reach the real PF object underneath, use this method. - - - - - An action may be turned ON, OFF, True and False in Particle . An operator has two states: ON (1) and OFF (0). A test has three states: ON (1), False (0) and True (-1). The method returns the state of the action. - - - - - A scene can be saved with third-party PFlow operators / tests that are currently unavailable. In such situation a PFlow operator is shown with "Undefined" icon (question mark) and it does not affect PFlow calculations. The operator / test stub is kept with the scene. A user can delete it but it cannot be copied or moved to different PFlow events. - - - - - Returns interface of the parent actionList of the given action. - - - - - Gets PFActionListPool from the scene. - - - - - Gets PFSystemPool from the scene. - - - Friend function declarations. - - - - - Gets PViewManager from the scene. - - - - - Creates an used by ParticleFlow objects (actions, engines etc.) The ParticleFlow has some properties that are different from a regular . - - - - - Deletes a PF-type . The ParticleFlow has some properties that are different from a regular . Also, deleting a node by the methods cleans up the scene from associated elements, for example deleting a PF emitter also removes all global actions and exclusive actionLists downstream. There won't be any harm done if a regular is deleted by the method. The plug-in is able to classify the given node to choose the appropriate way of action. - - - - - There is a special relationship between an action list and an action. The following four methods ensure the consistency in this relationship. Since PF particle system has a list of global action, the system can also be considered as an action list. - - - - - Ensures consistency in relationship between action list and action. See AppendPFAction();. - - - - - Ensures consistency in relationship between action list and action. See AppendPFAction();. - - - - - Ensures consistency in relationship between action list and action. See AppendPFAction();. - - - - - Returns X coordinate of half-plane of space free from any PF item. The method is usually used to calculate (x,y) location of newly created PF systems. If given node is not NULL, then the node is excluded from consideration while looking for free PView space. - - - - - All items in PView are shown according to their Z order index. Returns the highest Z order index amongst all particle systems and action lists. - - - - - The Z order sequence may have some "holes". The method makes the sequence to be more compact by eliminating these "holes". Returns true if there were "holes"; and false if it is already compact. - - - - - ParticleFlow has to track creation of new PF items. For ParticleFlow Shell: the system creates a default configuration and sets PView location. For ActionList: the system sets PView location. For Action: the system creates an ActionList that includes the Action, and sets PView location. To avoid this extra effort from the system side, use Suspend/Resume methods. - - - - - Avoids extra effort for tracking. See RegisterParticleFlowNotification();. - - - - - Avoids extra effort for tracking. See RegisterParticleFlowNotification();. - - - - - Avoids extra effort for tracking. See RegisterParticleFlowNotification();. - - - - - The method is used to release PViewManager when a scene is closed. For internal use only. - - - - - GetPFInt, GetPFFloat and GetPFTimeValue reinforce value boundaries set for parameter values. Can be used instead of pblock()->GetInt and pblock()->GetFloat to be sure that the result values are stay inside the parameter boundaries no matter what. - - - - - See GetPFInt();. - - - - - See GetPFInt();. - - - - - For internal use. The method is used to make all ParticleFlow elements valid. The method traverses the scene to collect all ParticleFlow elements then it removes the invalid ones and fixes elements that are fixable. Returns true is the scene was valid, and false if the scene was invalid. - - - - - Names of actions in PView may have a dynamic suffix to reflect the most important settings of the action. - - - - - Names of actions in PView may have a dynamic suffix to reflect the most important settings of the action. - - - - - Particle system and operators/tests may have reference object (i.e. define an emitting area). An operator may require TM of a reference object at different moments. If the reference object has a complex controller, the action of requesting the state of the reference object, if the time is different from the current time, may inflict REFMSG_CHANGE message thus provoking invalidation of the whole particle system. To prevent that, at the moment of acquiring the reference object TMs, the operator should disable particle invalidation, and then enable the invalidation when it is done with the reference object. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - For more selective tuning in notification change. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - See DisableParticleInvalidation();. - - - - - When a particle system is in the process of calculation/evaluation, it is not advisable to invalidate particle containers. This method sets the proceed status. - - - - - When a particle system is in the process of calculation/evaluation, it is not advisable to invalidate particle containers. This method clears the proceed status. - - - - - When a particle system is in the process of calculation/evaluation, it is not advisable to invalidate particle containers. This method checks if PF is proceeding. - - - - - Returns a pointer to the core interface. - - - - - Acquire a pointer to the render region manager. - - - A pointer to the manager. NULL on error. - - - - - Returns the interface to the Scene State Manager singleton object. - - - - - Return the interface. - - - - - External access to the 3DXI XRef manager. - - - - - These methods are used by many objects and modifiers to handle the app data required to tag an object as using phyically scaled UVs. - the current value of the flag stored in the app date. - - - The object to query for the real-world app data. - - - - - - The object to set for the real-world app data on. - - the new value of the toggle to set in the app data. - - - - Set/Get the property which says we should use real-world map size by default. This value is stored in the market defaults INI file. - the current value of the flag from the market defaults file. - - - - - This global function is available in release 2.0 and later only. - - Returns a pointer to a new structure. - - - - - This global function is available in release 2.0 and later only. - - Deletes the structure whose pointer is passed. - Parameters: - *is - - Points to the structure to free. - Data Members: - *first; - - A pointer to the first intersection. - - - - - This method will create and return a new instance of the class. - - - - - This method will destroy an instance of the class. - Parameters: - MaxNetManager* mgr - - Points to the object to destroy. - - - - - This function will initialize a job structure using the data read from a specified 3ds Max scene file. If you would want to submit a job based on a 3ds Max file alone, you would call this function passing it to the file specified. This function takes care of filling all the fields so you can turn around and just send the job to the queue.. - Parameters: - char* filename - - The filename of the 3ds Max scene file (*.max). - - Job* job - - A pointer to an empty job structure which will be initialized by the method. Because the function will initialize the structure any values present prior to calling this method will be reset. - - & jobText - - A reference to an empty class which will be initialized by the function. Just like the job structure, any values present prior to calling this function will be reset. - TRUE if reading the properties was successful, otherwise FALSE. - - - - - This function will set the default values for the given structure. You can use this function to prevent frequent resetting of the structure and its default fields such as size, version, etc. - Parameters: - *job - - The job structure containing the information about the job. See the structure description for an explanation. - - - - - This function creates a Network Rendering archive. This is the archive sent to the manager when submitting a new job. Note that even though you can use whatever name you feel like, the Manager and Servers will look for a "jobname.maz" file. - Parameters: - MCHAR* archivename - - The full path and filename of the archive you want to create. - - MCHAR* file_list - - A list of NULL terminated filenames to include in the archive. You should provide a full path and filename. However, only the file names will be saved in the archive and all files are going to be un-archived in the same directory. - - An example: file_list[] = {"c:\\path\\file.maz/0c:\\anotherpath\\maps.tga/0/0"}; - - DWORD* filesize - - Optional pointer to a variable to receive the accumulated size of all files included in the archive. This is the "uncompressed" size. You can use this to compute the disk space necessary to uncompress the archive. - TRUE if the archive was successfully created, otherwise FALSE. - - - - - This function is the opposite of Maz() and will un-archive the given archive into the specified directory. - Parameters: - MCHAR* archivename - - The full path and filename of the archive you want to un-archive. - - MCHAR* output_path - - The path you want the files extracted to. - TRUE if the archive was successfully extracted, otherwise FALSE. - - - - - Shows the missing maps dialog. The missing maps dialog displays a list of provided file paths for missing maps. It is up to the caller to accumulate that list. The dialog provides the user with the option to browse for the missing maps, adding to the list of search paths. Thus, if the user should press Continue, the renderer should attempt to re-resolve the missing map files before moving on to rendering. - - - This method internally handles logging, error reporting, network rendering, etc. - True if rendering should continue normally - either because the user pressed Continue, or because UI pop-ups are disabled (e.g. for network rendering) and the system is set to continue on errors. False if rendering should be cancelled, either because the user pressed Cancel or because UI pop-ups are disabled (e.g. for network rendering) and the system is set to abort on errors. - - The list of file paths to missing maps. - Handle to the parent window of the pop-up to be displayed. - - - - Shows the missing UVW channels dialog. The missing UVW channels dialog informs the user of a list of objects and UVW channels that are required by their materials, but missing from the geometry. This dialog is purely informative and allows the user to continue or cancel. - - - This method internally handles logging, error reporting, network rendering, etc. - True if rendering should continue normally - either because the user pressed Continue, or because UI pop-ups are disabled (e.g. for network rendering) and the system is set to continue on errors. False if rendering should be cancelled, either because the user pressed Cancel or because UI pop-ups are disabled (e.g. for network rendering) and the system is set to abort on errors. - - The list of strings to display in the missing UVW channels dialog. The standard format is as follows: or . - Handle to the parent window of the pop-up to be displayed. - - - - Constructor. - - - Constructor - - are the number of indices that make up each element. For instance a triangle is 3, a line segment is 2 etc. - - - - Constructor. - - - - are the number of indices that make up each element. For instance a triangle is 3, a line segment is 2 etc. - - - - Constructor. - - - HWIndexBuffer(unsigned int count, unsigned int indicesPerPrimitive, bool use16Bit) Constructor - - - - - this is the number of primitives for this buffer to be allocated - - this is the number of indices per primitive - - this is whether to use 16 bit buffers for the indices - - - - Constructor. - - - - is the vertex type ie Pos|Normals|UVWs etc that this mesh will use. See , enum VertexType for the list of supported types - - - - Constructor. - - - - - Constructor. - - - - the description of the HW vertex which can be any combination of VertexType - - - - Constructor. - - - - the description of the HW vertex which can be any combination of VertexType - - - - Constructor. - - - - - Max calls to ask how plug-in set canConvertUnits. - - - - - Max calls (if plug-in can convert units) to ask user whether to do so. - - - - - Plug-in calls to ask whether user has indicated to convert to/from system units (only should be called if last call to SetCanConvertUnits(ifSo) had arg value true) - - - - - Constructor. - Default Implementation: - { } - - - - - Constructor. - Default Implementation: - { } - - - - - Get the calling module's HINSTANCE. - - - Handle pointing to the start of the calling module. - - - - - Extract a resource from the calling module's string table. - - - GetResourceStringAsMSTR is essentially a thread-safe wrapper around the Win32 API's LoadString, but it saves client code from the bother of dealing with its HINSTANCE, of maintaining a buffer, and reduces duplicated code. - An MSTR containing the resource string, empty if the requested resource is not found. - - Identifier for the desired string resource within the calling module's string table. - - - - Extract a resource from the calling module's string table. - - - GetResourceStringAsMSTR is essentially a thread-safe wrapper around the Win32 API's LoadString, but it saves client code from the bother of dealing with its HINSTANCE, of maintaining a buffer, and reduces duplicated code. - true if the requested resource is found, false if not - - Identifier for the desired string resource within the calling module's string table. - Updated to contain the resource string if the requested resource is not found. - - - - Extract a resource from a module's string table. - - - GetResourceString is essentially a thread-safe wrapper around the Win32 API's LoadString, but it saves client code from the bother of maintaining a buffer and reduces duplicated code. Optimally, GetResourceString should be called through the single-parameter version from dllutilities.h. - An MSTR containing the resource string, empty if the requested resource is not found. - - Handle to the module whose string table will be queried for the resource. - Identifier for the desired string resource within the calling module's string table. - - - - Extract a resource from a module's string table. - - - GetResourceString is essentially a thread-safe wrapper around the Win32 API's LoadString, but it saves client code from the bother of maintaining a buffer and reduces duplicated code. Optimally, GetResourceString should be called through the single-parameter version from dllutilities.h. - true if the requested resource is found, false if not - - Handle to the module whose string table will be queried for the resource. - Identifier for the desired string resource within the calling module's string table. - Updated to contain the resource string if the requested resource is not found. - - - - Try to open the floating dialog for the described by the entry parameter. - - - - The whose parameter dialog we want to open with its parent context. - This time represents the horizontal position of where the user right clicked to bring up the modal edit track parameters dialog. See the flags below for when this parameter is valid. - The handle to the parent window that should be used to create the dialogs. - An interface pointer available for calling functions in 3ds . - One or more of the following values: The user is in the function curve editor. The user is in one of the track views. The user is editing a path in the scene. The user invoked by choosing the properties button. In this case the time parameter is NOT valid. The user invoked by right clicking with the mouse. In this case the time parameter is valid. - - - - Returns the UI scaling factor relative to a default of 96 DPI. The function reads the systems monitor settings and calculates the scaling factor based on the vertical logical DPI (what can be set and changed through the windows OS control panel). It will return 1.0f, if some value couldn't be retrieved or calculated, or a calculation result will be 0.0f; so it is safe to use the result of this function to simply multiply UI sizes without further checking. - - - The scaling factor, if it could be retrieved and calculated, 1.0f in other cases. - - The index of the monitor to get the actual logical vertical DPI from. Default value is set to -1, which means the primary system monitor. - - - - Get the additional user UI scaling factor. - - - The users ui scaling factor. - - - - - Scaling of a rectangle values based on UIScaleFactor. - - - - RECT struct to be scaled to UIScaleFactor - The index of the monitor to get the actual logical vertical dpi from. Default value is set to -1, which means the primary system monitor. - - - - Unscaling of a rectangle values based on UIScaleFactor. - - - - RECT struct to be unscaled to UIScaleFactor - The index of the monitor to get the actual logical vertical dpi from. Default value is set to -1, which means the primary system monitor. - - - - Returns a scaled copy of the bitmap if the UI scaling factor is not 1.0. - - - The dpi scaled bitmap if the UI scaling factor is not 1.0, otherwise null. - - The bitmap to be dpi scaled. - The index of the monitor to get the actual logical vertical dpi from. Default value is set to -1, which means the primary system monitor. - - - - Annotates the control with Microsoft Active Accessibility name property. - - - S_OK or the error codes - - The window handle of the control to be annotated - The name annotated to the control - - - - Removes the Microsoft Active Accessibility name from the control. - - - S_OK or the error codes - - The window handle of the control to be removed annotation - - - - Scales the toolbar size and icons in standard file open/save dialogs. - - - Scales the toolbar containing the 'Go To Last Folder Visisted', 'Up One Level', 'Create New Folder' buttons, and the ' Menu' dropdown, by the system dpi scaling value. The hDlg parameter is HWND passed to the LPOFNHOOKPROC specified in the OPENFILENAME structure. Technically, this HWND is a child of the win32 file open / save dialog - - The dialog's HWND. - - - - Multiple character search for ComboBoxes. - - - This method will select an entry in the ComboBox based on the multiple key entries over a set time period. The functionality mimics the standard windows ListView behavior, including the documented one second time period for key entries. It is intended to be used in conjunction with the WM_CHAR message in the ComboBox's callback. - Example usage: - true if match found, false if not - - Window handle of ComboBox - Character entered by user - Optional parameter. Default is NULL. Any leading characters in the ComboBox entries that are contained in szTrim will be removed prior to comparing to the search string. - - - - Multiple character search for ListBoxes. - - - This method will select an entry in the ListBox based on the multiple key entries over a set time period. The functionality mimics the standard windows ListView behavior, including the documented one second time period for key entries. It is intended to be used in conjunction with the WM_CHAR message in the ListBox's callback. - Example usage: - true if match found, false if not - - Window handle of ListBox - Character entered by user - Optional parameter. Default is NULL. Any leading characters in the ListBox entries that are contained in szTrim will be removed prior to comparing to the search string. - - - - Returns the default maximum width, in pixels, for tooltip windows in Max. Tooltips wider than the maximum are broken into multiple lines. - - - - - Create an empty pointing to kInvalidId . - - - - - Create an pointing to assetId. The constructor will automatically add a reference to the asset. - - - - on which the will point. - - - - Create an pointing to the same asset as assetU. - - - - we want to copy. - - - - Gets the total number of AssetUsers created during this 3dsmax session. - - - The number of AssetUsers created. - - - - - Gets the current number of instances. - - - The current number of AssetUsers. - - - - - Returns the only instance of this manager. - - - - - Constructor - - describes the data to be used for input - pointer to the actual data - - - - Constructor - - - - - Constructor. - - - - - Constructor - - describes the data to be used for output - pointer to the actual data - - - - Returns a pointer to the system-wide instance of . This is a faster alternative to - - Pointer to the system-wide instance. - - - - - Checks if a file exists and contains a storage called CustomFileStreamDataStorage. - - - true if the file exists and contains a storage called CustomFileStreamDataStorage - - The file name. - - - - Open a file as an OLE structured storage file with read/write access. - - - The CustomFileStream IStorage - - The file name. - [out] The IStorage associated with the file. This IStorage needs to be Released at the same time as the returned IStorage is released. - - - - Open a file as an OLE structured storage file with read access. - - - The CustomFileStream IStorage - - The file name. - [out] The IStorage associated with the file. This IStorage needs to be Released at the same time as the returned IStorage is released. - - - - Delete the specified CustomFileStream stream from the specified file. Only a stream in the CustomFileStream IStorage with the specified name will be deleted. - - - The success status - - The file name. - The stream name. The stream name must be less than 32 characters. - - - - Queries the state of the modifier keys and returns the appropriate right click modifier flags. - - - - - Helper function to access the core interface - A pointer to - - - - - Helper function to get shortcuts of customized mode. The output parameters are the shortcuts. Returns true if the shortcuts can be obtained, otherwise false. - - - - - Helper function to get the value of an operation parameter such as zoom in direction of customized zoom mode. - true if value can be obtained, otherwise false. - - - - - A method to call a debug break during runtime. If called while running a release build, it will throw an exception and generate a Crash Error Report. If called while running a debug build under the debugger, it will pause execution - - - - - This creates an instance of a context - - - - - This disposes an instance of a context - - - - - This creates an instance of an - - - - - This disposes an instance of an - - - - - This creates an instance of an - - - - - This disposes an instance of an - - - - - Built-in char input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in unsigned char input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in wchar_t input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in short input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in unsigned short input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in int input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in unsigned int input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in long input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in unsigned long input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in __int64 input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in unsigned __int64 input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in float input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in double input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in multi-byte string input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in Unicode string input/output type. This can be used in the constructor of class Input/Output. - - - - - Built-in dictionary input/output type. This can be used in the constructor of class Input/Output. - - - - - Checks if the given type is number type. - true if the type is a number type, (for example, char, wide char, int, double), false otherwise. - - type value. - - - - Checks if two types can be converted to each other. - true if two types are equal or both are numbers, false otherwise. - - The first type. - The second type. - - - - Get the vertex stride by a given vertex type, in bytes. - the vertex stride, in bytes. - - the vertex type. - - - - Get the index stride by a given index type, in bytes. - the index stride, in bytes. - - the index type. - - - - A utility function for generating hash code. - new code from seed and hash code. - - - - - Helper function to access the core interface - A pointer to - - - - - Helper function to test whether the new viewport graphics system is running - TRUE if new viewport graphics is active - - - - - Helper function to test whether the new viewport graphics system is performing hardware hit testing. - TRUE if new viewport graphics is performing hardware hit testing. - - The specific viewport in which we want to know whether we are performing hardware hit testing. - - - - Convert to - - the output - the source - - - - Convert to - - the output - the source - - - - Get a specified built-in mesh element description. - the specified mesh element description. - - the kind of built-in mesh element description - - - - Use this function for TargetFormatA8R8G8B8 only. DX10/11 doesn't support A8R8G8B8 which is only supported in DX9. So when we're using DX10/11 device, we will meet with color shift issue with the A8R8G8B8 format. So for a of TargetFormatA8R8G8B8, you may call this function to get a device compatible color. - the original color for a DX9 device. For DX10/DX11 device, returns a color with red and blue channels swapped. - - The original color data. - - - - Get the number of bytes for each pixel by a given target format. - The number of bytes for each pixel by that given target format. - - The given target format. - - - - Generate the instance data from a array - The input matrix array should contain object-to-world matrices. Each matrix is used to render an mesh instance. The return object is needed by GenerateInstanceRenderItem(). Multiple instance render items can share the same . The returned vertex buffer contains world matrices and inverse transpose world matrices. This function automatically compute inverse transpose world matrices from world matrices and then fill the buffer. - the instance data handle. - - pointer to world transform matrices. Each matrix is a instance of . - the number of the instances - - - - Generate the instance data from a texture coordinates array and a array - The input matrix array should contain object-to-world matrices. Each matrix is used to render an mesh instance which can have different texture coordinate. The return object is needed by GenerateInstanceRenderItem(). Multiple instance render items can sharing the same . The returned vertex buffer contains texture coordinate, world matrices and inverse transpose world matrices. This function automatically compute inverse transpose world matrices from world matrices and then fill the buffer. - the instance data handle. - - pointer to texture coordinate array.Each texture coordinate pair is for an instance of . - pointer to world transform matrices. Each matrix is an instance of . - the number of the instances - - - - Generate the instance render item from a tuple mesh and a array - Instance rendering is a way to draw many objects that use the same geometry. These objects shares same materials and modifiers. The only difference between objects is world transformation. You can specify a matrix array for the mesh, then the mesh will be drawn for many times. Each corresponds to a matrix in the array. Typical usage of these instance functions should like following: - true if successful created the instance render item. - - the instance render item handle which can replace original tuple mesh render item. - handle of a tuple mesh render item - handle generated by GenerateInstanceData - - - - Generate the instance render item from a tuple mesh which is a class. This is an extension of the bool GenerateInstanceRenderItem(RenderItemHandle& hInstanceRenderItem, const RenderItemHandle& hTupleMeshHandle, const VertexBufferHandle& hInstanceData) function with more overridable data for instances. The previous method could only override the transform matrix in world space and UV from the map channel #1. The class lets you override more data per instance. For more details, please see the header file maxsdk\include\Graphics\InstanceDisplayGeometry.h. - true if successful created the instance render item. - - the instance render item handle which can replace original tuple mesh render item. - handle of a tuple mesh render item - : an InstanceDisplayGeometry* - - - - Helper function to retrieve a pointer on the interface - a pointer on , the pointer cannot be null. - - - - - Method that verifies if at least one GPU is present on the current system - true if at least one GPU is present, false otherwise - - - - - Global function to save a raster as a (for debugging purpose, this is a slow process) - true if everything went right or false if an error occured in the saving process. - - - the full path filename such as : "d:/MyTexture.png" or "d:\\SubFolder\\MyTexture.exr", we will save it in the file format whose extension is set in this parameter. Make sure you have the rights to save a file in that folder. If the file already exists, we will replace it. To check if the target format used in the can be saved, please use TargetFormatCanBeSaved below. If you use this global function, please link with maxgraphicsObjects.lib since it is defined in that module. - - - - Global function to know if saving the current target format of the is implemented. If you use this function, please link with MaxGraphicsObjects.lib since it is defined in that module. - true if the target format can be saved or false if it is not yet implemented. If it can be saved, you can use the Save function above. - - - - - - Convert a 3ds Max into a viewport - a - - : the 3ds material. - : the time at which you want the conversion to happen (could be different from the current time). - : set it to true if the 3ds material is using Bump/Normal mapping or needs to be at the maximum quality available in the viewport. Be aware that this quality will stay the same even when switching to standard or high quality viewports. - - - - Create a viewport from a Physical material preset - true if the preset name was found and the correctly filled. - - : a which can be used with - : the name used in the preset, you can find the preset names from en-US\Plugcfg\PhysicalMaterialTemplates.ini But - : the time at which you want to conversion to happen (could be different from the current time). - : set it to true if the 3ds material is using Bump/Normal mapping or needs to be at the maximum quality available in the viewport. Be aware that this quality will stay the same even when switching to standard or high quality viewports. - - - - Get instance of the strategy. The instance is global object - instance of - - - - - Get instance of the strategy. The instance is global object - instance of - - - - - Constructor - - mesh to display, we will do a local copy of this mesh - indicate whether this item's mesh has fixed size on the screen - - - - Get instance of the strategy. The instance is global object - instance of - - - - - This function converts from a color r,g,b in bytes (range 0 to 255) to a combined DWORD used internally by 3ds Max for storing Vertex Colors. - - - - - This function is used to compute the (GPU compliant data) information from the used by the display parameters, the output is the DisplayParams::mGridGPUParams member of an instance of the structure stored locally in your plug-in so we don't recompute this data each frame. - true if successful or false otherwise. - - The grid construction parameters. - The Grid GPU parameters ready to be used by 3ds 's viewport functions. - - - - This function is used to let the volume API do everything for you to display the volume correctly from your plug-in method IObjectDisplay2::UpdatePerNodeItems. It will fill the targetRenderItemContainer with the suitable RenderItem using the display modes from the viewport (wireframe, shaded, clay etc.) and using the options you have set in the volumeDisplayParams parameter. - true if successful or false otherwise. - - The display context, which contains all the requirements for plugin to generate render items. - which contains all information required for adding per node relevant render items. - the target render item container to which this plugin object will be added. - The volume display parameters. - - - - This function is used to let the volume API do the hit testing of the volume when the user wants to select a volume in a viewport. The parameters are matching the parameters from BaseObject::HitTest, except the volumeDisplayParams which is the Volume Display Parameters that we use to do the hit testing. - Nonzero if the item was hit; otherwise 0. - - The time to perform the hit test. - A pointer to the node to test. - The type of hit testing to perform. See for details. - The state of the crossing setting. If TRUE crossing selection is on. - The hit test flags. See for details. - The screen point to test. - An interface pointer that may be used to call methods associated with the viewports. - The volume display parameters. - - - - constructor. integer is initialized to zero. - - - - - Constructor. - - the node obtained from . - the customized solid mesh material - - - - The default ctor. - - The primitive render that is to restore its world matrix - - - - Constructor. - - - - - Retrieves the sole instance of . - - - - - Gets the class ID that can identify this type of handle - Gets the class ID that can identify this type of handle - - - - - Get an instance of that class. - the unique instance of that class. - - - - - Create texture handle from . The size of texture is controlled by procedural texture size of viewport setting - of . - - A pointer to a . - the time. - - - - Default constructor. The default type of the variable is int and the default value is zero. - - - - - Constructs a char-type variable with the given value. - - The initial value of this variable. - - - - Constructs an unsigned char variable with the given value. - - The initial value of this variable. - - - - Constructs a short variable with the given value. - - The initial value of this variable. - - - - Constructs an unsigned short variable with the given value. - - The initial value of this variable. - - - - Constructs an int variable with the given value. - - The initial value of this variable. - - - - Constructs an unsigned int variable with the given value. - - The initial value of this variable. - - - - Constructs a __int64 variable with the given value. - - The initial value of this variable. - - - - Constructs an unsigned __int64 variable with the given value. - - The initial value of this variable. - - - - Constructs a float variable with the given value. - - The initial value of this variable. - - - - Constructs a double variable with the given value. - - The initial value of this variable. - - - - Constructs a multi-byte string variable with the given value. - - The initial value of this variable. Cannot be NULL. - - - - Constructs an auto-ptr variable with the given value. - - The initial value of this variable. Can be NULL. - - - - Copy constructor. - - The default value of this variable. - - - - Constructor. - - - - - Constructor. - - - - - GetManager static function - a pointer on - - - - - GetManager static function - a pointer on - - - - - Gets Active considering extended and non extended views. - the ViewExp* for the active viewport - - will be true if the view is an extended view. - - - - Gets the from its view undoID considering extended views and all tab panels not only the active tab panel. - the ViewExp* for the viewport whose undoId is viewUndoID - - the view undo ID - will be true if the view is an extended view. - - - - Gets the viewport label from its view undoID considering extended views and all tab panels not only the active tab panel. - - the view undo ID - the viewport label. - - - - To know if the renderer is locked - true if it is locked to a given viewport - - the render setting ID - - - - This method lets you set the number of threads on various parts of Max. - - - This method lets you set the maximum number of threads on various parts of Max. It also lets you set the minimum number of elements for each thread to prevent excessiving threading. It does not prevent you from oversubscribing threads. - - this is which part of you want to set the multi-thread level - this is the maximum number of threads to use for this operation. This is not limited so you can over subscribe and have more threads than CPUs. - this is used to restrict the number of threads. It controls the number of threads to use limited by maxNumThreads. The number of threads used equal to numberElements/minElementsPerThread. So for instance the KMeshThreads in the elements are the faces/vertices. This is here to prevent too few elements per thread. If set to 0 or less this value will be ignored and the numThreads will be used. - - - - This method returns the maximum number of threads on various parts used by Max. - - - This method returns the maximum number of threads on various parts of used by Max. - - this is which part of you want to set the multi-thread level - - - - This method returns the minimum number elements in each threads on various parts used by Max. - - - This method returns the minimum number elements in each threads on various parts used by Max - - this is which part of you want to set the multi-thread level - - - - This method returns the optimal grainsize to be used with Intel's TBB parallel_for and similar functions. - - - It will cap the amount of work according to the number of threads available - 1, or the setting in your preference ini file. If the MaxThreads setting is higher than number of threads available -1, we cap the thread count. - - this is the number of elements you will iterate over - - - - This method sets the maximum number of threads for Tbb. - - - This value should be set in the currentdefaults.ini preference file. - - The number of threads to use, -1 for max available threads. - - - - This method return the maximum number of threads for Tbb. - - - It returns the appropriate value, not the value set in the preferences. - numThreads The number of threads tbb will use, between 1 and max threads - 1. - - - - - These are global timers that can be started and stopped in different scopes. There are 1000 ids and the first 100 are reserverd for internal. - - - This starts a timer matching the ID - - - - - This ends a timer matching the ID and returns the accumlated time passed in MS. - - - - - This clears a timer matching the ID. - - - - - This returns the amount of time passed for the matching ID. - - - - - Starts a timer tied to the id example { timeBlock(15); <...> code to time } double result - Timer::GetTimerGlobal(15);. - - - - - Returns the interface to Populate. - - - - - Gets the interface to a Populate Flow object. - - - A pointer to an interface, or NULL. - - - flow object - - - - Gets the interface to a Populate Seat object. - - - - a pointer to an interface, or NULL. - - - seat object - - - - Calls MtlBase::Update() and Texmap::LoadMapFiles() on the given material/texmap and its sub-tree of materials and textures. This generally needs to be called before a material/texmap is used. This method is called automatically by this class () before the material is translated, but exposed here in case any external code might need to access it independently. - - The material/texmap that forms the root of the material/texmap tree to be updated. - The time at which the material is to be updated. - The validity of the material at the given time, to be intersected with the input value. - - - - Starts or stops the given timer. - - - - The name of the timer to be started or stopped. - The rendering process interface through which the timer is started or stopped. - When false, the timer is started in the constructor and stopped in the destructor. When true, the behaviour is reversed: the timer is stopped in the constructor and started in the destructor. - - - - Default constructor initializes state to Success. - - - - - Constructs (implicitly) from given state. - - - - - Initializes all statistics to 0. - - - - - Initializes the both shutter_duration and shutter_offset to 0. - - - - - Initializes the shutter duration and offset with the given values. - - - - - Returns true if in main thread. - - - - - Returns the worker thread id set via SetWorkerThread. If no worker thread is set, the returned value is 0. - - - - - Clears the worker thread id value. - - - - - Returns true if (a) the worker thread id is not set and in main thread, or (b) the worker thread id is set and in that thread. - - - - - Disables checking. - - - - - Specifies translation between a localized and non-localized (English) string pair for when MAXScript is performing property resolution. - - - - always returns true. A return value is specified so that this method can be used as a static variable initializer, registering translation once. /note The strings are stored in lower case as name resolution in MAXScript is case insensitive when dealing with 3dsMax objects. /note If the localized and non-localized strings are case-insensitive equivalent, the strings are not registered. /note Unique localized \ non-localized string pairs will only be registered once. - - - The property name resolution context where this translation will be used - - the localized string - - the non-localized (English) string - - - - Retrieves localized translations for a non-localized (English) string. - - - - returns true if localized strings were found, false otherwise. /note This method would not normally be used by 3rd party developers. - - - The property name resolution context - - the non-localized (English) string - - an array of the localized strings - - - - Retrieves non-localized (English) translations for a localized string. - - - - returns true if non-localized strings were found, false otherwise. - - returns true if localized strings were found, false otherwise. /note This method would not normally be used by 3rd party developers. - - - The property name resolution context - - the localized string - - an array of the non-localized (English) strings - - - - Utility function to get the main 3ds Max window handle for the given process handle. - - - The main 3ds Max window handle for the given process handle if found, NULL otherwise - - [in] The 3ds Process id to get data for. - [in, out] The 3ds version of the process. - - - - Returns the identifier of the language used by 3ds Max. - - - This method complements MaxSDK::Util::GetLanguageTLA. - The language identifier is made up of a primary language identifier and a sublanguage identifier, both of which are from a set pre-defined identifiers that are part of the Windows Platform SDK. - For more information on language identifiers see - - - - - Returns the locale ID value that is being used by 3ds Max, as set by the language pack being used at runtime. It is returned as a string. Ex: "409" (without the quotes) is what it will return for English-United States. - - - - - Returns the "three letter acronym" (TLA) of the language used by 3ds Max. - - - This method complements MaxSDK::Util::GetLanguageID. For more information on TLA see - The TLA of the language used by 3ds Max. - - - - - Returns the two-two (eg "en-US" or "ja-JP") language pack directory for the language pack in use by 3ds Max. - - - This method complements MaxSDK::Util::GetLanguageID. - The Language Pack directory name of the language used by 3ds Max. - - - - - copies a string to the system wide clipboard - - - - - The string to copy - - The Window that owns the original information to be copied - - - - Returns the file version as a string of form "#.#.#.#" where the numbers are the major version, the update version, the Hot Fix number, and the build number. - - - containing the file version, empty if the file is not found or does not have version information - - - the file name of the file to get the version number for. The function uses the search sequence specified by the LoadLibrary function. - - - - Returns the 3ds Max build number as a string of form "#.#.#.#" where the numbers are the major version, the update version, the Hot Fix number, and the build number. This is the same string seen as the Product Version of 3dsmax.exe in File Properties and at the top of the About 3ds Max dialog. - - - - - See if can create files in TEMP folder. If not, set TEMP env var to writable folder. - - - - - Get the current process name. - - - - - These service should replace every occurrence of the standard WIN32 implementation. The WIN32 implementation specifies that when the file name contains UNICODE character, the file will be created with a UNICODE BOM. This is ABSOLUTLY INCORRECT!!! In order to properly save UNICODE INI file, we need to enforce that every INI file has a BOM token. Copies a string into the specified section of an initialization file. This service will create the new INI file with a UTF-16LE and delegate to WIN32 implementation to actually write the new key value pair. If the INI file exist and is not a UNICODE file, it will be re-created as a UTF-16LE and the key|value pair will be written in the proper section. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - If the function successfully copies the string to the initialization file, the return value is nonzero. If the file was created using Unicode characters, the function writes Unicode characters to the file. Otherwise, the function writes ANSI characters. - - The name of the section to which the string will be copied. If the section does not exist, it is created. The name of the section is case-independent; the string can be any combination of uppercase and lowercase letters. - The name of the key to be associated with a string. If the key does not exist in the specified section, it is created. If this parameter is NULL, the entire section, including all entries within the section, is deleted. - A null-terminated string to be written to the file. If this parameter is NULL, the key pointed to by the pKeyName parameter is deleted. - The name of the initialization file. - - - - Copies data into a key in the specified section of an initialization file. As it copies the data, the function calculates a checksum and appends it to the end of the data. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - If the function successfully copies the string to the initialization file, the return value is nonzero. If the function fails, or if it flushes the cached version of the most recently accessed initialization file, the return value is zero. To get extended error information, call GetLastError. - - The name of the section to which the string will be copied. If the section does not exist, it is created. The name of the section is case independent, the string can be any combination of uppercase and lowercase letters. - The name of the key to be associated with a string. If the key does not exist in the specified section, it is created. If this parameter is NULL, the entire section, including all keys and entries within the section, is deleted. - The data to be copied. If this parameter is NULL, the key is deleted. - The size of the buffer pointed to by the pStruct parameter, in bytes. - The name of the initialization file. - - - - Replaces the keys and values for the specified section in an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError. - - The name of the section in which data is written. - The new key names and associated values that are to be written to the named section. This string is limited to 65,535 bytes. - The name of the initialization file. If this parameter does not contain a full path for the file, the function searches the Windows directory for the file. If the file does not exist and pFileName does not contain a full path, the function creates the file in the Windows directory. If the file exists and was created using Unicode characters, the function writes Unicode characters to the file. Otherwise, the function creates a file using ANSI characters. - - - - Gets a string from the specified section of an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. If neither pSection nor pKeyName is NULL and the supplied destination buffer is too small to hold the requested string, the string is truncated and followed by a null character, and the return value is equal to nSize minus one. If either pSection or pKeyName is NULL and the supplied destination buffer is too small to hold all the strings, the last string is truncated and followed by two null characters. In this case, the return value is equal to nSize minus two. - - The name of the section containing the key name. If this parameter is NULL, the GetPrivateProfileString function copies all section names in the file to the supplied buffer. - The name of the key whose associated string is to be retrieved. If this parameter is NULL, all key names in the section specified by the pSection parameter are copied to the buffer specified by the pReturnedString parameter. - A default string. If the pKeyName key cannot be found in the initialization file, GetPrivateProfileString copies the default string to the pReturnedString buffer. If this parameter is NULL, the default is an empty string, "". - A pointer to the buffer that receives the retrieved string. - The size of the buffer pointed to by the pReturnedString parameter, in characters. - The name of the initialization file. - - - - Gets a string from the specified section of an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. - - The name of the section containing the key name. If this parameter is NULL, the GetPrivateProfileString function copies all section names in the file to the supplied buffer. - The name of the key whose associated string is to be retrieved. If this parameter is NULL, all key names in the section specified by the pSection parameter are copied to the buffer specified by the pReturnedString parameter. - A default string. If the pKeyName key cannot be found in the initialization file, GetPrivateProfileString copies the default string to the pReturnedString buffer. If this parameter is NULL, the default is an empty string, "". - A reference to the MaxSDK::Array<MCHAR> buffer that receives the retrieved string. This service will adjust the size as necessary to hold the string. - The name of the initialization file. - - - - Retrieves the data associated with a key in the specified section of an initialization file. As it retrieves the data, the function calculates a checksum and compares it with the checksum calculated by the WritePrivateProfileStruct function when the data was added to the file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. - - The name of the section in the initialization file. - The name of the key whose data is to be retrieved.. - A pointer to the buffer that receives the data associated with the file, section, and key names. - The size of the buffer pointed to by the pStruct parameter, in bytes. - The name of the initialization file. - - - - Retrieves the names of all sections in an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. If the buffer is not large enough to contain all the section names associated with the specified initialization file, the return value is equal to the size specified by nSize minus two. - - A pointer to a buffer that receives the section names associated with the named file. The buffer is filled with one or more null-terminated strings; the last string is followed by a second null character. - The size of the buffer pointed to by the pReturnedString parameter, in characters. - The name of the initialization file. - - - - Retrieves the names of all sections in an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. - - A reference to the MaxSDK::Array<MCHAR> buffer that receives the section names associated with the named file. The buffer is filled with one or more null-terminated strings; the last string is followed by a second null character. This service will adjust the size as necessary to hold the string. - The name of the initialization file. - - - - Retrieves all the keys and values for the specified section of an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. If the buffer is not large enough to contain all the key name and value pairs associated with the named section, the return value is equal to the size specified by nSize minus two. - - The name of the section in the initialization file. - A pointer to a buffer that receives the key name and value pairs associated with the named section. The buffer is filled with one or more null-terminated strings; the last string is followed by a second null character. - The size of the buffer pointed to by the pReturnedString parameter, in characters. - The name of the initialization file. - - - - Retrieves all the keys and values for the specified section of an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the number of characters copied to the buffer, not including the terminating null character. - - The name of the section in the initialization file. - A reference to the MaxSDK::Array<MCHAR> buffer that receives the key name and value pairs associated with the named file. The buffer is filled with one or more null-terminated strings; the last string is followed by a second null character. This service will adjust the size as necessary to hold the string. - The name of the initialization file. - - - - Retrieves an integer associated with a key in the specified section of an initialization file. This service uses a instance to ensure only one 3ds Max session is accessing the .ini at a time. - The return value is the integer equivalent of the string following the specified key name in the specified initialization file. If the key is not found, the return value is the specified default value. - - The name of the section containing the key name. - The name of the key whose value is to be retrieved. - The default value to return if the key name cannot be found in the initialization file. - The name of the initialization file. - - - - Sets the name of the given thread. The given name will appear in the thread view of the debugger, enabling easier debugging. - - - - The ID of the thread for which to set the name. - The string to use as the name of the thread. - - - - Sets the name of the current thread. The given name will appear in the thread view of the debugger, enabling easier debugging. - - - - The string to use as the name of the thread. - - - - Sets the name of the given thread. The given name will appear in the thread view of the debugger, enabling easier debugging. If the thread name shouldn't appear in release builds (e.g. because of security risks), then use this method instead of SetThreadName(). - - - - The ID of the thread for which to set the name. - The string to use as the name of the thread. - - - - Sets the name of the current thread, but only if building for debug. The given name will appear in the thread view of the debugger, enabling easier debugging. If the thread name shouldn't appear in release builds (e.g. because of security risks), then use this method instead of SetThreadName(). - - - - The string to use as the name of the thread. - - - - Convert the codepage name string to the codepage number in codPageTable - True if the input codepage name is foundThe codepage numbers corresponding to the codepage names: {_M("utf-8"), CP_UTF8}, {_M("windows-1252"), 1252}, {_M("iso-8859-13"), 28603}, {_M("iso-8859-15"), 28605}, {_M("iso-8859-1"), 28591}, {_M("iso-8859-2"), 28592}, {_M("iso-8859-3"), 28593}, {_M("iso-8859-4"), 28594}, {_M("iso-8859-5"), 28595}, {_M("iso-8859-6"), 28596}, {_M("iso-8859-7"), 28597}, {_M("iso-8859-8"), 28598}, {_M("iso-8859-9"), 28599}, // Asiatic code pages. {_M("koi8-r"), 20866}, // Russian (KOI8-R); Cyrillic (KOI8-R) {_M("iso-2022-kr"), 50225}, // ISO 2022 Korean {_M("iso-2022-jp"), 50222}, // ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) {_M("shift_jis"), 932}, // ANSI/OEM Japanese; Japanese (Shift-JIS) {_M("gb2312"), 936}, // ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) {_M("ks_c_5601"), 949}, // ANSI/OEM Korean (Unified Hangul Code) {_M("big5"), 950}, // ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) {_M("utf-16"), 65012}, {NULL, 0}, - - The name of the code page - number corresponding to the input name - - - - Default Constructor - - - - - Detect the encoding of the passed buffer. - Returns true if the encoding was formally detected. Or false, if it was guessed. - - Buffer to detect the encoding - Size of the passed buffer - (in/out) In input, tell the detector what to expect. On output it contains what the detector found. - (out) On output, tell the caller how much bytes it must ignore at the beginning of the file because of the BOM. - - - - Determine the number of chars inside a buffer. - - - It's more complex than just strlen or wcslen. Those two functions will returns the number of char or WCHAR entries. This function will returns the number of of characters (or symbol). - of symbols - - Buffer containing a string to count the number of symbols - The size of the buffer in bytes - Encoding to use to count the number of symbols - - - - Determine the number of line feeds inside a buffer. - of line feed detected - - Buffer in which ' ' are counted. - The size of the buffer in bytes - Encoding of "data". Can be any valid encoding. ie. MSDE_CP_UTF16, CP_UTF8, CP_ACP, etc. - - - - Default Constructor - - - - - Default Constructor - - - - - Constructor. - - - Plug-ins may have functions of long busy process which can't be accepted by users. In this condition, users can use this interface to escape the long busy process by pressing ESC key. - - - - - Transform a C fopen-style file mode into a file mode that you can use in the BinaryStream::FromFilename parameter. - Here is the table of interpretation. It was made to match Microsoft's VC Runtime interpretation: - r: BINARYSTREAM_MODE_READ r+ or rw: BINARYSTREAM_MODE_READ | BINARYSTREAM_MODE_WRITE w: BINARYSTREAM_MODE_WRITE | BINARYSTREAM_MODE_CREATE | BINARYSTREAM_MODE_TRUNCATE w+: BINARYSTREAM_MODE_READ | BINARYSTREAM_MODE_WRITE | BINARYSTREAM_MODE_CREATE | BINARYSTREAM_MODE_TRUNCATE a: BINARYSTREAM_MODE_WRITE | BINARYSTREAM_MODE_APPEND | BINARYSTREAM_MODE_CREATE a+: BINARYSTREAM_MODE_READ | BINARYSTREAM_MODE_WRITE | BINARYSTREAM_MODE_APPEND | BINARYSTREAM_MODE_CREATE - And you can add the following suffix: b: BINARYSTREAM_MODE_BINARY t: BINARYSTREAM_MODE_TEXT e: BINARYSTREAM_MODE_EXCLUSIVE - If the stream mode contains any invalid sequence or unknown character, it will returns 0. - - - - - Create an abstract that will point to the specified file. - - The file's name you wish to open. - Specify how to open the file. - If this parameter is not null, it will contains an error string if this function fails. - - - - Create an abstract that will point to the specified file. - - The file's name you wish to open. - Open for write ? - Will erase the file prior to open it. - Prevent any other object or process to open it simultaneously. - If this parameter is not null, it will contains an error string if this function fails. - - - - Create an abstract out of a Win32 file handle. - - - The file handle. - - Will call CloseHandle(HANDLE) when the new object will be destroyed. - - - - Create an abstract pointing to a memory region. - - - Initial data. - - Initial data's length. (Can be 0.) - - to call when this object is destroyed. (Can be NULL.) - - - - Create an abstract pointing to a memory region. - - - Initial data. - - Initial data's length. (Can be 0.) - - to call when data needs to be resized. (Can be NULL.) - - to call when this object is destroyed. (Can be NULL.) - - - - Constructor - - - - - Constructor - - The name of the file to open - The mode to open the file in. This is the same mode specifier as win32 api fopen. - Whether to set buffer size. If false, the default win32 4KB buffer is used - - whether to potentially override defaultBufferSize value with environment variable / ini file setting - The default buffer size in bytes - - - - Calculate the buffer size to use when opening the file - Returns the buffer size to use. - The returned buffer size value should be passed to win32 api function setvbuf, testing return value. If fails, fall back and use DEFAULT_BUFFEREDFILE_BUFFER_SIZE as buffer size. - - The name of the file to open - True if opening file for write. If opening for read, the buffer size will be clamped to the file size - - whether to potentially override defaultBufferSize value with environment variable / ini file setting - The default buffer size in bytes - - - - Create a character with a single-byte Active Code Page character. - This constructor is best used with a compile-time constant because if you specify a only the first half of a DBCS character this function will throw an exception. - - - - - Create a character using a UCS4 character. - We specified "explicit" because "unsigned int" are so generic that we didn't want to construct a "Char" implicitly by mistake. - - - - - Determine if the UTF-8 string is valid. - True if the string is a valid UTF8, False otherwise - - Buffer pointer to validate encoding of - Size of the buffer to validate - If not null, returns if the presence of multi-bytes character was found. - If not null, returns if the number of bytes missing for the last character. The beginning was correct, but it missed the ending. - - - - Determine the length of an UTF-8 character. - length of the character in bytes. - - UTF-8 character to get the length of - - - - Determine if the UTF-16 char is a lead character. In some situation, UTF-16 can be stored on four bytes instead of two. - True if the character is a lead character, False otherwise - - Character to test - - - - Construct a new empty character accumulator. - - - - - Construct this iterator with a NULL pointer. - - - - - Construct this iterator with a string pointer. - - - - - Copy an existing character iterator. - - - - - constructor with a specific message. - - - - - Copy Constructor. - - - - - Create a named Mutex using the lower case filename with back slashes converted to forward slashes, and attempt to acquire the Mutex for the specified period of time. - - - - the filename used to form the named Mutex's name. Note that if the filename is null, a mutex isn't created or acquired. - the length of time in milliseconds to attempt to acquire the Mutex. - - - - Copy Constructor The implementation of this function can be considered cheap in processor and memory usage. As long as both objects aren't changed, they will share the same reference. All 's members that modify this object will perform a copy before modifying the data if it's referenced several times. - - - - - Construct a that will contain a copy of a string passed in. - - A new instance - - - The code page of the string that is passed in - - The string to copy - - The length of the string that is passed in. Use this when the string length is already known. Doing so will increase performance. - - - - Construct a from an Active Code Page encoded string - - A new instance - - - The string to copy - - The length of the string that is passed in. Use this when the string length is already known. Doing so will increase performance. - - - - Construct a from a UTF8 encoded string - - A new instance - - - The string to copy - - The length of the string that is passed in. Use this when the string length is already known. Doing so will increase performance. - - - - Construct a from a UTF16 encoded wide string - - A new instance - - - The string to copy - - The length of the string that is passed in. Use this when the string length is already known. Doing so will increase performance. - - - - Construct a from a UTF32 encoded wide string - - A new instance - - - The string to copy - - The length of the string that is passed in. Use this when the string length is already known. Doing so will increase performance. - - - - Generate a out of Win32 error code. - - - - - Generate a out of an ANSI error code. ANSI error codes are used principally when using the standard C libraries functions. Implemented using the strerror function. - - - - - Normalize the code page. Will resolve encoding aliases and returns their meaning. - The new code page value - - - The code page value to convert. CP_ACP (Active Code Page), returns GetACP(). CP_OEMCP (BIOS's Code Page), returns GetOEMCP(). CP_MACCP CP_THREAD_ACP (Current thread's Code Page). Calls GetLocaleInfo(). - - - - Gets a common code page. Determine the ideal intermediate codepage between two others to perform operation like string compare, string concatenate, etc. - - - - - - - - - Construct a out of a BSTR. - - - - - Construct a out of a OLESTR. - - - - - Default constructor - creates an empty path. - - - IsEmpty() returns true. - - - - - Construct a path from a path-filename string. - - - - path & filename as a string from which to construct a path object. - - - - Copy construct a from another. - - - This performs a deep copy. Subsequent operations on this path will not affect the copied path and vice versa. - - The path to copy. - - - - Construct the . - - - - - Calculates and returns the average overhead associated with Start/Stop and Pause/Resume. - - - Each paired call of Start/Stop and Resume/Pause imposes some overhead. The overhead is mainly the time associated with 2 calls to QueryPerformanceCounter. On average, the overhead is small (~ 1.6E-5 msec), but this can be significant if Pause/Resume is called many, many times while measuring something that runs very fast. The actual time associated with 2 calls to QueryPerformanceCounter is noisy, and it is not practical to correct for this overhead in the code. Thus it is the responsibility of the client code to handle this if need be. Example: - The average overhead of calling Start/Stop and Pause/Resume. - - The number of loops calling Pause/Resume to average overhead over. - - - - Initializes all members to zero, an invalid empty buffer. - - - - - Constructor. mData, mNumElements, and mStride are initialized to the values specified. - - - - initial value for mData - - initial value for mNumElements - - initial value for mStride - - - - Constructor - - - The string to pass to . - - - - Constructor. - - - - - Returns the interface. - - - - - Returns the class ID for the physical camera plugin. - - - - - The constructor enables an option, on the physical camera, which further calls to Object::Eval() ignore the tilt/shift feature. - This constructor also invalidates the node's object cache to ensure that further evaluations will behave correctly. - - The node which potentially evaluates to an object. It is OK to pass a null pointer, or a node which refers to an object that is not an . - The time at which the object is evaluated. While this call is not dependent on any animated parameters, it is preferable to pass the time value at which the renderer will be evaluating the camera, for efficiency purposes. - - - - Returns the class ID for the physical camera exposure control plugin. - - - - - Constructs the sampler using the parameter values extracted from and a callback interface used for fetching values from the aperture bitmap. - - The interface which provides access to contents of the aperture bitmap. - The physical camera's aperture center bias, as returned by . - Whether the aperture bitmap affects exposure, as returned by . - - - - Returns the only instance of this manager. - - - - - Returns the class ID for the Sun Positioner object plugin. - - - - - Get the single instance of the plugin package manager. - - - - - Constructor. - - - - The reference to hold. - - - - Constructor for a . - - The target . - The Animatables client (parent) in the scene. Important because most things only make sense in context with its parent. - Which sub 'a' is in 'c' such that: c->SubAnim(s) == a. - - - - Default Constructor - - - - - Copy Constructor - - - - - Constructor. - - - - - Constructors. - - - - - Create a MaxGuild value with random guid value. - - - - - Converts a string representation of a guid value to a guid value. - - - True if null or an empty string, or if string could be converted to a guid value. - - The string representation of a guid value. If null or an empty string, a guid value corresponding to an invalid guid is used and the function returns true. - The value to set. - If false and pString is not a proper string representation of a guid value, a guid value corresponding to an invalid guid is used and the function returns true. If true and pString is not a proper string representation of a guid value, a MaxException is thrown. - - - - Sets Scripting log file to specified file. - - - - true if the listener log file was created, false otherwise. - - - The fully qualified path for the listener log file - - The file open mode specification, typically "w" or "a". See the Help file, topic Values, for a description of the mode string values. Note that this method automatically adds 't' to the specified mode string. - - - - Gets the Scripting log file name if present. - - - - true if a listener log file name was acquired, false otherwise. - - - Returns the fully qualified path for the listener log file - - - - Test whether the specified ScriptingFeature can be executed. - - - This function checks to see whether the specified ScriptingFeature can be executed. The specified ScriptingFeature is disabled in the following cases: - - - - - Validate whether MAXScript system commands can be executed. - - - This function checks to see whether MAXScript system commands can be executed, and if not throws an exception. MAXScript system command execution is disabled in the following cases: - - - - - Validate whether MAXScript system commands can be executed. - - - This function checks to see whether MAXScript system commands can be executed, and if not throws an exception. MAXScript system command execution is disabled in the following cases: - - - - - Validate whether Python scripts can be executed. - - - This function checks to see whether Python scripts can be executed, and if not throws an exception. Python script execution through the python MAXScript interface is disabled in the following cases: - - - - - Validate whether Python scripts can be executed. - - - This function checks to see whether Python scripts can be executed, and if not throws an exception. Python script execution through the python MAXScript interface is disabled in the following cases: - - - - - Create string representation of argument list. - - - This function creates a string representation of the specified argument list. Note that this can be a fairly expensive call, and should only be called when necessary. This function would be typically be used in code that is a standard MAXScript primitive implementation. For example: - - - The list of arguments. - - The count of arguments in arg_list. - - - - Returns the NodeKey for a node object. Returns a node's key value, which is the AnimHandle for the node object. - - - The node's key value. - - The node object. - - - - Returns a node object from a NodeKey. Returns a node object from its key value, which is the AnimHandle for the node object. - - - The node object. - - The node's key value, which is the AnimHandle for the node object. - - - - Returns the base product registry key: "SOFTWARE\<Company Name>\<Product Name>\<version>". - - - Returns the base registry key. The application uses this key as the base for storing registry settings. A plugin can choose to store registry settings under the base (preferably in a subkey group), but likely will want store its registry settings under its own company root. Combines calls to GetRegistrySoftwareBase(), GetCompanyName(), GetProductName() and GetVersion(). Note: Tailing backslash is not appended. - base-key in this format: "SOFTWARE\<Company Name>\<Product Name>\<version>" - - - - - Returns the base company registry key: "SOFTWARE\<Company Name>". - - - Returns the base company registry key. This key in general should be used to store registry key settings. Combines calls to GetRegistrySoftwareBase(), GetCompanyName(). This is useful when we need to access registry settings for other Autodesk applications. Note: Tailing backslash is not appended. - base-key in this format: "SOFTWARE\<Company Name>" - - - - - Returns the software base (i.e. SOFTWARE - should be static from release to release.) - - - Returns the software base (i.e. SOFTWARE - should be static from release to release.) - - Returns the software base (i.e. SOFTWARE - should be static from release to release.) - - - - - Returns the company name (i.e. Autodesk). Mainly for branding purposes. - - - Returns the company name (i.e. Autodesk). Mainly for branding purposes. - - - - - Returns the product name (i.e. 3dsmax). - - - Returns the product name (i.e. 3dsmax). - - - - - Returns the current release-number (major, minor release: #.#). - - - Returns the current release-number (major, minor release: #.#) - - - - - Returns the true/false value of an environment variable. - - - Returns the true/false value of a specified environment variable, or the specified default value if the environment variable does not exist or the first character of its value is not one of "yYtT1" (true) or "nNfF0" (false) - Returns the true/false value of the environment variable or default - - Pointer to a null-terminated string that specifies the name of the environment variable - The default value used if the environment variable is not present, or doesn't contain a valid value - - - - Display a warning telling the user the application is out of memory. - - - - - Displays a warning telling the user the application is out of memory. Overloaded method that displays an extra message, and returns a value indicating if the user doesn't want to see this message again. - - - - true if the user checked that they don't want to show this warning, false otherwise. - - - An additional message - - - - Constructor - - - - - Constructor. Builds an adjacency list from the specified mesh. This class require the mesh to be constructed so that each edge has exactly one or two faces. - Parameters: - & amesh - - The mesh to build the adjacency list from. BOOL& bTemp - - Indicates if the edgeList is temporary, resulting in less time cleaning up/conserving memory - - - - - Constructor. The face indices are set to UNDEFINED. - - - - - Constructor. The mesh and edge list passed define the mesh used to construct the face list. - - - - - Constructor. No initialization is performed. - - - - - Constructor. The is initialized from the specified values. - Parameters: - float x - - The x component of the axis. - - float y - - The y component of the axis. - - float z - - The z component of the axis. - - float ang - - The angle component in radians. - - - - - Constructor. Data members are initialized to the specified values. - - - - - Constructor. Data members are initialized equal to the specified . - - - - - Constructor. The is initialized with the rotation from the specified matrix. - Parameters: - & m - - The rotation used to initialize the . - - - - - Clears one or more bits in the flags in all Animatables. - - - - The bits to turn off in the flags - - - - Clears one or more bits in the extended flags in all Animatables. - - - - The bits to turn off in the extended flags - - - - Requests an unique flag bit index. - - - The flag bit index is used with the Animatable::TestFlagBit(), Animatable::SetFlagBit(), Animatable::ClearFlagBit(), and Animatable::ClearFlagBitInAllAnimatables() methods. The flag bit index must be released using the Animatable::ReleaseFlagBit() method. The intended usage of the flag bit index is in enumerations where you want to visit each only once, and the usage of the flag bit is of a temporary, short term usage. The flag bits are not saved with the , nor copied via the assign operator. The flag bits referred to for these methods are not associated with the aflag or aflag_ex data members. After calling this method call ClearFlagBitInAllAnimatables to clear the flag in all Animatables before starting to use the flag bit. - The unique flag bit index - - - - - Releases the flag bit index. - - - - The flag bit index to release - - - - Clears the specified flag bit in all Animatables. - - - - The flag bit index to clear - - - - Debug method to determine whether an object has been deleted. - - - This method checks whether an object is alive in memory, or is deleted and is a dangling pointer. The check is not perfectly accurate. A result of TRUE is guaranteed to be accurate - the object is deleted - however a result of FALSE may be inaccurate. This method should be used together with other tools to aid in debugging and bulletproofing. - Returns TRUE if the object is invalid, FALSE if state is uncertain - - The object - - - - Get the unique handle for an object. - - - Every is given a handle value when allocated. The values are unique within a scene, but are not saved with the scene, and no guarantees are provided about handle values from one load to another. Handles are intended for use as sort/hash keys, when load and save are not required. They are safer than pointers, since the may be deleted, in which case the handle value is never reused for another within the current session, and searching for the via GetAnimByHandle() simply yields NULL. - The unique handle value for the - - The object - - - - Get an object from its unique handle. - - - Every is given a handle value when allocated. The values are unique within a scene, but are not saved with the scene, and no guarantees are provided about handle values from one load to another. Handles are intended for use as sort/hash keys, when load and save are not required. They are safer than pointers, since the may be deleted, in which case the handle value is never reused for another within the current session, and searching for the via GetAnimByHandle() simply yields NULL. - The object, or NULL if the has been deleted, or if the handle is invalid - - The unique handle value for the - - - - Get the unique handle for the next object to be created. - - - Every is given a handle value when allocated. This method returns the handle value that will be used for the next animatable created. This method is primarily intended for testing purposes, in particular for detecting if calling ClassDesc::Create() is creating an Animatable-derived object. - The unique handle value for the next created - - - - - Get the number of existing objects. - - - - - Get a list of existing objects. - - - - - Enumerator to enumerate across all animatables. - - - Implemented by the System. The Animatables are enumerated in order of creation. Use Animatable::EnumAnimTree when the enumerating the Animatables based on their hierarchy is required. EnumerateAllAnimatables is designed to be safe with recursive calls to EnumerateAllAnimatables, and is designed to be safe when Animatables are added/deleted during an enumeration. - - - The callback object called for each animatable. - - - - Constructor. - - - Suspends the "animate" mode, and optionally some other system states - - - If TRUE, macro recording is also suspended, otherwise it's not changed. See for more information. - - If TRUE, "setkey" mode is also suspended, otherwise it's not changed. See for more information. - - If TRUE, passing of reference messages is also suspended, otherwise it's not changed. See for more information. - - - - Constructor. The data members are initalized to the values pased. - - - - - Constructor. - - - The data members are initialized to the values passed. - Important: Not allocating on the heap the data passed to this method may lead to unexpected behavior of the application. - Important: Client code does not need to free the data that has been passed to this method. The system will free it when the is deleted or when client code explicitly removes the custom data chunk from the by calling Animatable::RemoveAppDataChunk. - - - The of the owner of the custom data. - - The SuperClassID of the owner of the custom data. - - An extra ID that lets the owner identify its sub-custom-data (chunks). - - The length of the data in bytes. - - Pointer to the actual data. The data should be allocated on the heap by client code using . This will allow the system to free it safely (using MAX_free()). and MAX_free() are memory management routines implemented by the system. - - - - Constructor The length of the data buffer is set to 0 and the data pointer set to NULL. - - - - - Constructor. The resulting object should be initialized with one of the initialization methods. - - - - - Constructor. Initializes the to the RGBA color values passed. - - - - - Constructor. Initializes the to the RGBA color values passed (cast to float). - - - - - Constructor. Initializes the to the RGBA color values passed (cast to float). - - - - - Constructor. Initializes the to the passed, optionally specifying an alpha value. - - - - - Constructor. Initializes the color to the value passed. - Parameters: - float af[3] - - Specifies the color. r=af[0], g=af[1], b=af[2], a=af[3]. - - - - - Constructor. Initializes this from the 24 bit color value passed. - Parameters: - & c - - The 24 bit color to initialize from. - - - - - Constructor. Initializes this from the 32 bit color value passed. - Parameters: - & c - - The 32 bit color to initialize from. - - - - - Constructor. Initializes this from the 48 bit color value passed. - Parameters: - & c - - The 48 bit color to initialize from. - - - - - Constructor. Initializes this from the 64 bit color value passed. - Parameters: - & c - - The 64 bit color to initialize from. - - - - - Constructor. Initializes this from the floating point color passed. - Parameters: - & c - - The floating point color to initialize from. No conversion or scaling is done. - - - - - Constructor. - - - - - Constructor. - - - - - Constructor. - - - - - Constructor. - - - - - Register for ATS Notification Messages. - - - true if success, false if failure - - pointer to interface - client supplied pointer that will be returned with all notifications - - - - UnRegister for ATS Notification Messages. - - - true if success, false if failure - - pointer to interface - - - - Broadcast ATS Notification Message. - - - three values: kATSNotifyResultOk, kATSNotifyResultCancel, or kkATSNotifyResultStop. - - pointer to object - - - - Broadcast ATS Notification Message. - - - three values: kATSNotifyResultOk, kATSNotifyResultCancel, or kkATSNotifyResultStop. - - ID of notification message. An object will be created with the specified ID and Provder Index. - Index of provider. An object will be created with the specified ID and Provder Index. - - - - Constructor. - - - - - Constructor. - - - - - Constructor. - - - - - Computes the x and y components of a basis vector given a z component. The orientation of x and y are arbitrary and may be oriented at any angle about z. - - The input z orientation. - The resultant x orientation. - The resultant y orientation. - - - - The data members are initialized as follows: - - - - - - - Constructor. The shape is initialized based on the fromShape. - - - - - Constructor. The data members are initialized as follows: - - ready = FALSE; - - - - - Initializer. Sets m and n to zero, and val to NULL. - - - - - Initializer. Sets the dimensions of the matrix to mm by nn, and allocates space for the contents. The total size of the matrix, mm*nn, cannot exceed 10,000. - - - - - Initializer. Sets this equal to from. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. The alpha component is not copied. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. The alpha component is not copied. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Constructor. The following defaults are set by this constructor. - - The width = 640; - - The height = 480; - - The custom width = 320; - - The custom height = 200; - - The custom flags = BMM_CUSTOM_RESFIT | BMM_CUSTOM_FILEGAMMA; - - The custom gamma = 1.0f; - - The frame number = 0; - - The aspect ratio = 1.0f; - - The gamma setting = 1.0f; - - The name and device name are set to NULL. - - The looping flag = BMM_SEQ_WRAP; - - - - - Constructor. The defaults are set as above excepting the bitmap name is set. - Parameters: - MCHAR *n - - The bitmap file name is set. - - - - - Constructor. The defaults are set as above excepting the bitmap asset is set. - Parameters: - AssetUser &asset - - The bitmap file asset is set. - - - - - This method is available in release 3.0 and later only. - - Copy Constructor. - Parameters: - &bi - - The to copy from. - - - - - Constructor, disables bitmap proxies. - - If true, bitmap proxies are disabled. If false, nothing is done (the class is essentially disabled). This parameter is necessary to conditionally disable proxies. - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. The alpha component is not copied. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. The alpha component is not copied. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Implemented by the System. - - Converts in to out clamping the RGB components to 0 to 65535. - Parameters: - & out - - The result of the conversion. - - & in - - The value to convert. - - - - - Default constructor. Sets the number of bits to 0. - - - - - Constructor. - Parameters: - int i - - The size of the in bits. - - - - - Constructor. Duplicates the passed. - Parameters: - & b - - The to duplicate. - - - - - Constructs a object. The box is initialized such that it is 'empty'. See IsEmpty() below. - - - - - Constructs a object from the specified corners. - Parameters: - a - - The upper left corner of the box. - - b - - The lower right corner of the box. - - - - - Constructor. The box is set to empty initially. - - - - - Constructor. The corners of the box are initialized such that the box is 'empty' and 'uninitialized'. See IsEmpty() and IsInitialized(). - - - - - Constructor. The corners of the box are initialized to the points passed. pmin=p; pmax = q. - - - - - Constructor. The bounding box is set to empty. - - - - - Constructor. The bounding box is set to empty and the matrix is initialized to the matrix passed. - - - - - Constructor. The description string is set to NULL, the capabilities are set to NONE, and the Class Descriptor is set to NULL. - - - - - Constructor. The flag that indicates that the list has been built is set to FALSE. - - - - - Retrieves the sole instance of class . - - - - - Constructor. - - Assigns a value of 0xFFFFFFFF to each 32-bit quantity. - - - - - Constructor. - - Creates a new class ID with the same values as the argument. - Parameters: - & cid - - A reference to the Class ID to copy. - - - - - Constructor. - - This is the standard constructor to be used by 3ds Max plug-ins. Each of the 32-bit quantities may be assigned separately. - Parameters: - ulong aa - - Assigned to the first 32-bit quantity. - - ulong bb - - Assigned to the second 32-bit quantity. - - - - - Constructor. - - - - - Constructor. The resulting object should be initialized with one of the initialization methods. - - - - - Constructor. Initializes the to the RGB color values passed. - Parameters: - float R - - Specifies the red component of the color. - - float G - - Specifies the green component of the color. - - float B - - Specifies the blue component of the color. - - - - - Constructor. Initializes the to the RGB color values passed. - Parameters: - double R - - Specifies the red component of the color. - - double G - - Specifies the green component of the color. - - double B - - Specifies the blue component of the color. - - - - - Constructor. Initializes the to the RGB color values passed. - Parameters: - int R - - Specifies the red component of the color. - - int G - - Specifies the green component of the color. - - int B - - Specifies the blue component of the color. - - - - - Constructor. Initializes the to the value of the passed. - Parameters: - p - - Specifies the color. r=x, g=y, b=z. - - - - - Constructor. Initializes the color to the value passed. - Parameters: - float af[3] - - Specifies the color. r=af[0], g=af[1], b=af[2]. - - - - - Constructor. Initializes the color to the structure passed. - Parameters: - rp - - Specifies the format to convert. - - - - - Constructor. Initializes this from the 24 bit color value passed. - Parameters: - & c - - The 24 bit color to initialize from. - - - - - Constructor. Initializes this from the 32 bit color value passed. - Parameters: - & c - - The 32 bit color to initialize from. - - - - - Constructor. Initializes this from the 48 bit color value passed. - Parameters: - & c - - The 48 bit color to initialize from. - - - - - Constructor. Initializes this from the 64 bit color value passed. - Parameters: - & c - - The 64 bit color to initialize from. - - - - - Constructor. Initializes this from the floating point color passed. - Parameters: - & c - - The floating point color to initialize from. No conversion or scaling is done. - - - - - Calculates the chromacity of a black body radiator at a given temperature in kelvins. - An RGB value, converted from a CIE XYZ color with the calculated chromacity and provided intensity. - The returned color components is guaranteed to have positive values, but may exceed 1.0. - - The black body temperature in kelvins. - The intensity of the color to be generated (the luminance Y of the CIE XYZ color from which the RGB color is converted). - - - - Constructor. - - - - - Constructor. The data members are initialized as follows: next=NULL; distance=0; - - hitInfo=0; nodeRef=NULL; - - - - - Constructor. The data members are initialized to the data passed. - - - - - Constructor. The data members are initialized to the parameter passed. - - - - - Constructor. - - - - - Points to the RefereceTarget whose dependents are iterated through. - - - - Verifies the validity of the specified plug-in DLL version. The supplied version number is valid if it identifies a 3ds Max SDK version that is binary compatible with the one used to compile the instance of 3ds Max that is being asked to validate this version number. - True if the supplied plug-in DLL version number corresponds to a plug-in DLL that is binary compatible with the instance of 3ds Max that is currently used. - - The plug-in DLL version to validate. This is a value returned by the plug-in DLL's LibVersion() function. - - - - Retrieves the sole instance of class . - - - - - Constructor. The graphics window pointer is set to NULL. - - - - - Constructor. The graphics window pointer is set to g. - - - - - Constructor. - - Each instance created is kept in the clipFmts table - - - - - This method returns a pointer to the (singleton) corresponding to the clip format in the given IDataObject, or NULL if the IDataObject contains no recognizable formats. This is primarily used by the low-level default DragEnter() function in drag and drop manager. - Parameters: - IDataObject* pDataObject - - The data object you wish to return the clip format for. - - - - - This method clears the currently-parsed drop data. - Default Implementation: - { current_dataobject = NULL; loaded = false; } - - - - - Constructor. The size of the object is set to a minimal value, and the color of the object is initialized to (0.6f, 0.8f, 1.0f); - - - - - Constructor. The corners of the box are initialized such that the box is 'empty'. See - - - - - Constructor. The corners of the box are initialized to the points passed. - - The first corner of the box - The second corner of the box - - - - Constructor. Matrix is initialized to Identity. - - - - - Constructor, Unused. The default constructor now initializes the matrix to identity. Kept for backward compatibility. - - - - - Constructor. Initializes the matrix with the row data passed and validates the matrix flags. - - The data for row 0. - The data for row 1. - The data for row 2. - The data for row 3. - - - - An global instance of set to the identity. An identity matrix has no rotation, scale or translation on it. In other words, it is a matrix that has no effect when multiplied with another matrix. - the structure of the Matrix is as follows: - - [1, 0, 0] - [0, 1, 0] - [0, 0, 1] - [0, 0, 0] - - - - - Constructor. Data members are initialized to X and Y. - - - - - Constructor. Data members are initialized to a.x and a.y. - - - - - Constructor. Data members are initialized as x = af[0] and y = af[1]. - - - - - Initializes all vector components to zero. - - - - - Constructor. x, y, and z are initialized to the values specified. - - - - - Constructor. x, y, and z are initialized to. af[0], af[1], and af[2] respectively. - - - - - Constructor. - - - - - Constructor. - - Creates an edge cluster list from the current selection. All adjacent selected edges are grouped into the same cluster. - Parameters: - &mesh - - The mesh associated with this . - - &esel - - The bit array containing the edge selection data for the mesh. - - &adj - - The adjacent edge list for the mesh. - - - - - Constructor. - - - Construct the - - The virtual base class that needs to get implemented. - The that's internally used to change the foreground procedure. - - - - The interface ID of class , used in combination with the mechanism to retrieve a Effect8* from a Effect*. - - - - - Converts an & to an Effect8*, if possible. May return NULL if the does not derive from class . - A pointer to interface , if implemented by the effect. - - - The effect for which you want to retrieve the interface. - - - - Checks whether the given effect supports the given bitmap. By default, all Effects which do not implement only support 16bits-per-channel bitmaps with alpha (BMM_TRUE_64). The reason for this is that, prior to Max 8, this was the only type of bitmap ever used for render output. With Max 8, 32bit floating-point bitmaps may be created. - true if the given effect supports the given bitmap, false otherwise. - - - The effect which you want to test for compatibilty. - - The bitmap which you want to test for compatibility. - - - - Constructor. - - - - - Constructor. Internal data structures are initialized as empty. - - - - - Constructor. The smoothing groups and face flags are initialized to zero. - - - - - Constructor. The flags and f are set to 0. - - - - - Constructor. The data members are initialized to the values passed. - Parameters: - DWORD ff The index of the face to change. This is a zero based index into the 's faces array. DWORD fl The flags to set. DWORD v The value to set. - - - - - Constructor. This version separates clusters using a minimum angle and optionally the selection set. A developer creates one of these cluster lists by specifying the mesh, the face list and an angle. What is built is a cluster number for each face identifying what cluster it is in. - - For example, if you create one of these for a sphere and set the angle threshold to 90 degrees, you would get back one cluster, and the cluster id for everything would be 0. If you ran it on a box, and you set the angle to < 90 degrees, you would get back 6 ids. Two faces in the box would have id 0, two would have id 1, etc. - Parameters: - *mesh - - The mesh to create the list for. - - & adj - - The face list for this mesh. - - float angle - - The maximum angle (in radians) that can be used in joining adjacent faces into the same cluster. - - BOOL useSel - - If FALSE, selection is ignored and all faces are grouped into clusters by angle. If TRUE, only selected faces are grouped into clusters, but angle is still relevant. Non-selected faces will have UNDEFINED for their id. - - const Point3* faceNormals - - Optional optimization parameter to pass in a precomputed face normal list. - - - - - - - Constructor. This version separates clusters using the selection set. In this case a cluster is defined as a set of faces that are selected and are adjacent. For example you could have a sphere with some faces selected on one side, and another group of faces selected on the other side. Each group of adjacent and selected faces would comprise clusters within the mesh. This is used for example by the axis tripods in 3ds Max where each selected group of faces gets their own coordinate system. - - In this case the unselected faces will not be in any cluster. These store the value UNDEFINED for their id. - Parameters: - & fsel - - This bit array defines the face selected state that the clusters will be grouped by. Each bit in the bit array corresponds to the parallel index in the mesh face table. - - & adj - - The face list for this mesh. - - - - - Constructor. Constructor. Initializes data members to the values passed. - - - - - Constructor. Constructor. Initializes face to the value passed, and initializes original to UNDEFINED. - - - - - Constructor. Constructor. Initializes original to the value passed. Does not initialize the face data member. - - - - - Constructor. Initializes original to UNDEFINED. Does not initialize the face data member. - - - - - Copy Constructor Constructor. Initializes data members to match those in fc. - - - - - Constructor. - Parameters: - &mesh - - The mesh that the element list is being built for. - - & af - - The face list for the mesh. - Operators: - - - - - Constructor. The flags and f are set to 0. - - - - - Constructor. - - - The face to remap. - - The flags to set. - - The array of vertex indices. - - - - Constructor. The flags and f are set to 0. - - - - - Constructor. The data members are initialized to the values passed. - - - - - This method clears the currently-parsed drop data. - Default Implementation: - DropType::Init(); } - - - - - This method finds and returns the subclass corresponding to the given filename suffix. See DropTypes for more details. - Parameters: - MCHAR* filename - - The filename suffix. - - IDataObject* pDataObject = NULL - - A pointer to the IDataObject. - The that corresponds to the filename suffix. This could be one of the following; sceneFileDropType, imageFileDropType, importFileDropType, dropScriptFileDropType. - - - - - This method serves as a utility function that can be used to download a package of URLs to the specified directory. If the hwnd argument is supplied, any progress or other messages are centered over that window. - Parameters: - & package - - A reference to the local copies of the URL strings. - - MCHAR* directory - - The directory path string to download to. - - HWND hwnd = NULL - - A handle to the window. If this is set to NULL, the default 3ds Max window is used. - - bool showProgress = false - - The download progress dialog can be displayed by passing true. - TRUE if the download was successful, otherwise FALSE. - - - - - This method returns the fully-specified path to the directory in which package drops are downloaded. - - - - - This method allows you to download the file referenced by the URL to disk. - Parameters: - HWND hwnd = NULL - - A handle to the window. - - MCHAR* url - - The URL string of the file to download. - - MCHAR* fileName - - The filename string of the URL to store on disk. - - DWORD flags=0 - - Additional controls to the download behavior. Currently only one flag is supported, DOWNLOADDLG_NOPLACE, which hides an option in the progress dialog that allows the user to place (move) a dropped object immediately after being dropped. - TRUE if the download was successful, otherwise FALSE. - - - - - Constructor. - - - - - Constructor. Sets FlagUserFlags to 0, clearing all flag bits. - - - - - Constructor. The frameDuration is set to 1.0 and relSubFrameDuration = 1.0f. - - - - - Constructor. The flag that indicates the list of filters has been built is set to FALSE. - - - - - Constructor. - - This will initialize the members to their empty default values. - - - - - Constructor. The data members are initialized as follows: - - flags = 0; description = 0; action_def = NULL; enumID = FP_NO_ENUM; - - - - - Constructor. No initialization is performed. - - - - - Constructor. - Parameters: - id - - The unique ID of the interface. - - MCHAR* int_name - - The fixed internal name for the interface. - - StringResID descr - - A string resource ID containing the description for this interface class. - - ClassDesc* cd - - A pointer to a class descriptor of the publishing plug-in. - - ULONG flag - - The flag bits. One or more of the following values: FP_ACTIONS, FP_MIXIN, FP_CORE, FP_STATIC_METHODS, FP_SCRIPTED_CLASS, FP_TEMPORARY. For a description see the data members descriptions. - - ... - - This constructor takes a variable number of arguments representing the 'properties' sections and function definitions. For more information see the advanced topics on ~{ Function Publishing }~. - - - - - Constructor. - - - - - Constructor using variable args. This method takes a variable number of arguments representing the parameter values that will be stored in the params table. - - - The number of parameter values to add. - - - - Constructor. - Default Implementation: - { description = 0; options = NULL; flags = FPP_IN_OUT_PARAM; enumID = FP_NO_ENUM; } - - - - - Constructor. - - - - - Constructor. The data members are initialized as follows: - - flags = 0; description = 0; getter_ID = setter_ID = FPS_NO_SUCH_FUNCTION; enumID = FP_NO_ENUM; options = NULL; - - - - - Constructor - Default Implementation: - Init(); } - - - - - Copy Constructor. - Parameters: - & from - - A reference to a to copy from. - Default Implementation: - Init(); *this = from; } - - - - - Constructor - Default Implementation: - {va_list ap; va_start(ap, type); ap = Loadva(type, ap); va_end(ap);} - - - - - Returns true if the data associated with the type is represented by a pointer. If the type is a TAB type, whether the data in the is represented by a pointer. - - - bool - True if the 's data, or the 's data if a TAB type, is a pointer - - - The ParamType2 type to test. - - - - Constructor. - - - - - Constructor. The hierarchy is set as initially empty. - - - - - Constructor. The private data members are inialized to the values passed and the corresponding Get methods of this class will return these data members. - - The name for this sub-object type. - The BMP imagelist file name prefix for this sub-object type. This is the file name, without the extension, and with the assumption that the file is in the ui/icons directory. For example specifying _M("SubObjectIcons") for this parameter indicates the file UI/icons/SubObjectIcons_16i.bmp if the small icons are in use and SubObjectIcons_24i.bmp if the large icons are in use. - This is the one based index into the image list of the icon to use. - - - - This constructor assumes that the icons are in either UI/icons/SubObjectIcons_16i.bmp or SubObjectIcons_24i.bmp depending on which size icons are in use by the system. In this case only the index into the image list is required. - - This is the one based index into the image list of the icon to use. - - - - Constructor. - - - - - Constructor. - - - - - Constructor. - Default Implementation: - { mLine.Init(); } - - - - - Constructor; disables global reference makers. - - - A boolean parameter may be used to conditionally have this class do nothing. - - - When true, this class will disable the global reference makers. When false, this class does nothing. - - - - Determines whether global reference makers are currently disabled. - true if global reference makers are disabled; false otherwise. - - - - - Gives the color corresponding to the id in the input. This function represents the color-id mapping that is done for - Parameters: - id - - The material or object id for which the color is wanted - - cOut - - The output color type. - - - - - Default constructor, set Identity matrix. - - - - - Constructor from a . - - - - - Constructor. - - - - - Constructor. - - - - - Constructor. The entry is initialized as empty. - - - - - Constructor. The entry is initialized to the data passed. - Parameters: - int d - - The value for data. This is the polygon number. - - *p - - The parent pointer is initialized to this value. - - *s - - The sibling pointer is initialized to this value. - - - - - Constructor. This does not call the Init() method, so wrapper must still be initialized before it can be used. - - - - - Constructor. The list of HitRecords is set to NULL. - - - - - Constructor. The number of points is set to zero and the point list is set to NULL. - - - - - Constructor. The number of points and the points are initialized from the passed. - Parameters: - & h - - The to init from. - - - - - Constructor. The number of vertices is set to the value n passed and the points array is allocated with that size. This is the constructor that plugin developers will typically use in conjunction with the setVert() method described below. - Parameters: - int n - - The number of points to allocate. - - - - - Default Constructor. Initializes all members to NULL. - - - - - Constructor. The data members are initialized to the data passed. - - - - - Constructor. The data members are initialized to the data passed. - - - - - constructor - - - - - Constructor. The matrix is initialized to the identity matrix. There is also a global instance of this class available for use: extern idTM; - - - - - Constructor. - - - - - Constructor - Suspends scene redraw. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - The ID for this interface. Pass this ID to Interface::GetInterface to get an pointer. - - - - - Constructor. The two parts of the ID are initialized to 0xffffffff. - - - - - Constructor. The two parts of the ID are initialized from the corresponding parts of the passed. - Parameters: - & iid - - The ID whose parts are used to initialize this ID. - - - - - Constructor. The two parts of the ID are initialized from the from the parts passed. - - - Parameters: - ulong aa - - Passed to initialize the first part of the ID. - - ulong bb - - Passed to initialize the second part of the ID. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor that assigns both the start and end times of the interval. If TimeValue e is less than - - TimeValue s the values are swapped before they are assigned. - Parameters: - TimeValue s - - Specifies the start time. - - TimeValue e - - Specifies the end time. - - - - - Constructor that returns an EMPTY interval, i.e. having a start and end time equal to TIME_NegInfinity - - - - - The ID for the interface. - - - - - Retrieves the interface from an object - - Pointer to the interface of the object or NULL if the object does not support the animation track interface - - - Pointer to an object - - - - Gets the Biped interface. - - - the Biped interface Gets the Biped interface - - - the whose Biped interface is returned - - - - Gets the Biped interface. - - - the Biped interface - - - the whose Biped interface is returned - - - - If the supports the interface, returns a pointer to it. - - a pointer to an IContainer interface, or NULL. - - - to be tested for support of the IContainer interface - - - - If the supports the interface, returns a pointer to it. - - a pointer to an interface, or NULL. - - - to be tested for support of the interface. - - - - If the supports the interface, returns a pointer to it. - - a pointer to an interface, or NULL. - - - to be tested for support of the interface. - - - - Returns an instance of the interface. - - - - - Retrieves the single instance of the Daylight system factory. - - - - - Access to the singleton. - - - - - Returns the only instance of this manager. - - - - - Create instance of 3ds Max's implementation of class. - - - The created instance. - - - - - Retrieves the single instance of the instance manager. - - - - - Retrieves the single instance of the Daylight system factory. - - - - - Retrieves the single instance of the ICEFlowParticleFactory. - - - - - Retrieves the single instance of the . - - - - - Constructor. The time and flags are set to zero. - - - - - If the supports the interface, returns a pointer to it. - - a pointer to an interface, or NULL. - - - to be tested for support of the interface - - - - Constructor. - - - - - Retrieves the single instance of the Main thread task Manager. - - - - - Does the material support a specific shading model in viewport. This will be used to enable\disable the SMIV options. - if the shading model is supported, return true; otherwise return false - - The material you want to test. If the material does not support interface, then only standard shading model is supported. - The shading model, for now it must be Standard or Hardware. - - - - Used to query the material for its current level of viewport rendering - current shading model. - - The material you want to get shading model from. If the material does not support interface, then the function will return Standard shading model. - - - - the shading model of the material in viewport and update the UI of material editor. - If the shading model is set successfully, return true; otherwise return false. - - The material you want to set its shading model. If the material does not support the shading model, the function will fail. - The shading model, must be Standard or Hardware. - - - - The map levels needs to be defined by the material, it will tell the various shader compilers how far to go in the search of materials/maps. Most materials will stop searching after one level, as the shader becomes too complex. For example specifiying 1 will mean the first map found will be used e.g a in a diffuse slot. The compiler will not search any further for maps to support. In this case it will probably bake the submaps to textures and will not try to generate - shader code for these submaps. - How deep the shader compilers will go in the search of material/Maps in the tree. - - The material you want to get map levels from. If the material does not support interface, the function returns 1. - - - - Get the instance of . - - - the instance of . - - - - - Use this function to retrieve a pointer to the interface. - A pointer to the interface. May be NULL if the interface is not supported by this release. - - - The node on which you want to query the interface. - - - - Retrieves a pointer to the interface. - - - IObjXRefManager8* - pointer to the object xref manager - - - - - Retrieves the interface from an . - - - - Pointer to the interface of the scene entity or NULL if it's not an xref record - - - Pointer to - - - - Returns the single instance of this manager. - - - Gets the single instance of this class. - The single instance of this class. - - - - - Returns the pointer to this interface. - - - - - Constructor. Data members are initialized to X and Y. - - - - - Constructor. Data members are initialized as x = af[0] and y = af[1]. - - - - - Initializes all vector components to zero. - - - - - Constructor. x, y, and z are initialized to the values specified. - - - - - Constructor. x, y, and z are initialized to. ai[0], ai[1], and ai[2] respectively. - - - - - Query this interface on a shade context. - - - - - Alternative for PFExport int NewRand(); but not in FnPub interface. - - - - - To read/modify the length/height of the wire nub extended from an emitter, or an action list, or a test. You must supply the node of the item. This method returns wire length. - - - - - Sets wire length. See GetWireExtension(). - - - - - Public classes only. - - - - - Public classes only. - - - - - The method is used by a PFlow module to register itself with the system. This way other PFlow modules can query whether a specific module is present/loaded with the system and act accordingly. Once a module is registered, it cannot be unregistered. - - - - - Returns true if a PFlow module was registered. - - - - - Create an instance of 3ds Max's implementation of class. - - - The created instance. - - Whether to hold the references as weak references - - - - Returns the wrapped . - - - The wrapped . - - The wrapper for which to potentially resolve the wrapped object. - - If true, the implementation should check to see if the wrapped derives from , and if so recurse into that object. - - - - Exported function to access the interface. - - - - - Exported function to access the interface. - - - - - Access to the interface. A developer would use something like the following. It is exported in the RTMax.dll - Access to the singleton - - - - - Access to the interface. A developer would use something like the following. It is exported in the RTMax.dll - Access to the singleton - - - - - Constructor. The list is set to empty. - - - - - Constructor - - - that publishes this interface - - - - Method to obtain the interface pointer for a given . - - - Parameters: - & n - - The node having the transformation pose. - - - ISkinPose* - - A pointer to this interface class. - - - - - - - Test if the filter will accept the passed tab. - - - The value can be a combination of TAB_DIALOG_REMOVE_TAB and TAB_DIALOG_ADD_TAB - - - The filter to compare tab against - - The dialog tab being filtered - - - - Determines whether it is safe to cast an to an . - - - true if the specified animatable can be safely cast to , false otherwise. - - - The animatable to test. - - - - Retrieves the interface from a scene entity. - - - - Pointer to the interface of the scene entity or NULL if it's not an xref atmospheric - - - Reference to scene entity - - - - Determines whether it is safe to cast an to an . - - - true if the specified animatable can be safely cast to , false otherwise. - - - The animatable to test. - - - - Retrieves the interface from a scene entity. - - - - Pointer to the interface of the scene entity or NULL if it's not an xref controller - - - Reference to scene entity - - - - Allows to determine whether a scene entity implements this interface. - - - - true if the scene entity implements the interface, false otherwise - - - Reference to scene entity - - - - Retrieves the interface from a scene entity. - - - - Pointer to the interface of the scene entity or NULL if it's not an xref item - - - Reference to scene entity - - - - Determines whether it is safe to cast an to an . - - - true if the specified animatable can be safely cast to , false otherwise. - - - The animatable to test. - - - - Retrieves the interface from a scene entity. - - - Pointer to the interface of the scene entity or NULL if it's not an xref material - - - Reference to scene entity - - - - Retrieves the interface from a scene entity. - - - Pointer to the interface of the scene entity or NULL if it's not an xref material - - - Reference to scene entity - - - - Allows to determine whethe a scene entity implements this interface. - - - - true if the scene entity implements the interface, false otherwise - - - Reference to scene entity - - - - Retrieves the interface from a scene entity. - - - - Pointer to the interface of the scene entity or NULL if it's not an xref object - - - Reference to scene entity - - - - Allows to determine whethe a scene entity is implements this interface. - - - - true if the scene entity implements the interface, false otherwise - - - Reference to scene entity - - - - Retrieves the interface from a scene entity. - - - - Pointer to the interface of the scene entity or NULL if it does not support the proxy feature - - - Reference to scene entity - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to those of the JointParam passed. - - - - - Constructor. The data members are initialized to the values passed. - Parameters: - DWORD type=JNT_POS - - The type, which corresponds to the JointParams::flags parameter. - - int dofs = 3 - - The degrees of freedom for the joint. - - float s = 1.0f - - The scale factor. - - - - - Constructor. The data members are initialized to those of the passed. - - - - - Constructor. The data members are initialized to those of the passed. - - - - - Constructor - - - - - Returns the interface for a custom attribute. - - - attrib is non-null - The interface to attrib, or NULL if attrib doesn't support the interface. - Returns NULL if the interface is not present. - - - The custom attribute whose interface is desired. - - - - Constructor. The affectDiffuse and affectSpecular data members are set to TRUE. - - - - - Constructor. - - - - - Constructor. - - - - - Constructor. The data members are initialized as follows: - - label = tip = imageName = NULL; imageID = -1; - - - - - Constructor. This one is used for keyboard macro buttons (MB_TYPE_KBD). The data members are initialized to the values passed as shown: - - macroType=MB_TYPE_KBD; tblID=tID; this->cb=cb; cmdID=cID; imageID=imID; label=NULL; SetLabel(lbl); tip=NULL; SetTip(tp); imageName=NULL; SetImageName(imName); - - - - - Constructor. This one is used for macro script buttons (MB_TYPE_SCRIPT). The data members are initialized to the values passed as shown: - - macroType=MB_TYPE_SCRIPT; macroScriptID=msID; imageID=imID; label=NULL; SetLabel(lbl); tip=NULL; SetTip(tp); imageName=NULL; SetImageName(imName); - - - - - Disables compile of all the macros. - - - A is implicitly marked as used if an attempt is made to compile it while compiles are disabled. Calls to this method must be paired with a call to EnableCompiles. The used MacroEntrys are DisableCompiles batch compiled with a call to CompileUsed. Nested calls to DisableCompiles are allowed, with compiles disabled until the call to outermost EnableCompiles occurs. See for a class that disables compiles when instance created, and enables compiles when instance is deleted. - - - - - Enables compile of all the macros. - - - A is implicitly marked as used if an attempt is made to compile it while compiles are disabled. Calls to DisableCompiles must be paired with a call to this method. The used MacroEntrys are then batch compiled with a call to CompileUsed. Nested calls to DisableCompiles are allowed, with compiles disabled until the call to outermost EnableCompiles occurs. - - - - - Batch compiles the macros flagged as used by MarkAsUsed. - - - A can be explicitly marked as used, or implicitly marked as used if an attempt is made to compile it while compiles are disabled. This method causes the MacroEntrys marked as used to be batch compiled. The batch compile may be multithreaded, so this can be faster than compiling the MacroEntrys individually. - - - - - constructor - disables macroscript compiles - - - - - Constructor. Disables the macro recorder automatically. - - if true, immediately disable macro recorder. - - - - Constructor. - - - - - Constructor. This constructor method is used to initialize a polyshape manipulator. - Parameters: - PolyShape* mpShape - - The polyshape gizmo. - - DWORD flags - - Display and hit testing flags. - - & unselColor - - The color of the gizmo when unselected. - - & selColor - - The color of the gizmo when selected. - - - - - Constructor. This constructor method is used to initialize a mesh manipulator. - Parameters: - Mesh* pMesh - - The polyshape gizmo. - - DWORD flags - - Display and hit testing flags. - - & unselColor - - The color of the gizmo when unselected. - - & selColor - - The color of the gizmo when selected. - - - - - Constructor. This constructor method is used to initialize a marker manipulator. - Parameters: - MarkerType markerType - - The marker type. See the MarkerType enum. - - & position - - The marker position. - - DWORD flags - - Display and hit testing flags. - - & unselColor - - The color of the gizmo when unselected. - - & selColor - - The color of the gizmo when selected. - - - - - Constructor. This constructor method is used to initialize a text manipulator. - Parameters: - MCHAR* pText - - The text string for the manipulator - - & position - - The manipulator position. - - DWORD flags - - Display and hit testing flags. - - & unselColor - - The color of the gizmo when unselected. - - & selColor - - The color of the gizmo when selected. - - - - - Constructor. - - A pointer to the manipulator to use. - - - - Default Constructor. - - - - - Constructor. Sets all channels to false. - - - - - Constructor. Sets all channels to the given default value. - - - - - Constructor. Sets all texture channels (1 and above) to the texture default, and all color channels (0 and below) to the color default. - - - - - Constructor. Initializes the with empty tables and 0's for input mesh map size. - - - - - Class constructor. The data members are initialized as follows: - - Ka[0] = Ka[1] = Ka[2] = 0.3f; - - Kd[0] = Kd[1] = Kd[2] = 0.9f; - - Ks[0] = Ks[1] = Ks[2] = 0.9f; - - shininess = 10.0f; - - shinStrength = 1.0f; - - opacity = 1.0f; - - selfIllum = 0.0f; - - dblSided = 0; - - shadeLimit = 3; - - texInfo; - - texture.Append(1, &texInfo); - - - - - Copy constructor. - - The object that will be copied. - - - - Constructor. Initialized to Identity. - - - - - Constructor. Initialized to Identity. - - - - - Constructor, Unused. Default constructor now initializes to identity. Kept for backward compatibility. - - - - - Constructor. Initializes the matrix with the row data passed and validates the matrix flags. - - The data for row 0. - The data for row 1. - The data for row 2. - The data for row 3. - - - - An global instance of set to the identity. An identity matrix has no rotation, scale or translation on it. In other words, it is a matrix that has no effect when multiplied with another matrix. - the structure of the Matrix is as follows: - - [1, 0, 0] - [0, 1, 0] - [0, 0, 1] - [0, 0, 0] - - - - - Constructor. - Default Implementation: - {} - - - - - Constructor. This matrix is initialized from the matrix passed. - Default Implementation: - {} - - - - - Constructor. Creates a new 32 element stack of Matrix3s. - - - - - Constructor. Creates a new depth element stack of Matrix3s. - - - - - Constructor. - - This constructor is for legacy icons stored as image list .bmp files in the UI_ln directory. - - The file prefix to initialize with. - The index of the icon. - - - - Constructor. Creates a which refers to a multi-resolution icon. - - The name of the icon. - - - - Constructor. - - The superclass ID - The class ID/ - - - - Constructor. - - - - - The category affected by locale. See _tsetlocale in MSDN help for more info - - The locale name. See _tsetlocale in MSDN help for more info - - - - Constructor - - - - - Constructor. Initializes the mesh object. The mesh counts are set to 0 and its pointers are set to NULL. - - - - - Constructor. The mesh is initialized equal to fromMesh. - - - - - Constructor. This gets the capper ready for the topology of the specified . - - - The to initialize the cap data from. - - - - Constructor. The verts pointer is set to NULL. - - - - - Constructor. This sets mdir to NULL. - - - - - Constructor. - Parameters: - &m - - The mesh to init this object from, allocating the vertex and mapping vertex tables as appropriate. - - - - - Constructor. Initializes the with NULL pointers and 0's for input mesh size. - - - - - Constructor. Initializes the to be based on the mesh given. MapDeltas and VDataDeltas are allocated as appropriate, and vnum and fnum are set. - - - - - Constructor. The flags are cleared, the vertex and face numbers are set to 0, and the tv and tf pointers are set to NULL. - - - - - Constructor. The name is set to the name passed. - - - - - Constructor - sets all corners to "unspecified". - - - - - Constructor. Sets all data members to NULL. - - - - - Constructor. Sets the internal mesh pointer to the mesh passed. - Parameters: - *m - - The mesh to set. - - - - - To determine the input type of a modifier, an instance of the modifier needs to be created. If the input type for a large number of modifiers are gathered (for example, when opening the modifier panel modifier dropdown list), creating an instance of each modifier is slow. This method creates an instance of the modifier if needed, and caches the input type. Later requests are satisfied via the cached value. - true if a modifier class with the specified SClass_ID and was found, and the output inputType was set to a valid value. - - [in] The classdesc of the modifier. Valid superclasses are OSM_CLASS_ID and WSM_CLASS_ID. - [out] The input type of the modifier. See for a list of the valid values. - - - - Constructor. The transformation matrix, bounding box, and local data pointer are initialized to NULL. - - - - - Constructor. The tm, bounding box and local data are initialized to those of the specified . - - The to copy. - - - - Constructor. The tm, bounding box, and local data are initialized to those specified. - - The transform matrix to copy. - The bounding box to copy. - The local data that will be cloned. - - - - Constructor. - - - - - Constructor. The data members are initialized to the values passed. - Parameters: - MCHAR* msg - - The exception message. - - int code=0 - - The exception error code. - Default Implementation: - {} - - - - - ctor: - - If true, disable c++ callstack capture in ctor exception is thrown. - - - - ctor: - - If true, disable mxs callstack capture in ctor - If true, call in if an exception is thrown. - - - - ctor: - - If true, disable mxs callstack capture in ctor - If true, call in if an - The current MAXScript_TLS* exception is thrown. - - - - Constructor. The data members are initialized to the values passed. - Parameters: - MCHAR* msg - - The exception message. - - int code=0 - - The exception error code. - Default Implementation: - {} - - - - - Constructor. - - - - - Constructor. This constructor Initializes to the mesh passed (allocates mapping channels, etc.) - Parameters: - const & m - - The specified mesh. - - - - - Initializes decorated object. Functions are forwarded to underlying object in_data. Some functions append additional functionality. Thus in_data is updated with every function call. - - - - underlying object. - - - - Constructor. Sets mFace and mDiagonal to the face and diagonal given. - - - - - Constructor. Initializes both faces to -1 and both vertices to 0. - - - - - Constructor. Initializes edge to run from vv1 to vv2 with f1 set to fc. - - - - - Constructor. - Parameters: - &m - - The mesh these clusters are based on. - - DWORD clusterFlags - - The edge flags to cluster the edges by. - - For instance, if this value was set to MN_SEL, then edges would be clustered by their selection. - - - - - Constructor. Initializes the face's arrays to NULL. - - - - - Constructor. Initializes the face's degree to d and allocates space for all the arrays. - - - - - Constructor. Copies flags, smoothing groups, and material from "from", but initializes the face's arrays to NULL and degree to 0. - - - - - Creates clusters from distinct selected components. This method will create face cluster lists based on the specified . Each contiguous group of selected faces is grouped into a cluster. - Parameters: - &mesh - - The mesh these clusters are based on. - - DWORD clusterFlags - - The face flags to cluster the faces by. - - For instance, if this value was set to MN_SEL, then faces would be clustered by their selection. - - - - - This method will create face cluster lists based on the specified . Cluster boundaries will be determined by the angle between faces and optionally by the face flags. - Parameters: - &mesh - - The mesh these clusters are based on. - - float angle - - The minimum edge angle (in radians) used to define a separation between clusters. - - DWORD clusterFlags - - The face flags to cluster the faces by. - - For instance, if this value was set to MN_SEL, then faces would be clustered by their selection. If this value is set to 0, then the clusters are based only on edge angles. - - const Point3* faceNormals - - Optional performance option to pass in the precomputed list of normals - - - - - - - Create an element list based on the specified . - Parameters: - &mesh - - A reference to the for which to create the element list. - - - - - Constructor. This calls Init(). - - - - - Constructor. Calls Init(). - - - - - Constructor. Sets the degree and hidden vertex count. - Parameters: - int d - - Desired degree. - - - - - Constructor. Initializes to empty data. - - - - - Initializes the with no components and the default flags. - - - - - Constructor. Initializes the with the mesh "from", and fills in the topology completely (using FillInMesh). - - - - - Copy constructor. - - - - - Constructor. Takes pointer, which is the mesh that is operated upon n all methods. - - Example: See example usage in the Editable Poly object, in maxsdk/samples/mesh/EditablePoly - - - - - Constructor - initializes mDegree to 0, mpNormalID to NULL. - - - - - - - Constructor - initializes to the degree specified. - - - - - - - Constructor. Initializes all data members. - - - - - - - Constructor with each parameter explicitly specified. - - The chamfer amount - When QCHAM_OPTION_VARIABLE_EDGE_WEIGHTS option is used, the chamfer amount at Crease == 0.0 - When QCHAM_OPTION_VARIABLE_EDGE_WEIGHTS option is used, the chamfer amount at Crease == 1.0 - The number of segments in the chamfers - The tension of the chamfer (0 = no tension, 0.5 = rounded, 1.0 = linear) - The depth of the chamfer (-1.0 = concave, 0.0 = linear, 1.0 = convex) - The inset amount - The number of segments for the inset - The inset offset amount - The miter end bias amount - Chamfer options (See ) - Chamfer result options (See ) - The MN_XXX flag that indicates edges to chamfer (See ) - The Quad Chamfer version to use (See ) - biasing factor controlling the radius of chamfered corners - scaling factor to be applied to weights when chamfer amount is specified via absolute weighting approach - - - - Constructor with base class parameters specified via an object. - - object specifying all base-class parameters - biasing factor controlling the radius of chamfered corners - scaling factor to be applied to weights when chamfer amount is specified via absolute weighting approach - - - - Constructor for 3ds Max 2020 and previous versions. - - object specifying all base-class parameters - - - - Constructor for operation as original version (3ds Max 2015) - - The chamfer amount - The number of segments in the chamfers - The tension of the chamfer (0 = no tension, 0.5 = rounded, 1.0 = linear) - Chamfer result options (See ) - The MN_XXX flag that indicates edges to chamfer (See ) - - - - Constructor for operation as Phoenix (Max 2016) version. (If QCHAM_OPTION_VARIABLE_EDGE_WEIGHTS option is used, the chamfers will vary from 0.0 at Crease == 0.0 to "amount" at Crease == 1.0.) - - The chamfer amount - The number of segments in the chamfers - The tension of the chamfer (0 = no tension, 0.5 = rounded, 1.0 = linear) - Chamfer options (See ) - Chamfer result options (See ) - The MN_XXX flag that indicates edges to chamfer (See ) - The Quad Chamfer version to use (See ) - - - - Constructor for operation as 3ds Max 2020 or later - - The chamfer amount - When QCHAM_OPTION_VARIABLE_EDGE_WEIGHTS option is used, the chamfer amount at Crease == 0.0 - When QCHAM_OPTION_VARIABLE_EDGE_WEIGHTS option is used, the chamfer amount at Crease == 1.0 - The number of segments in the chamfers - The tension of the chamfer (0 = no tension, 0.5 = rounded, 1.0 = linear) - The depth of the chamfer (-1.0 = concave, 0.0 = linear, 1.0 = convex) - The inset amount - The number of segments for the inset - The inset offset amount - The miter end bias amount - Chamfer options (See ) - Chamfer result options (See ) - The MN_XXX flag that indicates edges to chamfer (See ) - The Quad Chamfer version to use (See ) - - - - Copy constructor. - - - - - Constructor with each parameter explicitly specified. - - the MN_XXX flag that indicates vertices to chamfer (see ) - array of bits representing chamfer options; here, only QCHAM_OPTION_LIMIT_EFFECT is checked - specifies the geometry to be generated - number of line segments to use to connect the chamfered edge ends with the chamfered corner point - chamfer amount by which the edge endpoints at a vertex should be pushed back from the original vertex - depth value, specifying the shape of the chamfered surfaces - scaling factor to be applied to weights when chamfer amount is specified via absolute weighting approach - specifies the angles between the original edges at a chamfered vertex, and the lines connecting the chamfered edge endpoints and the chamfered corner point for the unit depth case - - - - Constructor. Sets all data members to NULL. - - - - - Constructor. Sets the internal mesh pointer to the mesh passed. (Sets all other data members to NULL.) - Parameters: - *m - - The internal mesh pointer to set. - - - - - Initializes the . - - - - - Constructor. - - - The 'include' flag is set to FALSE. - - - - - Copy constructor. - - - - - Constructor. The data members are initialized to default values. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized from the passed. - - - - - Constructor. The private data members are initialized by the passed parameters. - Parameters: - bool preCollapse - - Indicates if this is a pre- collapse or a post- collapse. Pass true for pre and false for post. - - *n - - Points to the node at the beginning of the pipeline that was collapsed. - - *collapsedObj = NULL - - If this is a post- collapse then points to the object which is the result of the collapse. - Sample Code: - The following code fragment shows using this constructor and then the EnumGeomPipeline with this object: - - PreNCEP(true,node); - - EnumGeomPipeline(&PreNCEP,node); - - - - - Constructor. The private data members are initialized by the passed parameters. - - - - Indicates if this is a pre- collapse or a post- collapse. Pass true for pre and false for post. - Points to the node at the beginning of the pipeline that was collapsed. - If this is a post- collapse then points to the object which is the result of the collapse. - - - - Constructor. The private data members are initialized by the passed parameters. - - - - Indicates if this is a pre- collapse or a post- collapse. Pass true for pre and false for post. - Points to the node at the beginning of the pipeline that was collapsed. - If this is a post- collapse then specifies whether to apply CAs collected from the node's base object. - If this is a post- collapse then points to the object which is the result of the collapse. - - - - Constructor. The data members are initialized as follows: - - - - - - - Constructor. The data members are initialized as follows: - - - - - - - Constructor. The name is set to NULL, the points are set to 0.0f and the weight is set to 1.0. - - - - - Constructor. The data members are initialized as follows: - - mKind = kNURBSCurve; - - mMatID = 1; - - - - - Constructor. The data members are initialized as follows: - - mType = kNCurveCPoint; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mCType = kNConstOnObject; - - ; - - mNormal = 0.0f; - - mUTangent = 0.0f; - - mUParam = 0.0; - - mTrimCurve = FALSE; - - mFlipTrim = FALSE; - - - - - Constructor. The data members are initialized by value: - - mType = kNCurveCurveIntersectionPoint; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId[0] = mParentId[1] = 0; - - mParentIndex[0] = mParentIndex[1] = -1; - - mCurveParam[0] = mCurveParam[1] = 0.0; - - mTrimCurve[0] = mTrimCurve[1] = FALSE; - - mFlipTrim[0] = mFlipTrim[1] = FALSE; - - - - - Constructor. The data members are initialized as follows: - - mType = kNCurveOnSurface; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mTrim = FALSE; - - mFlipTrim = FALSE; - - - - - Constructor. The data members are initialized as follows: - - mType = kNCurveSurfaceIntersectionPoint; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId[0] = mParentId[1] = 0; - - mParentIndex[0] = mParentIndex[1] = -1; - - mSeed = 0.5; - - mTrimCurve = FALSE; - - mFlipTrim = FALSE; - - - - - Constructor. The data members are initialized as follows: - - mType = kNCVCurve; - - mClosed = FALSE; - - mpCVs = NULL; - - mpKnots = NULL; - - - - - Constructor. The data members are initialized as follows: - - mDisplayCurves = TRUE; - - mDisplaySurfaces = TRUE; - - mDisplayLattices = FALSE; - - mDisplaySurfCVLattices = TRUE; - - mDisplayCurveCVLattices = TRUE; - - mDisplayDependents = TRUE; - - mDisplayTrimming = TRUE; - - mDegradeOnMove = TRUE; - - - - - Constructor. The data members are initialized as follows: - - - - - - - Constructor. The data members are initialized as follows: - - mCurve1 = mCurve2 = 0; - - mCV1 = mCV2 = 0; - - - - - Constructor. The data members are initialized as follows: - - mSurf1 = mSurf2 = 0; - - mRow1 = mCol1 = mRow2 = mCol2 = 0; - - - - - Constructor. The data members are initialized as follows: - - mType = kNPoint; - - mX = mY = mZ = 0.0; - - - - - Constructor. The data members are initialized as follows: - - mType = kNIsoCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mIsU = TRUE; - - mParam = 0.0; - - mTrim = FALSE; - - mFlipTrim = FALSE; - - (0.0, 0.0); - - - - - Constructor. The data members are initialized as follows: - - mType = kNMirrorCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mXForm.IdentityMatrix(); - - mAxis = kMirrorX; - - mDistance = 0.0; - - - - - Constructor. The data members are initialized as follows: - - mName[0] = '/0'; - - mId = 0; - - mpObject = NULL; - - mpNSet = NULL; - - mSelected = FALSE; - - - - - Constructor. The data members are initialized as follows: - - mType = kNOffsetCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mDistance = 0.0; - - - - - Constructor. The data members are initialized as follows: - - mType = kNPointCPoint; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mCType = kNConstOnObject; - - ; - - - - - Constructor. The data members are initialized as follows: - - mType = kNPointCurve; - - mClosed = FALSE; - - mpPts = NULL; - - - - - Constructor. The data members are initialized as follows: - - mType = kNPointCurveOnSurface; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mTrim = FALSE; - - mFlipTrim = FALSE; - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to the values passed. - - Both (*SurfEvalTan) and (*SurfEvalMixedProc) are optional. If NULLs are provided for either of these functions then 3ds Max will resort to a finite differences based solution. - Parameters: - - - - - Constructor. - - - - - Constructor. The data members are initialized as follows: - - mType = kNProjectVectorCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId[0] = mParentId[1] = 0; - - mParentIndex[0] = mParentIndex[1] = -1; - - mTrim = FALSE; - - mFlipTrim = FALSE; - - (0.0, 0.0); - - (0.0, 0.0, 1.0); - - - - - Constructor. The data members are initialized as follows: - - mpObject = NULL; - - mpVTess = NULL; - - mpRTess = NULL; - - mpRTessDisp = NULL; - - mpVTessCurve = NULL; - - mpRTessCurve = NULL; - - mTessMerge = 0.01f; - - mDisplay.mDisplayCurves = TRUE; - - mDisplay.mDisplaySurfaces = TRUE; - - mDisplay.mDisplayLattices = FALSE; - - mDisplay.mDisplayShadedLattice = FALSE; - - mDisplay.mDisplaySurfCVLattices = TRUE; - - mDisplay.mDisplayCurveCVLattices = TRUE; - - mDisplay.mDisplayDependents = TRUE; - - mDisplay.mDisplayTrimming = TRUE; - - mDisplay.mDegradeOnMove = TRUE; - - - - - Constructr. The data members are initialized as follows: - - mType = kNSurfaceEdgeCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - (0.0, 0.0); - - - - - Constructor. The data members are initialized as follows: - - mType = kNSurfaceNormalCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - - - - Constructor. The data members are initialized as follows: - - mType = kNSurfaceCPoint; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mCType = kNConstOnObject; - - ; - - mNormal = 0.0f; - - mUTangent = 0.0f; - - mUParam = 0.0; - - mVTangent = 0.0f; - - mVParam = 0.0; - - - - - Constructor. The data members are initialized as follows: - - mType = kNSurfSurfIntersectionCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId[0] = mParentId[1] = 0; - - mParentIndex[0] = mParentIndex[1] = -1; - - mTrim[0] = mTrim[1] = FALSE; - - mFlipTrim[0] = mFlipTrim[1] = FALSE; - - (0.0, 0.0); - - - - - Constructor. The data members (from ) are initialized as follows: - - mKind = kNURBSTexturePoint; - - mType = kNTexturePoint; - - - - - Constructor. The data members are initialized as follows: - - mMapperType = kNMapDefault; - - mpPoints = NULL; - - - - - Constructor. - Parameters: - double parameter - - This is point in parameter space at which the trim point exists. - - NURBSTrimDirection direction - - The positive or negative direction in parameter space of the portion that is being trimmed off. The direction can also be set to 'none' so no trimming is done. - - - - - Constructor. The data members are initialized as follows: - - mType = kNXFormCurve; - - mpObject = NULL; - - mpNSet = NULL; - - mParentId = 0; - - mParentIndex = -1; - - mXForm.IdentityMatrix(); - - - - - Constructor. The object pointer is initialized to NULL. - - - - - Constructor. The object pointer is set to the object passed. The tm pointer is set to NULL and the tm and mtl validity intervals are set to FOREVER. - - The object to initialize the object pointer to. - - - - Constructor. The object state is initialized to the object state passed. - - The object state to initialized to os. - - - - Constructor. The wrapper is set to an empty, uninitialized state. - - - - - Constructor. The inode data member is initialized to n. - - - - - internal use only. Used internally to interface with legacy code - - - - - Constructor to report only a commandResId and a module name to ADP. - - Resource string ID identifying the command name string. Must not be -1. - This parameter must not be null should be a localized string. - HINSTANCE of the dll or exe which instantiated the and initiated the command. - - - - Constructor to report the impacted object class ids(derived from the ReferenceTarget), a commandResId and a module name to ADP. - - Resource string ID identifying the command name string. Must not be -1. - This parameter must not be null should be a localized string. - HINSTANCE of the dll or exe which instantiated the and initiated the command. - of the scene entity currently being modified or created by the Accept invocation and from which the and the SClass_ID will be extracted and used as such in the way point. - - - - Constructor to report the impacted object class ids (derived from the ), a commandResId and a module name to ADP. - - Resource string ID identifying the command name string. Must not be -1. - This parameter must not be null should be a localized string. - HINSTANCE of the dll or exe which instantiated the and initiated the command. - Class Descriptor of the scene entity currently being modified or created by the Accept invocation and from which the and the SClass_ID will be extracted and used as such in the way point. - - - - Constructor to report only an arbitrary details string, a commandResId and a module name to ADP. - - Resource string ID identifying the command name string. Must not be -1. - This parameter must not be null should be a localized string. - HINSTANCE of the dll or exe which instantiated the and initiated the command. - Gives additional information on the command when other information like class ids, or are not readily available to the user. For instance: For a CREATE command, the type of object created. commandDetails must NOT be a localized string. - - - - returns number of trueBlocks allocated and set - - - - - Constructor. The data members are initialized to the values passed. - Parameters: - p3 - - The point that was hit in object space. - - Osnap* s - - Points to the instance which made this hit. - - int sub - - The sub-snap index which made this hit. - - *m - - Points to the mesh used to hilite the topology that was hit. - - - - - Constructor. The data members are initialized from the passed. - Parameters: - & h - - The data members are copied from this . - - - - - Constructor. The cache of marker points is set to NULL and the number of points is set to 0. - - - - - Constructor. This initializes the cache with the points and edge flags passed. - Parameters: - int n - - The number of points in the marker polyline. - - *ppt - - The array of points for the polyline. - - int *pes - - The edge state array. This is an array that indicates if the 'n-th' edge is one of three state: - - GW_EDGE_SKIP - - Nonexistent - totally invisible. - - GW_EDGE_VIS - - Exists and is solid. - - GW_EDGE_INVIS - - Exists and is hidden - shown as a dotted line. - - You may pass NULL for this array and the method will assume that the edges are all solid. - - - - - Constructor. The marker data is initialzed from the passed. - Parameters: - & om - - The settings are copied from this . - - - - - Constructor. The data members are initialized to the values passed. - - - - - This constructor takes a number of fixed, block-related arguments and then a varargs-based variable list of arguments that define the block and its parameters. - - The format of the definitions in this shown below, but basically is in the form of a sequence of fixed specs followed by a variable number of tagged optional specs for each parameter. - Parameters: - The generic form for the parameters of this constructor is shown below: - That is: - - <required_block_spec> - The following required first arguments to the constructor form the "required_block_spec" and "per block flags": - - BlockID ID - The permanent block ID for the parameter block2. - - MCHAR* int_name - The internal name string. This name is not localized. Internal names are meant to be parsable as identifiers. As such they should begin with an alpha character, have only alphanumerics, and have no spaces, punctuations, etc. The convention for multi-word names is to use studly-caps, eg, paintRadius. - - int local_name - The resource ID of the localized (sub-anim) name string. - - ClassDesc2* cd - Points to the class descriptor2 of the owning class. This is used to add this descriptor to the 's table of block descriptors for the class. Note: This value may be passed as NULL for situations where the blocks owning is not available for static initializations (such as in a separate file). Before using the descriptor for any block construction, the ClassDesc2* must be initialized with the method: - ParamBlockDesc2::SetClassDesc(ClassDesc2* cd); - You can only call this method once on a descriptor and then only if it has been constructed initially with a NULL cd. - - BYTE flags - Per block/descriptor flags. One or more of the following values (they may be added together as in P_AUTO_CONSTRUCT + P_AUTO_UI). - - - - - - Constructor. - - - - - This is an array of ParamVersionDescs. - - The number of elements in the array specified above. - - This is a pointer to the current version of the . - - This is a pointer to a reference target. This is usually the this pointer of the object. - - This is the reference index of the parameter block. - - - - float lowLim,float highLim,float scale, - - *dim=defaultDim); - Constructor. This constructor is used for a float or int controlled by a single spinner control: - Parameters: - int index - - This is the index into the virtual array of this UI control. - - EditSpinnerType spinType - - This parameter specifies the type of value which may be entered. The valid types (listed in CUSTCONT.H) are: - - EDITTYPE_INT - Any integer value. - - EDITTYPE_FLOAT - Any floating point value. - - EDITTYPE_UNIVERSE - This is a value in world space units. It respects the systems unit settings (for example feet and inches). - - EDITTYPE_POS_INT - Any integer >= 0 - - EDITTYPE_POS_FLOAT - Any floating point value >= 0.0 - - EDITTYPE_POS_UNIVERSE - This is a positive value in world space units. It respects the systems unit settings (for example feet and inches) . - - EDITTYPE_TIME - This is a time value. It respects the system time settings (SMPTE for example). - - int idEdit, int idSpin - - These are the resource IDs the edit control and the spinner control. - - float lowLim - - This is the minimum value the spinner can take on. - - float highLim - - This is the maximum value the spinner can take on. - - float scale - - This is the increment or decrement value used when the user uses the up or down arrow buttons of the spinner control. You may also pass the value SPIN_AUTOSCALE. This causes 3ds Max to automatically adjust the value used to increment or decrement based on the current value being edited. This allows the spinner to cover a wider range of values with less mouse movement or button clicking from the user. - - - - - Constructor. This constructor is used for an int controlled by n radio buttons where - - vals[i] represents the value if ctrlIDs[i] is checked. If vals=NULL then ctrlIDs[i] represents a value of i. - - Or it may be used for: - - An int controlled by multiple check boxes where each check boxes controls a single bit. - - vals[i] specifies which bit ctrlIds[i] controls. If vals=NULL then ctrlIDs[i] controls the i-th bit. - Parameters: - int index - - This is the index into the virtual array of this UI control. - - ControlType type - - This specifies the type of control to use. The available control are: - - TYPE_RADIO - Radio Buttons. - - TYPE_MULTICHECKBOX - Multiple Check Boxes. Note: This option is not currently supported. - - int *ctrlIDs - - An array of control IDs. See the Remarks above. - - int count - - This is the number of control IDs in the array above. - - int *vals=NULL - - An array of values. See the Remarks above. - - - - - Constructor. This version is used for an int controlled by a single check box (BOOL) or a controlled by a color swatch. - Parameters: - int index - - This is the index into the virtual array of this UI control. - - ControlType type - - This specifies the type of control to use. The available control types (defined in IPARAM.H) are: - - TYPE_SPINNER - Spinner . - - TYPE_RADIO - Radio Button. - - TYPE_SINGLECHECKBOX - Single Check Box. - - TYPE_MULTICHECKBOX - Multiple Check Boxes. Note: This option is not currently supported. - - TYPE_COLORSWATCH - Swatch. - - int id - - This is the resource ID of the control. - - - - - int idSpin3,float lowLim,float highLim,float scale, - - *dim=defaultDim); - Implemented by the System. - - This version if for a controlled by 3 spinners - Parameters: - int index - - This is the index into the virtual array of this UI control. - - EditSpinnerType spinType - - This parameter specifies the type of value which may be entered. The valid types (listed in CUSTCONT.H) are: - - EDITTYPE_INT - Any integer value. - - EDITTYPE_FLOAT - Any floating point value. - - EDITTYPE_UNIVERSE - This is a value in world space units. It respects the systems unit settings (for example feet and inches). - - EDITTYPE_POS_INT - Any integer >= 0 - - EDITTYPE_POS_FLOAT - Any floating point value >= 0.0 - - EDITTYPE_POS_UNIVERSE - This is a positive value in world space units. It respects the systems unit settings (for example feet and inches) . - - EDITTYPE_TIME - This is a time value. It respects the system time settings (SMPTE for example). - - int idEdit1,int idSpin1 - - These are the resource IDs of the first edit and spinner controls. - - int idEdit2,int idSpin2 - - These are the resource IDs of the second edit and spinner controls. - - int idEdit3,int idSpin3 - - These are the resource IDs of the third edit and spinner controls. - - float lowLim - - This is the minimum value the spinner can take on. - - float highLim - - This is the maximum value the spinner can take on. - - float scale - - This is the increment or decrement value used when the user uses the up or down arrow buttons of the spinner control. You may also pass the value SPIN_AUTOSCALE. This causes 3ds Max to automatically adjust the value used to increment or decrement based on the current value being edited. This allows the spinner to cover a wider range of values with less mouse movement or button clicking from the user. - - *dim=defaultDim - - This parameter represents the type and magnitude of the parameter. See Class . - - - - - Constructor. - Parameters: - *d - - This is an array of parameter block descriptors. - - int c - - This is the number of items in the array. - - int v - - This is the version number. - - - - - constructors/destructor/assigning - - - - - constructors/destructor/assigning - - - - - constructors/destructor/assigning - - - - - maximum number of available standard particle channels (constant) - - - - - empty mask - - - - - Constructor. The type is set to undefined, the smooth group is set to 1, and the flags indicate automatic interior points. Note: This constructor does not allocate arrays. Use SetType(type). - - - - - Constructor. The this pointer is set to the fromPatch. - - - - - Constructor. - Parameters: - &shape - - See Class . - - - - - Constructor. The verts and vecs are set to NULL. - - - - - Constructor. No initialization is performed. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. No initialization is performed. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized as undefined. - - - - - Copy Constructor. The data members are initialized from the passed. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. Initializes data members (see Init() below). - - - - - Constructor. This is initialized from the specified . - - - - - Constructor. The name is set to the name passed. - - - - - Constructor. - - - - - Constructor. The data members are set to the values passed. - - - - - Constructor. The UVVert is set to 0,0,0. The aux member is set to -1. - - - - - Constructor. The UVVert is set to the provided uvw parameters passed to the method. The aux member is set to -1. - Parameters: - float u, float v, float w; - - The u, v, and w values for the texture vertex. - Operators: - - - - - Constructor. The location is set to 0,0,0. The vertex owner is set to undefined. The patches using the vector is set to undefined. The flags are set to 0. - - - - - Constructor. The data members are initialized to those of the from patch vector. - Parameters: - &from - - The vector to copy from. - - - - - Constructor. The location is set to 0,0,0. The flags are set to 0. - - - - - Constructor. The data members are copied from the from . - Parameters: - &from - - The source . - - - - - Constructor. The number of elements is set to 0, the type is set to 0 and the data pointer is set to NULL. - - - - - Constructor. - - The number of elements to allocate. - The type to set. - - - - Constructor. This allocates the pixel buffer using the specified width. - Parameters: - int width - - The number of pixels to allocate for the buffer. - - - - - Constructor. - - Create a plane that passes through the given point with the given normal. - Parameters: - & normal - - The normal of the plane. - - & point - - The point the plane should pass through. - - - - - Constructor. - - Create a plane that passes through all three given points. - Parameters: - Points3& p1, Points3& p2, Points3& p3 - - The three points the plane should pass through. - - - - - - - Constructor. - - - - - Constructor. Data members are initialized to X and Y. - - - - - Constructor. Data members are initialized to X and Y cast as floats. - - - - - Constructor. Data members are initialized to X and Y cast as floats. - - - - - Constructor. Data members are initialized to a.x and a.y. - - - - - Constructor. Data members are initialized as x = af[0] and y = af[1]. - - - - - Initializes all vector components to zero. - - - - - Constructor. x, y, and z are initialized to the specified . - - - - - Constructor. x, y, and z are initialized to the values specified. - - - - - Constructor. x, y, and z are initialized to af[0], af[1], and af[2] respectively. - - - - - Constructor. x, y, and z are initialized to the specified values (cast as floats). - - - - - Constructor. x, y, and z are initialized to the specified values (cast as floats). - - - - - Constructor. x = r, y = g, and z = b. - - - - - Constructor. x = r, y = g, and z = b. - - - - - Constructor. x = x, y = y, and z = z. - - - - - Initializes vector components to zero. - - - - - Constructor. x, y, z and w are initialized to the values specified. - - - - - Constructor. x, y, z and w are initialized to the specified values (cast as floats). - - - - - Constructor. x, y, z and w are initialized to the specified values (cast as floats). - - - - - Constructor. x, y, z and w are initialized to the specified and W. - - - - - Constructor. x, y, z and w are initialized to af[0], af[1], af[2] and af[3] respectively. - - - - - Constructor. The number of points is set to zero, the points array is set to NULL, the flags are set to 0, the cache validity is set to FALSE and the bounding box is set to empty. - - - - - Constructor. The is initialized using the input object "from". - - - - - Constructor. All data members are initiated to their corresponding zero values. - - - - - Constructor. All data members are initialized to the input data. - - - - - Constructor. The number of lines is set to 0, the lines array is set to NULL, the flags and display flags are set to 0, the selection level is set to SHAPE_OBJECT, the geometry cache is invalidated, and the object is set to NULL. - - - - - Constructor. The is initialized from the specified . - - - - - Implemented by the System - - Constructor. The data member is initialized to the passed. The pointer is set to NULL. - - - - - Implemented by the System - - Constructor. The pointer is set to NULL. - - - - - Constructor. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to the values passed (cast as floats). - - - - - Constructor. The data members are initialized to the values passed. - - x = af[0]; y = af[1]; z = af[2]; w = af[3]; - - - - - Constructor. Convert the specified 3x3 rotation matrix to a unit quaternion. - - - - - Constructor. The is initialized to the passed. - - - - - Constructor. The quaternion is initialized from the vector V and angle W passed. The quaternion is then normalized. - - - - - - - The constructor will automatically initialize the seed. - - - - - Constructor. - - - - - Create a real-world map size undo record - - - the object which supports the undo/redo toggle - - the state of the real-world map size toggle to restore to. - - - - Method to validate that data is cleared on all ReferenceMakers in scene. Used internally. - - - - - Constructor. The initialization can be seen in the header file RENDER.H. - - - - - Constructor - - - - - Constructor - - - - - K Prototype - - Constructor. - - - - - Copy constructor. - - - - - Conveniency (static) method to test whether an integer corresponds to an enum of rotation representations used in of type Euler angles - - - - - - - Conveniency (static) method to test whether in cases where a call to IsEuler(int rep) is made, and the return value is of type Euler angles, this method call returns whether it has repetitive axes (such as XYX). - - - - - - - Conveniency (static) method to test whether an integer corresponds to an enum of rotation representations used in of type Quaternion. - - - - - - - Constructor. The smoothing group and material index are set to zero. - - - - - Constructor. The flags are set to zero and the ern pointer is set to NULL. - - - - - Constructor. s and q have their own initializers. - - - - - Constructor. The scale data member is initialized to as. The quaternion data member is set to the identity. - - - - - Constructor. The scale data member is initialized to as. The quaternion data member is set to aq. - Operators: - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized to the values passed. The matrix is set to the identity. - - - - - Constructor. The XFORM_SET command. - Parameters: - & mat - - The tmAxis value. - - {} - - The tmParent value. - - - - - Constructor. The XFORM_MOVE command. - Parameters: - pt - - The p value. - - {} - - The tmParent value. - - {} - - The tmAxis value. - - - - - Constructor. The XFORM_ROTATE command. - Parameters: - qt - - The q value. - - BOOL l - - The localOrigin value. - - {} - - The tmParent value. - - {} - - The tmAxis value. - - - - - Constructor. The XFORM_ROTATE command. - Parameters: - aA - - The aa value. - - BOOL l - - The localOrigin value. - - {} - - The tmParent value. - - {} - - The tmAxis value. - - - - - Constructor. The XFORM_SCALE command. - Parameters: - pt - - The p value. - - BOOL l - - The localOrigin value. - - {} - - The tmParent value. - - {} - - The tmAxis value. - - - - - Constructor. This constructor is provided in case you want to set the data members yourself. - - - - - Constructor. No initialization is performed. - - - - - Constructor. This constructor clears out the hierarchy, sets the number of polygons to poly and clears all the bits in the . - Parameters: - int polys - - The number of polygons in the hierarchy. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The name is set to the name passed. - - - - - Constructor. The name is set to the name passed. - - - - - Constructor. The name is set to the name passed. - - - - - Constructor. Initialize the class members. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. Initialize the class members. - - Constructor. The number of splines is set to 0. The pointer is set to NULL. - - - - - Constructor. The number of splines is set to 0. The pointer is set to NULL. - - - - - Constructor. - Parameters: - int shapeIndex - - This sets the shape index. - - Manipulator* pManip - - A pointer to the manipulator. - - - - - Constructor. - - - - - Constructor. - - - - - Constructor. - Parameters: - *m - - This is a pointer to the instance this WSM is based on. - - - - - Constructor. - - - - - Constructor. - - - - - specifies whether/when to auto drop the Reference on shutdown. - - specifies whether to check to see if held Reference still exists after dropping the reference to it. If it does, attempt to delete it by calling and then on it. If still exists, delete using 'delete'. This parameter is set when the Reference is normally handled as a singleton, and either its AutoDelete() implemetation just returns REF_SUCCEED or its implementation is a no-op. - - specifies whether/when this is a static instance and should be ignored when performing animatable leakage detection at shutdown. - - - - Constructor. - - - - - the reference to hold. - - specifies whether/when to auto drop the Reference on shutdown. - - specifies whether to check to see if held Reference still exists after dropping the reference to it. If it does, attempt to delete it by calling and then on it. If still exists, delete using 'delete'. This parameter is set when the Reference is normally handled as a singleton, and either its AutoDelete() implemetation just returns REF_SUCCEED or its implementation is a no-op. - - specifies whether/when this is a static instance and should be ignored when performing animatable leakage detection at shutdown. - - - - Constructor. The data members are initialized as follows: - - path = NULL; start = end = space = 0.0f; count = 1; oType = NODE_CPY; sType = SPACE_CENTER; follow = false; context = CTXT_FREE; width = 0.0f; countLimit = INT_MAX; - - - - - Constructor. - - Knot type at initial click. - Knot type at drag. - Interpolation parameter type - - - - Constructor. The data members are initialized to the values passed. - - Knot type - Line type - Point Location - In vector - Out vector - Used for capping. An integer value which may be used for temporary storage of data associated with the knot. This data will be overwritten by the internal EditSpline code. - Used to track topo changes in spline editing. - User aux field. - - - - - Constructor. Initialize the member variables. - - - - - Constructor. - - - - - Constructor. - - Initialize the class with the specified data. - Parameters: - SpringSysClient* c - - A pointer to the spring system client class. - - int count - - The number of spring system particles. - - - - - Constructor. The list is set to NULL. - - - - - Constructor. The first sub hit is set to NULL. - - - - - Constructor. The list is set to NULL. - - - - - Constructor. - - - Suspends all system states that are requested to be suspended - - - If TRUE, disables the hold system (undo/redo), otherwise it's not changed. See theHold.Suspend() for more information. - - If TRUE, macro recording is suspended, otherwise it's not changed. See for more information. - - If TRUE, creating animation keys is suspended, otherwise it's not changed. See class for more information. - - If TRUE, "setkey" mode is suspended, otherwise it's not changed. See for more information. - - If TRUE, auto-backup is suspended, otherwise it's not changed. See for more information. - - If TRUE, backs up the "save required" flag, otherwise it doesn't. - - - - Constructor - - - - - Constructor. - Default Implementation: - (0.0f, 0.0f, 0.0f); - - (0.0f, 0.0f, 0.0f); } - - - - - Constructor. - Parameters: - int id - - The index to initialize with. - Default Implementation: - ;} - - - - - Constructor. - Default Implementation: - { - - mass = 300.0f; - - drag = 1.0f; - - (0.0f,0.0f,0.0f); - - springs.ZeroCount(); - - } - - - - - Constructor. - Default Implementation: - ;} - - - - - Constructor. - Default Implementation: - { - - bone = NULL; - - (0.0f, 0.0f, 0.0f); - - tension = 1.0f; - - dampening = 0.5f; - - } - - - - - Constructor. - - This allows you to initialize the spring. - Parameters: - *b - - The constraint point to set. - - l - - The spring length to set. - - float t=2.0f - - The tension to set. - - float d=1.0f - - The dampening to set. - Default Implementation: - { - - bone = *b; - - length = l; - - tension = t; - - dampening = d; - - } - - - - - Default constructor. - - - - - Copy constructor. - - - - The that will be copied - - - - Constructor. - Parameters: - *spline - - Builds the template from this spline. - - - - - Constructor. - Parameters: - *line - - Builds the template from this polyline. - - - - - Constructor. - - - - - Constructor. The data members are initialized as follows: - - type = TESS_SET; - - u = v = 2; - - u_iso = 2; - - v_iso = 3; - - view = FALSE; - - ang = 20.0f; - - dist = 10.0f; - - edge = 10.0f; - - vpt_cfg = ISO_AND_MESH; - - merge = 0.0f; - - minSub = 0; - - maxSub = 5; - - maxTris = 20000; - - subdiv = SUBDIV_TREE; - - showInteriorFaces = FALSE; - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized from the object passed. - Operators: - - - - - Constructor. The data members are initialized as follows: - - useTex = 1; - - faceMap = 0; - - textHandle = 0; - - uvwSource = UVSOURCE_MESH; - - mapChannel = 1; - - tiling[0] = tiling[1] = tiling[2] = GW_TEX_REPEAT; - - colorOp = GW_TEX_MODULATE; - - colorAlphaSource = GW_TEX_TEXTURE; - - colorScale = GW_TEX_SCALE_1X; - - alphaOp = GW_TEX_LEAVE; - - alphaAlphaSource = GW_TEX_TEXTURE; - - alphaScale = GW_TEX_SCALE_1X; - - - - - Constructor. - - - - - See . - - The Out&Enabled index. - - The In&Enabled index. - - The Out&Disabled index. - - The In&Disabled index. - - The image width (size of the bitmap in the ImageList). - - The image height (size of the bitmap in the ImageList). - - The width of the button. - - The height of the button. - - The ID of the control. - - The help ID. For plug-in developers this id should be set to 0. - = NULL - The label of the button. - = CTB_HORIZ|CTB_VERT|CTB_FLOAT - The allowable orientation of the item. This may be one or more of the following: CTB_HORIZ - Horizontal, CTB_VERT - Vertical CTB_FLOAT - Floating (not docked) - - - - Constructor. - - - - - See . - - A pointer to the icon associated with the button. - - The image width (size of the bitmap in the ImageList). - - The image height (size of the bitmap in the ImageList). - - The width of the button. - - The height of the button. - - The ID of the control. - - The help ID. For plug-in developers this id should be set to 0. - - The label of the button. - - The orientation of the button item. - - - - Constructor. - - - - - See . - - A pointer to the icon associated with the button. - - A pointer to the in icon associated with the button. - - The image width (size of the bitmap in the ImageList). - - The image height (size of the bitmap in the ImageList). - - The width of the button. - - The height of the button. - - The ID of the control. - - The help ID. For plug-in developers this id should be set to 0. - - The label of the button. - - The orientation of the button item. - - - - Constructor that uses a multi-resolution icon for the button. - - - - - See . - - The name of the icon associated with the button. - - The image width. - - The image height. - - The width of the button. - - The height of the button. - - The ID of the control. - - The help ID. For plug-in developers this id should be set to 0. - - The label of the button. - - The orientation of the button item. - - - - Constructor. The data members are initialized to the values passed. The type parameter of is set to CTB_IMAGE. - - - - - Constructor. The data members are initialized to the values passed. The type parameter of is set to CTB_IMAGE. - Parameters: - const MSTR& iconName - - The filename of the icon. - - int w - - The width of the icon. - - int h - - The height of the icon. - - int id - - The ID of the icon. - - DWORD hID=0 - - The help ID. For plug-in developers this id should be set to 0. - - int ori - - The orientation of the toolbar where icon locates. - - - - - Constructor. - Parameters: - int wd - - The width of the item. - - int ht - - The height of the item. - - *data - - Points to the macro button data. - - int ori = CTB_HORIZ|CTB_VERT|CTB_FLOAT - - Specifies the orientation. One or more of the following values: - - CTB_HORIZ - - CTB_VERT - - CTB_FLOAT - - - - - Constructor. - Parameters: - MCHAR *cls - - The class name of the control. This may be one of the values listed above under data members. - - int w - - The width of the control. - - int h - - The height of the control. - - int id - - The ID of the control. - - DWORD_PTR style=WS_CHILD|WS_VISIBLE - - The style of the control window. - - int y=CENTER_TOOL_VERTICALLY - - The vertical justification. This is a y offset from the top of the toolbar in pixels. The default value simply centers the tool vertically. - - MCHAR *wt=NULL - - The window text. - - DWORD hID=0 - - The help ID. For plug-in developers this id should be set to 0. - - - - - Constructor. - Parameters: - int w - - The width of the separator. - - int h=16 - - The height of the separator. - - BOOL vis=TRUE - - TRUE for visible; FALSE for not. - - int ori=CTB_HORIZ|CTB_VERT|CTB_FLOAT - - The allowable orientations. One or more of the following values: - - CTB_HORIZ - - CTB_VERT - - CTB_FLOAT - - - - - Constructor. - Parameters: - int w - - The width of the status box. - - int h - - The height of the status box. - - BOOL f - - The fixed data member - see above. - - int id - - The ID of the control. - - DWORD hID=0 - - The help ID of the control. For plug-in developers this id should be set to 0. - - - - - Class constructor. No heap memory is allocated until tooltips are actually set. - - - - - Constructor. The data members are initialized to the values passed. - - - - - ctors - - - Constructor - - - - - - specifies whether/when to auto drop the Reference on shutdown. - - specifies whether to check to see if held Reference still exists after dropping the reference to it. If it does, attempt to delete it by calling and then on it. If still exists, delete using 'delete'. This parameter is set when the Reference is normally handled as a singleton, and either its AutoDelete() implemetation just returns REF_SUCCEED or its implementation is a no-op. - - specifies whether/when this is a static instance and should be ignored when performing animatable leakage detection at shutdown. - - - - Constructor. - - - - - the initial typed Reference to be held. - - specifies whether/when to auto drop the Reference on shutdown. - - specifies whether to check to see if held Reference still exists after dropping the reference to it. If it does, attempt to delete it by calling and then on it. If still exists, delete using 'delete'. This parameter is set when the Reference is normally handled as a singleton, and either its AutoDelete() implemetation just returns REF_SUCCEED or its implementation is a no-op. - - specifies whether/when this is a static instance and should be ignored when performing animatable leakage detection at shutdown. - - - - Constructor. No initialization is done. - - - - - Constructor. - - Specifies the index into the tVerts array for vertex 0. - Specifies the index into the tVerts array for vertex 1. - Specifies the index into the tVerts array for vertex 2. - - - - Constructor. - - - - - Copy Constructor. The this pointer is set to the fromPatch. - - - - - Constructor. - Parameters: - HWND hwnd - - The control dialog window handle where the FLT_UNDO message will be sent. This window handle is also passed to InvalidateRectangle() so a WM_PAINT message will be sent. - - - - - Constructor. - Default Implementation: - { downloaded = FALSE; } - - - - - Constructor. The string is set to NULL. - - - - - Constructor. The string is initialized to the string passed. - - - - - Constructor. The string is initialized to the string passed. - - - - - Constructor. The string is initialized to the string passed. - - - - - Constructor. The string is initialized to the string passed. - - - - - Constructor. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized as follows: - - type = MAP_BOX; - - utile = 1.0f; - - vtile = 1.0f; - - wtile = 1.0f; - - uflip = 0; - - vflip = 0; - - wflip = 0; - - cap = 0; - - tm.IdentityMatrix(); - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data members are initialized from the passed. - - - - - Constructor. - - - - - Constructor. The data members are initialized to the values passed. - - - - - Constructor. The data member out is set to NULL. - - - - - Constructor. The data members are set to the command modes passed. - - - - - Constructor. All the data members are set to NULL. - - - - - Constructor. - - - - - Constructor. - - - - - Returns the specified color c clipped (limited to) the range 0 to 65535. - - - - - Returns the specified color c clipped (limited to) the range 0 to 65535. - - - - - Constructor; initializes all values to zero, except the falloff, which is initialized to a default of 20.0. - - - - - Constructor. The data members are initialized to the data members passed. - - distance of the hit point - the sub object's index - - - - Returns TRUE if the memory used by a needs to be freed based on the specified type. - - The type of value held by a . - - - - Constructor - - - - - Constructor - - - - - Base class for all pluggable objects. This class will be implemented by the system. - - - - - Interface to a basic logging mechanism - - - - - Log a notification message - - Message to log - - - - Log an error message - - Message to log - - - - All plugins should implement a global class derived from this interface. An instance of this class - is created during plugin initialization and held throughout the plugins life - - - - - Called upon initialization of the plugin - - The global interface to the system to be used by the plugin - Object used for synchronization with the main thread (for multi-threaded plugins) - - - - Called right before the plugin is unloaded - - - - - Global configuration of MaxDotNet plugin system - - - - - Get or set whether dynamic plugin unloading can be done. If true the unloading is supported - but the system might require more resources to do so, so this should be turned on mostly for testing. - - - - - Get or set whether all assembly plugins are automatically loaded during system startup - - - - - Get or set whether assemblies dynamically added to plugins folder should be automatically loaded by the system - - - - - Get or set whether assemblies dynamically removed from plugins folder should be automatically unloaded by the system - - - - - Get or set whether currently opened scene should be automatically reloaded prior to a plugin unloaded dynamically. - - - - - Get or set whether all exceptions should be intercepted and handled by system internally, or let them escape outside of it - to allow some other mechanism (such as a unit testing framework) to handle them. - - This option should always be set to true for production environment. - - - - Gets or sets a list of directories from which plugins will be loaded by MaxDotNet - - - - - Saves the current configuration to local computer's hard-drive - - - - - Singleton manager class used to access the system and manage loaded plugins - - - - - Access to the global system interface - - - - - Load an assembly given its file name - - Name of the assembly file - - - - Unload an assembly given its file name - - Name of the assembly file - - - - Checks if specified assembly is loaded - - Name of the assembly file - true if assembly is loaded - - - - Returns true if the system has already passed the intial loading stage. This is used - for some objects which can only be created during system initialization. - - - - - Gets the current configuration of MaxDotNet system - - - - - Gets or sets the global logger object - - - - - Class ID's of built-in classes. The value is the first ULONG of the 8 byte Class ID: the second ULONG is 0 for all built-in classes. - - - - - The interface ID for class ILayerProperties - - - - - The interface ID for class IFPLayerManager - - - - - The interface ID for class ILayerProperties - - - - - The interface ID for class ILayerProperties - - - - - The interface ID for class IFPLayerManager - - - - - The interface ID for class ILayerProperties - - - - - Utility class to store any arbitrary native object not covered by any of the wrappers. Essentially a managed storage for void*. - - - - diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.dll b/instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.dll deleted file mode 100644 index df672822730bc387fcb49aae50f329290447cf68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88856 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%0DNj8t|833cuQy;P4idS{*(e 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 diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.xml b/instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.xml deleted file mode 100644 index ba6c7b9..0000000 --- a/instaladorCsharp/VR4Life-dll/bin/Debug/CSharpUtilities.xml +++ /dev/null @@ -1,4079 +0,0 @@ - - - - CSharpUtilities - - - - - Contains static generic ToArray method for producing an Array from a - collection. - - - - - Static generic method produces a new array of the generic parameter type - from the given ICollection. - - Target array item type - Source collection. All items in this collection - will be placed in the returned array. - A new array of Ts containing the items from collection. - - - - Generates a new array from a subset of the source array. This version - copies from the given index until the end of the array. - - - - Example: - - int[] source = {0,1,2,3,4,5}; - int[] result = ArrayProducer.Slice(source, 3); - // result is now: {3,4,5} - result = ArrayProducer.Slice(source, 6); - // result is now: {} - - - - Slice can operate on multidimensional arrays, but it only considers the - first array. - - - The array item type. - - Source array, the selected elements from here will be copied into the new - array. - - - The index at which to start selecting elements. - - - A new array of size source.Length - fromIndex, containing the - elements from source[fromIndex] until - source[source.Length - 1]. - - - - - Generates a new array from a subset of the source array. This version - copies the given length of elements starting from the given index. - - - - Example: - - int[] source = {0,1,2,3,4,5}; - int[] result = ArrayProducer.Slice(source, 3, 2); - // result is now: {3,4} - result = ArrayProducer.Slice(source, 5, 2); - // result is now: {5, 0} 0 is the default value for int - result = ArrayProducer.Slice(source, 0, 0); - // result is now: {} - - - - Slice can operate on multidimensional arrays, but it only considers the - first array. - - - The array item type. - - Source array, the selected elements from here will be copied into the new - array. - - - The index at which to start selecting elements. - - - The desired length of the resulting array. Up to this many elements - will be copied from the source array. Fewer than length will be copied - if length exceeds the size of the array past fromIndex. Any value less - than 0 will be clamped to 0. - - - A new array of size length, containing the - elements from source[fromIndex] until - source[Math.Min(source.Length - 1, fromIndex + length - 1)] - and padded with null or default values at the end as necessary. - - - - - Converts a set of Boolean input values into a single Boolean output value - by performing a logical 'and.' - - - May be used in XAML as a markup extension. - - - - - Common instance of this converter. May be shared to reduce memory demands, - and provided by the MarkupExtension. - - - - - Convert from multiple Boolean input values to a single Boolean output - using a logical 'and.' - - Input values, expected to be bool. - - Type of the output value. Must be assignable from bool. - - Ignored. - Ignored. - - The result of combining the input values using a logical 'and' operation. - - - - - Not supported. Throws a NotImplementedException. - - Ingored. - Ignored. - Ignored. - Ignored. - Never returns. - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - - This is not a real converter, but rather a useful stand-in to help you debug - a binding. - - - - - Constructor. - - - - - Put breakpoint here. - - standard - standard - standard - standard - standard - - - - not used. - - standard - standard - standard - standard - standard - - - - Provides the single static instance of this converter. - - - - - - - Convert a boolean value to an Orientation value and vice versa - true is converted horizontal - false is converted vertical - - - - - Convert a boolean value to an Orientation value - - - - - Convert an Orientation value to a boolean value - - - - - Adapts any converter that outputs a boolean into a Visibility value. - - - Deals generically with the case where you need to bind the result of one converter's - calculation to a Visibility value. - - - - - Constructor - - - - - Forwards this call to SubConverter.Convert(object,Type,object,CultureInfo) and - turns the expected boolean value to a Visibility value. - - - If the result is false, then IsNotVisibleTarget is returned. - - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - if SubConverter returns true, then Visible is returned, otherwise - IsNotVisibleTarget is returned. - - - - - Not implemented. - - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - throws an exception if called - - - - A Converter that outputs a boolean. - - - - - The Visibility returned if the converter returns false. - - - This property can be used to return Visibility.Hidden instead of - Visibility.Collapsed. - - - - - Same as the WPF standed BooleanToVisibilityConverter, except that you can specify the - visibility target when the bound value returns false. - - - - - Constructor - - - - - When the property is bound to a boolean value, the value - that is targeted when the value is false. By default, - returns Visibility.Collapsed. - - - - - Converts from boolean value to Visibility value. - - - True will return Visibility.Visible, false will return the value of TargetHiddenVisibility. - - bound value - not used - not used - not used - - - - - Not implemented. - - Not implemented. - Not implemented. - Not implemented. - Not implemented. - - - - - An inverter version of a classic BooleanToVisibility converter. - - - - - Convert function. - - see docs - see docs - see docs - see docs - If false, return Visible, else Collapsed. - - - - Unconvert function. - - see docs - see docs - see docs - see docs - If Visible, return false, else true. - - - - Converts a Boolean value by inverting it. - - - May be used in XAML as a markup extension. - - - - - Common instance of this converter. May be shared to reduce memory demands, - and provided by the MarkupExtension. - - - - - Invert the given value. - - Value to invert - Target type of the conversion. Must be bool. - Ignored. - Ignored. - - true if value is false, false if value is true, and DependencyProperty.UnsetValue - if value is DependencyProperty.UnsetValue. - - - - - Invert the given value. - - Value to invert - Target type of the conversion. Must be bool. - Ignored. - Ignored. - - true if value is false, false if value is true, and DependencyProperty.UnsetValue - if value is DependencyProperty.UnsetValue. - - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - Test fixture for general-purpose converters. - - - - - Converts from Enum values to human-readable localizable Strings. - - - The human-readable strings can be set directly, or can be inferred from a - ReferenceDictionary. - - - - - - - The Enum type to perform conversions on. - - - - - A Dictionary that contains the comma-seperated string definition of the enum - human-readable values to use. These strings should also be localized. - - - This value can either be set directly, or it can be inferred by setting the - ReferenceDictionary on the converter. The converter will attempt to look for - value with a key equal to the Full class name of the Enum type being converted. - If the AvailableValues array cannot be constructed, then the converter will throw - an exception. - - - - - Converts from an Enum value to a corresponding human-readable string version of the - enum drawn from AvailableValues. - - The enum value. - The target type is String. - not used - not used - The converted value. - - - - Converts from a human-readable string drawn from AvailableValues to a corresponding - Enum value. - - The human-readable string value. - The target Enum type. - not used - not used - The converted value. - - - - Contains the array of human-readable values. - - - This value can either be set directly, or it can be inferred by setting the - ReferenceDictionary on the converter. The converter will attempt to look for - value with a key equal to the Full class name of the Enum type being converted. - If the AvailableValues array cannot be constructed, then the converter will throw - an exception. - - - - - Returns true if the value is greater than zero. Only works with types that - are assignable to Int32. - - - - - Common instance of this converter. May be shared to reduce memory demands, - and provided by the MarkupExtension. - - - - - Returns true if the integer value passed in is greater than zero. - - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - true if > 0. Returns DependencyProperty.UnsetValue if an invalid value type is bound. - - - - Not implemented. - - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - see IValueConverter interface - throws an exception if called - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - Converts a sequence of booleans and returns Visible or Collapsed according to the logical - result. - - - You can make this and AND gate, or an OR gate, by setting the LogicalAnd boolean property. - If you make it an AND gate, then we respect parameter ordering so that an effective null - check can be introduced earlier that will result in a later, possibly invalid argument being - skipped. This is similar to: -
if(null != ref AND ref.SomeProperty) {
- Similarly, a true result on an OR will always result in an early exit. -
-
- - - Default constructor - - - - - Converts from a sequence of boolean values to a visibility value. - - - See Class description remarks for comments regarding parameter precedence. - - series of booleans to evaluate - standard - not used - not used - Visibility.Visible if true, Visibility.Collapsed if false - - - - Not used. - - standard - standard - standard - standard - not used - - - - If true, this converter will perform a logical and on the parameters. Otherwise - - - - - Performs an AND on a list of booleans and returns the NOT value of this. - - - May be used in XAML as a markup extension. - - - - - Common instance of this converter. May be shared to reduce memory demands, - and provided by the MarkupExtension. - - - - - Convert from multiple Boolean input values to a single Boolean output - using a logical 'and'. Returns the NOT of this evaluation. - - Input values, expected to be bool. - - Type of the output value. Must be assignable from bool. - - Ignored. - Ignored. - - The result of combining the input values using a logical 'and' operation, NOT-ed. - - - - - Not supported. Throws a NotImplementedException. - - Ingored. - Ignored. - Ignored. - Ignored. - Never returns. - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - Allows control to bind to a property and only be Visible if the property - is not null. When null, converter returns the value of VisibilityWhenNull, which - is Visibility.Collapsed by default. - - - - - Constructor - - - - - The Visibility returned by this converter when bound source is null. - - - - - Converts a bound source to Visibility, based on whether it's null or not. - - the binding source - not used - not used - not used - Visibility.Visible if not null, or VisibilityWhenNull - - - - Not implemented. - - Not implemented. - Not implemented. - Not implemented. - Not implemented. - Not implemented. - - - - An instance of the converter. Not static because the converter has a member variable. - - not used - An instance of the converter. - - - - Converts a set of Boolean input values into a single Boolean output value - by performing a logical 'or.' - - - May be used in XAML as a markup extension. - - - - - Common instance of this converter. May be shared to reduce memory demands, - and provided by the MarkupExtension. - - - - - Convert from multiple Boolean input values to a single Boolean output - using a logical 'or.' - - Input values, expected to be bool. - - Type of the output value. Must be assignable from bool. - - Ignored. - Ignored. - - The result of combining the input values using a logical 'or' operation. - - - - - Not supported. Throws a NotImplementedException. - - Ingored. - Ignored. - Ignored. - Ignored. - Never returns. - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - SelectMaxDoubleConverter converts an array of doubles - to the max value from the array - - - - - Choose the max value from the array of doubles - - List of doubles - The type of the binding target property - The converter parameter to use - The culture to use in the converter - the max double value from the list - - - - Convert back is not implemented - It throws a NotImplementedException exception when is used - - - - - Implements the MarkupExtension interface to return the shared Converter. - - Not used. - The Converter instance. - - - - Returns true if the passes in string is not null or empty. - - - - - Returns true if the passes in string is not null or empty. - - standard - standard - standard - standard - Converts passed in value to a string, - returns true if the passes in string is not null or empty. - - - - - Not implemented. - - Not implemented. - Not implemented. - Not implemented. - Not implemented. - Not implemented. - - - - Provides the instance used by the markup extension syntax. - - not used - Provides the instance used by the markup extension syntax. - - - - Returns true if the passes in string is null or empty. - - - - - Returns true if the passes in string is null or empty. - - standard - standard - standard - standard - Converts passed in value to a string, - returns true if the passes in string is null or empty. - - - - - Not implemented. - - Not implemented. - Not implemented. - Not implemented. - Not implemented. - Not implemented. - - - - Provides the instance used by the markup extension syntax. - - not used - Provides the instance used by the markup extension syntax. - - - - Removes ampersand hotkey markers from menu text. - - - - - Takes menu text with potential ampersand hotkey markers and strips them. - - value to convert - not used - not used - not used - Text without ampersands. - - - - Not implemented. - - not used - not used - not used - not used - not used - - - - Returns a static instance of the converter. - - not used - a static instance of the converter - - - - CSharpCompilationHelper is a helper class for compiling a c# string as an assembly, and loading that assembly. - - All hail: - https://kenslearningcurve.com/tutorials/compiling-c-code-at-runtime - https://kenslearningcurve.com/tutorials/run-compiled-c-code-at-runtime - - - - Compile a c# string as an assembly and load that assembly. - All assemblies currently loaded by max are automatically referenced. - - Source string. - An array of additional assemblies to reference. - The loaded assembly. - - - - Convenient stand-in for the thread-safe delegate invocation idiom. - - - For example, instead of invoking a Click event handler in a thread-safe - manner by writing: - - EventHandler<EventArgs> threadSafeDelegateCopy = Click; - if(null != threadSafeDelegateCopy) - { - threadSafeDelegateCopy(this, EventArgs.Empty); - } - - - It can be invoked equivalently, but more simply using the DelegateCaller as: - - DelegateCaller.Call(Click, this, EventArgs.Empty); - - - - - - Construct a DelegateCaller to call the given Delegate d. - - The delegate to safely call. - - - - Is the encapsulated delegate valid and callable? - - - - - Calls the encapsulated delegate (possibly a multicast delegate) and - returns the object returned by the delegate. - - - - Traps any thrown exception. - - Arguments passed to the delegate - The delegate's return value. - - - - Call the given delegate or event with the given arguments. - - The delegate to call. - The C# params modifier is roughly equivalent to the C++ ellipsis (...). - It will build the args parameter array from the caller site parameter list. - In this case, the arguments must be of the type and in the order expected - by the delegate. - The delgate's return value. - - - The encapsulated delegate. - - - - This is an adpater of System.Windows.Forms.Screen, in order to - get rid of System.Windows.Forms dependency for WPF dlls. I choose - the name "DesktopScreen" just don't want to mess up with some existing - code that uses System.Windows.Forms.Screen(e.g. UserInterfaceUtilities). - - - - - Return an Screen object that contains a specified point. - - - The testing point. - - - - - Adapts System.Windows.Forms.Screen.Bounds. - - - - - Adapts System.Windows.Forms.Screen.DeviceName. - - - - - Constructor - - - The underlying System::Windows::Forms::Screen object. - - - - - the underlying System::Windows::Forms::Screen object - - - - - Adding this attribute to a class that is instantiated via the Max bootstrapping - mechanism will provide 'natural' keyboard focus selection for elements that desire - it. This is mainly used to mark-up the MaxTextBox as being keyboard focus sensitive - (so that Max does not intercept keyboard commands and run that as command hotkeys). - Any other FrameworkElement that needs keyboard focus can add this attribute to the - class declaration to have Max assign it automatically. - - - - - Static class that contains function useful for UI DPI scaling. - - - - - Return the dpi scale factor. - - monitor ID. - - The dpi scale factor. - - - - - Return the dpi scale factor. - - - The dpi scale factor. - - - - - Return the user scale factor. - - - The user scale factor. - - - - - Scales the given measure according to DPI. - - measurement to scale. - - DPI scaled measure. - - - - - Scales the given size according to DPI. - - size to scale. - - DPI scaled size. - - - - - Scales the given size according to DPI. - - width to scale. - height to scale. - - DPI scaled System.Drawing.Size. - - - - - Dummy Enumerable to serve as a wrapper around an Enumerator for easy use - in a foreach loop. - - - - Given an enumerator for performing a custom iteration, this class serves to - spare the work of also creating an Enumerable just so that the enumerator - can be used in a foreach loop. - - - This class is generally used as: - - foreach(object myobject in new Enumerable<object>(myCustomEnumerator))... - - - - Type over which the Enumerator enumerates. - - - - Constructor taking the target enumerator. - - The enumerator to use for enumeration. - - - - Get the encapsulated enumerator. - - The encapsulated enumerator. - - - - Get the encapsulated enumerator. - - The encapsulated enumerator. - - - The encapsulated enumerator. - - - - Provides an extension of the typesafe enum idiom for complex types. - - The enumerated type. - - - The standard .NET enum implementation allows the programmer to create - a set of named object instances around one of the primitive data types such - as int or byte. ExtendedEnum provides much of enum's functionality around - any user-defined, preferably immutable, type that inherits from it. - This version of ExtendedEnum uses the curiously recursive template pattern - to allow users to create an Enum whose underlying value is the class itself. - - - To use ExtendedEnum, create a derived class in which the set of instances are - defined as static constant members of the class. For example, say we want a - predefined set of Balls each defined by its radius and bounciness, we could - declare these as an ExtendedEnum: - - class Ball : ExtendedEnum<Ball> - { - public static readonly Ball Golf = new Ball(1, 10); - public static readonly Ball Billiard = new Ball(2, 1); - public static readonly Ball Baseball = new Ball(3, 3); - public static readonly Ball Soccer = new Ball(8, 4); - public static readonly Ball Basketball = new Ball(10, 5); - // etc - - - - public int Radius { get { return mRadius;} } - public int Bounciness { get { return mBounciness;} } - - - private Ball(int radius, int bounciness) - { - mRadius = radius; - mBounciness = bounciness; - } - - private int mRadius; - private int mBounciness; - } - - - - Client code may now refer to members of the Ball enumeration as Ball.Golf or - Ball.Billiard, much as it would for any standard enumeration. This - enumeration is also closed at compile time since the constructor is private. - - - When creating a class such as Ball which inherits from ExtendedEnum, - the generic parameter T must be the generic class itself (i.e. Ball) or - one of its base classes. - - class Ball : ExtendedEnum<Ball> // Valid - {...} - - class TennisRacket : ExtendedEnum <Ball> // Invalid - {...} - - Note: This will add values to ExtendedEnum<Ball> - class SpecializedBall : Ball // Valid. - {...} - - - - - - - The underlying type exposed as an Enum through this class. - - - - - Produces an array of all the Enum's members. - - - Changing the returned array will not affect this ExtendedEnum type. - - - - - Finds the ExtendedEnum member wrapping the given value. - - The value to find in this Enum. - - Either the found Enum member or null if no member is found. - - - - - Determine if this ExtendedEnum type contains the given value. - - The value to try to find. - - true if value is found as a member of this Enum, false if not. - - - - - Determine if this ExtendedEnum type contains the given value. - - The value to try to find. - - true if value is found as a member of this Enum, false if not. - - - - - Determine the equality of this ExtendedEnum member to another - ExtendedEnum member. - - - The equivalence is established based on the rank of the extended enum elements. - - The other ExtendedEnum for comparison. - - true if this.Id == other.Id, - false if not. - - - - - Determine the equality of this ExtendedEnum member to another - value. - - - The equivalence is established based on the rank of the extended enum elements. - - - T value against which to compare this ExtendedEnum member. - - true if this.Id == other.Id. - - - - Determine the equality of this ExtendedEnum member to another object. - - - object against which to compare this ExtendedEnum member. - - - - Returns false if other is null. - Returns true if other is referentially equal to this. - Returns true if other is a T and this.Equals( (T)other ). - Returns true if other is an ExtendedEnum<T> and - this.Equals( (ExtendedEnum<T>)other ). - Returns false otherwise. - - - - - - Get a hash code for this ExtendedEnum member. - - - A hash code dependent on this enum type and on this enum member's Id. - - - - - Compare this to another member of this ExtendedEnum, ordered according - to their Ids. - - Other member against which to compare. - <0 if this member is ranked first, 0 if they are the same - member, and >0 if other should be ranked first. - - - - The underlying T value wrapped in this ExtendedEnum. - - - - - Static constructor - - - For the Ball example above, the static fields Ball.GolfBall, Ball.Basketball are - initialized in the static constructor. According to the .Net specifications, - a static constructor is called automatically to initialize the class - before the first instance is created or any static members are referenced. - If clients would call: Ball.Values, before any field in Ball would be referenced - (e.g. Ball.BasketBall.DoSomething()), then the Values array would be empty. - This happens because the .Net compiler performs optimizations and does not call - the derived class' (e.g. Ball) static constructor. Instead, it calls base.Values. - To avoid this, we use reflection to reference a static field in the caller class - which will trigger the call to the derived class' static constructor. - - - - - Constructor intended for the default case, where the enumerated type is - the derived type. - - - Also checks to see if the curiously recursive template pattern requirements - are satisfied. - - - - - Provides the next Id value to assign to an Enum member added to the list. - - - The next id is maintained in this counter instead of using - sValues.Count to be future-proof against the possibility of - removing Enum members from the list. - - - - - The list of members in this Enum. - - - - - Provides an extension of the typesafe enum idiom for complex types. - - The enumerated type. - The underlying value type. - - - The standard .NET enum implementation allows the programmer to create - a set of named object instances around one of the primitive data types such - as int or byte. ExtendedEnum provides much of enum's functionality around - any user-defined, preferably immutable, type. - This version of ExtendedEnum allows users to create an Enum whose underlying - value is a user-defined or primitive type. It also uses the curiously recursive - template pattern to ensure that enums with the same Underlying type, which are - derived from different classes, do not share their values. - - - To use ExtendedEnum, create a derived class in which the set of instances are - defined as static constant members of the class. For example, say we want a - predefined set of Balls with their name (String) as their UnderlyingValue, - each defined by their name, radius and bounciness, we could - declare these as an ExtendedEnum: - - class Ball : ExtendedEnum<Ball, String> - { - public static readonly Ball Golf = new Ball("Golf", 1, 2); - public static readonly Ball Billiard = new Ball("Billiard", 3, 2); - public static readonly Ball Baseball = new Ball("Baseball", 4, 3); - public static readonly Ball Soccer = new Ball("Soccer", 10, 7); - public static readonly Ball Basketball = new Ball("Basketball", 12, 10); - // etc - - - public String Name {get { return mName;} } - public int Radius { get { return mRadius;} } - public int Bounciness { get { return mBounciness;} } - - - private Ball(String name, int radius, int bounciness) : base(name) - { - mName = name; - mRadius = radius; - mBounciness = bounciness; - } - - private String name; - private int mRadius; - private int mBounciness; - } - - - - Client code may now refer to members of the Ball enumeration as Ball.Golf or - Ball.Billiard, much as it would for any standard enumeration. This - enumeration is also closed at compile time since the constructor is private. - - - When creating a class such as Ball which inherits from ExtendedEnum, - the generic parameter T must be the generic class itself (i.e. Ball) or - one of its base classes. - - class Ball : ExtendedEnum<Ball, String> // Valid - {...} - - class TennisRacket : ExtendedEnum <Ball, String> // Invalid - {...} - - class SpecializedBall : Ball // Valid - {...} - - - - - - - The underlying type exposed as an Enum through this class. - - - - - Produces an array of all the Enum's members. - - - Changing the returned array will not affect this ExtendedEnum type. - - - - - Finds the ExtendedEnum member wrapping the given value. - - The value to find in this Enum. - - Either the found Enum member or null if no member is found. - - - - - Determine if this ExtendedEnum type contains the given value. - - The value to try to find. - - true if value is found as a member of this Enum, false if not. - - - - - Determine if this ExtendedEnum type contains the given value. - - The value to try to find. - - true if value is found as a member of this Enum, false if not. - - - - - Converts from ExtendedEnum<T, U> to U. - - - This is equivalent to calling UnderlyingValue. - - The ExtendedEnum member to convert. - value's underlying value. - - - - Determine the equality of this ExtendedEnum member to another - ExtendedEnum member. - - - This is equivalent to calling - UnderlyingValue.Equals(other.UnderlyingValue). - - The other value for comparison. - - true if this.UnderlyingValue.Equals(other.UnderlyingValue), - false if not. - - - - - Determine the equality of this ExtendedEnum member to another - value. - - - This is equivalent to calling UnderlyingValue.Equals(other). - - - T value against which to compare this ExtendedEnum member. - - true if this.UnderlyingValue.Equals(other). - - - - Determine the equality of this ExtendedEnum member to another object. - - - object against which to compare this ExtendedEnum member. - - - - Returns false if other is null. - Returns true if other is referentially equal to this. - Returns true if other is a U and this.Equals( (U)other ). - Returns true if other is an ExtendedEnum<T, U> and - this.Equals( (ExtendedEnum<T, U>)other ). - Returns false otherwise. - - - - - - Get a hash code for this ExtendedEnum member. - - - A hash code dependent on this enum type and on this enum member's Id. - - - - - Compare this to another member of this ExtendedEnum, ordered according - to their Ids. - - Other member against which to compare. - <0 if this member is ranked first, 0 if they are the same - member, and >0 if other should be ranked first. - - - - The underlying T value wrapped in this ExtendedEnum. - - - - - Get the string representation for this ExtendedEnum member. - - - Equivalent to calling UnderlyingValue.ToString(). - - The string representation for this ExtendedEnum member. - - - - Static constructor - - - For the Ball example above, the static fields Ball.GolfBall, Ball.Basketball are - initialized in the static constructor. According to the .Net specifications, - a static constructor is called automatically to initialize the class - before the first instance is created or any static members are referenced. - If clients would call: Ball.Values, before any field in Ball would be referenced - (e.g. Ball.BasketBall.DoSomething()), then the Values array would be empty. - This happens because the .Net compiler performs optimizations and does not call - the derived class' (e.g. Ball) static constructor. It directly calls base.Values. - To avoid this, we use reflection to reference a static field in the caller class - which will trigger the call to the derived class' static constructor. - - - - - Constructor intended for enumerations designating a certain set of - instances from another type. - - - This means that instances of the generic - parameter U type can be constructed without labeling them as members - of the enumeration. - Also checks to see if the curiously recursive template pattern requirements - are satisfied. - - - U value to wrap as an ExtendedEnum member. - - - - - The underlying T value wrapped by this ExtendedEnum instance. - - - - - Provides the next Id value to assign to an Enum member added to the list. - - - The next id is maintained in this counter instead of using - sValues.Count to be future-proof against the possibility of - removing Enum members from the list. - - - - - The list of members in this Enum. - - - - - Base class used to identify the classes that derive from ExtendedEnum - - - Clients that want to identify which classes derive from the ExtendedEnum can do so, - by looking for this base class. - - - - - Constructor - - - The id for each value in the ExtendedEnum - - - - - Uses reflection to call the ExtendedEnum's Values property - - - The ExtendedEnum class type - - - An array containing all the ExtendedEnum's members. - - - - - Uses reflection to call the static constructor. - - - According to the .Net specifications a static constructor cannot be called directly. - However, using reflections to artificially reference one of the class' static variables, - its the static constructor will be automatically called. - - - The class type whose static constructor needs to be called. - - - - - Checks to see if the curiously recursive template pattern is being correctly - implemented between the two class types. - - - - The derived type which should be or derive from the enumeratedType. - - - The enumeratedType. - - - - - The numerical Id for this ExtendedEnum within the enum's set. - - - These Ids are used for ordering the members within the enum. - - - - - ExtendedEnum id. This provides the ordering within the set. - - - - - Class that inherits from ExtendedEnum, used for testing purposes - - - - - Class that inherits from ExtendedEnum with 2 generic parameters - - - - - This class extends standard ComponentResourceManager and adds the support to - MultiIcon, Icon and Image resources. - - - C++/CLI projects can manage a single instance of this class and use it - to implement resource management for the assembly. By providing static methods - accessing a single instance of this class, the resources management class may more - closely resemble the designer-generated resource management classes in C# projects. - - - - - Constructor. - - - - - Construct a resource manager that looks up resources in satellite - assemblies based on information from the specified type. - - - A Type from which the resource manager derives all information for - finding resource files. - - - - - Get a MultiIcon resource from the assembly's set of resources. - - - Key string used to identify the desired resource. - - - The resource specified by the given key, or null if the resource is not - found. - - - - - Get an Icon resource from the assembly's set of resources. - - - Key string used to identify the desired resource. - - - The resource specified by the given key, or null if the resource is not - found. - - - - - Get an Image resource from the assembly's set of resources. - - - Key string used to identify the desired resource. - - - The resource specified by the given key, or null if the resource is not - found. - - - - - Empty class paired to ExtendedResourceManagerTestResources.resx to allow - the resource manager instance in ExtendedResourceManagerTest to find - the resources through a type. - - - - - Test Class which inherits from an ExtendedEnum with 2 generic parameters. - - - The second generic parameter is a complex type - - - - - Test Class which inherits from an ExtendedEnum with 2 generic parameters. - - - The second generic parameter is an integral type - - - - - Test Class which inherits from an ExtendedEnum with 2 generic parameters. - - - Used to test that ExtendedEnums built around the same underlying types (String) - do not have the same values. - - - - - Test Class which inherits from an ExtendedEnum with 2 generic parameters. - - - Used to test that ExtendedEnums built around the same underlying types (String) - do not have the same values. - - - - - FileUtilities.SafeWrite passes control to this delegate to perform - specific writing. - - - Open stream to which the delegate may write. Note that the delegate - should close this stream or any enclosing writer (e.g. StreamWriter) object - to ensure that the output is flushed. - - - - - FileUtilities.SafeWrite passes control to this delegate to perform validation - of the temporary output file. If validation fails, original file if present remains, - otherwise the original file is replaced by the temporary output file. - - - The file name of the temporary file to validate. - - - The file name of the temporary file to validate. - - true if the validation succeeded. - - - - FileUtilities.SafeWriteXml passes control to this delegate to perform - specific writing. - - Open XmlWriter around an output stream. - - - - FileUtilities.SafeWriteText passes control to this delegate to perform - specific writing. - - Open StreamWriter around an output stream. - - - - Class that contains useful file-related operations. - - - - - Copies source file to destination and makes it writeable. - - The file to copy. - The place to copy it to. - - - - Wraps a delegate write method to ensure that any exception thrown - during the write process does not corrupt the original file. - - - - SafeWrite works by: - - Opening a FileStream on a temporary file with write permissions - Passing the stream to the delegate to carry out the actual writing - Moving the successfully written file to the actual destination path - - - - The WriteMethod must close any enclosing writer it creates, and the stream - through that close, in order to guarantee that all its output is flushed to - the file. - - - Output location for the written file. - Delegate to perform the specific writing. - - - - Wraps a delegate write method to ensure that any exception thrown - during the write process does not corrupt the original file. - - - - SafeWrite works by: - - Opening a FileStream on a temporary file with write permissions - Passing the stream to the delegate to carry out the actual writing - Moving the successfully written file to the actual destination path - - - - The WriteMethod must close any enclosing writer it creates, and the stream - through that close, in order to guarantee that all its output is flushed to - the file. - - - Output location for the written file. - Delegate to perform the specific writing. - Delegate to perform validation. - - - - Wraps a delegate write method to ensure that any exception thrown - during the write process does not corrupt the original file. - - - - SafeWriteXml is a convenience method around SafeWrite for writing - XML documents. It provides an XmlWriter to the delegate and ensures - that the writer is flushed and closed after the delegate returns control. - - - - This version uses the default FileUtilities.XmlWriterSettings as the - XmlWriter's settings. - - - Output location for the written file. - Delegate to perform the specific writing. - - - - Wraps a delegate write method to ensure that any exception thrown - during the write process does not corrupt the original file. - - - SafeWriteXml is a convenience method around SafeWrite for writing - XML documents. It provides an XmlWriter to the delegate and ensures - that the writer is flushed and closed after the delegate returns control. It - also provides an validator to ensure the written file is readable as an xml doc - - - Output location for the written file. - Delegate to perform the specific writing. - XmlWriterSettings to use in the XmlWriter - - - - Wraps a delegate write method to ensure that any exception thrown - during the write process does not corrupt the original file. - - - SafeWriteText is a convenience method around SafeWrite for writing - text output. It provides a StreamWriter to the delegate and ensures - that the writer is flushed and closed after the delegate returns control. - - - Output location for the written file. - Delegate to perform the specific writing. - - - - Recommended file settings for xml files written by the application. - - - - - A IconDeviceIndependentBitmap stores a device independent bitmap (DIB). - This class makes the loading and saving of *.ico files much easier. - - - The format of the wrapped bitmap in IconDeviceIndependentBitmap is a - little bit different with standard windows bitmap: It contains a - "xor mask" and an "and mask". - - For more information about the icon DIB format, please reference msdn: - http://msdn.microsoft.com/en-us/library/ms997538.aspx - - - - - Construct an empty IconDeviceIndependentBitmap with the given - width, height and color bit count. - - - The width of the icon. This parameter must be ranged in [1, 255] - - - The height of the icon. This parameter must be ranged in [1, 255] - - - The color bit count of the icon. This parameter must be greater than - 8 because we don't support palette colors for now. - - - Throws if width or height is not ranged in [1, 255], or if - colorBitCount is less than or equal to 8. - - - - - Construct an IconDeviceIndependentBitmap from the given bitmap. - - - The given bitmap. - - - Throws if bitmap.Width or bitmap.Height exceeds 255, or if color bit - count of the given bitmap is less than or equal to 8. - - - - - Load an IconDeviceIndependentBitmap from the given stream. - - - The given stream. - - - Throws if the stream contains an invalid icon. - - - - - Write this IconDeviceIndependentBitmap to the given stream. - - - The given stream. - - - - - Calculate the total bytes of a IconDeviceIndependentBitmap that - will be stored in file, including the dib header (Notice the dib - header is not icon file entry). - - - The width of that dib. - - - The height of that dib. - - - The color bit count of that dib. - - - The total bytes of that dib. - - - - - Get the dib header size. - - - The dib header size. - - - - - Get the palette size of this dib. - - - The palette size of this dib. - - - - - Get the xor mask size. - - - The xor mask size. - - - - - Get the and mask size. - - - The and mask size. - - - - - Get the total bytes of a IconDeviceIndependentBitmap that will be stored in file, - including the dib header. - - - - - The width of this dib. - - - - - The height of this dib. - - - - - The color bit count of this dib. - - - - - The xor mask array of this dib. In DEFAULT_COLOR_BIT_COUNT bit argb format. - - - - - The and mask array of this dib. Each bit represents a pixel. - - - - - Default color bit count of default pixel format. - - - - - Default pixel format. - - - - - Calculate the 4-bytes aligned byte count from the total bit count. - - - total bit count. - - - corresponding 4-bytes aligned size. In bytes. - - - - - Calculate the 4-bytes aligned size of each line of the DIB. - - - The width of the dib. - - - The color bit count of the dib. - - - The 4-bytes aligned size of each line of the dib. - - - - - Get the DEFAULT_COLOR_BIT_COUNT-bit rgb array from a given bitmap. - - - The given bitmap. - - - The DEFAULT_COLOR_BIT_COUNT-bit rgb array of the bitmap. If the bitmap - is other format, we performed a temporary format conversion. If the - conversion failed, this function returns null. - - - - - Create an empty "and mask" for this DIB. - - - - - Calculate how many colors should be used in palette. - - - The color bit count. - - - How many colors should be used in palette. - - - - - Get the size of bytes of each color entry in palette. - - - The size of bytes of each color entry in palette. - - - - - Get the size of bytes of color palette. - - - How many colors are used? - - - The size of bytes of color palette. - - - - - Check if the input parameters are valid. - - - true if the parameters are valid, false otherwise. - - - - - Calculate the total bytes of this IconDeviceIndependentBitmap that - will be stored in file, including the dib header (Notice the dib - header is not icon file entry). - - - - - Specifies the number of bytes required by the header structure. - - - - - Specifies the width of the bitmap, in pixels. - - - - - Specifies the height of the bitmap, in pixels. - - - - - Specifies the number of planes for the target device. - This value must be set to 1. - - - - - Specifies the number of bits-per-pixel. This determines the xor - mask format. - - - - - Specifies the type of compression of this bitmap. This is always - zero in our case because we don't handle compressed bitmaps. - - - - - Specifies the size, in bytes, of the image. Including bitmap headers - and palette. - - - - - Specifies the horizontal resolution, in pixels-per-meter, of the - target device for the bitmap. An application can use this value to - select a bitmap from a resource group that best matches the - characteristics of the current device. - - - - - Specifies the vertical resolution, in pixels-per-meter, of the - target device for the bitmap. - - - - - Specifies the number of color indexes in the color table that are - actually used by the bitmap. If this value is zero, the bitmap uses - the maximum number of colors corresponding to the value of the - mColorBitCount member for the compression mode specified by mCompression. - - - - - Specifies the number of color indexes that are required for - displaying the bitmap. If this value is zero, all colors are required. - - - - - The xor mask of this bitmap. Please see remarks of this class. - - - - - The and mask of this bitmap. Please see remarks of this class. - - - - - A utility class for converting Icon formats used in Windows Forms - and WPF. - - - - - Converts a Icon object (used by Windows Forms) into an ImageSource - supported by WPF. - - A valid Icon object. - An ImageSource object. - - - - This utility class is used for manipulating icons. - - - - - Convert a bitmap to an GDI+ Icon (32bit color). The returned icon - supports transparent color and alpha channel. - - - - This is much better than Icon.FromHandle(bitmap.GetHIcon()). If you - used the Bitmap.GetHIcon, you must explicitly depose that handle - by calling win32 api: DestroyIcon. However, using out method here you - don't need to worry about GDI resource leak because we perform the - conversion based on data stream but not on GDI handles. - - - For more information, please reference: - http://www.codeproject.com/dotnet/MultiIcon.asp - - - - - - Load all DIBs from the given stream, convert those DIBs to Icons, - and then returns an array of those separate Icons. - - - Stream containing one icon data. - - - An icon file may contains a set of DIBs for displaying under - different resolution. This function just separates those DIBs and - converts each DIB into an Icon. - - - - - Build an Icon from the given Icon specification information: the - file header, entry specification data, and data stream. - - Header data from the icon file. - - Descriptor for the current icon entry to be extracted. - - Stream containing the icon data. - A new Icon built from the given specification and data. - - - - Storage for the header information from the .ico file. - - - - - The size of this structure. - - - - - Construct from an Icon data stream. - - - - - Construct from icon count. - - - - - Write this header to a stream. - - - - - Storage for entry information from the .ico file. - - - - - The size of this structure. - - - - - Construct from a bitmap and the index of this icon entry. Notice - that the index starts from zero. - - - - - Construct from an Icon data stream. - - - - - Write this structure to a stream. - - - - - Icon header information for individual Icons. - - - - - Icon header information for individual Icons. - - - - - A first-class object, bit masks and query functions for the - DragEventArgs.KeyState and QueryContinueDragEventArgs.KeyState properties - as defined in the msdn documentation. - - These aren't formalised anywhere in the .NET framework. - - - Mask values taken from DragEventArgs.KeyState and - QueryContinueDragEventArgs.KeyState properties as specified in the msdn - documentation. - - - Left mouse button bit field. - - - Right mouse button bit field. - - - Shift key bit field. - - - Ctrl key bit field. - - - Middle mouse button bit field. - - - Alt key bit field. - - - - Constructor. Takes the bitfield from DragEventArgs.KeyState or - QueryContinueDragEventArgs.KeyState. - - The bitfield from DragEventArgs.KeyState or - QueryContinueDragEventArgs.KeyState. - - - The encapsulated KeyState bit field. - - - - Determine if this KeyState is equal to another KeyState value. Two - KeyStates are equal if they have exactly equal Bits. - - The object against which to compare. - true if other is a KeyState and has exactly the same Bits as - this. false otherwise. - - - - Get a hash code for this KeyState value. - - Hash code created from the Bits value. - - - - Is the left mouse button pressed? - - - - - Is the right mouse button pressed? - - - - - Is the middle mouse button pressed? - - - - - Is the Shift key pressed? - - - - - Is the Ctrl key pressed? - - - - - Is the Alt key pressed? - - - - - The encapsulated KeyState bit field. - - - - - Collection of convenience methods for establishing data bindings in code. - - - - - Construct and set a Binding from the given source property to the target - DependencyProperty, using the default BindingMode. - - Source object. - Path to the source property. - Target object. - Target DependencyProperty. - - BindingExpression for the newly established binding. - - - - - Construct and set a Binding from the given source property to the target - DependencyProperty, using the default BindingMode. - - Source object. - Path to the source property. - Target object. - Target DependencyProperty. - Converts from the source value to the target value. - - BindingExpression for the newly established binding. - - - - - Construct and set a Binding from the given source property to the target - DependencyProperty, using a specified BindingMode. - - Source object. - Path to the source property. - Target object. - Target DependencyProperty. - The desired BindingMode. - - BindingExpression for the newly established binding. - - - - - Construct and set a Binding from the given source property to the target - DependencyProperty, using a specified BindingMode. - - Source object. - Path to the source property. - Target object. - Target DependencyProperty. - Converts from the source value to the target value. - The desired BindingMode. - - BindingExpression for the newly established binding. - - - - - Construct and set a Binding from the given source property to the target - DependencyProperty, using a specified BindingMode. - - Source object. - Path to the source property. - Target object. - Target DependencyProperty. - Converts from the source value to the target value. - - Parameter passed to the converter's Convert and ConvertBack methods. - - The desired BindingMode. - - BindingExpression for the newly established binding. - - - - - - Debugging class useful for finding memory leaks. - - - - If you think you are leaking instances of a class, but are having a hard - time distinguishing valid instances from invalid ones in a memory profiler, - create a reference to a MemoryMarker object from your leaked object at a - point just before the object should terminate. - - - For example, to find leaked instances of WPFCustomControls.MaxRibbonControl, - we can add a reference to a new MemoryMarker during HandleUnloaded. We can - then identify the roots for the leaked MaxRibbonControl instance by looking - for the MemoryMarker instance. - - - - - - MultiIcon is a reader and container for icon resources. - - - - - Although an .ico file may be authored to include multiple icons, the .NET - Framework lacks any useful way to manage these files. - - - This implementation is inspired by this article on CodeProject: - http://www.codeproject.com/dotnet/MultiIcon.asp - The .ico file format is documented there as well. - - - CSharpUtilities.MultiIcon can be used as a ResXFileRef in a .resx file in C#, - but it doesn't seem to work in C++/CLI. Until we solve that, the resource - can be typed as a System.Byte[] in the resx file, and then the - MultiIcon constructor will extract the icons from that array. - - - - - - Construct from a String specifying the path to the icon file. - - Path pointing to the chosen icon file. - - - - Construct from an object Stream holding the icons. - - Stream holding the icon data. - - - - Construct from an array of icons. - - Array of icons to package as a MultiIcon. - - - - Construct from a single bitmap. - - Single bitmap to package as a MultiIcon. - - - - Construct from a single Icon. - - Single icon to package as a MultiIcon. - - - - Finalizer. - - - - - Sort icons in order of area - - - - - The list of Icons contained in this MultiIcon. - - - - - Get the largest Icon contained in this MultiIcon. - - - The largest Icon size is determined by comparing the areas of each Icon. - - - The largest Icon contained in this MultiIcon. - - - - - Get the largest Icon index contained in this MultiIcon. - - - The largest Icon size is determined by comparing the areas of each Icon. - - - The largest Icon index contained in this MultiIcon, or -1 if empty. - - - - - Get the largest Icon contained in this MultiIcon, converted to an Image. - - - The largest Icon size is determined by comparing the areas of each Icon. - This method is equivalent to ConvertIconToImage(GetLargestIcon()) - - - The largest Icon contained in this MultiIcon, converted to an Image. - - - - - Get the smallest Icon contained in this MultiIcon. - - - The smallest Icon size is determined by comparing the areas of each Icon. - - - The smallest Icon contained in this MultiIcon. - - - - - Get the smallest Icon index contained in this MultiIcon. - - - The smallest Icon size is determined by comparing the areas of each Icon. - - - The smallest Icon index contained in this MultiIcon, or -1 if empty. - - - - - Get the smallest Icon contained in this MultiIcon, converted to an Image. - - - The smallest Icon size is determined by comparing the areas of each Icon. - This method is equivalent to ConvertIconToImage(GetSmallestIcon()) - - - The smallest Icon contained in this MultiIcon, converted to an Image. - - - - - Get the largest Icon from this MultiIcon that fits within the given - maximum Size. - - - "Fits" means that Icon.Width <= maximumSize.Width and - Icon.Height <= maximumSize.Height. - - - The constraint size. The returned Icon must fit in this size. - - - The largest icon from this MultiIcon that fits within maximumSize, or - null if no such Icon is found. - - - - - Get the largest Icon index from this MultiIcon that fits within the given - maximum Size. - - - "Fits" means that Icon.Width <= maximumSize.Width and - Icon.Height <= maximumSize.Height. - - - The constraint size. The returned Icon must fit in this size. - - - The largest icon index from this MultiIcon that fits within maximumSize, or - -1 if no such Icon is found. - - - - - Get the largest Icon from this MultiIcon that fits within the given - maximum Size, converted to an Image. - - - "Fits" means that Icon.Width <= maximumSize.Width and - Icon.Height <= maximumSize.Height. - Equivalent to ConvertIconToImage(GetLargestIconNotLargerThan(maximumSize)). - - - The constraint size. The returned Icon must fit in this size. - - - The largest icon from this MultiIcon that fits within maximumSize, or - null if no such Icon is found. - - - - - Get the smallest Icon from this MultiIcon that completely covers the - given minimum Size. - - - Covering the minimum size means that minimumSize.Width <= Icon.Width - and maximumSize.Height <= Icon.Height. - - - The constraint size. Each of the icon's dimensions must be greater than - or equal to the corresponding dimension from this Size. - - - The smallest Icon from this MultiIcon that covers minimumSize, or null - if no such Icon is found. - - - - - Get the smallest Icon index from this MultiIcon that completely covers the - given minimum Size. - - - Covering the minimum size means that minimumSize.Width <= Icon.Width - and maximumSize.Height <= Icon.Height. - - - The constraint size. Each of the icon's dimensions must be greater than - or equal to the corresponding dimension from this Size. - - - The smallest Icon index from this MultiIcon that covers minimumSize, or -1 - if no such Icon is found. - - - - - Get the smallest Icon from this MultiIcon that completely covers the - given minimum Size, converted to an Image. - - - Covering the minimum size means that minimumSize.Width <= Icon.Width - and maximumSize.Height <= Icon.Height. - This method is equivalent to - ConvertIconToImage(GetSmallestIconNotSmallerThan(minimumSize)). - - - The constraint size. Each of the icon's dimensions must be greater than - or equal to the corresponding dimension from this Size. - - - The smallest Icon from this MultiIcon that covers minimumSize, or null - if no such Icon is found. - - - - - Calculates the size of the icon according to dpi and returns the downscaled icon. - This function does not upscale the original icon, make sure the icon supports a size big enough to cover specific dpi. - If there isn't an icon large enough to cover desired dpi, the largest icon available is returned. - Assumes that the base image size is 16x16 at 100% dpi, for a more customizable function, use GetDPIAwareIcon(int refWidth, int refHeight) - - - The scaled icon. - - - - - Calculates the size of the icon according to dpi and returns the downscaled icon index. - This function does not upscale the original icon, make sure the icon supports a size big enough to cover specific dpi. - If there isn't an icon large enough to cover desired dpi, the largest icon available is returned. - Assumes that the base image size is 16x16 at 100% dpi, for a more customizable function, use GetDPIAwareIcon(int refWidth, int refHeight) - - - The scaled icon index, or -1 if you need to compute it. - - - - - Calculates the size of the icon according to dpi and returns the downscaled icon. - This function does not upscale the original icon, make sure the icon supports a size big enough to cover specific dpi. - If there isn't an icon large enough to cover desired dpi, the largest icon available is returned. - - - image width at 100% dpi. If refWidth is equal -1, the width of the smallest image available in the ico file is considered. - - - image height at 100% dpi. If refHeight is equal -1, the height of the smallest image available in the ico file is considered. - - - The scaled icon. - - - - - Calculates the size of the icon according to dpi and returns the downscaled icon index. - This function does not upscale the original icon, make sure the icon supports a size big enough to cover specific dpi. - If there isn't an icon large enough to cover desired dpi, the largest icon available is returned. - - - image width at 100% dpi. If refWidth is equal -1, the width of the smallest image available in the ico file is considered. - - - image height at 100% dpi. If refHeight is equal -1, the height of the smallest image available in the ico file is considered. - - - The scaled icon index or -1 if you need to compute it. - - - - - Calculates the size of the icon according to dpi and returns the downscaled icon converted to image. - This function does not upscale the original icon, make sure the icon supports a size big enough to cover specific dpi. - - - The scaled image. - - - - - Converts the given Icon to a bitmap image. - - Icon to convert to an Image. - Image created from the given icon. - - - - Scales the given Icon to finalSize, producing a new Icon instance. - - - The original Icon to resize. This Icon instance will not be affected. - - - The desired final size for the resulting scaled Icon. - - - A new Icon, created by scaling the originalIcon to finalSize. - - - - - Load all Icons from the file specified by the given path. - - - Traps any thrown exceptions. - - - - - Load PNG Icons from the specified filepath. if filepath= Directory/filename.png, it loads all - files that are: directory/filename_XX.png. - - - - - Check wether specified file is png by testing the extension - - file name with or without path - - True if file extension is png. False otherwise. - - - - - Helper IComparer class for comparing two Sizes by area. - - - - - Compare the two given Sizes by area. - - left hand side operand - right hand side operand - - Less than zero if lhs is less than rhs. - Zero if lhs and rhs equal. - Greater than zero if lhs is greater than rhs. - - - - - Helper IComparer class for comparing two Icon Sizes by area. - - - - - Compare the two given Icon Sizes by area. - - left hand side operand - right hand side operand - - Less than zero if lhs is less than rhs. - Zero if lhs and rhs equal. - Greater than zero if lhs is greater than rhs. - - - - - Determine if the lhs Size is absolutely <= the rhs Size. That is, - lhs.Width <= rhs.Width and lhs.Height <= rhs.Height. - - Left hand side operand. - Right hand side operand. - - true if lhs is less than or equal to rhs. false otherwise. - - - - - Determine if the lhs Size is absolutely >= the rhs Size. That is, - lhs.Width >= rhs.Width and lhs.Height >= rhs.Height. - - Left hand side operand. - Right hand side operand. - - true if lhs is greater than or equal to rhs. false otherwise. - - - - - Share a single empty list for all empty MultiIcons. - - - - - The list of Icons contained in this MultiIcon. - - - - - Fills the image icon cache with images. - - - - - Share a single empty list for all empty cached icon images. - - - - - The list of Icons contained in this MultiIcon. - - - - - Generic Pair structure, often useful for keeping ordered lists of - associated objects. - - Type for the first item in the pair. - Type for the second item in the pair. - - - - Constructor. - - First item - Second item - - - - The first item in the Pair. - - - - - The second item in the Pair. - - - - - Get a hash code for this object. - - A hash code for this object. - - - - Determine if this Pair is equal to the passed in Object. - - Object to evaluate for equality with this Pair. - true if this Pair is equal to the passed in Object. - - - - The first item in the Pair. - - - - - The second item in the Pair. - - - - - Ordered associative list. - - Type of the first item in each Pair. - Type of the second item in each Pair. - - - - Produce a List of the just the First items from each Pair in this - PairList. - - - A List of the just the First items from each Pair in this - PairList. - - - - - Produce a List of the just the Second items from each Pair in this - PairList. - - - A List of the just the Second items from each Pair in this - PairList. - - - - - Encapsulates arguments for KeyDown, KeyUp and KeyPress .NET events - for events that may “bubble up” the source component's parent chain. - - - This is simply a convenience class whose main role is to allow for the - exposure of multiple key events via a single event. This helps in - situations where we're interested in bubbling up all significant key - events without having to expose three new events on each parent component - through which the bubbling occurs. - - - - - Corresponds to the KeyUp, KeyDown and KeyPress events in the Win32 API. - - - These enum values have purposefully been set to match the - corresponding Windows Message values (WM_KEYDOWN, WM_KEYUP, and - WM_CHAR). - - - - - Key Down event bit mask. - - - - - Key Up event bit mask. - - - - - Key Press bit mask (Down and then Up). - - - - - Constructor taking an event enum value and event args value. - - - The key event type for this routed event. - - - Arguments passed to event listeners. - - - - - The key event type for this routed event. - - - - - Event arguments intended for event listeners. - - - - - The key event type for this routed event. - - - - - Event arguments intended for event listeners. - - - - - Collection of distinct objects. - - - - Items in a Set are unique within the Set according to the - EqualityComparer used. - - - Set is implemented in terms of a Dictionary<T, Object>, so its - performance matches that of Dictionary<T, Object>. - - - Type of the Set's items. - - - - Construct an empty Set using the default equality comparer and default - capacity. - - - - The default equality comparer is EqualityComparer<T>.Default. - - - Using a constructor to specify a capacity may improve efficiency by - avoiding resizing while adding any initial objects. - - - - - - Construct an empty Set with a given minimum capacity, and using the - default equality comparer. - - - - The default equality comparer is EqualityComparer<T>.Default. - - - Using a constructor to specify a capacity may improve efficiency by - avoiding resizing while adding any initial objects. - - - - The number of elements that can be added before resizing is necessary. - - - - - Construct a Set from a collection of items, using the default equality - comparer. - - - The default equality comparer is EqualityComparer<T>.Default. - - - Initial collection of items to add to this Set. Since the Set is - guaranteed to contain unique items, any duplicate items in - the collection will be ignored. - - - - - Construct an empty Set with a specific equality comparer, using the - default capacity. - - - Used when comparing items. Every item in the Set is unique according to - this comparer. - - - - - Construct an empty Set with a given capacity and a specific equality - comparer. - - - The number of elements that can be added before resizing is necessary. - - - Used when comparing items. Every item in the Set is unique according to - this comparer. - - - - - Construct a Set from a collection of items, using a specific comparer. - - - Initial collection of items to add to this Set. Since the Set is - guaranteed to contain unique items, any duplicate items in - the collection will be ignored. - - - Used when comparing items. Every item in the Set is unique according to - this comparer. - - - - - Construct a new Set with the same items and comparer as an existing - Set. - - Set to copy. - - - - Adds an item to the Set. - - - If this.Contains(item), item is ignored. - - Item to add. - - - - Adds all items in a given collection to this set. - - - Any duplicate items in items and any items already in this Set - will be ignored. - - Collection of items to add. - - - - Removes all items from this Set. - - - - - Determines if this Set contains the given item. - - Item to locate in this Set. - true if the item is in this Set. false otherwise. - - - - Copies all of the items in this Set to the given array, starting at the - specified base index in the array. - - - Destination one-dimensional array into which this Set's items will be - copied. - - - Starting index in the destination array at which to begin copying - elements. - - - Throws if array.Length - baseIndex < this.Count. - - - Throws if baseIndex < 0 - - - Throws if array is null. - - - - - Used to determine the equality of items in this Set. - - - - - The current number of items in this Set. - - - - - Removes an item from this Set. - - - If the item is not a member of this Set, this Set remains unchanged. - - - Item to remove from this Set. - - - true if an item was removed. false if the item was not present. - - - - - Get an Enumerator for iterating over this Set's items. - - - An Enumerator for iterating over this Set's items. - - - - - Replaces the current Set with the union of this Set and the given - collection. - - - After applying Union, this Set will have all the original items from this - Set, and all distinct items from the passed in collection. - - Collection of items to unite with this Set. - - - - Replaces the current Set with the intersection of this Set and the - given collection. - - - After applying Intersection, this Set will contain all distinct items - that exist in both this original Set and in the given collection. - - - Collection of items to intersect with this Set. - - - - - Removes all items in the given collection from this Set. - - - Any items in the given collection that are not presented in this Set are - ignored. - - Collection of items to remove from this Set. - - - - Is this collection read-only? Always false. - - - - - Copies all of the items in this Set to the given array, starting at the - specified base index in the array. - - - Destination one-dimensional array into which this Set's items will be - copied. - - - Starting index in the destination array at which to begin copying - elements. - - - Throws if array.Length - baseIndex < this.Count. - - - Throws if baseIndex < 0 - - - Throws if array is null. - - - - - Indicates whether access to the collection is thread-safe. - - - - - Object used to synchronize access to the collection. - - - - - Backing storage for this Set's elements. For convenience, a Dictionary - is used, but the Value elements are ignored. - - - - - A very simple abstract command which supplies a default - implmentation for CanExecute, as well as a RaiseCanExecuteChanged - method. - - - - - Return true by default. - - The parameter to the command. - true, by default - - - - Part of the ICommand interface - - - - - - A method for notifying interested parties that the - value of CanExecute has potentially changed. - - - - - - Entry point for command execution. - - parameter to the command - - - - - Test Class which inherits from an ExtendedEnum with a single generic parameter. - - - - - Test Class which inherits from an ExtendedEnum with a single generic parameter. - Used to test if the Extended enum's static constructor will successfully - invoke this class' static constructor. - - - - - A value converter that simply calls Trim() on a string value. - - - - - Convert a String to its Trim()-ed version. Implementation of interface method. - - The String to convert. - The String type. - A conversion parameter (should be empty.) - The current system culture. - The trimmed string. - - - - Not implemented, as it is impossible to untrim a trimmed string. - - empty - empty - empty - empty - Throws an exception if used. - - - - Useful general utilites for working with strings. - - - - - Joins the string representations of all Items in a list, separated - by a delimiter, into a single string. - - - Works like System.String.Join, except on a list of arbitrary objects. - Each item the list is transformed into a string using ToString, and then - these string representations are joined as with System.String.Join. - - - String placed between each individual item in the list. - - - List of objects whose string representations will be joined. - - - A single string composed of the string representations of all Items in - list, separated by delimiter. - - - - - P/Invokes native method for string ordering like in Windows Explorer. - Compares two Unicode strings. Digits in the strings are considered as - numerical content rather than text. This test is not case sensitive. - - - Using P/Invoke here and letting the platform deal with marshalling the - strings in much simpler than trying to do everything manually. - - - A pointer to the first null-terminated string to be compared. - - - A pointer to the second null-terminated string to be compared. - - Returns zero if the strings are identical. - Returns 1 if the string pointed to by psz1 has a greater value than that - pointed to by psz2. - Returns -1 if the string pointed to by psz1 has a lesser value than that - pointed to by psz2. - - - - - Convert the a string to a hash with UTF8 Encoding - - - A string which will be transformed into a hash - - - Returns an integer with a hash value - - - - - Replaces the standard BackgroundWorker provided by the .NET Framework to - fix what seems to be a bug causing the BackgroundWorker to fire events in - the wrong thread. - - - We have encountered cases where the BackgroundWorker seems to lose track of - the main thread or just arbitrarily decide to fire ProgressChanged and - RunWorkerCompleted in a new thread rather than in the main thread. This - causes synchronization errors. This replacement class allows the client - to specify a ISynchronizeInvoke synchronizer object through which the events - will be fired. All Controls implement ISynchronizeInvoke, so any Control - should be adequate to act as a synchronizer to invoke the events in the main - thread. - - - - - The synchronizing context. - - - If this object is given a Synchronizer, ProgressChanged and - RunWorkerCompleted events will occur in the Synchronizer's thread. - - - - - Overrides the base OnProgressChanged to invoke ProgressChanged events - in the Synchronizer's thread. - - - EventArgs containing data for ProgressChanged listeners. - - - - - Overrides the base OnRunWorkerCompleted to invoke RunWorkerCompleted - events in the Synchronizer's thread. - - - EventArgs containing data for RunWorkerCompleted listeners. - - - - - Delegate type for ProgressChanged. - - - EventArgs containing data for ProgressChanged listeners. - - - - - Delegate type for RunWorkerCompleted. - - - EventArgs containing data for RunWorkerCompleted listeners. - - - - - The synchronizing context. - - - If this object is given a Synchronizer, ProgressChanged and - RunWorkerCompleted events will occur in the Synchronizer's thread. - - - - - Utility class helps unit tests find their data files, encapsulating the - different search schemes required on dev machines and on automation machines. - Holds a collection of found pathnames. - - - - For developers writing tests, the convention is to put data files in a - TestData folder next to the source code, inside the project's folder. - For example: \3dswin\src\dll\WeatherData\TestData. When running unit tests - inside a developer build (so in src\exe or src\x64\exe), the data in this - location should be found automatically. - - - After the build is produced on a build machine, all TestData folders in the - source code are packaged up in a zip file. When the automation machines run - the unit tests, they unzip this package and set up the environment so that - this class can find the data by searching in the following locations: - - - Inside the build, below a TestData directory, with subdirectories organized - to match the source branch. - - - Below a directory indicated by a UNIT_TEST_DATA environment variable, again - with subdirectories organized to match the source branch. - - - - - Instantiate this class with a basic glob pattern indicating the expected - location for the files under 3dswin\src. - - - - - - Contains static utility methods related to UI and drawing. - - - - - Determine if the given point is a valid screen location according to - the current monitor setup. - - The screen location to examine. - - true if aLocation is a valid screen location, false otherwise - - - - - EventArgs type indicating that a value has already changed from and old - value to a new value. - - - Contains the old and new values as properties. - - Type of the changed value - - - - Construct from the old and new value. - - The previous value for the changed property or - variable. - The new current value for the changed property or - variable. - - - - Abstract value change event args. Serves as a base class for the more - specific derived types - - The type of the value for which a change - - - - Default constructor. Uses null values for OldValue and NewValue. - - - - - Construct with old and new values. - - The original value - - The value to which the data has changed or will change. - - - - - The original value for the changed or changing data. - - - - - The new value for the changed or changing data. - - - - - The original value for the changed or changing data. - - - - - The new value for the changed or changing data. - - - - - EventArgs containing data for signalling that a data value will change - value. - - Type of the changing data value. - - - - Construct with an old and new value. - - The current (old) value. - - The new value to which the data value will change. - - - - - Handlers may use this property to control whether the value will be - permitted to change, - - - - - Handlers may use this property to control whether the value will be - permitted to change, - - - - - Encapsulates safely temporarily setting a variable value while some - operation is performed. - - - - VariableGuard safely encapsulates the following implementation pattern: - - 1. Set a variable to a given value while performing an operation - 2. Perform the operation - 3. Set the variable back to its original value - - - - For example, to disable event handlers in a class, we might write: - - EventHandler oldHandlers = SomeEvent; - SomeEvent = null; - DoOperation(arg1, arg2); // arg1 and arg2 are local variables - SomeEvent = oldHandlers. - - - - Unfortunately, this isn't particularly safe since any exception thrown in - DoOperation will leave SomeEvent disabled. We need a try/finally - block to prevent this deleterious side-effect. This class encapsulates - the pattern in a single call. Using an anonymous delegate, which is bound to - its calling environment (a closure), the client code can invoke this guard - using: - - VariableGuard.Guard( SomeEvent, null, delegate { DoOperation(arg1, arg2); } ); - - - - - - - Delegate type for the delegate passed to the Guard method below. - - - - - Temporarily set variable to value while calling the guardedCode delegate. - - - See the class documentation for more information. - - variable's type - - reference parameter pointing to the variable to temporarily modify. - - - the value to which to set the variable during the operation - - - the operation delegate to call while variable is set to value. - - - - - Maintains a list of event handlers through weak references. - - - - WeakEvent is intended for use as the backing storage for an event. Note that - WeakEvents invoke handlers through reflection and so are slower than standard - events. A WeakEvent is intended for cases where leaks are especially likely - to occur, such as for events published from a singleton object. - - - Example code for the publishing class: - - class MyClass - { - public event EventHandler MyEvent - { - add { WeakMyEvent.AddHandler(value) }; - remove { WeakMyEvent.RemoveHandler(value) }; - } - - protected virtual void OnMyEvent(EventArgs e) - { - WeakMyEvent.Raise(this, e); - } - - private readonly WeakEvent WeakMyEvent = new WeakEvent(); - } - - - - Event listeners add and remove themselves from such events as they would - for any standard event. - - - - - - Add a handler, maintained by weak reference, to the list of event handlers - for this event. - - Event handler - - - - Remove an event handler from this event. - - Event handler - - - - Raise this event, triggering any registered event handlers whose WeakReferences - have not been collected. - - Source object for this event. - Information about the event. - - - - Serves instead of a standard event handler to avoid maintaining a - strong reference to the handler target causing a possible memory leak. - - - - - Construct from an event handler Delegate. - - Event handler. - - - - WeakReference to the listening object. - - - - - The handler method. - - - - - Is the WeakReference target still alive? - - - - - Invokes this event handler. Does not check if the TargetReference is - alive. It is up to the caller to check IsAlive first. - - Function arguments to pass to the event listener. - - - - General utility methods for working with WPF. - - - - - Allows all pending Dispatcher messages to be processed before continuing. - - - Avoid overuse of this method. Generally, WPF does a better job of - managing message processing priorities than this brute-force approach. - - - - - Convert a point from WPF's device independent units to pixels based on - the Visual's presenter's DPI setting. - - WPF point to convert. - Visual providing the DPI setting. - The point converted to pixel coordinates. - - - - Convert a Rect from WPF's device independent units to pixels based on - the Visual's presenter's DPI setting. - - WPF Rect to convert. - Visual providing the DPI setting. - The Rect converted to pixel coordinates. - - - - Convert a point from pixels to WPF's device independent units based on - the Visual's presenter's DPI setting. - - Point in pixel coordinates to convert. - Visual providing the DPI setting. - The point converted to WPF's device independent units. - - - - Convert a Rect from pixels to WPF's device independent units based on - the Visual's presenter's DPI setting. - - Rect in pixel coordinates to convert. - Visual providing the DPI setting. - The Rect converted to WPF's device independent units. - - - - Get the current device transform, used to apply DPI settings among other - things, for rendering the given Visual. - - Visual with the desired rendering context. - Render transform matrix used for the given visual. - - - - P/Invokes GetWindowRect from the Windows API. - - IntPtr wrapping the native window handle. - Out parameter returning the dimensions of the native window. - nonzero on success, 0 on failure - - - - Data type created for marshalling to a Windows API RECT. Represents a - window's dimensions in pixels. - - - - - X-coordinate of the window's left edge. - - - - - Y-coordinate of the window's top edge. - - - - - X-coordinate of the window's right edge. - - - - - Y-coordinate of the window's bottom edge. - - - - - Gets a native window's location and dimensions in pixels. - - Handle to the native window. - The native window's location and dimensions in pixels. - - - - Centers a WPF Window to a native Win32 owner window. - - - - For centering a WPF Window to a WPF owner window, it suffices to set - Window.WindowStartupLocation to CenterOwner. Unfortunately, this does not - work when centering a WPF window on a native owner, at least when the - owner is maximized. - - - To center a Window at its startup, call CenterWindowToNativeOwner from - a Window.SourceInitialized event handler. CenterWindowToNativeOwner - requires the Window's HwndSource and Visual to have been created in order - to translate to Device Independent Units. - - - Window to center - - - - Given a UIElement, turns on the Display-style text rendering for this sub-tree of components. - - - Certain projects need to target the .NET 3.5 SDK. .NET 4.0 introduced a crucial WPF feature: - better rendering for small (less than or equal to 12pt) fonts, which mimics typical text rendering - in Win32. Since 3ds Max runs on the 4.0 platform (at a minimum) we can turn this feature on - dynamically, using reflection. Projects that target 4.0 should add the attached property - (TextOptions.TextFormattingMode = TextFormattingMode.Display) directly, using standard - mechanisms. This method is purely for projects that don't have the option to target the - 4.0 framework directly. - - The element for which Display-style formatting should be turned on. - - - - Looks up caches the reflection types needed in TurnOnSharpTextRendering(UIElement). - - - - - A static class which defines two useful attached properties: BindableToolTip.DataContext and BindableToolTip.ToolTip - - - This class bypasses a very annoying trait of WPF, which is that the PlacementTarget of a Popup (which includes ToolTips) indirectly - sets the DataContext of the element to be inherited context from the Target. This is very counter-intuitive, especially from the - logical definition standpoint, but it as a result of how the Visual tree is calculated. - This class allows you define the DataContext for a tooltip more explicitly. Given that this class is declared in the "CSharpWpf" - Xaml namespace: - - <SomeControl - ToolTipService.PlacementTarget="{Binding ElementName=SomeOtherElement}" - CSharpWpf:BindableToolTip.DataContext="{Binding}" - > - <CSharpWpf:BindableToolTip.ToolTip> - <ToolTip Content={Binding SomeMVVMPath} /> - </CSharpWpf:BindableToolTip.ToolTip> - </SomeControl> - - - The result of this will be a tooltip who's DataContext is set to the context of SomeControl, and not the DataContext of the element - named "SomeOtherElement". This allows you to bind Tooltip content or other properties relative to the logical context. - - - - - Attached Property ToolTip declaration - - - - - Attached Property mutator for ToolTip. - - The element on which the property value is being set. - The value to set. - - - - Attached Property accessor for ToolTip. - - The element for which the property value is being retrieved. - The value of the property for the given element. - - - - Attached Property DataContext declaration - - - - - Attached Property mutator for DataContext. - - The element on which the property value is being set. - The value to set. - - - - Attached Property accessor for DataContext. - - The element for which the property value is being retrieved. - The value of the property for the given element. - - - - A factory for generating attached properties that link specific routed - events to ICommands. - - - - - Generates an attached dependency property for a class that can be used to - hook up a specific event to a specific ICommand. - - RoutedEvent declaration to listen for. - The name of ths property to create. - The owning class of this generated property. - An attached property declaration that has been registered correctly. - - - - An internal class to handle listening for an event and executing a command, - when a Command is assigned to a particular DependencyProperty - - - - - Handles attaching or Detaching Event handlers when a Command is assigned or unassigned - - - - - - - - Listens for a change in the DependencyProperty that we are assigned to, and - adjusts the EventHandlers accordingly - - - - - - - A collection of useful Mouse utility functions - - - - - Get the absolute mouse position using the native Win32 SDK - - The absolute mouse position on screen in pixels - - - - - An extension of ObservableCollection which supports range adding and deleting - with only a single notification sent. - - - - - - Overriden to only raise notifications when notifications are not suppressed. - - event args - - - - Add a list of items to the collection. Only one notification will be made at the - end of the addition (NotifyCollectionChangedAction.Reset). - - A list to add to the tail end of the collection. - - - - Remove a list of items to the collection. Only one notification will be made at the - end of the removal (NotifyCollectionChangedAction.Reset). - - Not the the list of items do not need to be sequential. Each item passes through the - Remove(T) function. - - A list to add to the tail end of the collection. - -
-
diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.dll b/instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.dll deleted file mode 100644 index 97f77dd7fee264e9e3f20bf426b94eccc1fa3306..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329496 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%0A?l!u{LLQ*yv{TRyRqdMX zUP1eF`i$JrI#V4-|Lak4A4ni`QI z=hJMBTyX`9-RILu7Ro4S1zIdfuSA`6gCM>3bkY}sbmT9fHRHLr>nPpnbzeZ&ScoHk z5#4Gbj{F+BUyzRc#k5z@YP#6D+uHyT?kc{?y`Bn=;CicFH=}>KG#K{~T;C3`KmppS94Qk)>2XSdNJ z3tfS8soQC@Af0u0(waK1r*r8}x?LkVhrW{@vk;#{-$^f8=nVIx?z>3;lcZ~0=L6kM ztKl=~p9GM%_oBS?DyNEp))D zHx@^k2PvvS{B%|0DDxl<6Quk85KR%Jd;1W*FG%~ zEJ6Cr@hLi6kdDODbiN>MY zy+Jod)O(YDCrJ0`O}ei~*~=QaPK*uT&*7P=N^v45et zf>u*8&gb8va|G#8d57*4q(|i)vLDShb?fg@ks#fp_h_D=)il?;GU`2AsLNb~(cTBN z+(PMS?*qEfLXWr)7`y3O3%%%0rrmU>g+^6ukNS`vw@`V-3qUVgXl?$xY7hO{LbvDd z0Q#GSE{WS7wU_>7p&R2~0J0sUBe4ke{z`EcItTUsN*NY9sr-QZZ&YldGs=GksbQn*LmY zJ5rQ2UHjRLKJ24X3!RNV?4ueBy5**=n$|d^RD`mZnMx_&kmpm1g)dvqP*^}Xq%wb^f^}j{S<#J`?;E8 zqcfae(-1*xT!WMC(ce(Mh4PXYt8ZwMARVP|=`2AyO5f6Xf^?L=qokQ^Q)kxq^idCV z`>9-}^Xz+iStHkX#jfb@X}5*kC5s*3(-#){-MGZ)f73w=Jut4(@o$P>C@s)B^ymi~ zA!s$-j$_VGRA!+S(EOPSnpsnOeUMHPq`f{!iv?+~Nga0@YiiF7<=4oSQ+>cN)M^V= zRwv_*{xyQMO`F;wNL#U~uLbG8J5<`~VVe%czaPzKPj{9NiFT+fE%ZS7D4?4Kt)ms_ zk*PKdT205GM=o`*h2C%$M@Omqt$I%)lcUu$7J37j9IgIrp|7w)$Ed$s=x40ZG3o~k zan{AEn8n%`&bnAN!a|LsDx(Lf5(^zaY9dg*g*cN3tK%)inLJo6vJhu$oLXTa&ek|} zk%c&y;?;E);#`VXn+2_=(dII|GLqK9zUX)+siOqxF-lUi1?lLfs5b@a=%y*(nYvzG zdb=Y{RcjRWXY&zbh-$OY=RiZ%U4mBQk$w~RrgjQiM@M)XqSMuWt*IK*cc@`%GCw#% zdc7X5juoVHB16p)q+8EWiv;N%kPNlkLc9Z#tv-&Zm#eN&+^r|g0yG(YK@>z6t|bJ)@mf}6{sB+;`R#F zzXj>`iqtT__#*8Uska2_NQ_mx1?l#R)hB{#4koLM%ev^&YB_6Rd^_VV`K9s5b7UDjXD~~+S^ND!v zQ)>k2_A1mB8o5qGURS6t3$-J!E7XG#nw9DaLApnkYEO?c)h2y#ot|;Ps8mrFIyVFN zcvXU+9dvTWSZ9^Ww#qKaJTZElDznh_nN2{omgb0PpL4vLBWN|9I(l(*wOYJ_ThKFL zqPjtlo&gipZG!X+n55(%%(K?kT9tpccqT`nTGb$E2hAvNH)_>9T_!uFb!v%)c&D^Z zook_&a7JCP)>`O2oKe@S4T4tVj_z5}4eD+S;aC)Xq#j^|W$pCCOdQ`Jt5Tz|wK?o{=jh2Dc_Q`J5Txk}$v)6{nsN-Ny~WM3)0b-fsM zz?iO5Ec8BhjHjzH7Rtju!?9|-g^t8N!?EgEL91yd&WUEID+OImkLPwq&r*M~%Bo_n zaUZAlS|~qyS=0$?zaZV)xhnHqZe90wt|}0udwZhlun?cmpR8^Yr29T!ozN~`%NWg9 z^95aqe^=?^==o}?pmmgpReymxUzdsIsp<+{&-It|vFcQHorOM4kHa%Sw^(Qk#&4mz z!$MDC{1&SFEwmp|TBM$_&_P6Lk$T%gGt5Wb%_{CZ9naH%PE!qnE}~VY&w09P5~TaE zSpC-0{H*-)=*4Q2g$|To19Y#2Hk4i--J%|`(A}li06lFXyYHsxGt>(fO7?98+GU~B zOK*xkQ@w4W^GY`Y?X}S3C|jcTS?E=iEm8lpPzB1Csvj&g9c4?Ets@-kRuwJiLaLxU zqFYsZM44ZWj40!0_HgGkm7lyzNn`%e(aaC8z_afCNX87q^N*H%mekUkx8!l%u86u? z!upCdeJ&-;AC6q>7|HC<`IYRCiJha6wO>3e-zxSadHj3Omj8;LE@plc{It=w{IKV2 z*`Q*S_LTnvHbeGx>yefteU6kz@;WBE?~$HF);%2le{Sbs2KRBcw|9>sTaWZSl8@BU zd}L|gm`9dI@>;X6H7!{#W0zTNz|UW**-u?p`#cce*V;gRJREuC7!A~7U->}&8mL9> zbKiaq)ECa%{_;>;(4~EK2FjVpJ`U7kq&(8kzGJO5d)pj%mi3)|dY1iN)(UNn`N;nM zH`ds~f1}@bj%y$EDC_=4_AXMcH4mQ-G$Mz#5ZU5D@jo2PeeG-?$8kP%-N?T8jm$v) z9J)t+?F{4tuhNm3psW>M%k|j(x2t+zn~~NIU8>ip3uUF!y%ZV+g1l8nX-Is6=R$&>EqW zh0YK)^1s#hwCs;B=eS&l65`+2G zpvgkxXs5yQA-36t$J2UHJT-1#n|KQCrM2m;px5HGZYTW~yYa8lYo4pFn%pMlo=j83ldV#^ zRZ6!iPic&?RqaYhrj3f9T9|F=+%qPQwkp0WFq>kt3yh75pH$dtORnCbhM?WMRhHv% zSCvs^@SWEzV{Q5*Bg?op{YYaU-IX@o*sh`r=NRuuTPrO(vZ~EkskSBVQ2T60R<#@Z zY|oFm0Q5CbB{?$&mUk$wdzr!fdZR?zV!q3$a+Frxi59unTaZO}tF1P7%pG3qGUdkH%c^yTC8TGo;+g`=C#N|Jptibfx+z@m3fS&rl^FntN{7)-X$%9vuyaunkVkNKI9|JrwgZKbgR zqg*5XnhbifZKL#h2KX~yz!iBQ}EmQgu7%hU~G3|0k)Np}#rf3P?^FHpR9TEk0=5BCYIn zjL3Qu@{cRthveAek3p-8KesJHcI^kx_sO=}_<5-<#%&X0?AuW*j-vfGV}f+3Jh zPRg|Jwcml~{o$WMs#ixNtA8TxW$e!YF%kNXl(Yy_IHrY1ZafPi$=vLd!$ch^CzKUBNTWxpY3Civ2 z4#(||F^-$l-^JW{p<=URjBzUX8Ma^Cj~HW&AB6uF{B7dNO7V7vS()*=W3Ktwgtr{G z!MDAjm!$v0(PF#0;(Nz3+anp@J9etY)xUs#lg-pWlIh3bTg=mvoaQp~M?4*TiQ`wp z2bnW$uFBz{$D#GDwr$A38Mej355p5OTWzmb`pkW{%)$f4cH8CHo!f5g8a~^srt{Jd z;F+pv=_i=mZQpy(G&jS;^FiOjEZc6oDD_gvcaK_UzGfSgd%$=IrFW~%^snkJ=x`2f zw;ddH4|JaPJYarptMw(*JGMz9cbn_X>cWrAy|%wszKhXp9`>2J-h8-vzq!%48eVNQ z9?973*lYW89G*ZzG-93mY}X~FI^U7VY_Z*(ggY)ae(LCJ8$Vw(S7zvB#XE_U74H%@ z8ShOv#;NSC(izSt#am^6sro3}lj7BDwg*QwJMS{z#htf*%kJlEw#m`Sr0jceMA%|- zFZS7{k3Q4MGiW_lVBQxTVm|`w`DArZb-NQYG39kca$dDbTP^*`!`3>pB*R@)X*}w5 z(JtGQpl{l?gYFUjBjJbHS)OTU`6&DI&Mf*JZFi2w4%xK9MHEe!#1!Eyq#E@b?qwplbmY6KzyM%5Ox=pAJ_qVqr z{;auLXr1j1Y96$}#*$8|)8g6N3mvS# zUFfqy>r9p`6xu1YOXxPCdxVmUZIX*^W(uDv{3PKgSv=cUQEaV7=ysudg(^48vxIix zS(EL~EnmhLTeIOvQ6k7p$igO(kYaZn9mftP3Rt>lq}ImmS_l{Y4PH7inJm$GnM&C zLiY%zG?sJ;-6nL8P#VJWjY9Vd%^b>-ETNNxE*L5!JCxgP5=o~>Iz_TtBwZru5=qxk z_Gg<&wuxk$NVaQh>1@AK=r*Bygmw*+(HSPABm6dtm)>P?tp!4xMlioxXqV89LbnOs zE_AO@l_`A@Iw_OwPs(KbH6mFck_94JkjbqyiF{8sYwpQrO&ZBOjbuJk_)Lpu{RN|> zFPi4CW@ip-b_w4l{5IjYSv=Ru9L<`Uqgiv3@RNjJAp8Q0XU#n#*&`D2h$kNL$|I$D zEZLJMl6)!6XFgN-Op9mD&V2T>ODGjGpDC1zgcmw#Eb|M5ZWFpk(_)rW3Da#Q+{(5R zZe@?~dxR&iwC)v8yxiiXQkG0AWyu2J7YN@ee5b{;=7Mt8Tu{!Mox*nt-z9vP#k1x% zk!%ymwsPs0kG<*=x=rXFp_3}4FG9CfyvIHZzegxlvVv)Vk$Jjr~_e8K$A{I{9woZt*NFT&e1itM;*AB_F# zL~u!XzcZQKc-x-e*o>u7G>CFgIvQ;k%X{^YMXiPxnr<;2itr8=e%k`?U@=`Md|%0W zH#X1lE)>&q_+lULth@vLzO)l>0ffAAfHUEd6IbajcomKRV&GLQJQ{>|69(g7hr?T) zct>I+ydMqk^Wl9duCdF}10Sx}D{#Gj1g_T`pmii=(NWMkmOL~ASKu>ojXoPSjz`bt z;adD;?pN}?(b&Z(V7fW+0nm}DkAnV~@(0kWvCJPm=2_4|X*)sxQSmD1DV3~0JMj(B zX(`NWswGz!y#vXSQhG|lN8s1QGo2{(TcJ+~JwZyV#(svl|F#i=+ zf_(6^c$AP~C)S&z61n^rx4SE=FA1HbR)SyQZ1H2~K^ddgBo}P`1jzuKn?6Z-Ut3xP=kJ_wt&A4 z6nDeagWzumHRvJrF!+Z-4SGa93jR@0gC0{`!EXgM@TUF~;GYIHXq);2`0bzuJ)@om z|17A1=c%`Ye-6~3=hd^|UjQ}eMfDu`ouDq7gBcowS&)xa?OxDCL?a(7)7?Tht5U2? zFM}V3AF#{ED&hsrpp!uHHXdjub%JKm1E6Cl)0U58e%@cZ(trT;#9&;x~b*fv{ zPW6Mb86%B_#uK)2_8aa0v`=tMbsUdhy?EZS!o1!*$w}YZvHu+h`Wa<{eon=pU(h7b zFX>p&uV?}2Kj?<&w%RAtaK~iAD-8J2sJ7NA zO)LG&+e(V5dg8+Q^XprJXDw-3S+}Gq7%ZOOkFcDD4d*m3T;A3^@znW@iWau{1Dfx) zS6mWdyM#(h8hpj&6~2nPlG=vin)>>xy0W?&udk${yr#aqrna=9wzjso*jG|j+2Cs| zE%Vk@)YR0}R@M6|ORIdf_;rQyI&WEdZAEcqS!qR8ZB1i+xwoRevZArpS69+lRaV(h zQPNmbSMIB7sH-fmtE?|BuJ;vJRn^y(RQRguN~q4ibZJxTqS}_$Mfk<8`Bo1W&F@oE z*VJkiqHNmoB}f3w&C^c}HV0O4X`O$` zlIDeNE&f(6Yi?RJy>-dT9>Rtd&8=-m!J8$`0k%A)CD?}VDNUy~FPY|VonM36E1F9P zO*b!L2bU~g+FC*li(1;yZm_v6Si8Kf%@5J3*7xx(&1awG5452{|Jf0tFZM)1zxIe5ht4hD*<}7jh9!YQB;=}ycBA|%PmA$EiR2{q138Y+O1y7>Jci% zWfAISR8vw~<*g{ID=RPc`MgyX4Gq59+LDGUUrkw^ue_wHv8trB*o%y*sIMunuc)aj zsV}XsYxMej<;BH~Wo6y%M3^lu4>wWlqxth^wKcW1EUXCxnpRG3ZE2gm@~q}rE$22* zDDhEAZDmzOJ^sq-O3F(byfxkiUqfj_RY`3{LrrmGMPpqVGOYpG)X-Q`SLH)`RhIjF zrB$Uh#oqEtUqnk45qxC?UqyAu^^y`~HN0*t^?H5iOI>AY1$tHCMRqnel=v#WXwF+( zUxlU{8oc$j6^*{~^4hYBveGK@)i;zjqT{7Cr4^V%Rpt0At}Lyrtf;K7D68_8R#leQ z*H@I5)gqXf4K?2Sipt6c%&hX-s)m{>s-Eg!w0uePM5;bE(6RzqJ9+6@OPZG=3lSNA zYkhNDQ_GUzL@KGMEUT<2X=p$P%S&qzoyIbDq^7E_w79aarlQeXQtT})t*>vat*xm+ zQ^goPc!{=ZOG|60w#-}6P+wD4TV7J)t19=_`@H4F^$otd%7(JidN0Pap{lYD&eeLW z>gsDsAo11JA)e)!$ta=vQt0{WD{C6c8cWLRYisLk(Z>p3U0GR4Eh?2Zme-Z}D$6Ro zHMQQFn$o(m${LOtQp4-3@HJ3HLuEbI2`?HeuB|DrYAkN3uWf+M#ws5=R#Q?_URqWM zuWEb^jovye8MRn1itD^3B_$Q5<&C80<@96d^yaqtb7@7>lI6|w=hLi}!M5h5MJHhW z@Shzlnu_V))LU5J)CO4-$5z;ebI!ta4I;utwM&{?7ZrueV4!t*W6P4Z=0HR(Yj%r- z7p#^xVcC=V=F^&%FKL^Kp<2YvGzOZMHlOVeoOx`(e^zs#ZDn`KY`=fWsZD{|O{aFx z4(8kNu{sf6jDkf+Hn%nhS{Bkme`~8=wI(m3nnjDKY0;wjQ~XVfnioZy3D)^r+XDV2 zp`!Vy*M>Z@G`Z5`VBO;8g=aP|s$0wp<01+)FZHiz?kk_(+DBE_KdR;Q#Y^yM>&Hev zWz$<{FGezlnqwQ`MLZ<6oakFHv#BN6+*drk^>`lnP<1vstC`pJ=0$uU2+1w8{S{4b z?N1sugtQ1*(K)BpBg7#K5u(Y#hyXPD1AXf7Ivt!J9^p_E(_4>i3Sgj)^`Eu;tgtZB z#Xv|bqkwG3K=vHLNEt@2CzO^$HP{5lNrK47w@`rGn2N#S5nqhe4wc4cExp7P+3=3R#|ivT~<-v1%zFZ?H^><1!UC)K}Bij|2^m4 z-)kOeT2j~l|3e|k@4oLn_ug~QJ?GqWV$l@Eb|;TmQYp8#PqZ3TM{=W0i!wKfS4wUq z;HoyDRp&*t#mRhXd#W5- zh+ss0A~FJ-{6K7oX@U*$80}?k6Hk!?JEnMXt@dJdTH<9*mMBmz(NsLiU6JT89?e8I zCWzpYW9`B2G-BjP&FOMlBwpJw3aqD(NrlwB(f&{|I}%KZ;k+Ca-DK#MRy=x=q=D`o zj_Mm+fzq@!b@WMDcSWxri{kjuTO@30O^}W69tCcX_9e$s10W-rVATj!buMkkMu;Vf zB<_kH!b#8{Nn!N4#S5VRzR~DFED{GPB%wmYkrtNyF~{_cCkBR7$pmMY$=i}+>F74# z_8p1Mso0=U#}|Kt=t>MmQiF0Gr#Ws{GMV9z?KrzO#iH>+ap7JZVd>GxK=e%q_wDPB z3>*ZQRnm@BY$%q9#PuvxEI%9J45I1sQ`DKsI4D1r%2AJsBzMJApxtp3N~Y1J{NlVK z(L2UBv@-Lv>^N`$yKqw~IntjT-Ep9AAQg=!^0Q&L(Y!@d`ANH?XDzdu4?O|eN+x#3u?48IXlid_Q1q(pi`x_K*_a^41x%9C4fc{KsL@pNAmCI0 zWpIC{k&VVg*)|exow}wevS6arq-njh;wbL)2JEGbhPAkV))?xFMBrK_1XF8_d8Azl zzyt?=0u-8pP49-W7@=!WRVrq4G_#9<&PUkpQ7sxBE)=~X9*v~r5vt{+USYB^z@%DO zAb;gdQ1^-?6~Mv_gTBb2XjfWQWUi-R0#8l~J1DyGNGt=?5gXNTx}4u4X{K@@)W?e! z%ul3}vMZRt{Qj9DDJMvf0o-j07ATgsI~BVG>rG(!?oZ-u5PieIOSprMrT2A5f$RIg zNK#1~#s}h2I&XCfmkx)+R4P9SgfOSjtn{YkQAei+oh#z9$Vi-TIdqQG5yHm}Pleb0lI4cbgK7P1 zP~QCXFwYa83fyZ+Er{Nc$dIBOgn6fMv)W0j@-mo+cvoTLwm?`(MQ*}OVTH?vh`}2T8cC0(j4;(mcv~n`AQYdC<2FY#y%35DoH zRx#AD#*1T65n71=WhaK@RbS=fX)c_!3ztIl8-1ASzTY3q#G`Uusdh&8Cpl80!=xVU z8oX)@_a!5OCY&b5$ZdouO*_*1GUMn3_0$@Ji%BYii)+dnO+{%ta0&k4$|C#qNK7Vw z(^AkgXlqH|0($nsDOBkuuu(aiq&G2z*tl}dsc(=m^2VXU1M08Z!`+cIMuL`Uv&K23QjGO3 zW0_UVpMB8`)*FBFeH5H>9LyApjg{tj#Yy9Db!X>qBDk@+d7oo2krYDvByuErfMCm< z@MNl+jzB^Mbc6tb0*%DLQP**OS0V9vcYmkFfG0`O|h&eV12!*=DC`>0drUxRUQ7t41 zEG>iy8yl6_I4WmaPZ^FK$m~LLDq)G@>y#c7&1j$U>Y#-fuWJD_O$UZIF*$K6)388h zYM(tx@CR{29pc%cOxlsJK|?L*@SbRjHoZCP-c)3Clp^}kU9g@BqEy8$NG>2EpoFCK zcLY?+91EhOK%_-du}C7LlKRH><7!H|cO(?=gaL15r*QuYMD?Z_sZ()c8ux%5l^hb= zBAH>XWN&N`Uo>&@iHP(Zmok5d%VfQmlShsyJLlL~{RC+DPbbfrAqV zI3y{Gk-H%hha3g*w7B^WDZ2TDQvr(R#V!d^nM0C`@_WZYbDT!fNUUlwHx*-#l1-64 z(SbNfQ`r@GjY2o*sx_z>E_`ChXl;ghNpMCQZyt9_?pM0$n|W3uLko#Z5!Ga&9rW`A zhkqI%mNH`1U7$UnWo=dM*nbs>V5SeWDC16%4i`)w8BHeC4Is{wtCJYqRU@<+KC^%# za62CuHezLXXCy(r$Y7e}ClI3cxh--;iNa(OfrTeTu7z}0JkBlU#>r$#r4@h`l8SDN zByjQ%?v7#dNcxoy4b!_Jx)(N#L|J0udehN?xKeft24ACq)k}+h%Y<6y1lN8;y)e^oUy_e`x58T4E?! zBIGLP#lL$L`<(77oKpduzx4|O%LY>%7o+MV+(dzNLLMw<6||}?9U*$z(h-i(NLNgd z4s?tVWJ`at8*Br8{fOzo)+!?E}v zE|W4ctzG_^Vv(#tqbD-YKr+EC_0k7*hS(t-APlDmwqawAjcz=GNhXv{_YH;b4fk6k0%lw3eoicxSP3Iw0>QUFdAvFNmPgAK_2Qa3A;WJWGz zDo>@RN~eAomAA^7D<+NA00r7t=>pN@t1FR#8nJiHM29KCeD<58v42d#KJ0T78E#71 z-Mdlp$W3uH-X4%)5_)vLa(O*Qj<+|VF+o9INI0`95J*h0MK}T*$P@y}p{tWXIDTXx zI?B1YIpdBXaykoYVhBtVd87h545vfU_;~M7f>17zkt$IhHnLkP3LL+Is6MM&B{(4! zC9Gnw(s6G9IcbfiO~&UXpXYqCcBMh_sZyW_35#lVj3t-^P-p#NQ)p}SKt|^3Nve3P z#zQEJ?axsXQ|3fUgsbgBx-E$f^3KiQtRBW+kmn^b{H4(*92ixE3I{ZN4-Bs1dmVVZlB1YBzcqRXr4v}Va5bv!KznMjIa!3OTeSK$K}r#Y~WJbcwD!y8=tX7;^e z8Eyl+D4G(zebC4Q=M}J{YgY9YXJpg3)T!$I?4U^FWKxSGAdv4-;$B$kWUG z1XFk$@LVh>(zvP_870Kz8X?pW<$^{!(ZobiGEa@!GC3KDJT$V?ysL2lPfA?F3to@j z1^E+HG*W_BU>_gWJa@fmUce;!&_xkAQ-}B!Mf|8}x%)uVaOb=AOqLx% z3!acS9Td|*vX<;>u5lm7;he_dGDQvY(heSsrrD9U?o3lWtv6GU7P={@8r4`9YLh9X zp4PB}maJigymUqE7VEKwx%CP)+Sf>+ZWD_6tZDE; z2%V*QA#RI8uV+xF*-=t}&873aa(Q4yrr2l~=#vC;(Ud6)i<-nJd9VO8XcV!AC_;9r zOJn8nj!rYi$c@u@@44|Kxe>gU`=W%?uq{B~(e_dmV?U0Ks&DjBeH|jMWL{sfizJx< zU1w;}LX$qNi6dz{%ARYh8<}xgls(UlqiNUno#eI2vS!*Gtt+8M5qN`cQ5!;|aiO4q zgN?8PQFmP_v@W&!3{pKWL+;_srKUcaIZJ_Knd1$vwdug-6yvnkGJ?-z^pulLM>l8E z&TS4vXh4$U;LOZkv7!LNo!fD_I~0|BjU=eOiJh?{(Rk6>EDYYlv0)RjC~-JW3OUDg zW~8ZoC5(|_nrZApoJ}&Uwzws%^Cof^kgk5k%imZ;Mm$xo#Vh86b;aqCw01$B$R_Aq z#F~J1m&|Pro2xYE(VEfX6sG_Rjo4K+ehr8{v@?(-1gGN70-9@ zwGVYM`?n8Ts2MGadYg0oOKakJNi=C)(5W7v>l~gwU?Y!k2_4#ZU}E$9N{UHBN&BWY zd($M30~XaHX=3vtK|QL=vepY-&A$hNUD8uXYf1^g2m6yWOB{(lSRrqY_oVeNbbb<@cYI65`6W3_T(zWb zjX2t9xpBHcK`S^QuOnKJq?6irFCVg6D5_c_PO?71xa?zZv;MLX#~@;z9zycKCe(R~ zR2Ll{s@lK&%}1NCu=&iVFXu6xk>H)mdx9m7o{-3j_{cK}gk&sM#v#6%f~RHW8Re(% z9?g&Adw@K3wPfHK>@`-SjZbbMm=C^Q%_XQ>3yQ%=!trO zOX5ix?+OK#9#fdoab}YI0gu6Gu-wa>D1&t19P+t@dMZIU14j$V)b;C~#PXngwdbxX z!Yu7$UZNHs&8RP6Htv9iURV==A*1tyqk}S%V4fFATuYfe01>y5k@_t|{3Hf%h^Tk6 z6_5~o&{HJX3ZMb#tM70uGcZgGo=7&NUrS^#% zu2SQrcXj)bXkb2m)e2U+{40@qcXDu?;Q<68g|<2jFiXjlcHgAr%~3qvOG3Ux0h(!A z7Q2Zp8VB2K5FzbYmoP7yO85{^0`UiC&5*21Q_taw33n6UJ>8X7FG;}RkB@V;#nQSG zG96-+C@}dzRKNX>7Z76U5<8V((w0pT;=91Y2sVlMCs!>xr!Ak+0jH zn@+Q$7QdW4Jp(=pDWL1=>cD5lTvXq1da~4V)`NunaPh(lmRLq!U`@%IdafQt=z@g> zdW?q1nZIYmN+nu7Tu@6^Po-LkNk@o5kJK<7A0~RNrhKJG5DK;`Pw7d9o|7I$EfM7# z*JE-NA@q2ydD<^VBrpMOXFVcUn5!pPXe*ra`j*pkNHUGFy&fl5qkbLK2C4ft3L#1zuwCH7|4fF757i_{bJJDnawC{?nY^{D(Cnvuj$W#nB# zkJPDoJ%%QO*8`m?dMu4VQc8N1qGj~3i73$HG+IE9upaJuv~hFOql%svdX6H%8RWJq$BZHR;n7KzZdh5@G-rzB7?g&ff7fiar_ ze2s`v{7xVjrLBP3rwGSU#XVec1hM@npW(*L>BZv1Fi%Cb#D%EYgOX7gtuks56Q4R) z-Q32*7=tyi7#b%SK|HAsVyaYAm*;MPy{!}jkw9XuOW0vl=3rsK?Lup5fRf4%@b?PX z3W~6$E&@1BOB!~>thsv7(*d*sJv*MR6l{8#`Z9K=ZEZzOL$D@>dkShi%T~Sps3D38 zgrmmY(_c_wSWKhEHHva69utiK+9AR2vb@`pfdS7nEDP3yMA42*3{9-;KSxW1|n%IuNWb=gOHQXY~wHyi;I`pfLdr7OX@(hYkk{| zI6_e=ZiDtVo}Y5R36=xsQwD}4qcooL2=;OO7XjL$u(==cn#u&-2<{^1J^bH z{9x`S!Hdd^b=}BK?aBp5ty5jQQ7=p`pv5T483$|50^F#Tmi;2+Pq06zdNj>iyg_VY z`Y(uC&_*HV_M@&CZ#=msXnl;M&lp*Qc`O7c>irn;&Rus2QiDLh5|5bAu_0a!qh@F?+KQp==h?{LopOiJ{0JZIMKjtL zi*}&}jZ~u@P5XmZYtH&E>t^r`WA?N!kP`Yg$c;YQA=GP_v{QNa^V|>X;X#b(0P@gp z`l0`{?;-xO{uW-XPHId0Mq4G~JVM~q9vvw(s_mE>A~z{k?p7R7f!tg<=?zqhb`zB# z9I5ZQnLFY0w~scdgjCZ2IUzvWMj3P_0npPrrIU#ebsS(JRCE|AgXSr3$US0og5{6V zb?sau$jNg}e$gfaHx95QJZ(M|O}L>-o`!md=Mp&}0U(cis*}Q)!3Oh;nP*chEtawq zeM;en$Rb)ZSof9|a#nW0+MmRNt+ZWxv#_&V*rd$FMu1D6jm%k-Rz6E`y zbxo5k0=X+%mZlpD-Ks>LmQKh{8=nMhk2F5y#{NyLEZMkAVNl@S4GCR+7W&;T+Y*5AaP ze+nRwcs8AbUFn)8nH>X|%{XwMr29=+7nCw>HuJ{chFk`S^4_pT(KJmxvxV*rRff_OxhDCScY&x%ui?&X&G!gAav#!N-^C>KeigQX? z=gxx__Syn5!J98F+U!_3o3nReaA|a$I9H}?LV%W~IcFDUl_(`zlpqsYDV*y*>HET4LsG$;c0i}IU*EG~3!Uygv-}7HrUHpyT-I7Xe2@eZLu%yIo4~mjf zeE576tfXHyXV6ws>09H%A77WRtCWJ3oau7kO|n0Oo?liJ6-sgOVB zk5!4%Mt{tAw9bFDp{db7QW-35Y&3#ZL1&3M?12B67$O@hWu8VVL;Yy(t7 o@!N?dIQam2GPIjz%h~OG?m<7+h}n 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
CN>s8r5G`;=_WPaU0Khc)c%O*LqbAP_Kj|&n}Qk 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 Zi@9@e)`$czAC0(huiEELNAy!}{0}~i1Tp{s diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.xml b/instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.xml deleted file mode 100644 index 8f5f349..0000000 --- a/instaladorCsharp/VR4Life-dll/bin/Debug/CoreManagedUiControls.xml +++ /dev/null @@ -1,845 +0,0 @@ - - - - CoreManagedUiControls - - - - - A button class which can show both icon and text - - - - - Set to true if the icons for the buttons should be loaded asynchronously by a - worker thread. - - - Note: This will cause the initialization of the buttons to be faster, but may result - in flickering while the icons are being loaded. - - - - - Show Icon Property - - - - - Show Icon - - - - - Show Text property - - - - - Show Text - - - - - Icon Property - - - - - Icon - - - - - SubText property - - - - - Secondary text, normally displayed on the right side of the button - - - - - IsHighlightedForSelection property - - - - - Indicates that the button is in a highlight state and the visual should - reflect as much. - - - - - Event declaration for IsHighlightedChanged - - - - - Raised when the value of IsHighlightedForSelection changes - - - - - Shows underlined shortcut key - - - - - When set to true, will collapse down to the required size of the text only. If set to false, - will maintain the size of the item so that it stays even with items that might have an icon - set. - - - - - Extends the base WPF TextBox to add key bindings: Return and Enter commit the - current Text value to its binding source, Esc reverts the Text value to - current value in the binding source. - - - - - Constructor. - - - - - ClickSelectsAll property - - - - - If true, clicking in the textbox will select the text in its entirety. - - - - - Controls if the Enter key is bound to the UpdateSourceCommand RoutedCommand. - - - - Defaults to true. - - - It may be desirable to set this to false if the TextField's parent - container handles the enter key event to confirm the edited value. - - - - - - Controls if the Enter key is bound to the UpdateSourceCommand RoutedCommand. - - - - Defaults to true. - - - It may be desirable to set this to false if the TextField's parent - container handles the enter key event to confirm the edited value. - - - - - - Controls if keystrokes update the source right away. - - - - Defaults to false. - - - - - - Controls if keystrokes update the source right away. - - - - Defaults to false. - - - - - - we don't want this combo to actually do anything on selection changed - - default - - - - Clear filter command for MenuFilterControl. - - - - - Custom multi-converter for deciding visibility of ToolbarItems in MaxToolbar - - - Internal class. - - - - - A very simple layout panel specifically for our menu - We want the menu to layout from left to right, and - if there is not enough space to include all children - equally, then we shrink every child by an equal amount - - - - - Command for modifying top-level MGM display mode. - - - - - A list box class which can change a Toolbar panel orientation - - - - - Panle orientation propeprty - - - - - panel orientation - - - - - Interaction logic for GlobalSearchPopupWindow.xaml - - - GlobalSearchPopupWindow - - - - - ViewModel Dependency Property - - - - - Gets or sets the ViewModel property. This dependency property - indicates .... - - - - - InitializeComponent - - - - - Interaction logic for MenuFilterControl.xaml - - - MenuFilterControl - - - - - CurrentFilter dependency prop - - - - - CurrentFilter Items - - - - - Text that is displayed when the filter is empty - x - - - - InitializeComponent - - - - - Interaction logic for SearchPanel.xaml - - - SearchPanel - - - - - SearchFilter Dependency Property - - - - - The search filter being represented. - - - - - ResultItems Dependency Property - - - - - The items being represented. - - - - - Given a container element, finds the underlying button of the name - 'buttonName' and makes it highlighted. - - - This is necessary because of a weird quirk in WPF where disabled controls - receive no mouse input, ever. Therefore we have to catch the MouseMove on the container element - above it to actually be able to highlight a disabled item (which is something that the legacy - menus themselves do, so the axiom that disabled controls should never receive mouse input is - obviously faulty.) - - The container element. - The Name of the button to find. - - - - InitializeComponent - - - - - A simple textblock control which allows trimming of text from the left or - from the middle. - - - /// - - - - Gets or sets the Text DependencyProperty value. This is the text that will be displayed. - - - - - Text DependencyProperty declaration. - - - - - Constructor - - - - - Internal control used to size and measure text. - Actually takes care of displaying it as well. - - - - - Style of trimming to be applied to the textblock. - - - - - Will trim the text from the left and insert the EllipsisText in its place to fit available space. - - - - - Will trim text from the middle and insert EllipsisText to fit available space. - - - - - Gets or sets the Text DependencyProperty. This is the text that will be displayed. - - - - - TrimmingStyle dependency property - - - - - Text used to demark a trim. Normally an ellipsis. - - - - - Handles the measure part of the measure and arrange layout process. During this process - we measure the textBlock that we've created as content with increasingly smaller amounts - of text until we find text that fits. - - the available size - the base implementation of Measure after the resizing has been done - - - - Reduces the length of the text. Derived classes can override this to use different techniques - for reducing the text length. - - the original text - The index of the char that was removed from the string. - the reduced length text - - - - A behaviour class that can be used to link a ViewModel Command to a particular UI event. - In this case, we are listengin to UIElement.PreviewMouseRightButtonUpEvent. - - - - - Some sample data for presets to help the designers. - - - - - Converts a ViewportType to boolean: true if the view is Extended, false otherwise. - - - - - Interaction logic for ViewExSingletonPlaceholderWnd.xaml - - - ViewExSingletonPlaceholderWnd - - - - - Constructor - - - - - This event is raised with the Viewport button is clicked. - - - - - The name of the view port that has this placeholder - - - - - - - - - - - - InitializeComponent - - - - - Interaction logic for TabFlyoutControl.xaml - - - TabFlyoutControl - - - - - InitializeComponent - - - - - A control which displays a visual choice of the various - ViewPanel layout configurations. - - - ViewportLayoutControl - - - - - Calculates the maximum height of the PresetsGrid so that it is always offset nicely - the top of the screen - - - - - - Property for CreateCommand. - - - - - The creation command to call. - - - - - IsEditingPresets property name. - - - - - A state that represents that we are in an editing state. - - - - - Property to determine how far from the top of the screen this user control - should get - - - - - Utility property for specifying the parent owner popup. We use this to help adjust the - height of this control so that it fits well on screen. - - - - - InitializeComponent - - - - - A control which represents a single ViewPanel layout configuration. - - - ViewportLayoutRepresentationControl - - - - - InitializeComponent - - - - - Interaction logic for ViewportRepresentationControl.xaml - - - ViewportRepresentationControl - - - - - InitializeComponent - - - - - Interaction logic for ViewportTabsControlVerticalMono.xaml - - - ViewportTabsControlVerticalMono - - - - - InitializeComponent - - - - - A control which represents an Enum selection, but whose values can be localized and rendered - in human-readable form. - - - EnumSelector - - - - - The property that the combo-boxes contents are bound against. - - - - - The output value from this control. Clients can bind against this value - to extract an Enum value selection from this control. - - - - - An optional list of human-readable strings for the control to use. - - - The control is expecting a comma-seperated list of strings. - - - - - Sets the contents, regardless of whether they have been set previously. - - - - - Sets up the final SelectedValue binding, and generates the Items member, if - it needs to be generated - - - - - InitializeComponent - - - - - A control which represents a Flag-based Enum selection, but whose values can be localized and rendered - in human-readable form. - - - FlaggedEnumSelector - - - - - The property that the combo-boxes contents are bound against. - - - - - The output value from this control. Clients can bind against this value - to extract an Enum value selection from this control. - - - - - An optional list of human-readable strings for the control to use. - - - The control is expecting a comma-seperated list of strings. - - - - - Sets the contents, regardless of whether they have been set previously. - - - - - Sets up the final SelectedValue binding, and generates the Items member, if - it needs to be generated - - - - - The value to be used if nothing else is selected (checked). - Calculated at init time. - - - - - The text to be used if nothing else is selected (checked). - Calculated at init time. - - - - - The handler that binds the CheckBox in the list to a Value change. - - The selected CheckBox - default - - - - This method recalculates what should be the title of the combo. - - - - - Called at init time to create the entries list. - - - - - Figures out what the Default value should be. If a 0 doesn't exist, then - we take the first enum value as the default. - - - The default value doesn't appear in the dropdown list. The reason for this - is that we need a value that is selected if all checkboxes are selected off. - - The complete list of entries. - - - - Returns the localized Enum lookup key. - - The localized Enum lookup key. - - - - The entry viewmodel object. Contains the localized text, the selection state and - the enum value as a string. - - - - - InitializeComponent - - - - - A standard ViewWindow grip control. Not meant for public consumption. - - - StdViewWindowGrip - - - - - The current text in the Viewport View label. - - - - - This event is raised with the Viewport View label is clicked. - - - - - This event is raised when the viewport configuration label is clicked. - - - - - InitializeComponent - - - - - Localizable String dictionary of the string resources of the assembly - - - - - Resource property which gives the access to the resources - - - - - Converter for the workspace delete button in the workspaces dialog. Custom logic, not for public consumption. - - - - - Interaction logic for NewWorkspaceWindow.xaml - - - NewWorkspaceWindow - - - - - InitializeComponent - - - - - Interaction logic for WorkspaceManagement.xaml - - - WorkspaceManagement - - - - - InitializeComponent - - - - - Interaction logic for ListDialog.xaml - - - ListDialog - - - - - InitializeComponent - - - - - Takes care of dynamically loading Dark vs. Light color resources. - - - At runtime, the manager will load the color resources specified - in the resource files supplied. By adding this singleton's Resource property value - to the root of a control or window hierarchy, the client can participate in the application's theming system. - - - - - Singleton instance. - - - - - Theme Property Name - - - - - Reflects the current application theme - - - - - The dictionary which dynamically switches its content according to which application - theme is currently running. - - - - - A strongly-typed resource class, for looking up localized strings, etc. - - - - - Returns the cached ResourceManager instance used by this class. - - - - - Overrides the current thread's CurrentUICulture property for all - resource lookups using this strongly typed resource class. - - - - - GeneratedInternalTypeHelper - - - - - CreateInstance - - - - - GetPropertyValue - - - - - SetPropertyValue - - - - - CreateDelegate - - - - - AddEventHandler - - - - diff --git a/instaladorCsharp/VR4Life-dll/bin/Debug/ManagedServices.dll b/instaladorCsharp/VR4Life-dll/bin/Debug/ManagedServices.dll deleted file mode 100644 index 9ec0c3ea3538b8b492c7e3dcde04d3c51b6075cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 347936 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

SpEdK&OOt%inA_DSt;(TR$Sd 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