escapeenable = true struct sMapChannelSerializer ( objChannels = #{}, objChannelData = #(), objName, OBJ_DATA_DIR_ROOT = "x:/americas/cache/dev/export/islandx/", objDataDir, fn SetDataDir objName = ( if(this.objName == undefined) or (this.objName == "") do return false this.objDataDir = this.OBJ_DATA_DIR_ROOT + this.objName + "/" ), fn FlushChannelData = ( this.objChannelData = #() ), fn GetMapChannelData obj channels = ( local channelList = channels as Array for c=1 to channelList.count do ( local channelIdx = channelList[c]-3 pushprompt ("Gathering " + (channelIdx as string) + "...") if(meshop.getmapsupport obj channelIdx) do ( local channelMapData = for i = 1 to (meshop.getnummapverts obj channelIdx) collect (meshop.getmapvert obj channelIdx i) append this.objChannelData (DataPair channel:channelIdx data:channelMapData) ) popprompt() ) ), fn GetMatIdData obj = ( pushprompt "Gathering MatIds..." append this.objChannelData (DataPair channel:"matid" data:(for f=1 to obj.faces.count collect (getfacematid obj f))) popprompt() ), fn CleanSerializedData = ( local failedFiles = #() for item in (getFiles (this.objDataDir + "*.data")) do ( try ( deleteFile item ) catch ( append failedFiles item ) ) if (failedFiles.count > 0) do ( messagebox "Some previous stored channel data couldnt be deleted" title:"Delete failed" print failedFiles return failedFiles ) ), fn SerializeMapChannelDataBin = ( if (this.objChannelData == undefined) or (this.objChannelData.count == 0) or (this.objName == undefined) do return false local start = timestamp() if not (isDirectoryWriteable this.objDataDir) do makeDir this.objDataDir for item in objChannelData do ( pushprompt ("Writing Channel: " + (item.channel as string)) format "Writing data to: % \n" (this.objDataDir + "channeldata_" + (item.channel as string) + ".data") try ( local fs = fopen (this.objDataDir + "channeldata_" + (item.channel as string) + ".data") "wb" if item.channel == "matid" then ( WriteString fs "matid" for val in item.data do ( WriteByte fs val ) fclose fs ) else ( WriteString fs (item.channel as String) for val in item.data do ( WriteFloat fs val.x WriteFloat fs val.y WriteFloat fs val.z ) fclose fs ) ) catch ( print ("problem writing " + (item.channel as string)) fclose fs ) popprompt() ) format "Time Taken: %\n" ((timestamp() - start) / 1000) ), fn DeserializeMapChannelData = ( local dataFiles = getFiles (this.objDataDir+"*.data") if (dataFiles.count == 0) do ( return false ) --init data channels this.objChannelData = #() --increase size of heap for the expected data 2GB should be about enough for this case heapSize += 2000000000 fn GetChannelData channelDataPath = ( local fs = fopen channelDataPath "rb" local channelName = readString fs pushprompt ("Reading Channel " + channelName + "...") if (channelName == "matid") then ( local data = #() local currentVal = readByte fs while not (keyboard.escPressed) and (currentVal != undefined) do ( append data currentVal currentVal = readByte fs ) fclose fs popprompt() return (DataPair channel:channelName data:data) ) else ( local data = #() local currentVal = readFloat fs while not (keyboard.escPressed) and (currentVal != undefined) do ( append data currentVal currentVal = readFloat fs ) fclose fs --wrangle data into Point3 values local vec3Data = for i=1 to data.count by 3 collect [data[i], data[i+1], data[i+2]] popprompt() return (DataPair channel:channelName data:vec3Data) ) ) --get data files ProgressStart "Reading Data Files..." local counter = 0.0 for dataFile in dataFiles do ( append this.objChannelData (GetChannelData dataFile) counter += 1.0 progressUpdate (100.0 * (counter / dataFiles.count)) ) ProgressEnd() --return this.objChannelData ), fn ApplyMapChannelData obj = ( for item in this.objChannelData where (item.channel != "matid") do ( ProgressStart ("Apply Channel: " + item.channel) local channelId = item.channel as Integer if not (meshop.getmapsupport obj channelId) then ( messagebox ("Missing Map Channel: " + (channelId as string) + "\n" + "Are you sure this mesh matches what you saved from?") ) else ( with undo off ( for mv=1 to item.data.count do ( meshop.setmapvert obj channelId mv item.data[mv] progressUpdate (100.0 * (mv as float / item.data.count)) ) ) ) ProgressEnd() ) ), fn ApplyMatIdData obj = ( local matIdChannels = for item in this.objChannelData where (item.channel == "matid") collect item if (matIdChannels.count != 1) do return false pushprompt "Applying Material IDs..." with undo off ( for idx=1 to matIdChannels[1].data.count do ( setfacematid obj idx matIdChannels[1].data[idx] ) ) popprompt() ), fn Process = ( -- GetMatIdData $ -- GetMapChannelData $ #{2,3,6,10} -- SerializeMapChannelDataBin() --importMapChannelData = DeserializeMapChannelData "c:/temp/islandxMapChannelData.txt" --ApplyMapChannelData obj importMapChannelData -- fs = fopen "c:/temp/channeldata.data" "wb" -- -- for item in objMapChannelData[4].data do -- ( -- WriteFloat fs item.x -- WriteFloat fs item.y -- WriteFloat fs item.z -- ) -- fclose fs ) ) try(destroydialog RSTA_MapDataSerializerUI)catch() rollout RSTA_MapDataSerializerUI "MapData Serializer" width:400 ( dotNetControl rsBannerPanel "System.Windows.Forms.Panel" width:RSTA_MapDataSerializerUI.width height:32 pos:[0,0] local banner = makeRsBanner dn_Panel:rsBannerPanel versionName:"Country Fixins" versionNum:0.3 filename:(getThisScriptFilename()) -- INSTANCE THE STRUCT local dataStruct = sMapChannelSerializer() fn objFilter obj = ( (classof obj == editable_mesh) ) pickbutton pckObject "Object" filter:objFilter tooltip:"Pick an editable mesh" width:(RSTA_MapDataSerializerUI.width - 20) group "Store Map Channel Data" ( edittext txtChannels "Channels: " text:"1,2,5,9" tooltip:"Add comma seperated channel numbers" button btnStoreMapData "Store Channels" tooltip:"Store the defined channels to disk for selected object" width:(RSTA_MapDataSerializerUI.width - 20) ) group "Restore Map Channel Data" ( button btnRestoreMapData "Restore Channel" tooltip:"Restore channels for the selected object" width:(RSTA_MapDataSerializerUI.width - 20) ) --events on pckObject picked obj do ( if (obj != undefined) do ( pckObject.text = obj.name dataStruct.objName = obj.name ) ) on btnStoreMapData pressed do ( --check we have an object picked if (pckObject.object == undefined) do ( messagebox "Pick an editbale mesh object to begin" title:"Selection Error" return false ) --get the channels local channels = filterstring txtChannels.text "," if (channels.count == 0) do ( messagebox "No channels specified" title:"Channel Selection" return false ) local uniqueChannels = for item in (makeuniquearray channels) collect (3 + (item as Integer)) dataStruct.objChannels = uniqueChannels as BitArray dataStruct.FlushChannelData() dataStruct.GetMatIdData pckObject.object dataStruct.GetMapChannelData pckObject.object dataStruct.objChannels dataStruct.SetDataDir pckObject.object dataStruct.CleanSerializedData() dataStruct.SerializeMapChannelDataBin() messagebox "Done!" title:"Process" ) on btnRestoremapData pressed do ( --check we have an object picked if (pckObject.object == undefined) do ( messagebox "Pick an editbale mesh object to begin" title:"Selection Error" return false ) --find the folder with the mesh name dataStruct.SetDataDir pckObject.object.name dataStruct.DeserializeMapChannelData() dataStruct.ApplyMatIdData pckObject.object dataStruct.ApplyMapChannelData pckObject.object messagebox "Done!" title:"Process" ) on RSTA_MapDataSerializerUI open do ( banner.setup() ) ) createDialog RSTA_MapDataSerializerUI 300 200 style:#(#style_titlebar, #style_minimizebox, #style_sysmenu)