Files
2025-09-29 00:52:08 +02:00

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)