1175 lines
38 KiB
Plaintext
Executable File
1175 lines
38 KiB
Plaintext
Executable File
-- Model-specific includes
|
|
filein "pipeline/export/ui/weapon_exporter_ui.ms"
|
|
filein "pipeline/export/model.ms"
|
|
filein "pipeline/util/rb_script_generator.ms"
|
|
filein "pipeline/util/skinutils.ms"
|
|
filein "pipeline/export/rb_image.ms"
|
|
filein "pipeline/export/models/globals.ms"
|
|
|
|
-- Additional includes
|
|
filein "pipeline/util/ruby.ms"
|
|
filein "pipeline/util/texturemetatag_utils.ms"
|
|
|
|
filein (RsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms")
|
|
|
|
struct SlotItemStruct
|
|
(
|
|
index,
|
|
paths,
|
|
usage
|
|
)
|
|
|
|
struct plantsMgr_Constructor
|
|
(
|
|
iddArchivePath = (RsConfigGetAssetsDir()+"export/models/plantsmgr.idd.zip"),
|
|
iddArchiveTempPath = (RsConfigGetAssetsDir()+"export/models/plantsmgr.idd.TEMP.zip"),
|
|
iddFolderPath = (RsConfigGetAssetsDir()+"export/models/plantsmgr.idd"),
|
|
itdArchivePath = (RsConfigGetAssetsDir()+"export/textures/plantsmgr.itd.zip"),
|
|
zipFile,
|
|
modelArc,
|
|
extractPath = (sysInfo.tempdir + "PlantsMgr"),
|
|
modelPath,
|
|
modelName,
|
|
--zipHandler = dotnetobject "Ionic.zip",
|
|
modelItems = #(),
|
|
slot,
|
|
model,
|
|
lod,
|
|
usageAssigned = #(),
|
|
|
|
texturePath = (RsConfigGetArtDir()+"textures/vegetation"),
|
|
txIndex,
|
|
txLod,
|
|
baseTxName = "txgrass",
|
|
itdSourceTexturePaths = #(),
|
|
itdSourceTextureIndex = "PlantMgr_SrcTexture_Index.dat",
|
|
extractedINI = (extractPath + "/PlantMgr_SrcTexture_Index.dat"),
|
|
|
|
plantsTxdEnum = #( DataPair idx:1 name:"Country",
|
|
DataPair idx:2 name:"Ocean",
|
|
DataPair idx:0 name:"All"
|
|
),
|
|
|
|
plantsTxdPaths = #( DataPair name:#all path:(RsConfigGetAssetsDir()+"export/textures/plantsmgr.itd.zip"),
|
|
DataPair name:#country path:(RsConfigGetAssetsDir()+"export/textures/plantsmgr1.itd.zip"),
|
|
DataPair name:#ocean path:(RsConfigGetAssetsDir()+"export/textures/plantsmgr2.itd.zip")
|
|
),
|
|
|
|
changeListNum = undefined,
|
|
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn buildIdd =
|
|
(
|
|
--check access first
|
|
if (getFileAttribute iddArchivePath #readonly) then
|
|
(
|
|
messagebox ("The file: "+iddArchivePath+"\nIs write protected.\nIt needs to be checked out of perforce before continuing") title:"Error"
|
|
return false
|
|
)
|
|
|
|
if modelPath == undefined then
|
|
(
|
|
messagebox "There is no model path specified."
|
|
return false
|
|
)
|
|
|
|
--set base object name
|
|
base = ("grass"+model)
|
|
|
|
try
|
|
(
|
|
--extract current zip into it
|
|
deleteFile extractPath
|
|
if (not (doesfileExist extractPath)) then makeDir extractPath
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read iddArchivePath
|
|
zipFile.TempFileFolder = extractPath
|
|
modelArc = (dotNetClass "Ionic.Zip.ZipFile").Read modelPath
|
|
|
|
--build a directory name from slot and model
|
|
modelName = getFilenamePath modelArc.item[0].filename
|
|
|
|
local target = case lod Of
|
|
(
|
|
"base":base
|
|
"lod1":(base+"_lod1")
|
|
"lod2":(base+"_lod2")
|
|
)
|
|
|
|
|
|
--get files from the exported model
|
|
--for i = 1 to modelArc.count do print zipFile.item[i].filename
|
|
--for item in modelArc where item.fileName != "entity.textures" do
|
|
extractAction = dotNetClass "Ionic.Zip.ExtractExistingFileAction"
|
|
for i=0 to (modelArc.count - 1) where not (matchPattern modelArc.item[i].filename pattern:"*.textures") do
|
|
(
|
|
append modelItems modelArc.item[i].filename
|
|
modelArc.item[i].extract extractPath extractAction.OverwriteSilently
|
|
)
|
|
|
|
modelArc.dispose()
|
|
|
|
--remove the old entries
|
|
entries = #()
|
|
for i=0 to (zipFile.count - 1) where (matchPattern zipFile.item[i].filename pattern:(target+"/*")) do
|
|
(
|
|
append entries zipFile.item[i].filename
|
|
)
|
|
for item in entries do zipFile.RemoveEntry item
|
|
|
|
--add them to the plant manager archive
|
|
zipFile.UpdateDirectory (extractPath+"/"+modelName) target
|
|
|
|
--save the zip
|
|
try
|
|
(
|
|
print "saving"
|
|
zipFile.Save iddArchivePath
|
|
)
|
|
catch
|
|
(
|
|
--messagebox "Could not save PlantsMgr, Is it open somewhere else?" title:"Error"
|
|
--clean up
|
|
if modelArc != undefined then modelArc.dispose()
|
|
if zipFile != undefined then zipFile.dispose()
|
|
|
|
return false
|
|
)
|
|
)
|
|
|
|
catch
|
|
(
|
|
if modelArc != undefined then modelArc.dispose()
|
|
if zipFile != undefined then zipFile.dispose()
|
|
messagebox "problems" title:"Error"
|
|
return false
|
|
)
|
|
|
|
--clean up
|
|
if modelArc != undefined then modelArc.dispose()
|
|
if zipFile != undefined then zipFile.dispose()
|
|
|
|
deleteFile iddArchiveTempPath
|
|
|
|
return true
|
|
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn localBuild mode =
|
|
(
|
|
if mode == "idd" then
|
|
(
|
|
--RsRunIronRubyScript (RsConfigGetToolsDir() + "ironlib\\util\\data_convert_file.rb") args:#(iddArchivePath)
|
|
AP3Invoke.convert #(iddArchivePath) debug:true
|
|
)
|
|
else if mode == "itd" then
|
|
(
|
|
--RsRunIronRubyScript (RsConfigGetToolsDir() + "ironlib\\util\\data_convert_file.rb") args:#(itdArchivePath)
|
|
AP3Invoke.convert #(itdArchivePath) debug:true
|
|
)
|
|
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn pickTexture =
|
|
(
|
|
local oldTexturePath = texturePath
|
|
local newTexturePath = getOpenFileName caption:"Texture path" types:"dds(*.dds)|*.dds"
|
|
if newTexturePath == undefined then return false
|
|
if getFilenameType newTexturePath != ".dds" then texturePath = undefined
|
|
--if texturePath == undefined then texturePath = oldTexturePath
|
|
|
|
--return
|
|
--print texturePath
|
|
texturePath = newTexturePath
|
|
texturePath
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn extractItd =
|
|
(
|
|
if (getDirectories extractPath).count == 0 then makeDir extractPath
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
zipFile.TempFileFolder = extractPath
|
|
zipFile.ExtractAll extractPath (dotNetClass "Ionic.Zip.ExtractExistingFileAction").OverwriteSilently
|
|
|
|
--clean
|
|
zipFile.dispose()
|
|
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Perforce changelist handling
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn checkoutArchive inPath =
|
|
(
|
|
if (getFileAttribute inPath #readonly) do
|
|
(
|
|
if (changeListNum == undefined) do
|
|
(
|
|
changeListNum = gRsPerforce.createChangeList "PlantsMgr.itd changes"
|
|
)
|
|
|
|
gRsPerforce.add_or_edit inPath
|
|
gRsPerforce.addToChangelist changeListNum inPath
|
|
)
|
|
|
|
return ok
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Preapre the archive for building by adding or removing entries
|
|
-- based on what usage type is assigned
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn prepareArchive type =
|
|
(
|
|
--Perforce checkout
|
|
checkoutArchive itdArchivePath
|
|
|
|
--work through the list, if it matches the type then add the item to the archive, or remove it.
|
|
local typeName = type as String
|
|
|
|
local entries = for item in itdSourceTexturePaths where ((tolower item.usage) == (tolower typeName)) collect item.index
|
|
|
|
--now look through the entries in the archive
|
|
local archive = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
local theNames = for i=0 to (archive.count - 1) collect archive.item[i].filename
|
|
|
|
--Remove an entires that are not needed
|
|
for thisName in theNames do
|
|
(
|
|
if ((findString thisName "txgrass") != undefined) do --just the txgrass textures
|
|
(
|
|
local thisNameIndex = substituteString ((filterString (getFilenameFile thisName) "_")[1]) "txgrass" ""
|
|
--local lodName = if ((findstring thisName "_lod1") == undefined) then ((getFilenameFile thisName) + "_lod1.dds") else thisName
|
|
|
|
if ((findItem entries thisNameIndex) == 0) then --remove the zip entry
|
|
(
|
|
archive.RemoveEntry thisName
|
|
)
|
|
)
|
|
)
|
|
|
|
--Add any that are...
|
|
for filePath in (getFiles (extractPath + "/*.dds")) do
|
|
(
|
|
local fileName = pathConfig.stripPathToLeaf filePath
|
|
if ((findString fileName "txgrass") != undefined) do --just the txgrass textures
|
|
(
|
|
local thisNameIndex = substituteString ((filterString (getFilenameFile fileName) "_")[1]) "txgrass" ""
|
|
if ((findItem entries thisNameIndex) != 0) then --add the zip entry
|
|
(
|
|
archive.UpdateFile (extractPath + "/" + fileName ) ""
|
|
)
|
|
)
|
|
)
|
|
|
|
archive.Save()
|
|
archive.Dispose()
|
|
|
|
return True
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn buildItd type =
|
|
(
|
|
local doBuild = true
|
|
--prepare the temporary dir with the content required for the itd type
|
|
|
|
|
|
--build based on which itd archive is required, set the itdArchivepath accordingly
|
|
case type of
|
|
(
|
|
#country:
|
|
(
|
|
for item in plantsTxdPaths where (item.name == #country) do itdArchivePath = item.path
|
|
doBuild = prepareArchive #country
|
|
)
|
|
|
|
#ocean:
|
|
(
|
|
for item in plantsTxdPaths where (item.name == #ocean) do itdArchivePath = item.path
|
|
doBuild = prepareArchive #ocean
|
|
)
|
|
|
|
default: --building all
|
|
(
|
|
for item in plantsTxdPaths where (item.name == #all) do itdArchivePath = item.path
|
|
)
|
|
)
|
|
|
|
--Perforce checkout
|
|
checkoutArchive itdArchivePath
|
|
-- if (getFileAttribute itdArchivePath #readonly) then
|
|
-- (
|
|
-- messagebox ("The file: "+itdArchivePath+"\nIs write protected.\nIt needs to be checked out of perforce before continuing") title:"Error"
|
|
-- return false
|
|
-- )
|
|
|
|
--proceed wih build
|
|
if doBuild do
|
|
(
|
|
localBuild "itd"
|
|
)
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--return a list of the textures used in the slots
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn getItdFileList =
|
|
(
|
|
local itdItems = #()
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
local zipFileSorted = zipFile.EntriesSorted
|
|
|
|
for i=1 to zipFileSorted.count do
|
|
(
|
|
local thisEntry = zipFileSorted.item[i-1]
|
|
append itdItems thisEntry.fileName
|
|
)
|
|
|
|
--clean
|
|
zipFile.dispose()
|
|
|
|
return itdItems
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--Extract the source texture index file from the itd archive
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn getItdIndexList =
|
|
(
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
|
|
--extract the index list
|
|
local entry = zipFile.Item "PlantMgr_SrcTexture_Index.dat"
|
|
itdSourceTextureIndex = entry.Extract extractPath (dotNetClass "Ionic.Zip.ExtractExistingFileAction").OverwriteSilently
|
|
|
|
if doesFileExist extractedINI then
|
|
(
|
|
for slot in (getINIsetting extractedINI) do
|
|
(
|
|
local base = getINIsetting extractedINI slot "base"
|
|
local lod1 = getINIsetting extractedINI slot "lod1"
|
|
local usage = getINISetting extractedINI slot "usage"
|
|
append itdSourceTexturePaths (SlotItemStruct index:slot paths:#(base, lod1) usage:usage)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
print "cant find extractedINI"
|
|
)
|
|
|
|
--clean
|
|
zipFile.dispose()
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Insert an entry into the index
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn insertItdIndexListItem index column sourcePath =
|
|
(
|
|
--Perforce Checkout
|
|
checkoutArchive itdArchivePath
|
|
|
|
if itdSourceTexturePaths == undefined then getItdIndexList()
|
|
|
|
local formattedIndex = if index < 10 then "0" + (index as String) else index as String
|
|
|
|
local columnName = if (column == 1) then "base" else "lod1"
|
|
--update the index dat
|
|
setINISetting extractedINI formattedIndex columnName sourcePath
|
|
|
|
zipFile.UpdateFile extractedINI ""
|
|
zipFile.Save()
|
|
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Indsert the given source texture into the archive
|
|
-- renaming it for the slot its going into
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn insertItdTexture index column sourcePath =
|
|
(
|
|
--Perforce Checkout
|
|
checkoutArchive itdArchivePath
|
|
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
|
|
local formattedIndex = if index < 10 then "0" + (index as String) else index as String
|
|
lod = if (column == 2) then lod = "_lod1" else lod = ""
|
|
local slotFormattedName = "txgrass" + formattedIndex + lod + ".dds"
|
|
local tempSlotPath = (extractPath + "/" + slotFormattedName)
|
|
local sourceFileName = pathConfig.stripPathToLeaf sourcePath
|
|
|
|
--copy the new file and rename it to the slot name
|
|
--first try to delete the existing one if it exists at the extractpath
|
|
if doesFileExist tempSlotPath then
|
|
(
|
|
if (getFileAttribute tempSlotPath #readonly) do
|
|
(
|
|
setFileAttribute tempSlotPath #readonly false
|
|
)
|
|
|
|
deleteFile tempSlotPath
|
|
)
|
|
copyFile sourcePath tempSlotPath
|
|
|
|
if doesFileExist tempSlotPath then --copied okay
|
|
(
|
|
--update the file
|
|
zipFile.UpdateFile tempSlotPath ""
|
|
|
|
--update the index file
|
|
insertItdIndexListItem index column sourcePath
|
|
)
|
|
|
|
--clean up
|
|
zipFile.Dispose()
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Insert a usage type into the archive index dat
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn insertIndexUsage index usageName =
|
|
(
|
|
--Perforce Checkout
|
|
checkoutArchive itdArchivePath
|
|
|
|
itdSourceTexturePaths[index+1].usage = usageName
|
|
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
|
|
local formattedIndex = if index < 10 then "0" + (index as String) else index as String
|
|
setINISetting extractedINI formattedIndex "usage" usageName
|
|
|
|
zipFile.UpdateFile extractedINI ""
|
|
zipFile.Save()
|
|
|
|
zipFile.Dispose()
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn buildSourceTextureNameTable =
|
|
(
|
|
if itdSourceTexturePaths == undefined then getItdIndexList()
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--Delete a slot entry from the archive
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn deleteSlot index column =
|
|
(
|
|
local formattedIndex = if index < 10 then "0" + (index as String) else index as String
|
|
--local success = false
|
|
|
|
--if deleting the base slot then also delete the lod slot, else just get rid of the lod
|
|
local base = if column == 1 then true else false
|
|
|
|
local itdList = for item in getItdFileList() where matchPattern item pattern:"txgrass*" collect item
|
|
|
|
--delete the slot textures
|
|
zipFile = (dotNetClass "Ionic.Zip.ZipFile").Read itdArchivePath
|
|
--get the archive file list
|
|
local fileList = #()
|
|
local entryIt = zipFile.EntryFileNames.GetEnumerator()
|
|
while entryIt.MoveNext() != false do
|
|
(
|
|
append fileList entryIt.current
|
|
)
|
|
|
|
local basePath = ("txgrass" + formattedIndex + ".dds")
|
|
local lodPath = ("txgrass" + formattedIndex + "_lod1.dds")
|
|
|
|
if base then --delete base and lod
|
|
(
|
|
--base
|
|
--if entry exists then remove it
|
|
if findItem fileList basePath != 0 then
|
|
(
|
|
zipFile.RemoveEntry basePath
|
|
--delete extracted
|
|
deleteFile (extractPath + "/" + basePath)
|
|
)
|
|
|
|
--lod
|
|
if findItem fileList lodPath != 0 then
|
|
(
|
|
zipFile.RemoveEntry lodPath
|
|
--delete extracted
|
|
deleteFile (extractPath + "/" + lodPath)
|
|
)
|
|
|
|
--update the index dat
|
|
setINISetting extractedINI formattedIndex "base" "unknownsource"
|
|
setINISetting extractedINI formattedIndex "lod1" "unknownsource"
|
|
)
|
|
else --lod
|
|
(
|
|
zipFile.RemoveEntry lodPath
|
|
|
|
--delete extracted
|
|
deleteFile (extractPath + "/" + lodPath)
|
|
|
|
--update the index dat
|
|
setINISetting extractedINI formattedIndex "lod1" "unknownsource"
|
|
)
|
|
|
|
zipFile.UpdateFile extractedINI ""
|
|
zipFile.Save()
|
|
|
|
--clean up
|
|
zipFile.Dispose()
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Get a dotnet bitmap from a max bitmap
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn getDNBitmapFromMax imgPath =
|
|
(
|
|
if imgPath == undefined then return false
|
|
|
|
local bm = openbitmap imgPath
|
|
setclipboardbitmap bm
|
|
|
|
local clippy = dotnetclass "System.Windows.Forms.Clipboard"
|
|
if clippy.containsimage() then
|
|
(
|
|
free bm
|
|
return clippy.GetImage()
|
|
)
|
|
else
|
|
(
|
|
free bm
|
|
return false
|
|
)
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn getExtractedSlotPath index lod:false =
|
|
(
|
|
local padding = if index < 10 then "0" else ""
|
|
lodSuffix = if lod then "_lod1" else ""
|
|
|
|
local slotPath = (extractPath + "/txgrass" + padding + (index as String) + lodSuffix + ".dds")
|
|
if doesFileExist slotPath then
|
|
(
|
|
return (extractPath + "/txgrass" + padding + (index as String) + lodSuffix + ".dds")
|
|
)
|
|
|
|
return undefined
|
|
),
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn shutdown =
|
|
(
|
|
modelArc = undefined
|
|
zipFile = undefined
|
|
),
|
|
|
|
on create do
|
|
(
|
|
extractItd()
|
|
)
|
|
) ----END STRUCT
|
|
|
|
|
|
--check for existing tool instance
|
|
if PlantMgrUI != undefined then
|
|
(
|
|
destroydialog PlantMgrUI
|
|
)
|
|
|
|
--UI
|
|
rollout PlantMgrUI "Plant Manager"
|
|
(
|
|
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:PlantMgrUI.width
|
|
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"PlantsManagerMaker" filename:(getThisScriptFilename())
|
|
|
|
local plantMgr = plantsMgr_Constructor()
|
|
local banks = for i = 0 to 31 collect (if i<10 then ("0" + i as string) else (i as string))
|
|
|
|
local headers = #("Slot", "Texture", "LOD", "Usage")
|
|
|
|
local pickedRow = 0
|
|
local pickedCell = 0
|
|
|
|
local bitmapPreviews = #()
|
|
local emptyBitmapPath = (RsConfigGetWildWestDir() + "etc/config/general/collision_textures/Default.bmp")
|
|
local bmpPreviewSize = 192
|
|
local blankBitmap = bitmap bmpPreviewSize bmpPreviewSize color:black
|
|
local blankDNBitmap = dotNetObject "System.Drawing.Bitmap" bmpPreviewSize bmpPreviewSize
|
|
|
|
local streamPath = "x:/streamGTA5/models"
|
|
|
|
local usageTypes = sort(for item in plantMgr.plantsTxdEnum collect item.name)
|
|
|
|
------------------------------------------------------------------------------------
|
|
-- DotNet values:
|
|
------------------------------------------------------------------------------------
|
|
local textFont, dingFont, textFontBold
|
|
|
|
local DNknownColour = dotNetClass "system.Drawing.KnownColor"
|
|
local DNcolour = dotNetClass "System.Drawing.Color"
|
|
|
|
local selColour = DNcolour.fromKnownColor DNknownColour.MenuHighlight
|
|
|
|
local textCol = (colorMan.getColor #windowText) * 255
|
|
local windowCol = (colorMan.getColor #window) * 255
|
|
local notLoadedCol = if (windowCol[1] < 128) then (windowCol * 1.5) else (windowCol * 0.85)
|
|
|
|
local textColour = DNcolour.FromArgb textCol[1] textCol[2] textCol[3]
|
|
local backColour = DNcolour.FromArgb windowCol[1] windowCol[2] windowCol[3]
|
|
|
|
group "Drawable (idd)"
|
|
(
|
|
--label lblSlot "Slot" across:2 align:#left
|
|
--dropdownlist ddlSlot "" items:#("0", "1", "2", "3")
|
|
label lblModel "Model" across:2 align:#left
|
|
dropdownlist ddlModel "" items:banks across:1
|
|
label lblLod "Lod" across:2 align:#left
|
|
dropdownlist ddlLod "" items:#("base", "lod1", "lod2") across:1
|
|
button btnInsert "Insert" width:120
|
|
)
|
|
|
|
dotNetControl lstTextures "DataGridView" width:300 height:450 across:3
|
|
bitmap bmpPreview width:bmpPreviewSize height:bmpPreviewSize offset:[180, 0]
|
|
dropdownlist ddlUsageOpts "Usage" items:usageTypes offset:[-10, 200]
|
|
|
|
--group "Texture (itd)"
|
|
--(
|
|
--bitmap bmpPreview width:bmpPreviewSize height:bmpPreviewSize offset:[40,0]
|
|
|
|
groupbox grpItdControls "ITD" width:570 height:95 offset:[0, 0]
|
|
button btnReloadItd "Reload" width:550 offset:[0, -80]
|
|
|
|
dropdownlist ddlArchiveBuild "Archive:" items:#("All", "Country", "Ocean") across:2 offset:[10, 0]
|
|
button btnBuildItd "Build" width:230 offset:[0, 17]
|
|
|
|
--edittext txtIdtTx "" text:"Press Pick!"
|
|
--button btnPickTx "Pick" width:120
|
|
--label lblTxSlot "Index" across:2 align:#left
|
|
--dropdownlist ddlTxSlot "" items:(for i=0 to 31 collect i as String)
|
|
--label lblTxLod "Lod" across:2 align:#left
|
|
--dropdownlist ddlTxLod "" items:#("base", "lod1") across:1
|
|
--button btnTxInsert "Insert" width:120
|
|
--)
|
|
|
|
--#--#--#--#--#--#--#--#--#--#--#--#--#--#
|
|
--Functions
|
|
--#--#--#--#--#--#--#--#--#--#--#--#--#--#
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn getUsageIndex usageName =
|
|
(
|
|
local index = 0
|
|
for i=1 to usageTypes.count where ((tolower usageTypes[i]) == (tolower usageName)) do index = i
|
|
|
|
--retval
|
|
index
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn updateList =
|
|
(
|
|
--lstTextures.Rows.Clear()
|
|
plantMgr.getItdIndexList()
|
|
|
|
local itdRAWList = plantMgr.getItdFileList()
|
|
|
|
local cleanedList = for item in itdRAWList where matchPattern item pattern:"txgrass*" collect item
|
|
local filledSlots = makeUniqueArray (for item in cleanedList collect (item[8]+item[9]) as Integer)
|
|
--print filledSlots
|
|
local itdList = #()
|
|
|
|
local j = 1
|
|
for i=0 to 31 do
|
|
(
|
|
if filledSlots[j] != i then
|
|
(
|
|
append itdList undefined
|
|
)
|
|
else
|
|
(
|
|
append itdList (i as String)
|
|
j += 1
|
|
)
|
|
)
|
|
|
|
--now populate the rows accounting for gaps where itdList is empty
|
|
for i=0 to 31 do
|
|
(
|
|
local thisIdx = if i<10 then thisIdx = ("0"+ i as String) else i as String
|
|
--local itdIndex = itdList[itdIdx][8] + itdList[itdIdx][9]
|
|
local itdIndex = itdList[i+1]
|
|
--format "thisIdx: % itdIndex: % \n" thisIdx itdIndex
|
|
if itdList[i+1] != undefined then
|
|
(
|
|
local i = thisIdx as integer
|
|
|
|
--Base_Layer
|
|
local previewImage = blankDNBitmap
|
|
local imgPath = plantMgr.getExtractedSlotPath i
|
|
if imgPath != undefined then
|
|
(
|
|
previewImage = plantMgr.getDNBitmapFromMax imgPath
|
|
)
|
|
|
|
--print plantMgr.itdSourceTexturePaths[i+1].paths[1]
|
|
local sourceTexName = plantMgr.itdSourceTexturePaths[i+1].paths[1]
|
|
lstTextures.Rows.item[i].cells.item[1].value = previewImage
|
|
lstTextures.Rows.item[i].cells.item[1].tag = sourceTexName
|
|
|
|
--LOD
|
|
previewImage = blankDNBitmap
|
|
imgPath = plantMgr.getExtractedSlotPath i lod:true
|
|
if imgPath != undefined then
|
|
(
|
|
previewImage = plantMgr.getDNBitmapFromMax imgPath
|
|
)
|
|
|
|
sourceTexName = plantMgr.itdSourceTexturePaths[i+1].paths[2]
|
|
lstTextures.Rows.item[i].cells.item[2].value = previewImage
|
|
lstTextures.Rows.item[i].cells.item[2].tag = sourceTexName
|
|
|
|
--Usage
|
|
local usageText = plantMgr.itdSourceTexturePaths[i+1].usage
|
|
plantMgr.usageAssigned[i+1] = getUsageIndex usageText
|
|
lstTextures.Rows.item[i].cells.item[3].value = usageText
|
|
|
|
)
|
|
else
|
|
(
|
|
lstTextures.Rows.item[i].cells.item[1].value = "EMPTY"
|
|
lstTextures.Rows.item[i].cells.item[2].value = "EMPTY"
|
|
)
|
|
)
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn init =
|
|
(
|
|
--lstTextures.pos.x = 0
|
|
lstTextures.RowHeadersVisible = false
|
|
lstTextures.AllowUserToAddRows = false
|
|
lstTextures.AllowUserToDeleteRows = false
|
|
lstTextures.AllowUserToOrderColumns = false
|
|
lstTextures.AllowUserToResizeRows = false
|
|
lstTextures.AllowUserToResizeColumns = true
|
|
lstTextures.AllowDrop = false
|
|
lstTextures.MultiSelect = false
|
|
lstTextures.ReadOnly = true
|
|
|
|
lstTextures.dock = lstTextures.dock.fill
|
|
lstTextures.DefaultCellStyle.backColor = backColour
|
|
lstTextures.DefaultCellStyle.foreColor = textColour
|
|
|
|
textFont = lstTextures.font
|
|
dingFont = dotNetObject "System.Drawing.Font" "Webdings" textFont.size
|
|
textFontBold = dotnetobject "system.drawing.font" textFont (dotnetclass "system.drawing.fontstyle").bold
|
|
|
|
lstTextures.EnableHeadersVisualStyles = false
|
|
lstTextures.ColumnHeadersDefaultCellStyle.backColor = backColour
|
|
lstTextures.ColumnHeadersDefaultCellStyle.foreColor = textColour
|
|
lstTextures.ColumnHeadersDefaultCellStyle.font = textFontBold
|
|
lstTextures.ColumnHeadersHeight = 30
|
|
lstTextures.Rows
|
|
|
|
lstTextures.SelectionMode = (dotNetClass "DataGridViewSelectionMode").FullRowSelect
|
|
|
|
lstTextures.height = 450
|
|
lstTextures.width = 350
|
|
|
|
--startSize = GetIniRolloutSize()
|
|
|
|
--arrangeCtrls size:startSize
|
|
local colNum
|
|
for item=1 to headers.count do
|
|
(
|
|
case item of
|
|
(
|
|
1: --slot index
|
|
(
|
|
colNum = lstTextures.Columns.add headers[item] headers[item]
|
|
)
|
|
|
|
4: --Usage type
|
|
(
|
|
colNum = lstTextures.Columns.add headers[item] headers[item]
|
|
lstTextures.Columns.item[colNum].headertext = headers[item]
|
|
)
|
|
|
|
default: --Images
|
|
(
|
|
colNum = lstTextures.Columns.add (dotNetObject "DataGridViewImageColumn")
|
|
lstTextures.Columns.item[colNum].headertext = headers[item]
|
|
)
|
|
)
|
|
|
|
/*
|
|
if item == 1 then
|
|
(
|
|
colNum = lstTextures.Columns.add headers[item] headers[item]
|
|
)
|
|
else
|
|
(
|
|
colNum = lstTextures.Columns.add (dotNetObject "DataGridViewImageColumn")
|
|
lstTextures.Columns.item[colNum].headertext = headers[item]
|
|
)
|
|
*/
|
|
|
|
lstTextures.Columns.item[colNum].sortMode = (dotnetclass "DataGridViewColumnSortMode").NotSortable
|
|
)
|
|
|
|
local firstCol = lstTextures.Columns.item[0]
|
|
local lastCol = lstTextures.Columns.item[colNum]
|
|
|
|
firstCol.width = 40
|
|
lastCol.AutoSizeMode = lastCol.AutoSizeMode.Fill
|
|
|
|
--build slot rows
|
|
for i=0 to 31 do
|
|
(
|
|
local idx = i as String
|
|
lstTextures.Rows.add #(idx, "EMPTY", "EMPTY", "EMPTY")
|
|
lstTextures.Rows.item[i].height = 40
|
|
)
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn updateCellContents newPath =
|
|
(
|
|
lstTextures.Rows.item[pickedRow].cells.item[pickedCell].value = plantMgr.getDNBitmapFromMax newPath
|
|
lstTextures.Rows.item[pickedRow].cells.item[pickedCell].tag = newPath
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn createBitmapPreview bmPath =
|
|
(
|
|
bmpPreview.filename = bmPath
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--Events dear boy
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
fn ddlUsageOptsSelected arg =
|
|
(
|
|
--get the list index and set the item accordingly
|
|
lstTextures.Rows.item[pickedRow].cells.item[3].value = usageTypes[arg]
|
|
|
|
plantMgr.usageAssigned[pickedRow + 1] = getUsageIndex usageTypes[arg]
|
|
plantMgr.insertIndexUsage pickedRow usageTypes[arg]
|
|
|
|
)
|
|
on ddlUsageOpts selected arg do ddlUsageOptsSelected arg
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- The insert action for the Drawable idd
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on btnInsert pressed do
|
|
(
|
|
--check access first
|
|
if (getFileAttribute plantMgr.iddArchivePath #readonly) then
|
|
(
|
|
messagebox ("The file: " + plantMgr.iddArchivePath + "\nIs write protected.\nIt needs to be checked out of perforce before continuing") title:"Error"
|
|
return false
|
|
)
|
|
|
|
--get the slot and model
|
|
--print ddlSlot.selected
|
|
--plantMgr.slot = ddlSlot.selected
|
|
plantMgr.model = ddlModel.selected
|
|
plantMgr.lod = ddlLod.selected
|
|
|
|
--Export selected
|
|
if ( 0 == selection.count ) then
|
|
(
|
|
MessageBox "No objects selected." title:"Model Export Error"
|
|
return false
|
|
)
|
|
|
|
--check the model has all empty texture slots
|
|
local nonEmptyMaps = #()
|
|
|
|
if selection[1].material == undefined then
|
|
(
|
|
messagebox "This object is missing its material.\n Please correct it." title:"FATAL ERROR"
|
|
return false
|
|
)
|
|
else if classof selection[1].material == Multimaterial then
|
|
(
|
|
matIDs = #()
|
|
RsMatGetMapIdsUsedOnObject selection[1] matIDs
|
|
local meshMaterial = selection[1].material.materialList[(findItem selection[1].material.materialIDList matIDs[1])]
|
|
local numSubMaps = getNumSubTexmaps meshMaterial
|
|
local nonEmptyMaps = for i=1 to numSubMaps where getSubTexmap meshMaterial i != undefined collect true
|
|
)
|
|
else
|
|
(
|
|
local meshMaterial = selection[1].material
|
|
local numSubMaps = getNumSubTexmaps meshMaterial
|
|
local nonEmptyMaps = for i=1 to numSubMaps where getSubTexmap meshMaterial i != undefined collect true
|
|
)
|
|
|
|
if nonEmptyMaps.count == 0 then
|
|
(
|
|
messagebox "This object is missing some texture assignment. Please correct it." title:"Missing textures"
|
|
return false
|
|
)
|
|
|
|
|
|
-- Save our output directory.
|
|
|
|
--delete it if it exists to purge it
|
|
--RsDeleteDirectory streamPath
|
|
local dnDir = dotnetclass "System.IO.Directory"
|
|
if (dnDir.Exists @"x:\streamGTA5\models\") then
|
|
(
|
|
dnDir.Delete @"x:\streamGTA5\models\" True
|
|
)
|
|
|
|
RsModelSetOutputDirectory (streamPath + "/")
|
|
|
|
-- Export all geometry.
|
|
local drawableDirs = #()
|
|
RsModelExportGroup selection asciiMesh:false
|
|
local drawableDirs = for dir in (getdirectories (streamPath + "/*")) collect RsMakeSafeSlashes dir
|
|
|
|
--delete any textures, we want only the txd ones, no drawables textures
|
|
for dir in drawableDirs do
|
|
(
|
|
for f in getfiles (dir + "*.dds") do
|
|
(
|
|
deleteFile f
|
|
)
|
|
)
|
|
|
|
-- Constuct drawable dictionary IDD file.
|
|
local script = RsModelOutputDirectory + "create_idd.rb"
|
|
if ( 0 != ( RsModelScriptGenerator.BuildDrawableDictionary script plantMgr.iddArchiveTempPath drawableDirs ) ) then
|
|
MessageBox "Failed to build drawable dictionary file." title:"Model Export Error"
|
|
|
|
--get the exported drawable dict (idd)
|
|
plantMgr.modelPath = plantMgr.iddArchiveTempPath
|
|
|
|
--stuff into the appropriate place in
|
|
success = plantMgr.buildIdd()
|
|
|
|
--build the data
|
|
if success then
|
|
(
|
|
plantMgr.localBuild("idd")
|
|
messagebox "PlantsMgr.idd updated!" title:"Success"
|
|
)
|
|
|
|
)
|
|
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
--
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on btnReloadItd pressed do
|
|
(
|
|
updateList()
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- This saves the PlantsMgr.itd.zip
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on btnBuildItd pressed do
|
|
(
|
|
plantMgr.buildItd (ddlArchiveBuild.selected as Name)
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- Right click menu opts
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on lstTextures mouseDown args do
|
|
(
|
|
local clickPoint = dotNetObject "System.Drawing.Point" args.x args.y
|
|
local clickedItem = lstTextures.hitTest args.x args.y
|
|
|
|
if (clickedItem != undefined) do
|
|
(
|
|
pickedRow = clickedItem.rowIndex
|
|
pickedCell = clickedItem.columnIndex
|
|
|
|
--format "rowNum: % cellNum: % \n" rowNum cellNum
|
|
|
|
if (pickedRow != -1) and (lstTextures.selectedRows.count != 0) do
|
|
(
|
|
local rightClick = args.button.equals args.button.right
|
|
|
|
-- RIGHT CLICK
|
|
if rightClick then --show the popup menu options
|
|
(
|
|
-- Rightclick menu:
|
|
rcmenu RSmenu_textureOps
|
|
(
|
|
local selRows
|
|
|
|
menuItem itmSeltexture "Choose Texture"
|
|
menuItem itmPhotoshop "Open texture in Photoshop"
|
|
menuItem itmDelTexture "Delete Texture"
|
|
|
|
-- Select selected textures' objects:
|
|
on itmSeltexture picked do
|
|
(
|
|
local validPath = plantMgr.pickTexture()
|
|
if validPath == false then return false
|
|
|
|
if plantMgr.texturePath != undefined then
|
|
(
|
|
--print plantMgr.texturePath
|
|
--textureName = filenameFromPath plantMgr.texturePath
|
|
|
|
--stuff the name into the slot
|
|
updateCellContents plantMgr.texturePath
|
|
|
|
--add a new bitmap for the preview
|
|
createBitmapPreview plantMgr.texturePath
|
|
|
|
--replace the name in the itd index file
|
|
--plantMgr.insertItdIndexListItem pickedRow pickedCell plantMgr.texturePath
|
|
|
|
--replace the bitmap in the itd archive
|
|
plantMgr.insertItdTexture pickedRow pickedCell plantMgr.texturePath
|
|
plantMgr.insertIndexUsage pickedRow "All"
|
|
)
|
|
)
|
|
|
|
-- Open selected textures in Photoshop:
|
|
on itmPhotoshop picked do
|
|
(
|
|
local selTexFilename = lstTextures.Rows.item[pickedRow].cells.item[pickedCell].tag
|
|
--print selTexFilename
|
|
if selTexFileName == "unknownsource" then
|
|
(
|
|
messagebox "Unknown source texture" title:"Unknown"
|
|
)
|
|
else if (doesFileExist selTexFileName) then
|
|
(
|
|
format "Opening in Photoshop: %\n" selTexFilename
|
|
shelllaunch ("Photoshop.exe") selTexFilename
|
|
)
|
|
else
|
|
(
|
|
messagebox "Cant find that file locally" title:"Missing File"
|
|
)
|
|
|
|
)
|
|
|
|
--delete the item from the dictionary
|
|
on itmDelTexture picked do
|
|
(
|
|
--delete base + lod
|
|
if pickedCell == 1 then
|
|
(
|
|
lstTextures.Rows.item[pickedRow].cells.item[pickedCell].value = undefined
|
|
lstTextures.Rows.item[pickedRow].cells.item[pickedCell+1].value = undefined
|
|
)
|
|
else
|
|
(
|
|
lstTextures.Rows.item[pickedRow].cells.item[pickedCell].value = undefined
|
|
)
|
|
|
|
plantMgr.deleteSlot pickedRow pickedCell
|
|
|
|
)
|
|
|
|
on RSmenu_textureOps open do
|
|
(
|
|
|
|
)
|
|
)
|
|
popUpMenu RSmenu_textureOps
|
|
)
|
|
--LEFT CLICK
|
|
else --left click will update the texture preview
|
|
(
|
|
local cellValue = lstTextures.Rows.item[pickedRow].cells.item[pickedCell].value
|
|
--print cellValue
|
|
if cellValue != "EMPTY" then
|
|
(
|
|
local slotTex = "/txgrass" + (if pickedRow < 10 then "0" else "") + pickedRow as String + (if pickedCell == 2 then "_lod1" else "") + ".dds"
|
|
--print (plantMgr.extractPath + slotTex)
|
|
if doesFileExist (plantMgr.extractPath + slotTex) then
|
|
(
|
|
bmpPreview.filename = plantMgr.extractPath + slotTex
|
|
)
|
|
else
|
|
(
|
|
bmpPreview.bitmap = blankBitmap
|
|
)
|
|
|
|
--set the usage combo value
|
|
local usageColumnValue = lstTextures.Rows.item[pickedRow].cells.item[3].value
|
|
ddlUsageOpts.selection = plantMgr.usageAssigned[pickedRow + 1]
|
|
)
|
|
else --empty slot
|
|
(
|
|
bmpPreview.bitmap = blankBitmap
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- init
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on PlantMgrUI open do
|
|
(
|
|
banner.setup()
|
|
RS_CustomDataGrid forceRecompile:true
|
|
init()
|
|
updateList()
|
|
)
|
|
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
-- shutdown
|
|
--////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
on PlantMgrUI close do
|
|
(
|
|
HiddenDosCommand ("rmdir " + plantMgr.extractPath)
|
|
plantMgr = undefined
|
|
gc light:true
|
|
)
|
|
|
|
)
|
|
|
|
-------------------
|
|
--Lets go
|
|
createDialog PlantMgrUI width:590 height:700 style:#(#style_titlebar, #style_resizing, #style_sysmenu, #style_minimizebox, #style_maximizebox)
|