myara CG blog

CG Design Blog. Thoughts, experiments and experiences.

SI | プロジェクトフォルダの整理(不要なモデルとテクスチャを削除)

今のプロジェクトのSIデータ整理をしている最中です。

このプロジェクトではリグやキャラクター、背景データ、演出自体も何回も変更され、何回も修正が入りました。
その為、プロジェクトフォルダもゴミでいっぱいになり、要らないテクスチャやリファレンスモデルも山ほど残ってしまいました。

これを目で確認して、データ整理するのは無理!

なので、未使用のリファレンスモデルとテクスチャを削除してくれるツールを書くことにしました。

scntoc ファイルが残っていればリファレンスモデルデータは取得できますけど、
使用されているテクスチャの情報を取得するにはSCNファイルを開くしかないです。
少なくても、自分はその方法しか知りません。

なので、シーンファイルを一つずつ開いて、使用されているテクスチャとリファレンスモデルをテキストでメモっておく。
そして、PicturesとModelsフォルダに入っているファイルをこのリストと見比べて、リストに入っていないデータを削除という単純なアプローチです。

それを自動にしたいだけです。


まずは、テクスチャとモデルの情報を取得します。


// JScript
function WriteUsedModels(){
var extFiles = ActiveSceneRoot.ExternalFiles

for ( var i=0, a = extFiles.Count; i < a; i++ ) {
extFilePath = extFiles(i).UNCpath
ext = extFilePath.substring(extFilePath.lastIndexOf(".")+1, extFilePath.length)
// Get only emdl file references
if (ext == "emdl") {
// Create or Open Models.txt
if ( fso.FileExists( ProjPath + "\\Models.txt" )) {
var txtModelsR = fso.OpenTextFile( ProjPath + "\\Models.txt", 1, true )
// Check if the model is already in the list
if ( txtModelsR.ReadAll().indexOf(extFilePath) == -1 ){
txtModelsR.Close();
var txtModelsW = fso.OpenTextFile( ProjPath + "\\Models.txt", 8, true )
txtModelsW.WriteLine( extFilePath )
txtModelsW.Close();
}
else{
txtModelsR.Close();
}
}
else{
var txtModelsW = fso.OpenTextFile( ProjPath + "\\Models.txt", 8, true )
txtModelsW.WriteLine( extFilePath )
txtModelsW.Close();
}
}
}
}


そしてテクスチャの取得


// JScript
function WriteUsedPicFiles(){
// Get All Clips
var oClips = ActiveProject.ActiveScene.ImageClips;

for ( var i=0, a = oClips.Count; i < a; i++ ) {
var PicSource = (oClips(i).parameters('SourceFileName').value)

// Create or Open Pictures.txt
if ( fso.FileExists( ProjPath + "\\Pictures.txt" )) {
var txtPicR = fso.OpenTextFile( ProjPath + "\\Pictures.txt", 1, true )
// Check if the texture is already in the list
if ( txtPicR.ReadAll().indexOf( PicSource ) == -1 ) {
txtPicR.Close();
var txtPicW = fso.OpenTextFile( ProjPath + "\\Pictures.txt", 8, true )
txtPicW.WriteLine( PicSource )
txtPicW.Close();
}
else{
txtPicR.Close();
}
}
else{
var txtPicW = fso.OpenTextFile( ProjPath + "\\Pictures.txt", 8, true )
txtPicW.WriteLine( PicSource )
txtPicW.Close();
}
}
}


よし、これで Pictures.txt に使用されているテクスチャのリストと、Models.txt にリファレンスで使われているモデルリストが出来ました。

次は、Pictures フォルダ等に入っているファイルと比べて、合っていない奴を消す。


function DeleteUnused( inList ){
// inList = "Models" / "Pictures"
var sPath = ProjPath + "\\" + inList
if (fso.FolderExists(sPath)){
var fsoPath = fso.GetFolder(activeproject.path + "\\"+ inList)

// Convert TXT files to Array (is faster to work with simple arrays)
var txtArray = []
var txtFile = fso.OpenTextFile( ProjPath + "\\" + inList +".txt", 1, true )
while (!txtFile.AtEndOfStream){
txtArray.push( txtFile.ReadLine() )
}
txtFile.Close();

// Compare the files in the "inList" directory with the TXT array
// And create a Delete Collection
var oDelColl = XSIFactory.CreateObject( "XSI.Collection" );
var files = new Enumerator(fsoPath.Files);
for(; !files.atEnd(); files.moveNext()){
if ( Check (txtArray, String(files.item()) ) == 0){
oDelColl.Add( files.item() )
}
}

// Convert the Delete Collection to an Array just to display it in the MsgBox
var aLog = []
for ( var i=0, a = oDelColl.Count; i < a; i++ ) {
sDelCollItem = String( oDelColl(i) )
aLog.push( sDelCollItem.substring(sDelCollItem.lastIndexOf( inList ), sDelCollItem.length) +"\n")
}

// Ask before Delete all unused files
var DeleteQuestion = XSIUIToolkit.MsgBox("Do you want to delete these files? \n\n" + aLog, 4 )
if (DeleteQuestion == 6){
for ( var i=0, a = oDelColl.Count; i < a; i++ ) {
fso.DeleteFile(oDelColl(i))
}
}
fso.DeleteFile(ProjPath + "\\" + inList +".txt")
}
}
function Check(array, sItem){
// Compare all array items with an specific string
// 1 = equal, 0 = string doesn't exist in the array
for ( var i=0, a = array.length; i < a; i++ ) {
if ( array[i].toUpperCase() == sItem.toUpperCase() ) return 1;
}
return 0
}


これで全部出来たので、あとは全シーンをループするだけです。
削除するコレクションを作って、念のために本当に削除していいのか?というMsgBoxも入れて、とりあえず完成です。


// Get Path
var ProjPath = XSIInputBox( "This will open all your scene files and delete models and pictures than aren't in use.\n\nOnly works with SI default folder structure\n\n\nInput Project Path","CleanSCN external Files" )
if (ProjPath == "") var ProjPath = ActiveProject.path // <-- WARNING You can't cancel this script in this step!

// Since we can't cancel in the previous step, I'll add an extra confirm message.
if (ProjPath == ActiveProject.path){
var ProceedQuestion = XSIUIToolkit.MsgBox(ProjPath +"\n will start to be cleaned. \n Do you want to continue?", 4 ,"CleanSCN external Files")
}
else{
ProceedQuestion = 6
logmessage ("CleanSCNextFiles canceled")
}

if (ProceedQuestion ==6){
// Set Global variables
var ScnPath = ProjPath + "\\Scenes"
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
var oFol = fso.GetFolder(ScnPath) ;

// Delete TXT Files if they exist
if ( fso.FileExists( ProjPath + "\\Pictures.txt" )) fso.DeleteFile( ProjPath + "\\Pictures.txt" )
if ( fso.FileExists( ProjPath + "\\Models.txt" )) fso.DeleteFile( ProjPath + "\\Models.txt" )

// Loop Files in Scenes folder and write a txt file with Pictures and Models that are in use
oEnum1 = new Enumerator( oFol.files ) ;
for (;!oEnum1.atEnd();oEnum1.moveNext() )
{
var f = oEnum1.item() ;
var sf = String(f);
if (fso.GetExtensionName(f.name) == "scn") {
OpenScene (f.path, false)
WriteUsedPicFiles()
WriteUsedModels()
}
}
// Delete unused Pics and Models
DeleteUnused ("Models")
DeleteUnused ("Pictures")
}


これで楽にプロジェクトフォルダのデータ整理が出来ます。

DOWNLOAD

注意、SIのデフォルトフォルダ構造にしか対応していません。

でも難しいコードではないから、自分でカスタマイズしてみてください。

それでは、また。
Next page