global idxExportGeometryGtaObj = getattrindex "Gta Object" "Export Geometry" global idxFragProxyGtaObj = getattrindex "Gta Object" "Is FragProxy" global idxAnimProxyGtaObj = getattrindex "Gta Object" "Is AnimProxy" global idxDontExportGtaObj = getattrindex "Gta Object" "Dont Export" global idxDontExportLightPhoto = getattrindex "Gta LightPhoto" "Dont Export" global idxDontAddToIplGtaObj = getattrindex "Gta Object" "Dont Add To IPL" global idxIsOcclusionGtaObj = ( GetAttrIndex "Gta Object" "Is Occlusion" ) global idxIsNewDLCGtaObj = ( GetAttrIndex "Gta Object" "New DLC" ) global LinkType_LOD = 0 -------------------------------------------------------------- -- Is this an RSref object? -------------------------------------------------------------- fn isRSref obj includeDelegates:false = ( (isValidNode obj) and ( (isKindOf obj.baseObject ::RSrefObject) or ( -- isRsRef can optionally show/hide Rsref-based object-types: includeDelegates and ( isKindOf obj.baseObject ::RsContainerLodRef ) ) ) ) -------------------------------------------------------------- -- Is this an RsInternalRef? -------------------------------------------------------------- fn isRsInternalRef obj = ( (isValidNode obj) and ( (isKindOf obj.baseObject ::RsInternalRef) ) ) -------------------------------------------------------------- -- Is this any kind of InternalRef? -------------------------------------------------------------- fn isInternalRef obj = ( (isKindOf obj InternalRef) or (isRsInternalRef obj) ) -------------------------------------------------------------- -- Is this any kind of InternalRef? -------------------------------------------------------------- fn getIRefSource obj = ( case of ( (isKindOf obj InternalRef):(ixref_gettarget obj) (isRsInternalRef obj):(obj.getSourceObj()) default:undefined ) ) -------------------------------------------------------------- -- Is this an RSref-based object-class? -------------------------------------------------------------- fn isRSrefSuperClass obj = ( (isValidNode obj) and ( local baseObj = obj.baseObject (isKindOf baseObj ::RSrefObject) or ( (isProperty baseObj #delegate) and (isKindOf baseObj.delegate ::RSrefObject) ) ) ) -------------------------------------------------------------- -- Is it an RSref/Xref? -------------------------------------------------------------- fn isRefObj obj includeDelegates:true = ( (isRSref obj includeDelegates:includeDelegates) or (isKindOf obj XRefObject) ) -- -- name: RsMapIsOcclusion -- desc: Return whether this object is an occlusion object. -- fn RsMapIsOcclusion obj = ( (isKindOf obj RsOcclusionBox) or ( ("Gta Object" == GetAttrClass obj) and ( true == GetAttr obj idxIsOcclusionGtaObj ) ) ) ----------------------------------------------------------------------------- -- returns true if the passed in object is a valid map-export object ----------------------------------------------------------------------------- fn IsMapObject obj CheckParent:True = ( if (not isValidNode obj) do return False local retval = true local objClass = getattrclass obj case objClass of ( "Gta Object": ( if (getAttr obj idxDontExportGtaObj) then ( setattr obj idxDontAddToIplGtaObj true retval = false ) else ( if (getAttr obj idxFragProxyGtaObj) or (getAttr obj idxAnimProxyGtaObj ) do ( retval = false ) ) ) -- AJM: These Photometric lights aren't to be exported. The serialiser also checks and stops them being output -- but doing it here in maxscript too just incase. Whether removing photometric lights from the map.objects list -- will cause problems, we'll soon find out... "Gta LightPhoto": ( if (isKindOf obj mr_Sky_Portal) or (isKindOf obj Target_light) or (isKindOf obj Free_Light) do ( setattr obj idxDontExportLightPhoto true retval = false ) ) ) if (not retVal) do return False -- Test object/parent classes: retval = case of ( (isDeleted obj):(False) (isRefObj obj):(False) (isKindOf obj InternalRef):(False) (isKindOf obj Gta_MILO):(True) (isKindOf obj GtaMloRoom):(True) (isKindOf obj Container):(True) (objClass != "Gta Object"):(False) (RsMapIsOcclusion obj):(False) ((CheckParent) and (obj.parent != undefined)): ( -- Test parent-class: case ClassOf Obj.Parent of ( Gta_MILO:(True) GtaMloRoom:(True) Container:(True) Default:(False) ) ) Default:True ) return retval ) -------------------------------------------------------------- -- returns true if the passed in object is a valid map export object -------------------------------------------------------------- fn IsMapObjectWithXref obj ignoreExportFlags:false = ( local retVal = true local attrClass case of ( (isDeleted obj):false ( case (classOf obj.parent) of ( UndefinedClass:false Gta_MILO:false GtaMloRoom:false Container:false Default:true ) ):false (isKindOf obj Gta_MILO):true (isKindOf obj GtaMloRoom):true ( attrClass = getattrclass obj (attrClass != "Gta Object") and (attrClass != "Gta MILOTri") ):false ((not isRefObj obj) and (attrClass == "Gta Object") and (not ignoreExportFlags)): ( case of ( --valFragProxy: (getattr obj idxFragProxyGtaObj):false -- isAnimProxy: (getattr obj idxAnimProxyGtaObj ):false --valDontExport: (getattr obj idxDontExportGtaObj):false default:true ) ) default:true ) ) fn RsGetMapObjectsFromRoom source target childobj = ( for actualobj in childobj.children do ( if IsMapObject actualobj then ( appendIfUnique target actualobj ) ) ) -------------------------------------------------------------- -- Turn all objects in the input list into valid export objects -------------------------------------------------------------- global RsMapObjectSourceCache = #() global RsMapObjectCache = #() global RsMapMiloCache = #() fn RsGetMapObjects source target isCutsceneObject:false miloHelpers:#() = ( -- See if the cached source-list matches the new one; if so, we can reuse the output: local cacheMatched = (source.count == RsMapObjectSourceCache.count) for obj in source while cacheMatched do ( if (findItem RsMapObjectSourceCache obj == 0) do (cacheMatched = false) ) if cacheMatched and (isCutsceneObject == false) then ( for item in RsMapObjectCache where isValidNode item do ( appendIfUnique target item ) for item in RsMapMiloCache where isValidNode item do ( appendIfUnique miloHelpers item ) ) else ( for obj in source do ( if IsMapObject obj then ( if classof obj == Gta_MILO then ( appendIfUnique miloHelpers obj lodobj = RsSceneLink.getparent LinkType_LOD obj if lodobj != undefined then ( appendIfUnique target lodobj lod2obj = RsSceneLink.getparent LinkType_LOD lodobj if lod2obj != undefined then append target lod2obj ) for childobj in obj.children do ( if classof childobj == GtaMloRoom then ( RsGetMapObjectsFromRoom source target childobj ) else ( if IsMapObject childobj then ( appendIfUnique target childobj ) ) ) ) else if classof obj == GtaMloRoom then ( RsGetMapObjectsFromRoom source target obj ) else if classof obj == Container then ( appendIfUnique target obj -- Recurse into the Container. for childobj in obj.children do ( if IsMapObject childobj then ( appendIfUnique target childobj ) ) ) else if isdeleted obj == false then ( addObject = true if getattrclass obj == "Gta Object" then ( addObject = getattr obj idxExportGeometryGtaObj ) if addObject then ( appendIfUnique target obj ) ) ) ) RsMapObjectSourceCache = #() + source RsMapObjectCache = #() + target RsMapMiloCache = #() + miloHelpers ) return target ) fn RsGetMapObjectsFromRoomWithXref source target childobj = ( for actualobj in childobj.children do ( if IsMapObjectWithXref actualobj then ( append target actualobj ) ) ) -------------------------------------------------------------- -- Turn all objects in the input list into valid export objects -------------------------------------------------------------- fn RsGetMapObjectsWithXrefs source target ignoreExportFlags:false = ( for obj in source do ( if IsMapObjectWithXref obj ignoreExportFlags:ignoreExportFlags then ( if classof obj == Gta_MILO then ( for childobj in obj.children do ( if classof childobj == GtaMloRoom then ( RsGetMapObjectsFromRoomWithXref source target childobj ) else ( if IsMapObject childobj then ( append target childobj ) ) ) ) else if classof obj == GtaMloRoom then ( RsGetMapObjectsFromRoomWithXref source target obj ) else ( append target obj ) ) ) ) -------------------------------------------------------------- -- Get the root container for the specified object -------------------------------------------------------------- fn RsGetObjContainer obj = ( if (isKindOf obj Container) then obj else (Containers.IsInContainer obj) ) -------------------------------------------------------------- -- Returns false if any objs are in different containers -------------------------------------------------------------- fn RsObjsInSameContainer objs = ( local objConts = #() for obj in objs while (objConts.count < 2) do ( appendIfUnique objConts (RsGetObjContainer obj) ) return (objConts.count < 2) ) -------------------------------------------------------------- -- Checks object for transforms on its pivot -------------------------------------------------------------- fn RsObjHasXformedPivot obj badXforms:#{} = ( local notRef = not ((isRefObj obj) or (isInternalRef obj)) badXforms[1] = ((distance obj.objectOffsetPos [0,0,0]) > 0.000001) badXforms[2]= (obj.objectOffsetRot != quat 0 0 0 1) or (notRef and (obj.rotation != quat 0 0 0 1)) badXforms[3] = (obj.objectOffsetScale != [1,1,1]) or (notRef and (obj.scale != [1,1,1])) (badXforms.numberSet != 0) ) --------------------------------------------------------------------------------------- -- Returns True if 'obj' is the topmost object in a given scene-link hierarchy -- (i.e. if it's the main map-object) -- 'linkType' enums can be found in 'RsSceneLinkInit.ms' --------------------------------------------------------------------------------------- fn RsIsTopSceneLink linkType obj = ( -- LOD-links have lower-detail models as parent (mapObjIsChild = True) -- but other link-types may have reversed priority: local mapObjIsChild = ::gRsSceneLinkTypeData[linkType + 1].mapObjIsChild local linkedObj if mapObjIsChild then ( -- If map-object is child for this linktype: local children = #() RsSceneLink.getChildren linkType obj &children higherObj = children[1] ) else ( higherObj = RsSceneLink.getParent linkType obj ) return (not isValidNode higherObj) ) --------------------------------------------------------------------------------------------- -- Returns list of mesh-objects that'll be packed with map-object 'obj' on export -- Returns empty list if object is non-exportable -- or if it isn't top object (if 'CheckParent' is true) --------------------------------------------------------------------------------------------- fn RsGetPackedObjs obj CheckParent:True = ( if (getAttrClass obj != "Gta Object") or (not IsMapObject obj CheckParent:CheckParent) do return #() -- Return empty list if this isn't the topmost mapobject for its drawable/reflect-proxy/cloth links: local isTopObj = True for linkType in ::RsObjPackedLinktypes while isTopObj do ( isTopObj = RsIsTopSceneLink linkType obj ) if (not isTopObj) do return #() local objs = #(obj) -- Add objects, which will be queued for their own child-adding: local objNum = 0 while (objNum < objs.count) do ( objNum += 1 local thisObj = objs[objNum] -- Add linked objects: Drawable-lod, Cloth, Shadow/Reflection proxy: for linkType in RsObjPackedLinktypes do ( -- Which direction does this link-type's priority go? local mapObjIsChild = ::gRsSceneLinkTypeData[linkType + 1].mapObjIsChild local linkedObjs = #() if mapObjIsChild then ( -- If map-object is child for this linktype, get its parent: linkedObjs = #(RsSceneLink.getParent linkType thisObj) ) else ( -- If map-object is parent for this linktype, get its children: local linkedObjs = #() RsSceneLink.getChildren linkType thisObj &children ) for linkedObj in linkedObjs where (getAttrClass linkedObj == "Gta Object") and not (getAttr linkedObj idxDontExportGtaObj) do ( -- Don't add more than once, to avoid falling into loops: appendIfUnique objs linkedObj ) ) -- Add child-objects to to-process list: -- (i.e. frag-components) local addChildren = for childObj in thisObj.children where (getAttrClass childObj == "Gta Object") and not (getAttr childObj idxDontExportGtaObj) collect childObj join objs addChildren ) return objs )