ZFileUtils is a DLL (dynamic link library) that provides useful utilities to ZScript. This page describes these utilities. A sample zscript showing how to use all the functions is included in the zip (see below).
The latest version, for ZBrush 2021, includes a DLL file for Windows and a LIB file for MacOSX. Note that these are 64 bit – as ZBrush 2021 is only 64 bit, 32 bit is no longer supported.
Download the latest ZFileUtils DLL (with example zscript) for ZBrush 2021 here
Latest version ZFileUtils 2021 01A updated November 17 2020. Still works in ZBrush 2022!
Functions and Examples
In the code examples below, comments are shown in blue and strings are shown in green.
-
- Setting the path to the DLL
- Checking if a Folder Exists
- Making a new Folder
- Copying a File
- Renaming a File
- Emptying a Folder
- Deleting a File
- Deleting a Folder
- Launching an Open Files dialog
- Listing the Contents of a Folder
- Launching an Application with a File
- Finding the Public/Shared folder
- Creating a Public/Shared Data folder
- Launching a Select Folder dialog
- Renaming a SubTool
- Append a blank SubTool
- Dropdown menu
- Localization
Setting the path to the DLL
Before calling a function from the ZFileUtils DLL, ZBrush must know where to find it. The DLL file is different for Windows and Mac, so the simplest way to set the path correctly is to call a CheckSystem routine before trying to access the DLL. Here is an example:
[RoutineDef, CheckSystem, //check ZBrush version [VarSet,Zvers,[ZBrushInfo,0]] [If,[Val,Zvers] >= 2021.0,, [Note,"\Cff9923This zscript\Cffffff is not designed for this version of \Cff9923ZBrush\Cffffff.",,3,4737096,,300] [Exit] ] [VarSet,isMac, [ZBrushInfo,6]] //check Mac or PC // Make sure we have the dll and set its path [If,[ZBrushInfo,16]==64,//64 bit [If,isMac, //use the path below for testing only [VarSet,dllPath,"MyPluginData/ZFileUtils.lib"] //use the path below for installed plugins //[VarSet,dllPath,"ZBRUSH_ZSTARTUP/ZPlugs64/MyPluginData/ZFileUtils.lib"] , //use the path below for testing only [VarSet,dllPath,"MyPluginData\ZFileUtils64.dll"] //use the path below for installed plugins //[VarSet,dllPath,"ZBRUSH_ZSTARTUP\ZPlugs64\MyPluginData\ZFileUtils64.dll"] ] ,//else 32 bit - no longer supported [Note,"\Cff9923This zscript\Cffffff is not designed for this version of \Cff9923ZBrush\Cffffff.",,3,4737096,,300] [Exit] ] [If, [FileExists, [Var,dllPath]], //check that correct version [VarSet, dllVersion, [FileExecute, [Var,dllPath], Version]] [If, [Val,dllVersion] >= 8.0,//dll version //OK ,//else earlier version [Note,"\Cff9923Note :\Cc0c0c0 The \Cff9923 ZFileUtils plugin \CffffffDLL\Cc0c0c0 is an earlier version which does not support this plugin. Please install correct version."] [Exit] ] , // else no DLL. [Note,"\Cff9923Note :\Cc0c0c0 The \Cff9923 ZFileUtils plugin \CffffffDLL\Cc0c0c0 could not be found at the correct location. Please re-install the plugin, making sure the relevant files and folders are in the \CffffffZStartup/ZPlugs\Cc0c0c0 folder."] [Exit] ] ]//end routine
Checking If a Folder Exists
The FolderExists function will return 1 if a folder exists and 0 if it does not.
Example:
//the full path to the folder [VarSet,folderName,"C:/Test Folder"]] //check to see if folder exists [VarSet,folderExists,[FileExecute,[Var,dllPath],"FolderExists",#folderName]] [If,folderExists, [Note,"Folder exists.",,3] ,//else [Note,"Folder does not exist.",,3] ]
Making a new Folder
The MakeFolder function will create a new folder. First check that the folder does not already exist.
Example:
//the full path to the new folder [VarSet,folderName,"C:/Test Folder"]] [VarSet,folderExists,[FileExecute,[Var,dllPath],"FolderExists",#folderName]] [If,folderExists, [Note,"Folder exists. Operation cancelled.",,3] [Exit] ,//else no folder [VarSet,err,[FileExecute,[Var,dllPath],"MakeFolder",#folderName]] [If,err,[Note,"An error occurred.",,2],[Note,"Folder created",,2]] ]
Copying a File
The FileCopyTo function will copy a file. When passing two file paths to the ZFileUtils DLL, a memory block must be used for the second path.
Example:
//the file to be copied [VarSet,fileName,"MyPluginData\FromThis.txt"] //we need the full path [VarSet,fileName,[FileNameResolvePath,fileName]] //the destination - any existing file will be overwritten! [VarSet,copyFileName,"Test Folder\ToThis.txt"] //we need the full path [VarSet,copyFileName,[FileNameResolvePath,copyFileName]] //copy the file [MemCreate, ZFileUtils_CopyFile, 256, 0] [MemWriteString,ZFileUtils_CopyFile,copyFileName,0] [If,[FileExists,fileName], [VarSet,err,[FileExecute,[Var,dllPath],"FileCopyTo",fileName,,ZFileUtils_CopyFile]] ] [MemDelete,ZFileUtils_CopyFile] [If,err,[Note,"An error occurred.",,2],[Note,"File copied",,2]]
Renaming a File
The FileRename function renames a file.
Example:
//the file to be renamed [VarSet,fileName,"Test Folder\ToThis.txt"] //we need the full path [VarSet,fileName,[FileNameResolvePath,fileName]] //the new name [VarSet,copyFileName,"Test Folder\NewName.txt"] //we need the full path [VarSet,copyFileName,[FileNameResolvePath,copyFileName]] //copy the file //create a memblock to take the copy file name [MemCreate, ZFileUtils_CopyFile, 256, 0] //write the file name to the memblock [MemWriteString,ZFileUtils_CopyFile,copyFileName,0] //if the file exists, rename it [If,[FileExists,fileName], [VarSet,err,[FileExecute,[Var,dllPath],"FileRename",fileName,,ZFileUtils_CopyFile]] ] //delete the memblock as we've finished with it [MemDelete,ZFileUtils_CopyFile] [If,err,[Note,"An error occurred.",,2],[Note,"File renamed",,2]]
Emptying a Folder
The EmptyFolder function will delete all the files in a folder. (Subfolders will not be deleted or emptied.)
Example:
//the full path to the folder [VarSet,folderName,"C:\Test Folder"] //empty the folder of files [VarSet,err,[FileExecute,[Var,dllPath],"EmptyFolder",#folderName]] [If,err,[Note,"An error occurred.",,2],[Note,"Folder emptied",,2]]
Deleting a File
The FileDelete function will delete a file.
Example:
//the file to be deleted [VarSet,fileName,"Test Folder\ToThis.txt"] //we need the full path [VarSet,fileName,[FileNameResolvePath,fileName]] //if the file exists, delete it [If,[FileExists,fileName], [VarSet, err, [FileExecute, [Var,dllPath],"FileDelete",#fileName]] // Delete this file... [If,err, [Note,"An error occurred.",,2] ,//else OK [Note,"File deleted",,2] ] ,//else no file [Note,"No file to delete!",,2] ]
Deleting a Folder
The DeleteFolder function will delete a folder. It must already be empty of all files and subfolders.
Example:
//the full path to the folder [VarSet,folderName,"C:\Test Folder"] //delete the folder [VarSet,err,[FileExecute,[Var,dllPath],"DeleteFolder",#folderName]] //an error may mean the folder has files in it [If,err,[Note,"An error occurred.",,2],[Note,"Folder deleted",,2]]
Launching an Open Files Dialog
A combination of functions will launch an Open File dialog box and return the number of files selected. The file names can then be retrieved.
-
Set the Default Folder
The SetDefaultFolder function is optional and is not implemented on Mac OSX. It will set the ‘starting’ folder for the dialog.
Example:
//***this code just for setting the default folder for open dialog //get the full path to this script file [VarSet,folderName,[FileNameResolvePath,"ZFileUtils_TestZScript.txt"]] //use this to create the full path to the folder [VarSet,folderName,[FileNameExtract,folderName,1]] //(optional) set the default folder (not implemented on Mac OSX) [FileExecute, [Var,dllPath], SetDefaultFolder, folderName]
-
The Files Dialog
The GetFilesDialog function launches the Open file dialog so that the user can select some files. You can set the Title for the dialog and the File extensions (separated by commas). If no file extensions are specified then all file types can be selected by the user.
The function returns the number of files selected.
Example:
//text for the dialog title (optional) [VarDef,dialogTitle, "Please select some files"] //string containing file extensions separated by commas(,) //if not used then all files will be used [VarSet,fileExt,"obj,GoZ,ma"] //create memblock for file extensions [MemCreate,ZFileUTils_FileExt, 256, 0] //copy file extensions to memblock [MemWriteString,ZFileUTils_FileExt,fileExt,0] //create and launch Open File dialog //returns the number of files selected [VarSet,fileCount,[FileExecute,[Var,dllPath],"GetFilesDialog",#dialogTitle,,ZFileUTils_FileExt]] //***alternative GetFilesDialog function call with no title text or file extensions: //[VarSet, fileCount, [FileExecute, [Var,dllPath], "GetFilesDialog"]] //delete the memblock as we've finished with it [MemDelete,ZFileUTils_FileExt] //display the number of files selected [Note,[StrMerge,fileCount," files selected"],,2]
-
Getting the File Paths
The GetFilePath function is used to get the full path for the file at the index specified.
Note that a memory block is used to get the path.
Example:
//now get the full file path to each file selected [If,fileCount > 0, //Create a memblock to get the file path [MemCreate,Test_ZFileUTils, 256, 0] //get each of the file paths [VarSet,index,1] [Loop,fileCount, [VarSet,err,[FileExecute, [Var,dllPath],GetFilePath,,index,Test_ZFileUTils]] [VarInc,index] //if all is OK copy from memblock to variable [If,err == 0, [MemReadString, Test_ZFileUTils, fileName] //do stuff //display the file name and path [Note,fileName,,1] ,//else [LoopContinue] ]//end if ]//end loop [MemDelete,Test_ZFileUTils] ]//end if fileCount
Listing the Contents of a Folder
A combination of functions for examining the contents of a folder.
-
GetFileNumber
The GetFileNumber function returns the number of files and/or subfolders in a folder.
Example:
[VarSet,folderName,[FileNameResolvePath,folderName]]
//get the number of files/folders [VarSet,fileCount,[FileExecute,[Var,dllPath],"GetFileNumber",folderName]] [If,fileCount < 0,[Note,"Error getting number of files in folder"]]
If the file count is greater than zero then we can proceed to examine the contents.
-
Opening the Folder
The OpenFolder function opens the folder so that the contents can be read.
Example:
//open the folder [VarSet,err,[FileExecute,[Var,dllPath],"OpenFolder",folderName]] //if we can't open the folder exit the zscript [If,err,[Note,"Error opening folder."][Exit]]
-
Getting a File
The GetFile function is used to get the file or folder names. Note that a memory block is used to get each name.
Example:
//create a memblock to get the file name [MemCreate,ZFileUtils_list, 256, 0] [Loop,fileCount,//loop through the files //get the filename [VarSet,err,[FileExecute,[Var,dllPath],"GetFile",,,ZFileUtils_list]] //an error means we've reached the end of the list, so exit the loop [If,err,[LoopExit]] //otherwise write the file name from the memblock to a variable [MemReadString, ZFileUtils_list,fileName] [Note,#fileName]//display each file or folder name ]//end loop //delete the memblock as we've done with it [MemDelete,ZFileUtils_list]
(See the zscript included in the zip file for a more extensive example.)
-
Closing the Folder
The CloseFolder function closes the folder after it has been examined. This function must be called after the above functions, so that the folder is not left open.
Example:
//***must close the folder*** [VarSet,err,[FileExecute,[Var,dllPath],"CloseFolder",folderName]] [If,err,[Note,"Error closing folder."]]
Launching an Application with a File
The LaunchAppWithFile function will open a file using a specified application. If no application is specified then the default application will be used.
Example:
//the full path to the app to launch [If,isMac,//if we're on Mac OSX [VarSet,appPath,"/Applications/TextEdit.app"] ,//else we're on Windows [VarSet,appPath,"C:\Windows\System32\notepad.exe"] ] //full path to the file to open [VarSet,fullFilePath,[FileNameResolvePath,"MyPluginData\FromThis.txt"]] //create memblock for app path [MemCreate,ZFileUTils_AppPath, 256, 0] //write app path to memblock [MemWriteString,ZFileUTils_AppPath,appPath,0] [VarSet,err,[FileExecute,[Var,dllPath],"LaunchAppWithFile",#fullFilePath,,ZFileUTils_AppPath]] //delete the memblock as we've done with it [MemDelete,ZFileUTils_AppPath] //an error [If,err,[Note,"An error occurred.",,2]]
Getting the Public/Shared folder
The GetPublicFolder function provides a way of getting the path to the Public/Shared folder on the user’s system. ZBrush and its plugins now write any temporary files to folders within the ZBrushData folder at this location. Writing to the Public/Shared folder avoids issues with file read/write permissions. If your plugin is going to use the Public/Shared folder in this way then it should be able to create its own data folder as needed. Follow the method Creating a Public/Shared plugin Data folder outlined below.
//create memblock to get the path [If,[MemGetSize,MC_SharedPath],, [MemCreate,MC_SharedPath,256,0] [FileExecute, [Var,dllPath],GetPublicFolder,,,MC_SharedPath] ] //copy path from memblock tpo variable [MemReadString,MC_SharedPath,gSharedPath,0,1] //add ZBrushData to path [If,isMac, [VarSet,gSharedPath,[StrMerge,gSharedPath,"/Shared/ZBrushData/"]] ,//else Windows [VarSet,gSharedPath,[StrMerge,gSharedPath,"/ZBrushData/"]] ] //display result [Note,gSharedPath]
Creating a Public/Shared plugin Data folder
The routine below can be used to check for a custom plugin folder MyPluginData and create it if necessary inside the ZBrushData/ZPluginData folder. The variable gSharedPath is then set to the path to MyPluginData and can be used when working with temp files.
[RoutineDef,CheckSharedFolder, [VarSet,gSharedFolder,"ZPluginData/"]//all plugins use same folder [VarSet,gPluginFolder,"MyPluginData/"]//unique folder for your plugin //create memblock to get public/shared folder [If,[MemGetSize,MC_SharedPath], //memblock exists - do nothing ,//else create memblock [MemCreate,MC_SharedPath,256,0] [FileExecute, [Var,dllPath],GetPublicFolder,,,MC_SharedPath] ] //copy path to variable [MemReadString,MC_SharedPath,gSharedPath,0,1] //check for folders and create as necessary [If,isMac, [VarSet,gSharedPath,[StrMerge,gSharedPath,"/Shared/ZBrushData/",gSharedFolder]] [If,[FileExists,[StrMerge,"!:",gSharedPath,gPluginFolder,"folder.txt"]],, [FileExecute, [Var,dllPath],MakeFolder,gSharedPath] [FileExecute, [Var,dllPath],MakeFolder,[StrMerge,gSharedPath,gPluginFolder]] [MemSaveToFile,MC_SharedPath,[StrMerge,"!:",gSharedPath,gPluginFolder,"folder.txt"]] ] [VarSet,gSharedPath,[StrMerge,"!:",gSharedPath,gPluginFolder]] ,//else Windows [VarSet,gSharedPath,[StrMerge,gSharedPath,"/ZBrushData/",gSharedFolder]] [If,[FileExists,[StrMerge,gSharedPath,gPluginFolder,"folder.txt"]], //file exists - do nothing ,//else create folders and file [FileExecute, [Var,dllPath],MakeFolder,gSharedPath] [FileExecute, [Var,dllPath],MakeFolder,[StrMerge,gSharedPath,gPluginFolder]] [MemSaveToFile,MC_SharedPath,[StrMerge,gSharedPath,gPluginFolder,"folder.txt"]] ] //set variable so can be used when saving temp files [VarSet,gSharedPath,[StrMerge,gSharedPath,gPluginFolder]] ] ]//end routine
Launching a Select Folder dialog
The ChooseFolder function will launch a dialog so the user can select a folder. Creation of a new folder is supported.
[IButton,SelectFolder,"Launch a Select Folder dialog", [RoutineCall, CheckSystem] [VarDef,folderPath,""] //create memblock to get the path [If,[MemGetSize,MC_FolderPath],, [MemCreate,MC_FolderPath,256,0] ] [VarSet,err,[FileExecute, [Var,dllPath],ChooseFolder,,,MC_FolderPath]] [If,err, [Note,err]//function will return -1 if no folder chosen , //copy path from memblock to variable [MemReadString,MC_FolderPath,folderPath,0,1] //show the selected folder path [Note,folderPath]//Notes do not display backslashes //*** when using the path remember to append a slash before the file name!*** //*** for example: //[VarSet,fileName,"My_Model.ztl"] //[FileNameSetNext,[StrMerge,folderPath,"/",fileName]] ] [MemDelete,MC_FolderPath] ]//end button
Renaming a SubTool
The RenameSetNext function can be used to rename a SubTool, 3D Layer or the Transpose Units. The function is called just before the relevant button is pressed. Layer names are limited to 15 characters but the example below does not check for this.
[IButton,SubtoolRename,"Rename selected subtool", [RoutineCall, CheckSystem] [VarSet,newName,"My New Name"] [VarSet,buttonPath,"Tool:SubTool:Rename"] //set buttonPath to the button you want //"Tool:SubTool:Rename" - for SubTool //"Tool:Layers:Rename" - for Layers //"Preferences:Transpose Units:Set Units" - for Transpose Units [If, (([IExists, buttonPath]) && ([IsEnabled, buttonPath])), [FileExecute, [Var, dllPath], RenameSetNext, newName] [IPress, buttonPath] ] ]//end button
Append a blank SubTool
The AppendNewSubTool function can be used to add a new Polymesh3D star at the end of the subtool list. This simplifies operations such as importing files as the imported file will replace the newly appended polymesh.
[VarSet,name,"My Name"] [VarSet, resIndex, [FileExecute, [Var, dllPath], AppendNewSubTool, name]] //value of resIndex will be the index of the new subtool