2,112
edits
Paradox-01 (talk | contribs) m (improved example of obj/camera movement tracking) |
m (using Image: consistently to make it easier to find all image refs on a page) |
||
| (32 intermediate revisions by 3 users not shown) | |||
| Line 14: | Line 14: | ||
'''Links''' | '''Links''' | ||
* [http://softimage.wiki.softimage.com/index.php?title=Scripting_Tips_and_Tricks_%28XSISDK%29 xsi wiki page about scripting] | * [http://web.archive.org/web/20160803061035/http://softimage.wiki.softimage.com/index.php?title=Scripting_Tips_and_Tricks_%28XSISDK%29 xsi wiki page about scripting] | ||
* '''[http://softimage.wiki.softimage.com/sdkdocs/scriptsdb/scriptsdb/scrdb_vbscript.htm many vbscript examples]''' | * '''[http://web.archive.org/web/20170616035120/http://softimage.wiki.softimage.com/sdkdocs/scriptsdb/scriptsdb/scrdb_vbscript.htm many vbscript examples]''' | ||
* '''[ | * '''[https://ss64.com/vb/ vbs commands]''' | ||
* [ | * [https://web.archive.org/web/20070510173452/https://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/filesfolders/files/ objFSO/objWSHShell: Scripts to manage Files] (replace "Wscript.Echo" with "logmessage") | ||
* [http://activexperts.com/activmonitor/windowsmanagement/adminscripts/other/textfiles/ objFSO/objWSHShell: Scripts to manage Text Files] | * [https://web.archive.org/web/20150504221146/http://activexperts.com/activmonitor/windowsmanagement/adminscripts/other/textfiles/ objFSO/objWSHShell: Scripts to manage Text Files] | ||
* [http://www.kxcad.net/ | * [http://web.archive.org/web/20080905102848/http://www.kxcad.net/softimage_xsi/Softimage_XSI_Documentation/script_basics_IncludingExternalScripts.htm using external scripts] | ||
* [ | * [https://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=si_om/XSIUIToolkit.html,topicNumber=si_om_XSIUIToolkit_html progress bar and open file dialog<!-- (hm, InitialDirectory code for quick save idea ?)-->] | ||
<!--* [http://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=files/cus_ppg_FileBrowserWidget.htm,topicNumber=d30e11980,hash=WS34BA39B437A993419C80CAB58E3BEFA1-0059 text box]--> | <!--* [http://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/index.html?url=files/cus_ppg_FileBrowserWidget.htm,topicNumber=d30e11980,hash=WS34BA39B437A993419C80CAB58E3BEFA1-0059 text box]--> | ||
| Line 83: | Line 83: | ||
logmessage GetGlobal ("MyGloVar") | logmessage GetGlobal ("MyGloVar") | ||
Further information are found over [ | Further information are found over [https://download.autodesk.com/global/docs/softimage2014/en_us/sdkguide/si_cmds/SetGlobal.html HERE.] | ||
| Line 100: | Line 100: | ||
logmessage XSIUtils.Environment("MyVar") | logmessage XSIUtils.Environment("MyVar") | ||
As the information is a string you need to convert it back to what it was meant originally e.g. with cBool and cInt. For more conversion see [http://www.w3schools.com/vbscript/vbscript_ref_functions.asp HERE] | As the information is a string you need to convert it back to what it was meant originally e.g. with cBool and cInt. For more conversion see [http://web.archive.org/web/20150707131602/http://www.w3schools.com/vbscript/vbscript_ref_functions.asp HERE] | ||
| Line 131: | Line 131: | ||
===Events=== | ===Events=== | ||
====OnStartup==== | |||
Loading objects on startup can fail in some aspects even though you use the same function for OnActivate. | |||
For example a console might get correct position but wrong rotation. | |||
In that case you might want to switch to another program and then back to XSI to use the OnActivate event. Or you do something else e.g. let the user click on a button. With that everything that happened OnStartup should had enough time to process. | |||
====OnActivate==== | ====OnActivate==== | ||
function siOnActivateEventTest_OnEvent( in_ctxt ) | function siOnActivateEventTest_OnEvent( in_ctxt ) | ||
| Line 365: | Line 373: | ||
logmessage MyVar | logmessage MyVar | ||
end if | end if | ||
===Dealing with different decimal marks=== | |||
Decimal sign is either period or comma. | |||
Detect the used sign: | |||
logmessage Mid(FormatNumber(0.1, 1, true, false, -2), 2, 1) | |||
OniSplit always uses the period sign but XSI uses the system used one, which is language-specific. | |||
When xml files are loaded into XSI, the OniSplit formatted values need to be converted if necessary. Example: | |||
if Mid(FormatNumber(0.1, 1, true, false, -2), 2, 1) = "," then | |||
posX = cdbl(replace(posX, ".", ",")) | |||
posY = cdbl(replace(posY, ".", ",")) | |||
posZ = cdbl(replace(posZ, ".", ",")) | |||
end if | |||
Actually you only the replacement function because it will skip the operation if the sign to replace is not found. | |||
When xml files are written, comma signs have to be replaced again. | |||
posX = replace(posX, ",", ".") | |||
posY = replace(posY, ",", ".") | |||
posZ = replace(posZ, ",", ".") | |||
| Line 492: | Line 525: | ||
End Select | End Select | ||
''' | '''Via CMD''' | ||
' relative path | ' relative path | ||
| Line 535: | Line 568: | ||
''' | '''Via winmgmts''' | ||
' slightly modified code from [ | ' slightly modified code from [https://devblogs.microsoft.com/scripting/how-can-i-start-a-process-and-then-wait-for-the-process-to-end-before-terminating-the-script/ that site] | ||
' ''logmessage "onisplit finished."'' will be executed after the conversion finished, there should be also an delay of 3 seconds to support very slow computers | ' ''logmessage "onisplit finished."'' will be executed after the conversion finished, there should be also an delay of 3 seconds to support very slow computers | ||
' if you are going to use this method consider to extent the code to check if input file and output directory exist | ' if you are going to use this method consider to extent the code to check if input file and output directory exist | ||
| Line 564: | Line 597: | ||
logmessage "onisplit finished." | logmessage "onisplit finished." | ||
' now you can work with the extracted xml file | ' now you can work with the extracted xml file | ||
===Detect a running program=== | |||
detectProgram = "Simple_OniSplit_GUI.exe" | |||
programIsActive = false | |||
sComputerName = "." | |||
Set objWMIService = GetObject("winmgmts:\\" & sComputerName & "\root\cimv2") | |||
sQuery = "SELECT * FROM Win32_Process" | |||
Set objItems = objWMIService.ExecQuery(sQuery) | |||
For Each objItem In objItems | |||
if objItem.name = detectProgram then | |||
programIsActive = true | |||
exit for | |||
end if | |||
Next | |||
logmessage programIsActive | |||
outputs either True or False | |||
The code above triggers a bug. When Mod Tool gets minimized you can't bring it back to front. | |||
ExecuteScript doesn't help. | |||
===Taking a viewport screenshot=== | |||
SetDisplayMode "Camera", "texturedecal" | |||
DeselectAll | |||
cf = ActiveProject.Properties.Item("Play Control").Parameters.Item("Current").Value | |||
set oViewportCapture = Dictionary.GetObject("ViewportCapture") | |||
oViewportCapture.NestedObjects.Item("Start Frame").Value = cf | |||
oViewportCapture.NestedObjects.Item("End Frame").Value = cf | |||
oViewportCapture.NestedObjects.Item("OpenGL Anti-Aliasing").Value = 4 | |||
oViewportCapture.NestedObjects.Item("File Name").Value = "C:\Oni\AE\Tools\Simple_OniSplit_GUI\OutputFolder\test.jpg" | |||
CaptureViewport 2, false | |||
command-line access via: | |||
C:\Softimage\Softimage_Mod_Tool_7.5\Application\bin\flip.exe | |||
For CMD options use "true" and Help > Command Line Options | |||
CaptureViewport 2, true | |||
It might be possible to further automate html creation with this. | |||
When screenshots are big enough the info text doesn't overlay object and can be cut away in further image processing. | |||
==Write file== | |||
===Export DAE=== | |||
Before you go crazy, yes, the command "CreateExportCrosswalkOptions" doesn't get logged in the script history. | |||
set oProps = ActiveProject.ActiveScene.Root.Properties | |||
if typename (oProps.find("ExportCrosswalkOptions")) = "Nothing" then | |||
CreateExportCrosswalkOptions , "ExportCrosswalkOptions" | |||
end if | |||
' sets the extension to dae | |||
SetValue "ExportCrosswalkOptions.Format", 1 | |||
' set export path and file name | |||
SetValue "ExportCrosswalkOptions.Filename", CreateObject("WScript.Shell").SpecialFolders("Desktop") & "\export_test.dae" | |||
' selection only | |||
SetValue "ExportCrosswalkOptions.ExportSelectionOnly", True | |||
' export | |||
ExportCrosswalk "ExportCrosswalkOptions" | |||
===Export FBX=== | |||
FBXExportLights (false) | |||
FBXExportSelection (true) | |||
' mark FBXExport and hit F1 to get more options | |||
FBXExport (CreateObject("WScript.Shell").SpecialFolders("Desktop") & "\export_test.fbx" ) | |||
===Write text file=== | |||
txt_location = "C:\Softimage\Softimage_Mod_Tool_7.5\test.txt" | |||
Set fso = CreateObject ("Scripting.FileSystemObject") | |||
Set wText = fso.CreateTextFile (txt_location, 1) | |||
wText.WriteLine "I'm a test file." | |||
wText.WriteLine "Yo!" | |||
wText.Close | |||
==Read file== | ==Read file== | ||
=== | ===Import DAE=== | ||
CopyPaste, filePath, parentObject, 2 | |||
'use scene object if you don't want to group the imported object under a parent, e.g.: | |||
CopyPaste, filePath, ActiveProject.ActiveScene, 2 | |||
===Import DAE (and get name)=== | |||
Sometimes you want to get the name of the object you just imported. | |||
In that case you use "ImportModel" instead of "CopyPaste" | |||
ImportModel filePath, [parentObject], , , "0" | |||
logmessage selection(0).parent | |||
logmessage selection(0) 'this gets root object (file name) | |||
logmessage selection(0).children(0) 'this gets first object of file | |||
If you want to remove the null object and select the new parent you add these lines: | |||
set nullObject = selection(0) | |||
set newParent = selection(0).children(0) | |||
CutObj newParent | |||
DeleteObj nullObject | |||
SelectObj newParent | |||
===Read text file=== | |||
Set objFileToRead = CreateObject("Scripting.FileSystemObject").OpenTextFile("C:\Softimage\Softimage_Mod_Tool_7.5\test.txt", 1) | |||
do while not objFileToRead.AtEndOfStream | |||
strLine = objFileToRead.ReadLine() | |||
logmessage strLine | |||
loop | |||
' INFO : I'm a test file. | |||
' INFO : Yo! | |||
objFileToRead.Close | |||
Set objFileToRead = Nothing | |||
===Read binary file=== | |||
scan_AKEV_file_table | scan_AKEV_file_table | ||
| Line 661: | Line 811: | ||
' INFO : TXMPWH_DCTRBND | ' INFO : TXMPWH_DCTRBND | ||
====AKEV AGQG==== | |||
read_AGQG_binary | |||
sub read_AGQG_binary | |||
OniInputFile = "C:\Oni\AE\GameDataFolder\L3\AKEVlab.oni" | |||
' ############################################## | |||
Set OniInputFileStream = CreateObject("ADODB.Stream") | |||
OniInputFileStream.Type = 1 | |||
OniInputFileStream.Open | |||
OniInputFileStream.LoadFromFile OniInputFile | |||
data_table_offset = "&H20" | |||
AGQG_table_offset = "&H94" | |||
AGQG_table_size = "&H9C" | |||
ByteNum = 4 | |||
OniInputFileStream.Position = clng(data_table_offset) | |||
BArr0 = OniInputFileStream.Read(ByteNum) | |||
ByteNum = 4 | |||
OniInputFileStream.Position = clng(AGQG_table_offset) | |||
BArr1 = OniInputFileStream.Read(ByteNum) | |||
ByteNum = 4 | |||
OniInputFileStream.Position = clng(AGQG_table_size) | |||
BArr2 = OniInputFileStream.Read(ByteNum) | |||
newhex = "" | |||
data_table_offset_hex = SimpleBinaryToString(BArr0) | |||
for i = ubound(data_table_offset_hex) - 1 to 0 step -1 | |||
h = hex(Asc(data_table_offset_hex(i))) | |||
if len(h) = 1 then | |||
h = "0" & h | |||
end if | |||
newhex = newhex & h | |||
next | |||
logmessage newhex | |||
logmessage "data table offset: " & cLng("&H" & newhex) | |||
data_table_offset_int = cLng("&H" & newhex) | |||
newhex = "" | |||
AGQG_offset_hex = SimpleBinaryToString(BArr1) | |||
for i = ubound(AGQG_offset_hex) - 1 to 0 step -1 | |||
h = hex(Asc(AGQG_offset_hex(i))) | |||
if len(h) = 1 then | |||
h = "0" & h | |||
end if | |||
newhex = newhex & h | |||
next | |||
logmessage newhex | |||
logmessage "AGQG table offset: " & cLng("&H" & newhex) | |||
AGQG_offset_int = cLng("&H" & newhex) | |||
newhex = "" | |||
AGQG_size_hex = SimpleBinaryToString(BArr2) | |||
for i = ubound(AGQG_size_hex) - 1 to 0 step -1 | |||
h = hex(Asc(AGQG_size_hex(i))) | |||
if len(h) = 1 then | |||
h = "0" & h | |||
end if | |||
newhex = newhex & h | |||
next | |||
logmessage newhex | |||
logmessage "AGQG table size: " & cLng("&H" & newhex) | |||
AGQG_size_int = cLng("&H" & newhex) | |||
logmessage "------------------------------" | |||
AGQG_start = data_table_offset_int + AGQG_offset_int - 8 | |||
AGQG_end = data_table_offset_int + AGQG_offset_int + AGQG_size_int - 8 | |||
logmessage "AGQG_start: " & AGQG_start | |||
' AGQG array size | |||
ByteNum = 4 | |||
OniInputFileStream.Position = AGQG_start + 28 | |||
BArr3 = OniInputFileStream.Read(ByteNum) | |||
TContent = SimpleBinaryToString(BArr3) | |||
logmessage "------------------------------" | |||
newhex = 0 | |||
for i = ubound(TContent) to 0 step -1 | |||
h = hex(Asc(TContent(i))) | |||
if len(h) = 1 then | |||
h = "0" & h | |||
end if | |||
newhex = newhex & h | |||
next | |||
AGQG_array_size = clng("&H" & newhex) | |||
logmessage "AGQG array size: " & clng("&H" & newhex) | |||
' reduce number by header space | |||
ByteNum = AGQG_size_int - 31 | |||
' skip bytes used by header | |||
OniInputFileStream.Position = AGQG_start + 32 | |||
BArr4 = OniInputFileStream.Read(ByteNum) | |||
TContent2 = SimpleBinaryToString(BArr4) | |||
c = -1 | |||
loop_count = 1 | |||
h = "" | |||
newhex = "" | |||
color = 0 | |||
logmessage "----------" | |||
logmessage "element: 1" | |||
for i = 0 to ubound(TContent2) - 1 | |||
c = c + 1 | |||
if c = 56 then | |||
c = 0 | |||
loop_count = loop_count + 1 | |||
logmessage "----------" | |||
logmessage "element: " & loop_count | |||
end if | |||
h = hex(Asc(TContent2(i))) | |||
if len(h) = 1 then | |||
h = "0" & h | |||
end if | |||
newhex = newhex & h | |||
if i mod 56 = 32 then | |||
color = 1 | |||
end if | |||
if i mod 56 = 48 then | |||
color = 0 | |||
end if | |||
if i mod 56 = 52 then | |||
objid = 1 | |||
end if | |||
if i mod 56 = 0 then | |||
objid = 0 | |||
end if | |||
if len(newhex) = 8 then | |||
if color = 1 then | |||
logmessage newhex & " (color: " & clng(("&H" & left(newhex, 2))) _ | |||
& " " & clng("&H" & mid(newhex, 3, 2)) _ | |||
& " " & clng("&H" & mid(newhex, 5, 2)) _ | |||
& " " & clng("&H" & mid(newhex, 7, 2)) & ")" | |||
elseif objid = 1 then | |||
if newhex = "FFFFFFFF" then | |||
logmessage newhex & " (object id: -1)" | |||
else | |||
logmessage newhex | |||
end if | |||
else | |||
logmessage newhex | |||
end if | |||
newhex = "" | |||
end if | |||
next | |||
end sub | |||
Function SimpleBinaryToString(Binary) | |||
ReDim tmpArr(LenB(Binary) - 1) | |||
For I = 1 To LenB(Binary) | |||
S = Chr(AscB(MidB(Binary, I, 1))) | |||
tmpArr(I - 1) = S | |||
'logmessage "hex = " & hex(AscB(S)) | |||
Next | |||
SimpleBinaryToString = tmpArr | |||
End Function | |||
| Line 736: | Line 1,052: | ||
===Byte array -> string=== | ===Byte array -> string=== | ||
Function ByteArrayToString(Binary) | Function ByteArrayToString(Binary) | ||
'Antonin Foller, | 'Antonin Foller, https://www.motobit.com/ | ||
'Optimized version of a simple BinaryToString algorithm. | 'Optimized version of a simple BinaryToString algorithm. | ||
| Line 966: | Line 1,282: | ||
End Select | End Select | ||
end sub | end sub | ||
==3D mesh== | |||
===General mesh information=== | |||
logmessage selection.count | |||
logmessage selection(0).Name | |||
logmessage selection(0).Materials(0).Name | |||
logmessage selection(0).Materials(0).Library.name | |||
logmessage selection(0).Materials(0).shaders(0).name | |||
logmessage selection(0).Materials(0).CurrentImageClip.source.filename.value | |||
logmessage selection(0).Materials(0).CurrentImageClip.source.Parameters("XRes").Value | |||
logmessage selection(0).Material.CurrentImageClip.source.Parameters("YRes").Value | |||
logmessage selection(0).Material.CurrentUV.name | |||
logmessage selection(0).activeprimitive.geometry.clusters(0).name | |||
' look for UV cluster names | |||
' xsi-generated: "Texture_Coordinates_AUTO" | |||
' onisplit-generated: "NodeProperties" | |||
logmessage selection(0).sclx.value | |||
logmessage selection(0).scly.value | |||
logmessage selection(0).sclz.value | |||
logmessage selection(0).rotx.value | |||
logmessage selection(0).roty.value | |||
logmessage selection(0).rotz.value | |||
logmessage selection(0).posx.value | |||
logmessage selection(0).posy.value | |||
logmessage selection(0).posz.value | |||
logmessage selection(0).rotorder.value | |||
===Materials and textures=== | |||
====Get all targets of an image clip==== | |||
set imgClip = GetValue("Clips._marker_blackness_tga") | |||
set imgClipTargets = imgClip.GetShaderParameterTargets | |||
logmessage imgClipTargets.count | |||
for each t in imgClipTargets | |||
logmessage t | |||
next | |||
====Get all material libraries and materials==== | |||
for each ml in Application.ActiveProject.ActiveScene.MaterialLibraries | |||
logmessage ml | |||
for each m in ml.items | |||
logmessage m.name ' (material) | |||
next | |||
logmessage "--------------------------" | |||
next | |||
' INFO : Sources.Materials.DefaultLib | |||
' INFO : Scene_Material | |||
' INFO : sosMatBarrier | |||
' INFO : sosMatBlackness | |||
' INFO : sosMatDanger | |||
' INFO : sosMatGhost | |||
' INFO : sosMatImpassable | |||
' INFO : sosMatStairs | |||
' INFO : -------------------------- | |||
' INFO : Sources.Materials.MaterialLibrary | |||
' INFO : AIR_STAIRWALL_LOB1 | |||
' INFO : AIR_WAITSEAT3 | |||
' INFO : AIR_WAITSEAT2 | |||
' INFO : COLLISION | |||
' INFO : -------------------------- | |||
====Check an object's main material for TwoSided-ness==== | |||
' test and toggles an object's main material for TwoSided-ness | |||
' this is also a prerequired test for transparency | |||
' the difficulty is to get the TextureObject (often named Image) | |||
' the magic happens at FindShaders, I often fail to find such trivial stuff | |||
' imo the xsi is terrible incomplete/unintuitive | |||
' e.g. look at "Find (ShaderCollection)" in the help | |||
' it will give you information about meshes such as cubes ... | |||
matLib = selection(0).Materials(0).Library.name | |||
set mat = selection(0).Material | |||
materialName = mat.name | |||
' let us see if there is an Image TextureObject | |||
set shaders = mat.FindShaders(siShaderFilter) | |||
textureObj = "Image" | |||
'if typename(shaders(textureObj)) = "Texture" then ' if not it is Nothing | |||
' logmessage "material has texture object ""Image""" | |||
'end if | |||
Set list = CreateObject("System.Collections.ArrayList") | |||
for each n in shaders | |||
list.Add n.name | |||
next | |||
foundShaderParameterTransparency = false | |||
'foundUniqueShaderName = false | |||
shaderName = "" | |||
if list.Contains(textureObj) = true then | |||
set oColorShareShader = GetValue("Sources.Materials." & matLib & "." & mat.name & "." & textureObj) | |||
set oTargets = oColorShareShader.GetShaderParameterTargets("") | |||
scriptObjArray = split(oTargets(0), ".") | |||
'logmessage scriptObjArray(0) ' Sources (fixed name? Could be considered a folder.) | |||
'logmessage scriptObjArray(1) ' Materials (fixed name? Could be considered a folder.) | |||
'logmessage scriptObjArray(2) ' MaterialsLib (usually each object has its own MaterialsLib) | |||
'logmessage scriptObjArray(3) ' Material | |||
'logmessage scriptObjArray(4) ' Shader e.g. Phong | |||
shaderName = scriptObjArray(4) | |||
for each t in oTargets | |||
logmessage t | |||
if t.name = "transparency" then | |||
foundShaderParameterTransparency = true | |||
exit for | |||
end if | |||
next | |||
end if | |||
if foundShaderParameterTransparency = false then | |||
logmessage "material is not TwoSided, lets reverse now" | |||
SIConnectShaderToCnxPoint "Sources.Materials." & matLib & "." & materialName & ".Image", "Sources.Materials." & matLib & "." & materialName & "." & shaderName & ".transparency", False | |||
else | |||
logmessage "material is TwoSided, lets reverse now" | |||
RemoveAllShadersFromCnxPoint "Sources.Materials." & matLib & "." & materialName & "." & shaderName & ".transparency", siShaderCnxPointBasePorts | |||
end if | |||
Output example: | |||
' INFO : Sources.Materials.DefaultLib.Material.Phong.diffuse | |||
' INFO : material is not TwoSided, lets reverse now | |||
SIConnectShaderToCnxPoint "Sources.Materials.DefaultLib.Material.Image", "Sources.Materials.DefaultLib.Material.Phong.transparency", False | |||
' INFO : Sources.Materials.DefaultLib.Material.Phong.diffuse | |||
' INFO : Sources.Materials.DefaultLib.Material.Phong.transparency | |||
' INFO : material is TwoSided, lets reverse now | |||
RemoveAllShadersFromCnxPoint "Sources.Materials.DefaultLib.Material.Phong.transparency", siShaderCnxPointBasePorts | |||
===Clusters=== | |||
'does a certain cluster type exist ? | |||
'set cls = selection(0).activeprimitive.geometry.clusters.find( siPolygonCluster ) | |||
' more interesting is how many of that type exist | |||
for each n in selection(0).activeprimitive.geometry.clusters | |||
logmessage "Cluster " & n.name & " is of type " & n.type | |||
next | |||
' "poly" = polygon cluster | |||
' "sample" = UV cluster | |||
Output example: | |||
' INFO : Cluster Polygon4 is of type poly | |||
' INFO : Cluster Polygon1 is of type poly | |||
' INFO : Cluster Texture_Coordinates_AUTO is of type sample | |||
====Bounding box values==== | |||
' this could be useful to create a bounding box for [[XML:OFGA|OFGA files]] | |||
' let's get the bounding box of a simple cylinder | |||
' the output values will be absolute positions | |||
CreatePrim "Cylinder", "MeshSurface" | |||
dim xmin, ymin, zmin, xmax, ymax, zmax | |||
dim list | |||
'if you use SelectionList the objects will be treated as one single object | |||
'set list = GetValue( "SelectionList" ) | |||
set list = GetValue( selection(0) ) | |||
GetBBox list, TRUE, xmin, ymin, zmin, xmax, ymax, zmax | |||
LogMessage "Lower Bound: " & xmin & " / " & ymin & " / " & zmin | |||
LogMessage "Upper Bound: " & xmax & " / " & ymax & " / " & zmax | |||
' expected output: | |||
' INFO : Lower Bound: -1 / -2 / -1 | |||
' INFO : Upper Bound: 1 / 2 / 1 | |||
====Get the scaling, rotation and position of selected objects==== | |||
logmessage "mesh name: " & selection(0) | |||
logmessage selection(0).sclx.value | |||
logmessage selection(0).scly.value | |||
logmessage selection(0).sclz.value | |||
logmessage selection(0).rotx.value | |||
logmessage selection(0).roty.value | |||
logmessage selection(0).rotz.value | |||
logmessage selection(0).posx.value | |||
logmessage selection(0).posy.value | |||
logmessage selection(0).posz.value | |||
====Get scaling, rotation, and position of not selected objects==== | |||
' GetValue("NAME.kine.global.rotx") | |||
' NAME must be the exact mesh name | |||
' let's say you want the data of one character's pelvis | |||
logmessage GetValue("pelvis.kine.global.sclx") | |||
logmessage GetValue("pelvis.kine.global.scly") | |||
logmessage GetValue("pelvis.kine.global.sclz") | |||
logmessage GetValue("pelvis.kine.global.rotx") | |||
logmessage GetValue("pelvis.kine.global.roty") | |||
logmessage GetValue("pelvis.kine.global.rotz") | |||
logmessage GetValue("pelvis.kine.global.posx") | |||
logmessage GetValue("pelvis.kine.global.posy") | |||
logmessage GetValue("pelvis.kine.global.posz") | |||
===Points=== | |||
====Get position of points (with selection mode point)==== | |||
' a point must be selected | |||
' gets xyz position of first selected point of the first selected object | |||
logmessage Selection(0).SubComponent.ComponentCollection(0).position.x | |||
logmessage Selection(0).SubComponent.ComponentCollection(0).position.y | |||
logmessage Selection(0).SubComponent.ComponentCollection(0).position.z | |||
====Get position of points (with selection mode object)==== | |||
' an object must be selected | |||
' gets xyz position of point 0 of the first selected object | |||
logmessage selection(0).activeprimitive.geometry.Points(0).Position.x | |||
logmessage selection(0).activeprimitive.geometry.Points(0).Position.y | |||
logmessage selection(0).activeprimitive.geometry.Points(0).Position.z | |||
====Get and set position of points (without selection) right after object creation==== | |||
' point positions are relative to the object's center | |||
' to get the absolute point positions add center to point | |||
' to set the absolute point positions subtract center from point | |||
set oRoot = application.activeproject.activescene.root | |||
set oObj = oRoot.addgeometry( "Cube", "MeshSurface", "test" ) | |||
' to test our code move center to somewhere else | |||
Translate oObj, 9, 11, 13, siRelative, siGlobal, siCtr, siXYZ, , , , , , , , , , 0 | |||
SaveKey oObj & ".kine.local.posx," & oObj & ".kine.local.posy," & oObj & ".kine.local.posz", 1, , , , True | |||
FreezeObj oObj | |||
set oGeometry = oObj.activeprimitive.geometry | |||
aPositions = oGeometry.Points.PositionArray | |||
' get old position | |||
' (xyz, point) | |||
logmessage "old point 0 posx: " & aPositions(0, 0) + GetValue(oObj & ".kine.global.posx") | |||
logmessage "old point 0 posy: " & aPositions(1, 0) + GetValue(oObj & ".kine.global.posy") | |||
logmessage "old point 0 posz: " & aPositions(2, 0) + GetValue(oObj & ".kine.global.posz") | |||
' set new position | |||
aPositions(0, 0) = -7 - GetValue(oObj & ".kine.global.posx") | |||
aPositions(1, 0) = -7 - GetValue(oObj & ".kine.global.posy") | |||
aPositions(2, 0) = -7 - GetValue(oObj & ".kine.global.posz") | |||
' update the array | |||
oGeometry.Points.PositionArray = aPositions | |||
' get new position | |||
logmessage "new point 0 posx: " & aPositions(0, 0) + GetValue(oObj & ".kine.global.posx") | |||
logmessage "new point 0 posy: " & aPositions(1, 0) + GetValue(oObj & ".kine.global.posy") | |||
logmessage "new point 0 posz: " & aPositions(2, 0) + GetValue(oObj & ".kine.global.posz") | |||
' INFO : old point 0 posx: -4 | |||
' INFO : old point 0 posy: -4 | |||
' INFO : old point 0 posz: -4 | |||
' INFO : new point 0 posx: -7 | |||
' INFO : new point 0 posy: -7 | |||
' INFO : new point 0 posz: -7 | |||
====Get global point position==== | |||
set oObj = selection(0) | |||
set oTrans = oObj.Kinematics.Local.Transform | |||
set oPoint0 = oObj.ActivePrimitive.Geometry.Points(0) | |||
set oPoint7 = oObj.ActivePrimitive.Geometry.Points(7) | |||
set oPos0 = oPoint0.Position | |||
set oPos7 = oPoint7.Position | |||
' scaling must be frozen to 1 before we can calculate the size from local values | |||
ResetTransform selection(0), siCtr, siScl, siXYZ | |||
logmessage "local p0: "& oPos0.X & " " & oPos0.Y & " " & oPos0.Z | |||
set oGlobalPos0 = XSIMath.MapObjectPositionToWorldSpace( oTrans, oPos0) | |||
logmessage "global p0: "& oGlobalPos0.X & " " & oGlobalPos0.Y & " " & oGlobalPos0.Z | |||
logmessage "local p7: "& oPos7.X & " " & oPos7.Y & " " & oPos7.Z | |||
set oGlobalPos7 = XSIMath.MapObjectPositionToWorldSpace( oTrans, oPos7) | |||
logmessage "global p7: "& oGlobalPos7.X & " " & oGlobalPos7.Y & " " & oGlobalPos7.Z | |||
logmessage "size: " & oPos7.X - oPos0.X & " " & _ | |||
oPos7.Y - oPos0.Y & " " & _ | |||
oPos7.Z - oPos0.Z | |||
' with a rotation of: -3,8792 16,4039 -13,5017 | |||
' INFO : local p0: -4 -4 -4 | |||
' INFO : local p7: 4 4 4 | |||
' INFO : global p0: -5,74764582364017 -3,00250371537919 -2,43916767056426 ' TRGV start point | |||
' INFO : global p7: 5,74764582364017 3,00250371537919 2,43916767056426 | |||
' INFO : size: 8 8 8 | |||
===Edges=== | |||
... | |||
===Polygons=== | |||
... | |||
==Layers== | |||
===Check if object is member of layer=== | |||
logmessage isMemberOfLayer(selection(0), "layerNameToTest") | |||
function isMemberOfLayer(obj, layerName) | |||
dim list | |||
set list = selectMembers ("Layers." & layerName, 0) ' 0 = for not changing the current selection | |||
for each o in list | |||
if o = obj then | |||
isMemberOfLayer = "yes" | |||
exit for | |||
end if | |||
next | |||
end function | |||
===Get layer name of an object=== | |||
logmessage RecursiveEnum (selection(0), false, false) | |||
function RecursiveEnum( in_Comp, in_Type, in_FirstParentOnly ) | |||
dim list, elem, layerNameToCheck | |||
set list = EnumElements( in_Comp, in_Type ) | |||
if TypeName(list) <> "Nothing" then | |||
for each elem in list | |||
if instr(elem, "Layers") = 1 and instr(elem, ".Members") > 1 then | |||
layerNameToCheck = replace(replace(elem,"Layers.", ""),".Members", "") | |||
if not layerNameToCheck = "" then | |||
RecursiveEnum = layerNameToCheck | |||
end if | |||
exit for | |||
end if | |||
next | |||
end if | |||
end function | |||
' INFO : Layer_Default | |||
==Property Page== | ==Property Page== | ||
| Line 1,005: | Line 1,661: | ||
===PPG content=== | ===PPG content=== | ||
====Button==== | |||
If you need quote signs in the Logic section you write two signs: "" (Not shown in example.) | |||
oPPGLayout.AddButton("btnFuncName", "click here to trigger afunction").setAttribute siUICX, 200 | |||
oPPGLayout.Logic = " sub btnFuncName_OnClicked" & vbCrlf & _ | |||
" btnFuncNameReal" & vbCrlf & _ | |||
" end sub" | |||
function btnFuncNameReal | |||
logmessage "hello world" | |||
end function | |||
New lines in Logic need | |||
& vbCrlf & _ | |||
on the earlier line. | |||
====Text input==== | ====Text input==== | ||
oPSet.AddParameter3 "ParamName", siString | oPSet.AddParameter3 "ParamName", siString | ||
| Line 1,062: | Line 1,736: | ||
==Softimage ICE== | ==Softimage ICE== | ||
===Show a simple value in the viewport=== | ===Show a simple value in the viewport=== | ||
[[Image:XSI_ModTool_ICE_workaround_displaying_a_flag.png|thumb|400px]] | |||
CreatePrim "Cube", "MeshSurface" | CreatePrim "Cube", "MeshSurface" | ||