[url]--------------------------------------------------------------------------------
-- Script file guard
-- Examine its value to see how many times the script was run.
--------------------------------------------------------------------------------
if (guardModelNames == undefined) then
(
global guardModelNames = 0
)
guardModelNames += 1
--------------------------------------------------------------------------------
-- Make sure TB2 starup was executed first.
--------------------------------------------------------------------------------
if (guardTB2Startup == undefined) then
(
global guardTB2Startup = 0
FileIn ((getDir #startupScripts) + "\\TB2Startup.ms")
)
-------------------------------------------------------------------------------
-- Includes
-------------------------------------------------------------------------------
FnTB2FileInOnce "StringUtils.ms" guardStringUtils
-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------
fn FnExtractNextNumber str &start =
(
if start > str.count then
(
return undefined
)
local char = str[start]
while (start <= str.count and (findstring "0123456789" char) == undefined) do
(
start += 1
char = str[start]
)
if start > str.count then
(
return undefined
)
local result = 0
while (start <= str.count and (findstring "0123456789" char) != undefined) do
(
result *= 10
result += (char as integer)
start += 1
char = str[start]
)
return result
)
--------------------------------------------------------------------------------
-- struct stDate
--------------------------------------------------------------------------------
struct stDate
(
-- Data members
day,
month,
year,
-- Methods
-----------------------------------------------------------------------------
-- Function: IsValid
-----------------------------------------------------------------------------
fn IsValid =
(
return day != undefined
),
-----------------------------------------------------------------------------
-- Function: Clear
-----------------------------------------------------------------------------
fn Clear =
(
day = undefined
month = undefined
year = undefined
ok
),
-----------------------------------------------------------------------------
-- Function: Init
-----------------------------------------------------------------------------
fn Init d m y =
(
day = d
month = m
year = y
),
-----------------------------------------------------------------------------
-- Function: InitFromStr
-----------------------------------------------------------------------------
fn InitFromStr strDate =
(
Clear()
if strDate.count < 10 then
(
return false
)
local idx = 1
local auxMonth = FnExtractNextNumber strDate &idx
if auxMonth == undefined or auxMonth == 0 then
(
return false
)
local auxDay = FnExtractNextNumber strDate &idx
if auxDay == undefined or auxDay == 0 then
(
return false
)
local auxYear = FnExtractNextNumber strDate &idx
if auxYear == undefined or auxYear == 0 then
(
return false
)
-- Make sure the aux variables do conatin valid values
-- date formats differ in various locales
-- CAUTION: The algorithm is not 100% acurate. It simply tries to
-- make the best guess.
if auxYear < 100 then
(
if auxMonth > 100 then
(
local temp = auxMonth
auxMonth = auxYear
auxYear = temp
)
else if auxDay > 100 then
(
local temp = auxDay
auxDay = auxYear
auxYear = temp
)
else
(
auxYear += 2000
)
)
if auxYear < 2000 or (auxMonth > 12 and auxDay > 12) then
(
return false
)
if auxMonth > 12 then
(
if auxDay > 12 then
(
return false
)
local temp = auxDay
auxDay = auxMonth
auxMonth = temp
)
day = auxDay
month = auxMonth
year = auxYear
return true
),
-----------------------------------------------------------------------------
-- Function: Init
-----------------------------------------------------------------------------
fn InitNow =
(
return InitFromStr localTime
),
-----------------------------------------------------------------------------
-- Function: IsLeapYear
-----------------------------------------------------------------------------
fn IsLeapYear y =
(
local aux = (mod y 4) as integer
if aux == 0 then
(
aux = (mod y 100) as integer
if aux == 0 then
(
aux = (mod y 400) as integer
return aux == 0
)
return true
)
return false
),
-----------------------------------------------------------------------------
-- Function: Init
-----------------------------------------------------------------------------
fn FnGetDaysInMonth m y =
(
local days
case m of
(
1: days = 31
2:
( days = 28
if (IsLeapYear y) then
days += 1
)
3: days = 31
4: days = 30
5: days = 31
6: days = 30
7: days = 31
8: days = 31
9: days = 30
10: days = 31
11: days = 30
12: days = 31
)
return days
),
-----------------------------------------------------------------------------
-- Function: Compare
-----------------------------------------------------------------------------
fn Compare date =
(
if not IsValid() or not date.IsValid() then
(
return undefined
)
if year > date.year then
return 1
else if year < date.year then
return -1
if month > date.month then
return 1
else if month < date.month then
return -1
if day > date.day then
return 1
else if day < date.day then
return -1
return 0
),
-----------------------------------------------------------------------------
-- Function: GetDaysFromBeginingOfYear
-----------------------------------------------------------------------------
fn GetDaysFromBeginingOfYear =
(
if IsValid() then
(
local numOfDays = day
if month > 1 then
(
local idx
for idx = 1 to month - 1 do
(
numOfDays += FnGetDaysInMonth idx year
)
)
return numOfDays
)
return undefined
),
-----------------------------------------------------------------------------
-- Function: GetDaysToEndOfYear
-----------------------------------------------------------------------------
fn GetDaysToEndOfYear =
(
if IsValid() then
(
local numOfDays = 365 - GetDaysFromBeginingOfYear()
if IsLeapYear year then
numOfDays += 1
return numOfDays
)
return undefined
),
-----------------------------------------------------------------------------
-- Function: GetDaysFromPriv
-----------------------------------------------------------------------------
fn GetDaysFromPriv date =
(
if year > date.year then
(
local numOfDays = GetDaysFromBeginingOfYear() + date.GetDaysToEndOfYear()
if year > date.year + 1 then
(
numOfDays += 365 * (year - date.year - 1)
-- Add leap days
local firstLeap
if (IsleapYear (date.year + 1)) then
(
firstLeap = date.year + 1
)
else
(
firstLeap = (((mod (date.year + 1) 4) as integer) + 1) * 4
)
local lastLeap
if (IsleapYear (year - 1)) then
(
lastLeap = year - 1
)
else
(
lastLeap = ((mod (year - 1) 4) as integer) * 4
)
if lastLeap >= firstLeap then
(
numOfDays += (lastLeap - firstLeap) / 4 + 1
)
)
return numOfDays
)
else if year == date.year then
(
return GetDaysFromBeginingOfYear() - date.GetDaysFromBeginingOfYear()
)
return undefined
),
-----------------------------------------------------------------------------
-- Function: GetDaysFrom
-----------------------------------------------------------------------------
fn GetDaysFrom date =
(
local compareResult = Compare date
if compareResult == undefined then
(
return undefined
)
local numOfDays = 0
if compareResult > 0 then
(
numOfDays = GetDaysFromPriv date
)
else if compareResult > 0 then
(
local aux = stDate()
aux.Init day month year
numOfDays = -date.GetDaysFromPriv aux
)
return numOfDays
)
)
-----------------------------------------------------------------------------
-- Function: FnGenerateGZGUID
-----------------------------------------------------------------------------
fn FnGenerateGZGUID asHexString:true=
(
today = stDate()
if not (today.InitNow()) then
(
return undefined
)
date0 = stDate()
date0.Init 2 2 1997
local numOfDays = today.GetDaysFrom date0
if numOfDays == undefined then
(
return undefined
)
local rand = bit.shift (random 0 7) 29
local guid = numOfDays * 24 * 3600
guid += timeStamp() / 1000
guid = bit.and guid 536870911
guid = bit.or guid rand
if asHexString then
(
return "0x" + (bit.intAsHex guid)
)
else
(
return guid
)
)
--------------------------------------------------------------------------------
-- struct stModelName
-- a little class to handle the building file naming conventions
--------------------------------------------------------------------------------
struct stModelName
(
-- Class constants and variables
compassNames = #("S","W","N","E","NS","EW","X"), -- lookup table for naming the rotations
nameParts = #(), -- Human readable sections of the Max filename
destPath = "",
tempSubDir = ((getDir #export) + "\\Temp\\"),
zoom = 1, -- current zoom
rot = 1, -- current rotation
mUseNamingConvention = false,
kPropertyFileName = "File Name",
kPropertyModelID = "Model ID",
-- S3D type IDs
kIntS3DTypeID = (HexStrToInt "0x5ad0e817"),
kIntBuildingGroupID = (HexStrToInt "0xbadb57f1"),
-- FSH type ID
kIntFSHTypeID = (HexStrToInt "0x7ab50e44"),
kIntFSHGroupID = (HexStrToInt "0x1abe787d"),
kDefaultInstanceID = "0x00030000",
---------------------------------------------------------------------------------------------------
-- Function: Destination
-- Param: which:#final
-- Desc: Returns the folder to put things in this class tracks two possible paths
-- for the filenames it generates one is a temp folder under the destination
-- the which parameter chooses where the filename ends up
---------------------------------------------------------------------------------------------------
fn Destination which:#final =
(
if (which == #temp) then
return tempSubDir
else
return destPath
),
----------------------------------------------------------------------------------------------------
-- Function: FnGenerateModelGUID
----------------------------------------------------------------------------------------------------
fn FnGenerateModelKey =
(
local groupGUID = FnGenerateGZGUID()
if groupGUID != undefined then
(
return "0x5ad0e817" + kNamePartDelim + groupGUID + kNamePartDelim + kDefaultInstanceID
)
else
(
return GenerateModelGUID()
)
),
----------------------------------------------------------------------------------------------------
-- Function: InitUsingNamingConvention
-- Param: maxName - name of the Max file
-- Param: dest - destination folder
-- Param: modelType - model type
----------------------------------------------------------------------------------------------------
fn InitUsingNamingConvention maxName dest modelType =
(
-- parse out portions of the filename
nameParts = filterstring (getfilenamefile maxName) kNamePartDelim
destPath = dest
-- Verify format of the file name
if (nameParts.count != 3) do
(
FnErrorMessage ("The MAX file name: \"" + maxName +"\" does not follow the naming convention.")
return false
)
if ((nameParts[3].count != 4) or (not (verifyHex nameParts[3]))) do
(
FnErrorMessage ("\"" + maxName + "\"\n" + nameParts[3] + " is not a proper GUID id.")
return false
)
-- Have to init tempDir after destPath since Destination() refers to destPath
local tempDir = (Destination which:#temp)
-- Make sure it exists for later
if (not doesFileExist tempDir) do
(
--NOT AVAILABLE IN GMAX: makeDir tempDir
return false
)
-- Hack the new naming convention in : swap nameParts 1 & 3
local tmpStr = nameParts[3]
nameParts[3] = nameParts[1]
nameParts[1] = tmpStr
if (modelType==#building) then
nameParts[1] += "0"
else
nameParts[1] += "1"
return true
),
----------------------------------------------------------------------------------------------------
-- Function: InitUsingFileProperties
-- Param: maxName - name of the Max file
-- Param: dest - destination folder
-- Param: modelType - model type
----------------------------------------------------------------------------------------------------
fn InitUsingFileProperties maxName dest modelType =
(
local updateID = false
local modelID
destPath = dest
nameParts = #()
-- Look for Model ID in file properties
local typeIndex = (fileProperties.findProperty #custom kPropertyModelID)
if (typeIndex > 0) then
(
modelID = fileProperties.getPropertyValue #custom typeIndex
)
if (modelID == undefined) then
(
updateID = true
)
-- Check if the file name changed
-- If so, changed the ID
if (not updateID) then
(
typeIndex = (fileProperties.findProperty #custom kPropertyFileName)
if (typeIndex > 0) then
(
local fileName = fileProperties.getPropertyValue #custom typeIndex
if (fileName == undefined or fileName != maxName) then
(
updateID = true
)
)
else
(
updateID = true
)
)
if updateID then
(
modelID = FnGenerateModelKey()
)
if (modelID == undefined) then
(
return false
)
local guids = filterstring modelID kNamePartDelim
if (guids.count != 3) then
(
guids = filterstring modelID "-"
)
if (guids.count != 3) then
(
guids = filterstring modelID "_"
)
if (guids.count != 3) then
(
return false
)
local idx
for idx in 1 to 3 do
(
if (not (VerifyHex guids[idx])) then
(
return false
)
)
if updateID then
(
fileProperties.addProperty #custom kPropertyFileName maxName
fileProperties.addProperty #custom kPropertyModelID modelID
)
kIntS3DTypeID = HexStrToInt guids[1]
kIntBuildingGroupID = HexStrToInt guids[2]
kIntFSHGroupID = kIntBuildingGroupID
append nameParts (substring guids[3] 3 4)
append nameParts (getFileNameFile maxName)
append nameParts "UserModel"
if (modelType==#building) then
nameParts[1] += "0"
else
nameParts[1] += "1"
return true
),
----------------------------------------------------------------------------------------------------
-- Function: Init
-- Param: maxName - name of the Max file
-- Param: dest - destination folder
-- Param: modelType:#building - model type
----------------------------------------------------------------------------------------------------
fn Init maxName dest modelType:#building useNamingConvention:false =
(
mUseNamingConvention = useNamingConvention
if useNamingConvention then
(
return InitUsingNamingConvention maxName dest modelType
)
else
(
return InitUsingFileProperties maxName dest modelType
)
),
----------------------------------------------------------------------------------------------------
-- Function: Category
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn Category =
(
return nameParts[3]
),
----------------------------------------------------------------------------------------------------
-- Function: ModelName
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn ModelName =
(
return nameParts[2]
),
----------------------------------------------------------------------------------------------------
-- Function: ModelID
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn ModelID =
(
return nameParts[1]
),
----------------------------------------------------------------------------------------------------
-- Function: ModelIDAsInt
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn ModelIDAsInt =
(
return (HexStrToInt (ModelID() + "000"))
),
----------------------------------------------------------------------------------------------------
-- Function: ModelGroupIDAsInt
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn ModelGroupIDAsInt =
(
return kIntBuildingGroupID
),
----------------------------------------------------------------------------------------------------
-- Function: InstanceID
-- Desc:
----------------------------------------------------------------------------------------------------
fn InstanceID =
(
return (ModelID()) +
((zoom-1) as string) +
((rot-1) as string) +
"0"
),
----------------------------------------------------------------------------------------------------
-- Function: InstanceID
-- Desc:
----------------------------------------------------------------------------------------------------
fn InstanceIDAsInt =
(
return (HexStrToInt (InstanceID()))
),
----------------------------------------------------------------------------------------------------
-- Function: ModelGUID
-- Desc: Valid only after initialization!
----------------------------------------------------------------------------------------------------
fn ModelGUID =
(
return FnMakeResKey kIntS3DTypeID kIntBuildingGroupID (InstanceIDAsInt())
),
----------------------------------------------------------------------------------------------------
-- Function: ModelOutputName
-- Param: which:#final
-- Desc: the full pathname of the S3D file
----------------------------------------------------------------------------------------------------
fn ModelOutputName which:#final =
(
return (Destination which:which) +
(InstanceID()) +
"_" +
(ModelName()) +
"_" +
(Category()) +
"_Z" +
(zoom as string) +
compassNames[rot] +
".S3D"
),
----------------------------------------------------------------------------------------------------
-- Function: TextureOutputIDStr
-- Param: texIndex
-- Desc:
----------------------------------------------------------------------------------------------------
fn TextureOutputIDStr texIndex:0 =
(
local highSwizzle = 0
-- awful kludge to be able to handle more than 16 textures per view
-- sharing the second digit between rot & the high bit of the texture index
local digit2 = (texIndex as integer)/16
texIndex = (mod texIndex 16) as integer
if (digit2 > 3) then
(
DoMessage ("This building is huge! It's just not going to work!")
)
else
(
highSwizzle = digit2 * 4
)
return guidStr = (ModelID()) +
((zoom-1) as string) +
(bit.intAsHex (highSwizzle + (rot-1))) +
(bit.intAsHex texIndex)
),
----------------------------------------------------------------------------------------------------
-- Function: TextureOutputGUID
-- Param: texIndex
-- Desc:
----------------------------------------------------------------------------------------------------
fn TextureOutputGUID texIndex:0 =
(
local instID = (HexStrToInt (TextureOutputIDStr texIndex:texIndex))
return FnMakeResKey kIntFSHTypeID kIntFSHGroupID instID
),
----------------------------------------------------------------------------------------------------
-- Function: NightTextureIDStr
-- Param: texIndex
-- Desc:
----------------------------------------------------------------------------------------------------
fn NightTextureIDStr texIndex:0 =
(
local guid4 = (substring (ModelID()) 1 4)
local typeDigit = ((ModelID())[5] as integer) + 8
local highSwizzle = 0
-- awful kludge to be able to handle more than 16 textures per view
-- sharing the second digit between rot & the high bit of the texture index
local digit2 = (texIndex as integer)/16
texIndex = (mod texIndex 16) as integer
if (digit2 > 3) then
(
DoMessage ("This building is huge! It's just not going to work!")
)
else
(
highSwizzle = digit2 * 4
)
return guidStr = guid4 +
(bit.intAsHex typeDigit) +
((zoom-1) as string) +
(bit.intAsHex (highSwizzle + (rot-1))) +
(bit.intAsHex texIndex)
),
----------------------------------------------------------------------------------------------------
-- Function: NightTextureGUID
-- Param: texIndex
-- Desc:
----------------------------------------------------------------------------------------------------
fn NightTextureGUID texIndex:0 =
(
local instID = (HexStrToInt (NightTextureIDStr texIndex:texIndex))
return FnMakeResKey kIntFSHTypeID kIntFSHGroupID instID
),
----------------------------------------------------------------------------------------------------
-- Function: TextureOutputName
-- Param: texIndex
-- Param: which:#final
-- Param: wext:".TGA"
-- Desc: the full pathname of the n-th texture file
----------------------------------------------------------------------------------------------------
fn TextureOutputName texIndex which:#temp ext:".TGA" =
(
local highSwizzle = 0
-- awful kludge to be able to handle more than 16 textures per view
-- sharing the second digit between rot & the high bit of the texture index
local digit2 = (texIndex as integer)/16
texIndex = (mod texIndex 16) as integer
if (digit2 > 3) then
(
DoMessage ("This building is huge! It's just not going to work!")
)
else
(
highSwizzle = digit2 * 4
)
return (Destination which:which) +
(ModelID()) +
((zoom-1) as string) +
(bit.intAsHex (highSwizzle + (rot-1))) +
(bit.intAsHex texIndex) +
"_" +
(ModelName()) +
"_" +
(Category()) +
"_Z" +
(zoom as string) +
compassNames[rot] +
ext
),
----------------------------------------------------------------------------------------------------
-- Function: NightTextureName
-- Param: texIndex
-- Param: which:#final
-- Param: wext:".TGA"
-- Desc: the full pathname of the n-th texture file
----------------------------------------------------------------------------------------------------
fn NightTextureName texIndex which:#temp ext:".TGA" =
(
local guid4 = (substring (ModelID()) 1 4)
local typeDigit = ((ModelID())[5] as integer) + 8
local highSwizzle = 0
-- awful kludge to be able to handle more than 16 textures per view
-- sharing the second digit between rot & the high bit of the texture index
local digit2 = (texIndex as integer)/16
texIndex = (mod texIndex 16) as integer
if (digit2 > 3) then
(
DoMessage ("This building is huge! It's just not going to work!")
)
else
(
highSwizzle = digit2 * 4
)
return (Destination which:which) +
guid4 +
(bit.intAsHex typeDigit) +
((zoom-1) as string) +
(bit.intAsHex (highSwizzle + (rot-1))) +
(bit.intAsHex texIndex) +
"_" +
(ModelName()) +
"_Night_Z" +
(zoom as string) +
compassNames[rot] +
ext
),
---------------------------------------------------------------------------------------------------
-- Function: TextureSourceName
-- Param: texIndex
-- Param: oldName
-- Desc: for the model mill, generate a conforming texture name for a given texture name
---------------------------------------------------------------------------------------------------
fn TextureSourceName texIndex oldName =
(
local texFile = (getFilenameFile oldName)
local texType = (getFilenameType oldName)
return (ModelID()) +
((zoom-1) as string) +
((rot-1) as string) +
(bit.intAsHex texIndex) +
"_" +
(ModelName()) +
"_" +
texFile +
"_" +
(Category()) +
"_Z" +
(zoom as string) +
compassNames[rot] +
texType
),
---------------------------------------------------------------------------------------------------
-- Function: TempMaxName
-- Param: frameIndex
-- Param: which:#temp
-- Desc:
---------------------------------------------------------------------------------------------------
fn TempMaxName frameIndex which:#temp =
(
return (Destination which:which) + "temp" + (frameIndex as string) + ".MAX"
),
---------------------------------------------------------------------------------------------------
-- Function: MeshName
-- Param: texIndex
-- Desc: Name to give to generated materials that will come through as mesh names
-- in S3D format (should be useful for debuging)
---------------------------------------------------------------------------------------------------
fn MeshName texIndex =
(
return (ModelName()) +
"_" +
(Category()) +
"_Z" +
(zoom as string) +
compassNames[rot] +
"_" +
(texIndex as string)
),
---------------------------------------------------------------------------------------------------
-- Function: RenderTempName
-- Param: which:#temp
-- Desc: Name for temporary renderfile (for diced renders)
---------------------------------------------------------------------------------------------------
fn RenderTempName which:#temp =
(
return (Destination which:which) +
(InstanceID()) +
"_" +
(ModelName()) +
"_RenderTemp_Z" +
(zoom as string) +
compassNames[rot] +
".TGA"
),
---------------------------------------------------------------------------------------------------
-- Function: NightRenderTempName
-- Param: which:#temp
-- Desc: Name for temporary night mask (for diced renders)
---------------------------------------------------------------------------------------------------
fn NightRenderTempName which:#temp =
(
return (Destination which:which) +
(InstanceID()) +
"_" +
(ModelName()) +
"_NightMaskTemp_Z" +
(zoom as string) +
compassNames[rot] +
".TGA"
)
)[/url]
Ptdrrrr c'est un truc zarbi sur le site officiel
