├── LICENSE ├── README.md ├── ksy ├── cyclone.ksy └── test.bat ├── plugins ├── 3dsmax │ └── cff_clf │ │ ├── an_import_export.ms │ │ ├── ani.ini │ │ ├── ani_import.ms │ │ ├── ani_import.toml │ │ ├── build │ │ ├── ani_import.ms │ │ ├── ani_import.zip │ │ ├── cff_clf_import.ms │ │ └── cff_clf_import.zip │ │ ├── build_ani_import_script.bat │ │ ├── build_cff_clf_import_script.bat │ │ ├── cff.ini │ │ ├── cff_clf_import.ms │ │ ├── clf_export.ms │ │ ├── def_import.ms │ │ ├── export.ini │ │ ├── import.toml │ │ ├── join_ani_import_files.bat │ │ ├── join_import_files.bat │ │ ├── join_maxscript_files.py │ │ ├── lib │ │ ├── an.ms │ │ ├── an_model.ms │ │ ├── an_viewer.ms │ │ ├── ani.ms │ │ ├── ani_model.ms │ │ ├── ani_viewer.ms │ │ ├── cyclone.ms │ │ ├── cyclone_model.ms │ │ ├── cyclone_viewer.ms │ │ ├── def.ms │ │ ├── def_model.ms │ │ ├── def_viewer.ms │ │ ├── dialogs.ms │ │ ├── ini.ms │ │ ├── math.ms │ │ ├── max.ms │ │ ├── ms.ms │ │ ├── settings.ms │ │ ├── sls.ms │ │ ├── sls_model.ms │ │ ├── sls_viewer.ms │ │ ├── stream.ms │ │ ├── system.ms │ │ └── utils.ms │ │ ├── mzp.run │ │ └── strom_panel.mcr └── noesis │ ├── fmt_aos2_pak.py │ ├── fmt_sd2_tx.py │ ├── fmt_sd2_zap.py │ ├── fmt_sd_cff_clf.py │ ├── fmt_sd_dlt.py │ ├── fmt_sd_tf.py │ └── noewinext.py ├── scripts └── 010editor │ ├── PackPAK(PB).1sc │ ├── PackPAK.1sc │ ├── TFtoTGA.1sc │ ├── UnpackPAK(PB).1sc │ ├── UnpackPAK.1sc │ ├── decodeActionFile.1sc │ ├── decodeDAT.1sc │ └── encodeActionFile.1sc └── templates └── 010Editor ├── AN.bt ├── ANI.bt ├── CFF.bt ├── CLF.bt ├── CMP.bt ├── DEF.bt ├── DLM.bt ├── DLT.bt ├── GM.bt ├── IDF.bt ├── PAK(PB).bt ├── PAK.bt ├── SC.bt ├── SLS.bt ├── TF.bt ├── TX.bt ├── XPS.bt └── ZAP.bt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alexander Evdokimov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ksy/test.bat: -------------------------------------------------------------------------------- 1 | ksv C:\Program Files\1C\Корсары\RESOURCE\TEXTURES\Hubernator_Spa.clf cyclone.ksy -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/an_import_export.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: .an files (Sea Dogs 2/3) import/export script 4 | Version: 0.1 5 | */ 6 | 7 | filein "lib/ms.ms" 8 | filein "lib/utils.ms" 9 | filein "lib/an.ms" 10 | filein "lib/an_viewer.ms" 11 | filein "lib/ini.ms" 12 | filein "lib/system.ms" 13 | filein "lib/settings.ms" 14 | 15 | struct anStrings 16 | ( 17 | importRolloutTitle = "Import/Export", 18 | settingsRolloutTitle = "Import settings", 19 | buttonImportCaption = "Import", 20 | buttonExportCaption = "Export", 21 | editStartFrameTitle = "Start frame", 22 | editEndFrameTitle = "End frame", 23 | checkboxLoadSkeletonCaption = "load skeleton", 24 | checkboxAllAnimationsCaption = "load animations", 25 | dialogTitle = "Storm 2 .an Import/Export", 26 | groupAnimatedObjectCaption = "Apply animation to:", 27 | radioSelectAnimatedObjectItems = #("skeleton", "selection"), 28 | exportRolloutTitle = "Export settings", 29 | groupGetObjectCaption = "Get object", 30 | radioGetObjecttItems = #("by selection", "by name", "by group"), 31 | editExportStartFrameTitle = "Start frame", 32 | editExportEndFrameTitle = "End frame", 33 | checkboxAllFramesCaption = "All frames", 34 | importDialogCaption = "Open .an file", 35 | importDialogTypes = "Storm 2 an format (*.an)|*.an", 36 | fn loadFromIni filename = 37 | ( 38 | local sets = iniSettings(this) 39 | sets.loadFromIniFile filename "settings" 40 | ) 41 | ) 42 | 43 | struct anSettings 44 | ( 45 | startFrame = 1, 46 | endFrame = 1000, 47 | loadSkeleton = true, 48 | allAnimations = true, 49 | exportStartFrame = 1, 50 | exportEndFrame = 1000, 51 | exportAllFrames = true, 52 | fn loadFromIni filename = 53 | ( 54 | local sets = iniSettings(this) 55 | sets.loadFromIniFile filename "settings" 56 | ) 57 | ) 58 | 59 | struct anUI 60 | ( 61 | settings, 62 | strings, 63 | iniFilename = "an.ini", 64 | fn importANFile filename: = 65 | ( 66 | if filename == unsupplied then 67 | ( 68 | dialogs.caption = strings.importDialogCaption 69 | dialogs.types = strings.importDialogTypes 70 | filestream = dialogs.openFileDialog &fname "rb" 71 | filename = fname 72 | ) 73 | 74 | if filestream != undefined then 75 | ( 76 | file = anFile() 77 | file.openStream filestream filename 78 | if file.readFile() then 79 | ( 80 | viewer = anViewer file.object 81 | --viewer.settings. = 82 | viewer.create() 83 | ) 84 | file.closeFile() 85 | ) 86 | ), 87 | fn exportANFile = 88 | ( 89 | print "wip" 90 | ), 91 | exportRollout = 92 | ( 93 | rollout exportRollout strings.exportRolloutTitle 94 | ( 95 | local owner = if owner != undefined do owner 96 | 97 | groupBox group_getObjs owner.strings.groupGetObjectCaption \ 98 | pos:[10, 5] width:165 height:60 99 | radiobuttons radio_selectObjects columns:2 100 | labels:owner.strings.radioGetObjecttItems pos:[20, 25] 101 | 102 | checkbox checkbox_allFrames owner.strings.checkboxAllFramesCaption \ 103 | checked:owner.settings.exportAllFrames pos:[80, 70] 104 | 105 | spinner spinner_exportStartFrame owner.strings.editExportStartFrameTitle \ 106 | fieldWidth:70 type:#integer align:#right pos:[22, 90] \ 107 | range:[1, 5000, owner.settings.exportStartFrame] 108 | spinner spinner_exportEndFrame owner.strings.editExportEndFrameTitle \ 109 | fieldWidth:70 type:#integer align:#right pos:[28, 110] \ 110 | range:[1, 5000, owner.settings.exportEndFrame] 111 | ) 112 | ), 113 | settingsRollout = 114 | ( 115 | rollout settingsRollout strings.settingsRolloutTitle 116 | ( 117 | local owner = if owner != undefined do owner 118 | 119 | checkbox checkbox_loadSkeleton owner.strings.checkboxLoadSkeletonCaption \ 120 | checked:owner.settings.loadSkeleton pos:[80, 5] 121 | checkbox checkbox_allAnimations owner.strings.checkboxAllAnimationsCaption \ 122 | checked:owner.settings.allAnimations pos:[80, 25] 123 | 124 | spinner spinner_startFrame owner.strings.editStartFrameTitle \ 125 | fieldWidth:70 type:#integer align:#right pos:[22, 45] \ 126 | range:[1, 5000, owner.settings.startFrame] 127 | spinner spinner_endFrame owner.strings.editEndFrameTitle \ 128 | fieldWidth:70 type:#integer align:#right pos:[28, 65] \ 129 | range:[1, 5000, owner.settings.endFrame] 130 | 131 | groupBox group_textures owner.strings.groupAnimatedObjectCaption \ 132 | pos:[10, 85] width:165 height:45 133 | radiobuttons radio_selectAnimatedObject \ 134 | labels:owner.strings.radioSelectAnimatedObjectItems pos:[30, 105] 135 | ) 136 | ), 137 | importRollout = 138 | ( 139 | rollout importRollout strings.importRolloutTitle 140 | ( 141 | local owner = if owner != undefined do owner 142 | 143 | button button_importAnFile owner.strings.buttonImportCaption width:120 144 | button button_exportAnFile owner.strings.buttonExportCaption width:120 145 | 146 | on button_importAnFile pressed do 147 | ( 148 | owner.importANFile() 149 | ) 150 | 151 | on button_exportAnFile pressed do 152 | ( 153 | owner.exportANFile() 154 | ) 155 | ) 156 | ), 157 | dialog = 158 | ( 159 | rollout dialog strings.dialogTitle 160 | ( 161 | local owner = if owner != undefined do owner 162 | 163 | subrollout subroll_container "container" height:395 width:196 pos:[2, 2] 164 | on dialog resized point do 165 | ( 166 | subroll_container.height = dialog.height 167 | ) 168 | ) 169 | ), 170 | fn close = try (destroyDialog dialog) catch(), 171 | fn show = 172 | ( 173 | createDialog dialog width:200 pos:mouse.screenpos \ 174 | style:#(#style_sysmenu, #style_resizing, #style_titlebar) 175 | AddSubRollout dialog.subroll_container settingsRollout 176 | AddSubRollout dialog.subroll_container exportRollout 177 | AddSubRollout dialog.subroll_container importRollout 178 | ), 179 | fn init = 180 | ( 181 | if settings == undefined then 182 | ( 183 | settings = anSettings() 184 | settings.loadFromIni (sys.currentPath + iniFilename) 185 | ) 186 | 187 | if strings == undefined then 188 | ( 189 | strings = anStrings() 190 | strings.loadFromIni (sys.currentPath + iniFilename) 191 | ) 192 | 193 | dialog.owner = this 194 | importRollout.owner = this 195 | settingsRollout.owner = this 196 | exportRollout.owner = this 197 | ), 198 | on create do init() 199 | ) 200 | 201 | fn main = 202 | ( 203 | sys.currentPath = fileUtils.getCurrentPath(getThisScriptFilename()) 204 | anDialog = anUI() 205 | anDialog.show() 206 | ) 207 | 208 | main() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/ani.ini: -------------------------------------------------------------------------------- 1 | [SETTINGS] 2 | pathToModelsFolder= 3 | pathToTexturesFolder= 4 | allLods=false 5 | allFrames=true 6 | isTextured=true 7 | path= 8 | to3dsMaxSystem=true 9 | isClockwizeOrder=true 10 | lod=1 11 | frame=1 12 | texFormat=tf 13 | addCamera=false 14 | 15 | [STRINGS] 16 | rolloutTitle=Import .ani scene 17 | rolloutImportTitle=Import 18 | buttonImportCaption=Open .ani file 19 | groupModelsCaption=Folder 20 | buttonSetPathCaption=Get path 21 | buttonClearPathCaption=Clear 22 | rolloutSettingsTitle=Paths 23 | rolloutImportSettingsTitle=Models 24 | importDialogCaption=Import .ani file 25 | importDialogTypes=Sea Dogs 1 animated scenes file (*.ani)|*.ani 26 | openFolder=Open Models folder 27 | editChooseLodModelTitle=LOD 28 | groupModelCaption=Model 29 | groupTexturesCaption=Textures 30 | editChooseFrameTitle=Frame 31 | checkboxAllLodsCaption=all lods 32 | checkboxAllFramesCaption=all frames 33 | labelChoosePath=Path 34 | checkboxTexturedCaption=add textures 35 | buttonSetTexturePathCaption=Get path 36 | buttonClearTexturePathCaption=Clear 37 | openTexturesFolder=Choose textures folder 38 | dropdownlistExtensionCaption=ext. 39 | dropdownlistExtensionItems=tf,bmp,tga,png 40 | checkboxConvertCoordSystem=convert coordinate system 41 | checkboxFaceOrder=change face order 42 | editChooseStartFrameTitle=Start 43 | groupIniCaption=Path 44 | buttonClearCaption=Clear scene 45 | rolloutClearTitle=Clear 46 | editPathToModelsText=Path to Models folder -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/ani_import.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: .ani files (Sea Dogs 2000) import script 4 | Version: 0.1 5 | */ 6 | 7 | filein "lib/ms.ms" 8 | filein "lib/utils.ms" 9 | filein "lib/ani.ms" 10 | filein "lib/ani_viewer.ms" 11 | filein "lib/ini.ms" 12 | filein "lib/system.ms" 13 | filein "lib/settings.ms" 14 | 15 | struct settingsImportAni 16 | ( 17 | pathToModelsFolder = "", 18 | pathToTexturesFolder = "", 19 | allLods = false, 20 | allFrames = true, 21 | isTextured = true, 22 | path = "", 23 | to3dsMaxSystem = true, 24 | isClockwizeOrder = true, 25 | lod = 1, 26 | frame = 1, 27 | texFormat = "tf", 28 | addCamera = false, 29 | fn loadFromIni filename = 30 | ( 31 | local sets = iniSettings(this) 32 | sets.loadFromIniFile filename "settings" 33 | ) 34 | ) 35 | 36 | struct stringsImportAni 37 | ( 38 | rolloutTitle = "Import .ani scene", 39 | rolloutImportTitle = "Import", 40 | buttonImportCaption = "Open .ani file", 41 | groupModelsCaption = "Folder", 42 | buttonSetPathCaption = "Get path", 43 | buttonClearPathCaption = "Clear", 44 | rolloutSettingsTitle = "Paths", 45 | rolloutImportSettingsTitle = "Models", 46 | importDialogCaption = "Import .ani file", 47 | importDialogTypes = "Sea Dogs 1 animated scenes file (*.ani)|*.ani", 48 | openFolder = "Open \"Models\" folder", 49 | editChooseLodModelTitle = "LOD", 50 | groupModelCaption = "Model", 51 | groupTexturesCaption = "Textures", 52 | editChooseFrameTitle = "Frame", 53 | checkboxAllLodsCaption = "all lods", 54 | checkboxAllFramesCaption = "all frames", 55 | labelChoosePath = "Path", 56 | checkboxTexturedCaption = "add textures", 57 | buttonSetTexturePathCaption = "Get path", 58 | buttonClearTexturePathCaption = "Clear", 59 | openTexturesFolder = "Choose textures folder", 60 | dropdownlistExtensionCaption = "ext.", 61 | dropdownlistExtensionItems = #("tf", "bmp", "tga", "png"), 62 | checkboxConvertCoordSystem = "convert coordinate system", 63 | checkboxFaceOrder = "Change face order", 64 | editChooseStartFrameTitle = "Start" , 65 | groupIniCaption = "Path", 66 | buttonClearCaption = "Clear scene", 67 | rolloutClearTitle = "Clear", 68 | groupCameraCaption = "Camera", 69 | checkboxCameraCaption = "Add camera", 70 | editPathToModelsText = "Path to Models folder", 71 | fn loadFromIni filename = 72 | ( 73 | local sets = iniSettings(this) 74 | sets.loadFromIniFile filename "strings" 75 | ) 76 | ) 77 | 78 | struct aniSceneImportUI 79 | ( 80 | settings, 81 | strings, 82 | iniFilename = "ani.ini", 83 | fn importModel filename: = 84 | ( 85 | if filename == unsupplied then 86 | ( 87 | dialogs.caption = strings.importDialogCaption 88 | dialogs.types = strings.importDialogTypes 89 | filestream = dialogs.openFileDialog &fname "rb" 90 | filename = fname 91 | ) 92 | 93 | if filestream != undefined then 94 | ( 95 | file = aniFile() 96 | file.openStream filestream filename 97 | if file.readFile() then 98 | ( 99 | sceneViewer = aniSceneViewer file.scene 100 | viewerSettings = sceneViewer.settings 101 | 102 | viewerSettings.modelsFolderPath = settings.pathToModelsFolder 103 | viewerSettings.isTextured = settings.isTextured 104 | if settings.allLods then 105 | viewerSettings.lodIndex = 0 106 | else 107 | viewerSettings.lodIndex = viewerSettings.lodIndex 108 | if settings.allFrames then 109 | viewerSettings.frameIndex = 0 110 | else 111 | viewerSettings.frameIndex = viewerSettings.frameIndex 112 | viewerSettings.texturesPath = settings.path 113 | viewerSettings.texFormat = settings.texFormat 114 | viewerSettings.to3dsMaxSystem = settings.to3dsMaxSystem 115 | viewerSettings.isClockwizeOrder = settings.isClockwizeOrder 116 | viewerSettings.addCamera = settings.addCamera 117 | 118 | sceneViewer.create() 119 | ) 120 | file.closeFile() 121 | ) 122 | ), 123 | fn getPath = 124 | ( 125 | path = dialogs.openFolder strings.openFolder 126 | ), 127 | clearRollout = 128 | ( 129 | rollout clearRollout strings.rolloutClearTitle 130 | ( 131 | local owner = if owner != undefined do owner 132 | 133 | button button_removeObjects owner.strings.buttonClearCaption width:120 134 | 135 | on button_removeObjects pressed do 136 | ( 137 | print "none" 138 | ) 139 | ) 140 | ), 141 | importSettingsRollout = 142 | ( 143 | rollout importSettingsRollout strings.rolloutImportSettingsTitle 144 | ( 145 | local owner = if owner != undefined do owner 146 | groupBox group_model owner.strings.groupModelCaption \ 147 | pos:[5, 97] width:175 height:110 148 | groupBox group_textures owner.strings.groupTexturesCaption \ 149 | pos:[5, 0] width:175 height:92 150 | groupBox group_camera owner.strings.groupCameraCaption \ 151 | pos:[5, 210] width:175 height:45 152 | 153 | checkbox checkbox_addCamera owner.strings.checkboxCameraCaption \ 154 | checked:owner.settings.addCamera pos:[25, 230] 155 | 156 | checkbox checkbox_convertCoord owner.strings.checkboxconvertCoordSystem \ 157 | checked:owner.settings.to3dsMaxSystem pos:[25, 115] 158 | checkbox checkbox_faceOrder owner.strings.checkboxFaceOrder \ 159 | checked:owner.settings.isClockwizeOrder pos:[25, 135] 160 | 161 | spinner spinner_lod owner.strings.editChooseLodModelTitle \ 162 | fieldWidth:40 type:#integer align:#right pos:[25, 160] \ 163 | range:[1, 10, owner.settings.lod] 164 | spinner spinner_frame owner.strings.editChooseFrameTitle \ 165 | fieldWidth:40 type:#integer align:#right pos:[15, 180] \ 166 | range:[1, 2000, owner.settings.frame] 167 | 168 | checkbox checkbox_allLods owner.strings.checkboxAllLodsCaption \ 169 | checked:owner.settings.allLods pos:[105, 160] 170 | checkbox checkbox_allFrames owner.strings.checkboxAllFramesCaption \ 171 | checked:owner.settings.allFrames pos:[105, 180] 172 | 173 | edittext edit_texPath "" \ 174 | fieldWidth:155 pos:[10, 40] readOnly:true text:owner.settings.pathToTexturesFolder 175 | 176 | button button_getTexturePath owner.strings.buttonSetTexturePathCaption \ 177 | width:75 pos:[15, 62] 178 | button button_clearTexturePath owner.strings.buttonClearTexturePathCaption \ 179 | width:75 pos:[95, 62] 180 | checkbox checkbox_isTextured owner.strings.checkboxTexturedCaption \ 181 | checked:owner.settings.isTextured pos:[15, 20] 182 | 183 | dropdownlist dropdownlist_extension items:owner.strings.dropdownlistExtensionItems \ 184 | pos:[120, 15] width:50 185 | 186 | on button_getTexturePath pressed do 187 | ( 188 | pathToTexFolders = owner.getPath() 189 | if pathToTexFolders != undefined then edit_texPath.text = pathToTexFolders 190 | ) 191 | on button_clearTexturePath pressed do 192 | ( 193 | edit_texPath.text = "" 194 | ) 195 | ) 196 | ), 197 | settingsRollout = 198 | ( 199 | rollout settingsRollout strings.rolloutSettingsTitle 200 | ( 201 | local owner = if owner != undefined do owner 202 | 203 | --groupBox group_model owner.strings.groupModelsCaption \ 204 | --pos:[5, 0] width:175 height:90 205 | edittext edit_modelsPath owner.strings.editPathToModelsText fieldWidth:154 \ 206 | pos:[15, 5] readOnly:true labelOnTop:true text:owner.settings.pathToModelsFolder 207 | 208 | button button_setModelsPath owner.strings.buttonSetPathCaption \ 209 | width:75 pos:[15, 45] 210 | button button_clearModelsPath owner.strings.buttonClearPathCaption \ 211 | width:75 pos:[95, 45] 212 | 213 | on button_setModelsPath pressed do 214 | ( 215 | pathToModFolders = owner.getPath() 216 | if pathToModFolders != undefined then edit_modelsPath.text = pathToModFolders 217 | ) 218 | on button_clearModelsPath pressed do 219 | ( 220 | edit_modelsPath.text = "" 221 | ) 222 | ) 223 | ), 224 | importRollout = 225 | ( 226 | rollout importRollout strings.rolloutImportTitle 227 | ( 228 | local owner = if owner != undefined do owner 229 | 230 | button button_importAniScene owner.strings.buttonImportCaption width:120 231 | 232 | on button_importAniScene pressed do 233 | ( 234 | setRollout = owner.dialog.subroll_container.importSettingsRollout 235 | importSetRollout = owner.dialog.subroll_container.settingsRollout 236 | importSettings = owner.settings 237 | 238 | importSettings.pathToModelsFolder = importSetRollout.edit_modelsPath.text 239 | importSettings.isTextured = setRollout.checkbox_isTextured.checked 240 | importSettings.allLods = setRollout.checkbox_allLods.checked 241 | importSettings.allFrames = setRollout.checkbox_allFrames.checked 242 | importSettings.lod = setRollout.spinner_lod.value 243 | importSettings.frame = setRollout.spinner_frame.value 244 | importSettings.path = setRollout.edit_texPath.text 245 | importSettings.texFormat = setRollout.dropdownlist_extension.text 246 | importSettings.to3dsMaxSystem = setRollout.checkbox_convertCoord.checked 247 | importSettings.isClockwizeOrder = setRollout.checkbox_faceOrder.checked 248 | importSettings.addCamera = setRollout.checkbox_addCamera.checked 249 | 250 | owner.importModel() 251 | ) 252 | ) 253 | ), 254 | dialog = 255 | ( 256 | rollout dialog strings.rolloutTitle 257 | ( 258 | local owner = if owner != undefined do owner 259 | 260 | subrollout subroll_container "container" height:410 width:196 pos:[2, 2] 261 | on dialog resized point do 262 | ( 263 | subroll_container.height = dialog.height 264 | ) 265 | ) 266 | ), 267 | fn close = try (destroyDialog dialog) catch(), 268 | fn show = 269 | ( 270 | if settings == undefined then 271 | ( 272 | settings = settingsImportAni() 273 | settings.loadFromIni (sys.currentPath + iniFilename) 274 | ) 275 | 276 | if strings == undefined then 277 | ( 278 | strings = stringsImportAni() 279 | strings.loadFromIni (sys.currentPath + iniFilename) 280 | ) 281 | 282 | createDialog dialog width:200 pos:mouse.screenpos \ 283 | style:#(#style_sysmenu, #style_resizing, #style_titlebar) 284 | AddSubRollout dialog.subroll_container settingsRollout 285 | AddSubRollout dialog.subroll_container importSettingsRollout rolledUp:true 286 | AddSubRollout dialog.subroll_container clearRollout rolledUp:true 287 | AddSubRollout dialog.subroll_container importRollout 288 | ), 289 | fn init = 290 | ( 291 | dialog.owner = this 292 | importRollout.owner = this 293 | settingsRollout.owner = this 294 | importSettingsRollout.owner = this 295 | clearRollout.owner = this 296 | ), 297 | on create do init() 298 | ) 299 | 300 | fn main = 301 | ( 302 | sys.currentPath = fileUtils.getCurrentPath(getThisScriptFilename()) 303 | aniSceneImport = aniSceneImportUI() 304 | aniSceneImport.show() 305 | ) 306 | 307 | main() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/ani_import.toml: -------------------------------------------------------------------------------- 1 | [clf_cff_import] 2 | 3 | filename = "ani_import.ms" 4 | folder = "build" 5 | 6 | files = [ 7 | "lib/ms.ms", 8 | "lib/utils.ms", 9 | "lib/dialogs.ms", 10 | "lib/ini.ms", 11 | "lib/settings.ms", 12 | "lib/system.ms", 13 | "lib/max.ms", 14 | "lib/stream.ms", 15 | "lib/ani_model.ms", 16 | "lib/ani.ms", 17 | "lib/cyclone_model.ms", 18 | "lib/cyclone.ms", 19 | "lib/cyclone_viewer.ms", 20 | "lib/ani_viewer.ms" 21 | ] -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/build/ani_import.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexKimov/seadogs-file-formats/e8521eafe6c801398dfea8df72247ed045c3f636/plugins/3dsmax/cff_clf/build/ani_import.zip -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/build/cff_clf_import.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexKimov/seadogs-file-formats/e8521eafe6c801398dfea8df72247ed045c3f636/plugins/3dsmax/cff_clf/build/cff_clf_import.zip -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/build_ani_import_script.bat: -------------------------------------------------------------------------------- 1 | SET SourceDir=%~dp0 2 | SET DestDir=%~dp0 3 | SET Filename=ani_import.zip 4 | SET MSFilename=ani_import.ms 5 | SET OutputFolder=Build 6 | SET Inifile=ani.ini 7 | SET ZipArchver=C:\Program Files\7-Zip 8 | 9 | call "join_ani_import_files.bat" 10 | 11 | CD /D "%ZipArchver%" 12 | 7z.exe a -tzip "%SourceDir%%OutputFolder%\%Filename%" "%DestDir%%OutputFolder%\%MSFilename%" "%SourceDir%\%Inifile%" -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/build_cff_clf_import_script.bat: -------------------------------------------------------------------------------- 1 | SET SourceDir=%~dp0 2 | SET DestDir=%~dp0 3 | SET Filename=cff_clf_import.zip 4 | SET MSFilename=cff_clf_import.ms 5 | SET Inifile=cff.ini 6 | SET OutputFolder=Build 7 | SET ZipArchver=C:\Program Files\7-Zip 8 | 9 | call "join_import_files.bat" 10 | 11 | CD /D "%ZipArchver%" 12 | 7z.exe a -tzip "%SourceDir%%OutputFolder%\%Filename%" "%DestDir%%OutputFolder%\%MSFilename%" "%SourceDir%\%Inifile%" -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/cff.ini: -------------------------------------------------------------------------------- 1 | [SETTINGS] 2 | lod=1 3 | frame=1 4 | texFormat=tf 5 | allLods=false 6 | allFrames=true 7 | isTextured=true 8 | path= 9 | to3dsMaxSystem=true 10 | isClockwizeOrder=true 11 | 12 | [STRINGS] 13 | rolloutTitle=Import Storm 1 Engine model 14 | importDialogCaption=Open 3d Model file 15 | importDialogTypes=Cyclone final format (*.cff;*.clf)|*.cff;*.clf 16 | formatsArray=.cff,.clf 17 | rolloutSettingsTitle=Settings 18 | rolloutImportTitle=Import 19 | buttonImportCaption=Import model 20 | editChooseLodModelTitle=LOD 21 | groupModelCaption=Model 22 | groupTexturesCaption=Textures 23 | editChooseFrameTitle=Frame 24 | checkboxAllLodsCaption=all lods 25 | checkboxAllFramesCaption=all frames 26 | labelChoosePath=Path 27 | checkboxTexturedCaption=add textures 28 | buttonSetTexturePathCaption=Set 29 | buttonClearTexturePathCaption=Clear 30 | openTexturesFolder=Choose textures folder 31 | dropdownlistExtensionCaption=ext. 32 | dropdownlistExtensionItems=tf,bmp,tga,png 33 | checkboxConvertCoordSystem=convert coordinate system 34 | checkboxFaceOrder=change face order -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/cff_clf_import.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: Storm 1 Engine (Sea Dogs, Age of Sail 2/Privateer's Bounty) 3d models files import script 4 | Version: 0.1 5 | */ 6 | 7 | filein "lib/ms.ms" 8 | filein "lib/utils.ms" 9 | filein "lib/settings.ms" 10 | filein "lib/cyclone.ms" 11 | filein "lib/cyclone_viewer.ms" 12 | 13 | struct settingsImportUI 14 | ( 15 | lod = 1, 16 | frame = 1, 17 | texFormat = "tf", 18 | allLods = False, 19 | allFrames = True, 20 | isTextured = True, 21 | path = "", 22 | to3dsMaxSystem = True, 23 | isClockwizeOrder = True, 24 | fn loadFromIni filename = 25 | ( 26 | local sets = iniSettings(this) 27 | sets.loadFromIniFile filename "settings" 28 | ) 29 | ) 30 | 31 | struct stringsImportUI 32 | ( 33 | rolloutTitle = "Import Storm 1 Engine model", 34 | importDialogCaption = "Open 3d Model file", 35 | importDialogTypes = "Cyclone final format (*.cff;*.clf)|*.cff;*.clf", 36 | formatsArray = #(".cff", ".clf"), 37 | rolloutSettingsTitle = "Settings", 38 | rolloutImportTitle = "Import", 39 | buttonImportCaption = "Import model", 40 | editChooseLodModelTitle = "LOD", 41 | groupModelCaption = "Model", 42 | groupTexturesCaption = "Textures", 43 | editChooseFrameTitle = "Frame", 44 | checkboxAllLodsCaption = "all lods", 45 | checkboxAllFramesCaption = "all frames", 46 | labelChoosePath = "Path", 47 | checkboxTexturedCaption = "add textures", 48 | buttonSetTexturePathCaption = "Set", 49 | buttonClearTexturePathCaption = "Clear", 50 | openTexturesFolder = "Choose textures folder", 51 | dropdownlistExtensionCaption = "ext.", 52 | dropdownlistExtensionItems = #("tf", "bmp", "tga", "png"), 53 | checkboxConvertCoordSystem = "convert coordinate system", 54 | checkboxFaceOrder = "change face order", 55 | fn loadFromIni filename = 56 | ( 57 | local sets = iniSettings(this) 58 | sets.loadFromIniFile filename "strings" 59 | ) 60 | ) 61 | 62 | struct cycloneImportUI 63 | ( 64 | settings, 65 | strings, 66 | iniFilename = "cff.ini", 67 | fn importModel filename: = 68 | ( 69 | if filename == unsupplied then 70 | ( 71 | dialogs.caption = strings.importDialogCaption 72 | dialogs.types = strings.importDialogTypes 73 | filestream = dialogs.openFileDialog &fname "rb" 74 | filename = fname 75 | ) 76 | 77 | if filestream != undefined then 78 | ( 79 | local ext = fileUtils.getFileExtension filename 80 | file = case (ext) of 81 | ( 82 | (strings.formatsArray[1]): cffFile() 83 | (strings.formatsArray[2]): clfFile() 84 | ) 85 | 86 | file.openStream filestream filename 87 | if file.readFile() then 88 | ( 89 | viewer = modelViewer file.model 90 | viewer.settings.isTextured = settings.isTextured 91 | viewer.settings.texturesPath = settings.path 92 | viewer.settings.texFormat = settings.texFormat 93 | if settings.allLods == True then 94 | viewer.settings.lodIndex = 0 95 | else 96 | viewer.settings.lodIndex = settings.lod 97 | if settings.allFrames == True then 98 | viewer.settings.frameIndex = 0 99 | else 100 | viewer.settings.frameIndex = settings.frame 101 | viewer.settings.to3dsMaxSystem = settings.to3dsMaxSystem 102 | viewer.settings.isIntermediateFormat = \ 103 | (if (classOf(file) == clfFile) then True else False) 104 | 105 | viewer.settings.isClockwizeOrder = settings.isClockwizeOrder 106 | 107 | viewer.createScene() 108 | ) 109 | file.closeFile() 110 | ) 111 | ), 112 | fn getPath = 113 | ( 114 | path = dialogs.openFolder strings.openTexturesFolder 115 | if path != undefined then 116 | ( 117 | this.dialog.subroll_container.settingsRollout.edit_texPath.text = path 118 | ) 119 | ), 120 | fn clearPath = 121 | ( 122 | this.dialog.subroll_container.settingsRollout.edit_texPath.text = "" 123 | ), 124 | settingsRollout = 125 | ( 126 | rollout settingsRollout strings.rolloutSettingsTitle 127 | ( 128 | local owner = if owner != undefined do owner 129 | groupBox group_model owner.strings.groupModelCaption \ 130 | pos:[5, 97] width:175 height:110 131 | 132 | groupBox group_textures owner.strings.groupTexturesCaption \ 133 | pos:[5, 0] width:175 height:92 134 | 135 | checkbox checkbox_convertCoord owner.strings.checkboxconvertCoordSystem \ 136 | checked:owner.settings.to3dsMaxSystem pos:[25, 115] 137 | checkbox checkbox_faceOrder owner.strings.checkboxFaceOrder \ 138 | checked:owner.settings.isClockwizeOrder pos:[25, 135] 139 | 140 | spinner spinner_lod owner.strings.editChooseLodModelTitle \ 141 | fieldWidth:40 type:#integer align:#right pos:[25, 160] \ 142 | range:[1, 10, owner.settings.lod] 143 | spinner spinner_frame owner.strings.editChooseFrameTitle \ 144 | fieldWidth:40 type:#integer align:#right pos:[15, 180] \ 145 | range:[1, 2000, owner.settings.frame] 146 | 147 | checkbox checkbox_allLods owner.strings.checkboxAllLodsCaption \ 148 | checked:owner.settings.allLods pos:[105, 160] 149 | checkbox checkbox_allFrames owner.strings.checkboxAllFramesCaption \ 150 | checked:owner.settings.allFrames pos:[105, 180] 151 | 152 | --label label_choosePath owner.strings.labelChoosePath pos:[15, 20] 153 | edittext edit_texPath "" fieldWidth:155 pos:[10, 40] readOnly:true 154 | 155 | button button_setTexturePath owner.strings.buttonSetTexturePathCaption \ 156 | width:75 pos:[15, 62] 157 | button button_clearTexturePath owner.strings.buttonClearTexturePathCaption \ 158 | width:75 pos:[95, 62] 159 | checkbox checkbox_isTextured owner.strings.checkboxTexturedCaption \ 160 | checked:owner.settings.isTextured pos:[15, 20] 161 | 162 | dropdownlist dropdownlist_extension items:owner.strings.dropdownlistExtensionItems \ 163 | pos:[120, 15] width:50 164 | 165 | on button_setTexturePath pressed do 166 | ( 167 | owner.getPath() 168 | ) 169 | on button_clearTexturePath pressed do 170 | ( 171 | owner.clearPath() 172 | ) 173 | ) 174 | ), 175 | importRollout = 176 | ( 177 | rollout importRollout strings.rolloutImportTitle 178 | ( 179 | local owner = if owner != undefined do owner 180 | 181 | button button_importModel owner.strings.buttonImportCaption width:120 182 | on button_importModel pressed do 183 | ( 184 | setRollout = owner.dialog.subroll_container.settingsRollout 185 | importSettings = owner.settings 186 | 187 | importSettings.isTextured = setRollout.checkbox_isTextured.checked 188 | importSettings.allLods = setRollout.checkbox_allLods.checked 189 | importSettings.allFrames = setRollout.checkbox_allFrames.checked 190 | importSettings.lod = setRollout.spinner_lod.value 191 | importSettings.frame = setRollout.spinner_frame.value 192 | importSettings.path = setRollout.edit_texPath.text 193 | importSettings.texFormat = setRollout.dropdownlist_extension.text 194 | importSettings.to3dsMaxSystem = setRollout.checkbox_convertCoord.checked 195 | importSettings.isClockwizeOrder = setRollout.checkbox_faceOrder.checked 196 | 197 | owner.importModel() 198 | ) 199 | ) 200 | ), 201 | dialog = 202 | ( 203 | rollout dialog strings.rolloutTitle 204 | ( 205 | local owner = if owner != undefined do owner 206 | 207 | subrollout subroll_container "container" height:295 width:196 pos:[2, 2] 208 | on dialog resized point do 209 | ( 210 | subroll_container.height = dialog.height 211 | ) 212 | ) 213 | ), 214 | fn close = try (destroyDialog dialog) catch(), 215 | fn show = 216 | ( 217 | if settings == undefined then 218 | ( 219 | settings = settingsImportUI() 220 | settings.loadFromIni (sys.currentPath + iniFilename) 221 | ) 222 | 223 | if strings == undefined then 224 | ( 225 | strings = stringsImportUI() 226 | strings.loadFromIni (sys.currentPath + iniFilename) 227 | ) 228 | 229 | createDialog dialog width:200 pos:mouse.screenpos style:#(#style_toolwindow, #style_sysmenu) 230 | AddSubRollout dialog.subroll_container settingsRollout 231 | AddSubRollout dialog.subroll_container importRollout 232 | ), 233 | fn init = 234 | ( 235 | dialog.owner = this 236 | importRollout.owner = this 237 | settingsRollout.owner = this 238 | ), 239 | on create do init() 240 | ) 241 | 242 | fn main = 243 | ( 244 | currentPath = fileUtils.getCurrentPath(getThisScriptFilename()) 245 | importUI = cycloneImportUI() 246 | importUI.show() 247 | ) 248 | 249 | main() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/clf_export.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: Storm 1 Engine (Sea Dogs, Age of Sail 2/Privateer's Bounty) 3d models files export script 4 | Version: 0.1 5 | */ 6 | 7 | filein "lib/ms.ms" 8 | filein "lib/utils.ms" 9 | filein "lib/dialogs.ms" 10 | filein "lib/cyclone.ms" 11 | 12 | struct settingsExportUI 13 | ( 14 | exportMaterials = true, 15 | exportAnimations = true, 16 | extension = "", 17 | selectionType = 1, 18 | modelName = "", 19 | spinnerFrameNumber = 1000 20 | ) 21 | 22 | struct stringsExportUI 23 | ( 24 | buttonExportCaption = "Export model", 25 | rolloutExportTitle = "Export", 26 | rolloutTitle = "Export .clf model", 27 | rolloutSettingsTitle = "Settings", 28 | groupLodCaption = "LOD", 29 | radioSelectItems = #("by selection", "by group", "by prefix"), 30 | radioSelectCaption = "Select objects:", 31 | groupMeshCaption = "Mesh", 32 | dropdownlistExtensionItems = #("", "bmp", "tga", "png", "tf"), 33 | labelTextureType = "Texture type", 34 | checkboxExportMaterials = "Export materials", 35 | checkboxexportAnimations = "Export animations", 36 | meshNotSelected = "Meshes aren't selected.", 37 | editFrameNumberTitle = "Frames", 38 | exportDialogCaption = "Save Cyclon Model file", 39 | exportDialogTypes = "Cyclone final format (*.clf)|*.clf" 40 | ) 41 | 42 | struct cycloneExportUI 43 | ( 44 | settings, 45 | strings, 46 | fn exportModel filename: = 47 | ( 48 | if settings.selectionType == 1 then 49 | ( 50 | if selection.count == 0 then 51 | dialogs.showMessage strings.meshNotSelected 52 | else 53 | ( 54 | local objs = for obj in selection where isproperty obj #verts collect obj 55 | local model = cycloneModel() 56 | model.addLod objs 57 | dialogs.caption = strings.exportDialogCaption 58 | dialogs.types = strings.exportDialogTypes 59 | local filestream = dialogs.openFileDialog &fname "wb" 60 | if filestream != undefined then 61 | ( 62 | local file = clfFile() 63 | file.openStream filestream fname 64 | file.writeFile() 65 | file.closeFile() 66 | ) 67 | ) 68 | ) 69 | else if settings.selectionType == 2 then 70 | ( 71 | local model = cycloneModel() 72 | for modelGroup in objects where isGroupHead obj do 73 | ( 74 | local objs = for obj in modelGroup.children where isproperty obj #verts collect obj 75 | --model.addLod objs 76 | ) 77 | ) 78 | else 79 | ( 80 | local objs = for obj in objects \ 81 | where isproperty obj #verts and findString obj.name exportSettings.modelName collect obj 82 | local model = cycloneModel() 83 | --model.addLod objs 84 | ) 85 | ), 86 | settingsRollout = 87 | ( 88 | rollout settingsRollout strings.rolloutSettingsTitle 89 | ( 90 | local owner = if owner != undefined do owner 91 | 92 | groupBox group_lod owner.strings.groupLodCaption pos:[5, 0] width:175 \ 93 | height:115 94 | radiobuttons radio_selectObject owner.strings.radioSelectCaption \ 95 | labels:owner.strings.radioSelectItems pos:[20, 20] 96 | edittext edit_modelName "" fieldWidth:145 pos:[15, 87] 97 | 98 | groupBox group_mesh owner.strings.groupMeshCaption pos:[5, 120] width:175 \ 99 | height:110 100 | dropdownlist dropdownlist_extension items:owner.strings.dropdownlistExtensionItems \ 101 | pos:[100, 140] width:50 102 | label label_texType owner.strings.labelTextureType pos:[30, 143] 103 | 104 | checkbox checkbox_exportMaterials owner.strings.checkboxExportMaterials \ 105 | checked:owner.settings.exportMaterials pos:[30, 165] 106 | checkbox checkbox_exportAnimations owner.strings.checkboxexportAnimations \ 107 | checked:owner.settings.exportAnimations pos:[30, 185] 108 | 109 | spinner spinner_frameNumber owner.strings.editFrameNumberTitle \ 110 | fieldWidth:40 type:#integer align:#right pos:[30, 205] \ 111 | range:[1, 2000, owner.settings.spinnerFrameNumber] 112 | 113 | ) 114 | ), 115 | exportRollout = 116 | ( 117 | rollout exportRollout strings.rolloutExportTitle 118 | ( 119 | local owner = if owner != undefined do owner 120 | 121 | button button_exportModel owner.strings.buttonExportCaption width:120 122 | on button_exportModel pressed do 123 | ( 124 | setRollout = owner.dialog.subroll_container.settingsRollout 125 | exportSettings = owner.settings 126 | 127 | exportSettings.selectionType = setRollout.dropdownlist_extension.selection 128 | exportSettings.exportAnimations = setRollout.checkbox_exportAnimations.checked 129 | exportSettings.exportMaterials = setRollout.checkbox_exportMaterials.checked 130 | exportSettings.modelName = setRollout.edit_modelName.text 131 | exportSettings.extension = setRollout.dropdownlist_extension.text 132 | 133 | owner.exportModel() 134 | ) 135 | ) 136 | ), 137 | dialog = 138 | ( 139 | rollout dialog strings.rolloutTitle 140 | ( 141 | local owner = if owner != undefined do owner 142 | 143 | subrollout subroll_container "container" height:315 width:196 pos:[2, 2] 144 | on dialog resized point do 145 | ( 146 | subroll_container.height = dialog.height 147 | ) 148 | ) 149 | ), 150 | fn close = try (destroyDialog dialog) catch(), 151 | fn init = 152 | ( 153 | if settings == undefined then 154 | settings = settingsExportUI() 155 | if strings == undefined then 156 | strings = stringsExportUI() 157 | 158 | dialog.owner = this 159 | exportRollout.owner = this 160 | settingsRollout.owner = this 161 | 162 | createDialog dialog width:200 pos:mouse.screenpos \ 163 | style:#(#style_sysmenu, #style_resizing, #style_titlebar) 164 | AddSubRollout dialog.subroll_container settingsRollout 165 | AddSubRollout dialog.subroll_container exportRollout 166 | ), 167 | on create do init() 168 | ) 169 | 170 | fn main = 171 | ( 172 | currentPath = fileUtils.getCurrentPath(getThisScriptFilename()) 173 | exportUI = cycloneExportUI() 174 | ) 175 | 176 | main() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/def_import.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: .def files (Sea Dogs 2000) import script 4 | Version: 0.1 5 | */ 6 | 7 | filein "lib/ms.ms" 8 | filein "lib/utils.ms" 9 | filein "lib/def.ms" 10 | filein "lib/def_viewer.ms" 11 | filein "lib/ini.ms" 12 | filein "lib/system.ms" 13 | filein "lib/settings.ms" 14 | 15 | struct settingsImportDef 16 | ( 17 | pathToModelsFolder = "D:\Program Files\1C\Корсары\RESOURCE\MODELS", 18 | pathToTexturesFolder = "D:\Program Files\1C\Корсары\RESOURCE\MODELS\CHARACTERS", 19 | allLods = false, 20 | allFrames = true, 21 | isTextured = true, 22 | path = "", 23 | to3dsMaxSystem = true, 24 | isClockwizeOrder = true, 25 | lod = 1, 26 | frame = 1, 27 | texFormat = "tf", 28 | addCamera = false, 29 | fn loadFromIni filename = 30 | ( 31 | local sets = iniSettings(this) 32 | sets.loadFromIniFile filename "settings" 33 | ) 34 | ) 35 | 36 | struct stringsImportDef 37 | ( 38 | rolloutTitle = "Import .def scene", 39 | rolloutImportTitle = "Import", 40 | buttonImportCaption = "Open .def file", 41 | groupModelsCaption = "Folder", 42 | buttonSetPathCaption = "Get path", 43 | buttonClearPathCaption = "Clear", 44 | rolloutSettingsTitle = "Paths", 45 | rolloutImportSettingsTitle = "Models", 46 | importDialogCaption = "Import .def file", 47 | importDialogTypes = "Sea Dogs 1 defmated scenes file (*.def)|*.def", 48 | openFolder = "Open \"Models\" folder", 49 | editChooseLodModelTitle = "LOD", 50 | groupModelCaption = "Model", 51 | groupTexturesCaption = "Textures", 52 | editChooseFrameTitle = "Frame", 53 | checkboxAllLodsCaption = "all lods", 54 | checkboxAllFramesCaption = "all frames", 55 | labelChoosePath = "Path", 56 | checkboxTexturedCaption = "add textures", 57 | buttonSetTexturePathCaption = "Get path", 58 | buttonClearTexturePathCaption = "Clear", 59 | openTexturesFolder = "Choose textures folder", 60 | dropdownlistExtensionCaption = "ext.", 61 | dropdownlistExtensionItems = #("tf", "bmp", "tga", "png"), 62 | checkboxConvertCoordSystem = "convert coordinate system", 63 | checkboxFaceOrder = "Change face order", 64 | editChooseStartFrameTitle = "Start" , 65 | groupIniCaption = "Path", 66 | buttonClearCaption = "Clear scene", 67 | rolloutClearTitle = "Clear", 68 | groupCameraCaption = "Camera", 69 | checkboxCameraCaption = "Add camera", 70 | editPathToModelsText = "Path to Models folder", 71 | fn loadFromIni filename = 72 | ( 73 | local sets = iniSettings(this) 74 | sets.loadFromIniFile filename "strings" 75 | ) 76 | ) 77 | 78 | struct defSceneImportUI 79 | ( 80 | settings, 81 | strings, 82 | iniFilename = "def.ini", 83 | fn importModel filename: = 84 | ( 85 | 86 | if filename == unsupplied then 87 | ( 88 | dialogs.caption = strings.importDialogCaption 89 | dialogs.types = strings.importDialogTypes 90 | filestream = dialogs.openFileDialog &fname "rb" 91 | filename = fname 92 | ) 93 | 94 | if filestream != undefined then 95 | ( 96 | file = defFile() 97 | file.openStream filestream filename 98 | if file.readFile() then 99 | ( 100 | sceneViewer = defSceneViewer file.scene 101 | viewerSettings = sceneViewer.settings 102 | 103 | viewerSettings.modelsFolderPath = settings.pathToModelsFolder 104 | viewerSettings.isTextured = settings.isTextured 105 | if settings.allLods then 106 | viewerSettings.lodIndex = 0 107 | else 108 | viewerSettings.lodIndex = viewerSettings.lodIndex 109 | if settings.allFrames then 110 | viewerSettings.frameIndex = 0 111 | else 112 | viewerSettings.frameIndex = viewerSettings.frameIndex 113 | viewerSettings.texturesPath = settings.path 114 | viewerSettings.texFormat = settings.texFormat 115 | viewerSettings.to3dsMaxSystem = settings.to3dsMaxSystem 116 | viewerSettings.isClockwizeOrder = settings.isClockwizeOrder 117 | viewerSettings.addCamera = settings.addCamera 118 | 119 | sceneViewer.create() 120 | ) 121 | file.closeFile() 122 | ) 123 | ), 124 | fn getPath = 125 | ( 126 | path = dialogs.openFolder strings.openFolder 127 | ), 128 | clearRollout = 129 | ( 130 | rollout clearRollout strings.rolloutClearTitle 131 | ( 132 | local owner = if owner != undefined do owner 133 | 134 | button button_removeObjects owner.strings.buttonClearCaption width:120 135 | 136 | on button_removeObjects pressed do 137 | ( 138 | print "none" 139 | ) 140 | ) 141 | ), 142 | importSettingsRollout = 143 | ( 144 | rollout importSettingsRollout strings.rolloutImportSettingsTitle 145 | ( 146 | local owner = if owner != undefined do owner 147 | groupBox group_model owner.strings.groupModelCaption \ 148 | pos:[5, 97] width:175 height:110 149 | groupBox group_textures owner.strings.groupTexturesCaption \ 150 | pos:[5, 0] width:175 height:92 151 | groupBox group_camera owner.strings.groupCameraCaption \ 152 | pos:[5, 210] width:175 height:45 153 | 154 | checkbox checkbox_addCamera owner.strings.checkboxCameraCaption \ 155 | checked:owner.settings.addCamera pos:[25, 230] 156 | 157 | checkbox checkbox_convertCoord owner.strings.checkboxconvertCoordSystem \ 158 | checked:owner.settings.to3dsMaxSystem pos:[25, 115] 159 | checkbox checkbox_faceOrder owner.strings.checkboxFaceOrder \ 160 | checked:owner.settings.isClockwizeOrder pos:[25, 135] 161 | 162 | spinner spinner_lod owner.strings.editChooseLodModelTitle \ 163 | fieldWidth:40 type:#integer align:#right pos:[25, 160] \ 164 | range:[1, 10, owner.settings.lod] 165 | spinner spinner_frame owner.strings.editChooseFrameTitle \ 166 | fieldWidth:40 type:#integer align:#right pos:[15, 180] \ 167 | range:[1, 2000, owner.settings.frame] 168 | 169 | checkbox checkbox_allLods owner.strings.checkboxAllLodsCaption \ 170 | checked:owner.settings.allLods pos:[105, 160] 171 | checkbox checkbox_allFrames owner.strings.checkboxAllFramesCaption \ 172 | checked:owner.settings.allFrames pos:[105, 180] 173 | 174 | edittext edit_texPath "" \ 175 | fieldWidth:155 pos:[10, 40] readOnly:true text:owner.settings.pathToTexturesFolder 176 | 177 | button button_getTexturePath owner.strings.buttonSetTexturePathCaption \ 178 | width:75 pos:[15, 62] 179 | button button_clearTexturePath owner.strings.buttonClearTexturePathCaption \ 180 | width:75 pos:[95, 62] 181 | checkbox checkbox_isTextured owner.strings.checkboxTexturedCaption \ 182 | checked:owner.settings.isTextured pos:[15, 20] 183 | 184 | dropdownlist dropdownlist_extension items:owner.strings.dropdownlistExtensionItems \ 185 | pos:[120, 15] width:50 186 | 187 | on button_getTexturePath pressed do 188 | ( 189 | pathToTexFolders = owner.getPath() 190 | if pathToTexFolders != undefined then edit_texPath.text = pathToTexFolders 191 | ) 192 | on button_clearTexturePath pressed do 193 | ( 194 | edit_texPath.text = "" 195 | ) 196 | ) 197 | ), 198 | settingsRollout = 199 | ( 200 | rollout settingsRollout strings.rolloutSettingsTitle 201 | ( 202 | local owner = if owner != undefined do owner 203 | 204 | --groupBox group_model owner.strings.groupModelsCaption \ 205 | --pos:[5, 0] width:175 height:90 206 | edittext edit_modelsPath owner.strings.editPathToModelsText fieldWidth:154 \ 207 | pos:[15, 5] readOnly:true labelOnTop:true text:owner.settings.pathToModelsFolder 208 | 209 | button button_setModelsPath owner.strings.buttonSetPathCaption \ 210 | width:75 pos:[15, 45] 211 | button button_clearModelsPath owner.strings.buttonClearPathCaption \ 212 | width:75 pos:[95, 45] 213 | 214 | on button_setModelsPath pressed do 215 | ( 216 | pathToModFolders = owner.getPath() 217 | if pathToModFolders != undefined then edit_modelsPath.text = pathToModFolders 218 | ) 219 | on button_clearModelsPath pressed do 220 | ( 221 | edit_modelsPath.text = "" 222 | ) 223 | ) 224 | ), 225 | importRollout = 226 | ( 227 | rollout importRollout strings.rolloutImportTitle 228 | ( 229 | local owner = if owner != undefined do owner 230 | 231 | button button_importDefScene owner.strings.buttonImportCaption width:120 232 | 233 | on button_importDefScene pressed do 234 | ( 235 | setRollout = owner.dialog.subroll_container.importSettingsRollout 236 | importSetRollout = owner.dialog.subroll_container.settingsRollout 237 | importSettings = owner.settings 238 | 239 | importSettings.pathToModelsFolder = importSetRollout.edit_modelsPath.text 240 | importSettings.isTextured = setRollout.checkbox_isTextured.checked 241 | importSettings.allLods = setRollout.checkbox_allLods.checked 242 | importSettings.allFrames = setRollout.checkbox_allFrames.checked 243 | importSettings.lod = setRollout.spinner_lod.value 244 | importSettings.frame = setRollout.spinner_frame.value 245 | importSettings.path = setRollout.edit_texPath.text 246 | importSettings.texFormat = setRollout.dropdownlist_extension.text 247 | importSettings.to3dsMaxSystem = setRollout.checkbox_convertCoord.checked 248 | importSettings.isClockwizeOrder = setRollout.checkbox_faceOrder.checked 249 | importSettings.addCamera = setRollout.checkbox_addCamera.checked 250 | 251 | owner.importModel() 252 | ) 253 | ) 254 | ), 255 | dialog = 256 | ( 257 | rollout dialog strings.rolloutTitle 258 | ( 259 | local owner = if owner != undefined do owner 260 | 261 | subrollout subroll_container "container" height:410 width:196 pos:[2, 2] 262 | on dialog resized point do 263 | ( 264 | subroll_container.height = dialog.height 265 | ) 266 | ) 267 | ), 268 | fn close = try (destroyDialog dialog) catch(), 269 | fn show = 270 | ( 271 | if settings == undefined then 272 | ( 273 | settings = settingsImportDef() 274 | settings.loadFromIni (sys.currentPath + iniFilename) 275 | ) 276 | 277 | if strings == undefined then 278 | ( 279 | strings = stringsImportDef() 280 | strings.loadFromIni (sys.currentPath + iniFilename) 281 | ) 282 | 283 | createDialog dialog width:200 pos:mouse.screenpos \ 284 | style:#(#style_sysmenu, #style_resizing, #style_titlebar) 285 | AddSubRollout dialog.subroll_container settingsRollout 286 | AddSubRollout dialog.subroll_container importSettingsRollout rolledUp:true 287 | AddSubRollout dialog.subroll_container clearRollout rolledUp:true 288 | AddSubRollout dialog.subroll_container importRollout 289 | ), 290 | fn init = 291 | ( 292 | dialog.owner = this 293 | importRollout.owner = this 294 | settingsRollout.owner = this 295 | importSettingsRollout.owner = this 296 | clearRollout.owner = this 297 | ), 298 | on create do init() 299 | ) 300 | 301 | fn main = 302 | ( 303 | sys.currentPath = fileUtils.getCurrentPath(getThisScriptFilename()) 304 | defSceneImport = defSceneImportUI() 305 | defSceneImport.show() 306 | ) 307 | 308 | main() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/export.ini: -------------------------------------------------------------------------------- 1 | [SETTINGS] 2 | exportMaterials=true 3 | exportAnimations=true 4 | extension= 5 | selectionType=1 6 | modelName= 7 | 8 | [STRINGS] 9 | buttonExportCaption=Export model 10 | rolloutExportTitle=Export .clf model 11 | rolloutTitle=Export 12 | rolloutSettingsTitle=Settings 13 | groupLodCaption=LOD 14 | radioSelectItems=by selection,by group,by prefix 15 | radioSelectCaption=Select objects 16 | groupMeshCaption=Mesh 17 | dropdownlistExtensionItems=,bmp,tga,png,tf 18 | labelTextureType=Texture type 19 | checkboxExportMaterials=Export materials 20 | checkboxexportAnimations=Export animations -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/import.toml: -------------------------------------------------------------------------------- 1 | [clf_cff_import] 2 | 3 | filename = "cff_clf_import.ms" 4 | folder = "build" 5 | 6 | files = [ 7 | "lib/ms.ms", 8 | "lib/utils.ms", 9 | "lib/dialogs.ms", 10 | "lib/ini.ms", 11 | "lib/settings.ms", 12 | "lib/max.ms", 13 | "lib/stream.ms", 14 | "lib/cyclone_model.ms", 15 | "lib/cyclone.ms", 16 | "lib/cyclone_viewer.ms" 17 | ] -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/join_ani_import_files.bat: -------------------------------------------------------------------------------- 1 | python3 join_maxscript_files.py ani_import.toml -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/join_import_files.bat: -------------------------------------------------------------------------------- 1 | python3 join_maxscript_files.py import.toml -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/join_maxscript_files.py: -------------------------------------------------------------------------------- 1 | import toml 2 | import sys 3 | 4 | 5 | class MaxscriptJoiner: 6 | def __init__(self, build_filename): 7 | self.toml_filename = build_filename 8 | self.output_filename = "" 9 | self.files = [] 10 | 11 | def get_file_data(self, filename): 12 | try: 13 | with open("{}\\{}".format(sys.path[0], filename), "r") as ms_file: 14 | file_data = "" 15 | comments = "" 16 | comments_is_on = True 17 | comments_end = False 18 | for line in ms_file: 19 | if not comments_end and line.find('/*') != -1: 20 | comments_is_on = True 21 | 22 | if line.find('filein') == -1 and not comments_is_on: 23 | file_data += line 24 | elif comments_is_on: 25 | comments += line 26 | 27 | if line.find('*/') != -1: 28 | comments_is_on = False 29 | comments_end = True 30 | except: 31 | return None 32 | 33 | return file_data 34 | 35 | def join_maxscript_files(self): 36 | main_ms_file = self.get_file_data(self.filename) 37 | 38 | if main_ms_file == None: 39 | raise Exception("Can't read file {}.".format(self.filename)) 40 | 41 | included_ms_files = "" 42 | for file in self.files: 43 | included_ms_files += "-- {}\n".format(file) 44 | included_ms_files += self.get_file_data(file) 45 | included_ms_files += "\n\n" 46 | 47 | ms_file = included_ms_files + main_ms_file 48 | 49 | try: 50 | with open("{}\\{}\\{}".format(sys.path[0], self.build_folder, self.filename), "w") as file: 51 | file.writelines(ms_file) 52 | except: 53 | raise Exception("Can't create output file {}.".format(self.filename)) 54 | 55 | return 1 56 | 57 | def parse_toml_file(self, toml_filename): 58 | try: 59 | build_file = open(toml_filename, "r").read() 60 | build_config = toml.loads(build_file) 61 | except: 62 | raise Exception('Error parsing file {}'.format(toml_filename)) 63 | 64 | for section, params in build_config.items(): 65 | self.filename = params.get("filename") 66 | self.files = params.get("files") 67 | self.build_folder = params.get("folder") 68 | if not self.build_folder or not self.filename or not self.files: 69 | raise Exception('Error parsing section {}'.format(toml_filename)) 70 | 71 | def join_files(self): 72 | self.parse_toml_file(self.toml_filename) 73 | self.join_maxscript_files() 74 | 75 | 76 | if __name__ == "__main__": 77 | if sys.argv: 78 | msj = MaxscriptJoiner(sys.argv[1]) 79 | msj.join_files() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/an.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "dialogs.ms" 6 | filein "stream.ms" 7 | filein "an_model.ms" 8 | 9 | struct aniStrings 10 | ( 11 | types = "Storm 2 (*.an)|*.an", 12 | openFileCaption = "Open .an file" 13 | ) 14 | 15 | struct anFile 16 | ( 17 | strings = aniStrings(), 18 | fstream, 19 | filename, 20 | freader, 21 | object = anObject(), 22 | fn readHeader = 23 | ( 24 | object.header.frameCount = ReadLong fstream #unsigned 25 | object.header.boneCount = ReadLong fstream #unsigned 26 | object.header.speed = ReadFloat fstream 27 | ), 28 | fn readSkeleton = 29 | ( 30 | for i = 1 to object.header.boneCount do 31 | ( 32 | bne = anBone() 33 | bne.parentId = ReadLong fstream #unsigned 34 | append object.anBones bne 35 | ) 36 | 37 | for i = 1 to object.header.boneCount do 38 | ( 39 | object.anBones[i].position = freader.readVector3F() 40 | ) 41 | ), 42 | fn readAnimations = 43 | ( 44 | -- read root bone positions 45 | for i = 1 to object.header.frameCount do 46 | append object.animations.positions (freader.readVector3F()) 47 | 48 | -- read bones rotations 49 | for i = 1 to object.header.boneCount do 50 | ( 51 | boneRotations = #() 52 | for i = 1 to object.header.frameCount do 53 | append boneRotations (freader.readQuatValues()) 54 | append object.animations.boneRotations (boneRotations) 55 | ) 56 | ), 57 | fn readFile = 58 | ( 59 | readHeader() 60 | readSkeleton() 61 | readAnimations() 62 | result = True 63 | ), 64 | fn closeFile = 65 | ( 66 | fclose fstream 67 | ), 68 | fn openStream fstream filename = 69 | ( 70 | this.fstream = fstream 71 | this.filename = filename 72 | freader = streamReader(fstream) 73 | ), 74 | fn openFile mode:"rb" = 75 | ( 76 | result = False 77 | 78 | dialogs.types = strings.types 79 | dialogs.caption = strings.openFileCaption 80 | 81 | local fname = filename 82 | fstream = dialogs.openFileDialog &fname mode 83 | if fstream != undefined then 84 | ( 85 | filename = fname 86 | freader = streamReader(fstream) 87 | result = true 88 | ) 89 | ) 90 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/an_model.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | 6 | struct anHeader 7 | ( 8 | frameCount = 0, 9 | boneCount = 0, 10 | speed = 0 11 | ) 12 | 13 | struct anBone 14 | ( 15 | position = (point3 0 0 0), 16 | parentId = 0 17 | ) 18 | 19 | struct anAnimations 20 | ( 21 | positions = #(), 22 | boneRotations = #() 23 | ) 24 | 25 | struct anObject 26 | ( 27 | header = anHeader(), 28 | anBones = #(), 29 | animations = anAnimations() 30 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/an_viewer.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "lib/max.ms" 6 | 7 | struct anViewerSettings 8 | ( 9 | startFrame = 1, 10 | endFrame = 0, 11 | showSkeleton = true, 12 | addAnimations = false 13 | ) 14 | 15 | struct anViewer 16 | ( 17 | object, 18 | settings = anViewerSettings(), 19 | -- transform bone coordinates to 3dsmax ones 20 | fn transformCoordinates pos = 21 | ( 22 | result = (point3 pos.x pos.y pos.z) 23 | ), 24 | fn create = 25 | ( 26 | with undo off, redraw off 27 | ( 28 | if settings.showSkeleton then 29 | ( 30 | skeletoneBones = #() 31 | rootBone = bone pos:(transformCoordinates object.anBones[1].position) name:"Root Bone" 32 | append skeletoneBones rootBone 33 | 34 | for i = 2 to object.anBones.count do 35 | ( 36 | bne = object.anBones[i] 37 | parentBone = skeletoneBones[bne.parentId + 1] 38 | in parentBone skelBone = \ 39 | bone pos:(parentBone.position + (transformCoordinates bne.position)) 40 | append skeletoneBones skelBone 41 | ) 42 | ) 43 | 44 | if settings.addAnimations then 45 | ( 46 | progressStart "creating animations" 47 | progress = (100.0/object.header.boneCount as float) 48 | 49 | max.animation.setLength object.header.frameCount 50 | for boneIndex = 1 to object.header.boneCount do 51 | ( 52 | boneRotations = object.animations.boneRotations[boneIndex] 53 | for i = 1 to object.header.frameCount do 54 | ( 55 | rootBonePosition = object.animations.positions[i] 56 | boneRotation = boneRotations[i] 57 | 58 | bne = skeletoneBones[boneIndex] 59 | max.controller.addKey bne.position.controller i 60 | max.controller.addKey bne.rotation.controller i 61 | animate on 62 | ( 63 | at time (i - 1) bne.position.controller.value = rootBonePosition 64 | at time (i - 1) bne.rotation.controller.value = boneRotation 65 | ) 66 | ) 67 | progressUpdate (progress*boneIndex) 68 | if getProgressCancel() then 69 | ( 70 | setProgressCancel true 71 | exit 72 | ) 73 | ) 74 | 75 | progressEnd() 76 | ) 77 | ) 78 | ) 79 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/ani.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "dialogs.ms" 6 | filein "stream.ms" 7 | filein "ani_model.ms" 8 | 9 | struct aniStrings 10 | ( 11 | types = "Sea Dogs 1 animated scene (*.ani)|*.ani", 12 | openFileCaption = "Open .ani file" 13 | ) 14 | 15 | struct aniFile 16 | ( 17 | strings = aniStrings(), 18 | scene = aniScene(), 19 | fstream, 20 | filename, 21 | freader, 22 | fn readHeader = 23 | ( 24 | fseek fstream 4 #seek_cur 25 | scene.header.objectCount = ReadLong fstream #unsigned 26 | fseek fstream 4 #seek_cur 27 | scene.header.frameCount = ReadLong fstream #unsigned 28 | ), 29 | fn readObjects = 30 | ( 31 | for i = 1 to scene.header.objectCount do 32 | ( 33 | local type = ReadLong fstream #unsigned 34 | local frame = ReadLong fstream #unsigned 35 | local size = ReadLong fstream #unsigned 36 | if type == 0 then 37 | ( 38 | sceneObject = aniSceneObject() 39 | sceneObject.frame = frame 40 | sceneObject.name = freader.ReadChars size 41 | append scene.objects sceneObject 42 | ) 43 | else 44 | fseek fstream size #seek_cur 45 | ) 46 | ), 47 | fn readAnimations = 48 | ( 49 | for i = 1 to scene.header.frameCount do 50 | ( 51 | frame = aniAnimationFrame() 52 | 53 | frame.position = freader.readVector3F() 54 | frame.rotation = freader.readVector3F() 55 | frame.time = ReadFloat fstream 56 | 57 | append scene.animations frame 58 | ) 59 | ), 60 | fn readFile = 61 | ( 62 | readHeader() 63 | readObjects() 64 | readAnimations() 65 | result = True 66 | ), 67 | fn closeFile = 68 | ( 69 | fclose fstream 70 | ), 71 | fn openStream fstream filename = 72 | ( 73 | this.fstream = fstream 74 | this.filename = filename 75 | freader = streamReader(fstream) 76 | ), 77 | fn openFile mode:"rb" = 78 | ( 79 | result = False 80 | 81 | dialogs.types = strings.types 82 | dialogs.caption = strings.openFileCaption 83 | 84 | local fname = filename 85 | fstream = dialogs.openFileDialog &fname mode 86 | if fstream != undefined then 87 | ( 88 | filename = fname 89 | freader = formatReader(fstream) 90 | result = True 91 | ) 92 | ) 93 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/ani_model.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct aniSceneHeader 6 | ( 7 | objectCount = 0, 8 | frameCount = 0 9 | ) 10 | 11 | struct aniSceneObject 12 | ( 13 | type = 0, 14 | frame = 0, 15 | name = 0 16 | ) 17 | 18 | struct aniAnimationFrame 19 | ( 20 | position = (point3 0 0 0), 21 | rotation = (point4 0 0 0 0), 22 | time = 0 23 | ) 24 | 25 | struct aniScene 26 | ( 27 | header = aniSceneHeader(), 28 | objects = #(), 29 | animations = #() 30 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/ani_viewer.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "lib/max.ms" 6 | filein "lib/cyclone.ms" 7 | filein "lib/cyclone_viewer.ms" 8 | 9 | struct aniViewerSettings 10 | ( 11 | showAnimations = True, 12 | modelsFolderPath = "", 13 | texturesPath = "", 14 | isTextured = True, 15 | texFormat = "tf", 16 | lodIndex = 1, 17 | frameIndex = 0, 18 | to3dsMaxSystem = True, 19 | isClockwizeOrder = True, 20 | startFrame = 0, 21 | addCamera = true 22 | ) 23 | 24 | struct aniCameraAnimationViewer 25 | ( 26 | fn create msh frame transfCoordinates:true = 27 | ( 28 | -- rads to degrees 29 | local angles = eulerAngles (frame.rotation.x * (180/pi)) \ 30 | (frame.rotation.y * (180/pi)) (frame.rotation.z * (180/pi)) 31 | 32 | local transformMatrix = matrix3 1 33 | transformMatrix.row4 = frame.position 34 | transformMatrix = preRotateY transformMatrix angles.y 35 | transformMatrix = preRotateX transformMatrix angles.x 36 | transformMatrix = preRotateZ transformMatrix angles.z 37 | 38 | if transfCoordinates then 39 | ( 40 | transMatrix = (matrix3 [0, -1, 0] [-1, 0, 0] [0, 0, -1] [0, 0, 0]) 41 | transformMatrix = transformMatrix*transMatrix 42 | ) 43 | 44 | max.controller.addKey msh.position.controller frame.time 45 | max.controller.addKey msh.rotation.controller frame.time 46 | 47 | animate on 48 | ( 49 | at time frame.time msh.position.controller.value = transformMatrix.translationpart 50 | at time frame.time msh.rotation.controller.value = transformMatrix.rotationpart 51 | ) 52 | ) 53 | ) 54 | 55 | struct aniSceneViewer 56 | ( 57 | aniScene, 58 | settings = aniViewerSettings(), 59 | camAnimationViewer = aniCameraAnimationViewer(), 60 | sceneModels = #(), 61 | fn setAnimationFrame cam frame = 62 | ( 63 | camAnimationViewer.create cam frame transfCoordinates:settings.isClockwizeOrder 64 | ), 65 | fn loadModel modelName = 66 | ( 67 | result = undefined 68 | 69 | modelsFilePath = settings.modelsFolderPath + "/" + modelName 70 | charactersFilePath = settings.modelsFolderPath + "/CHARACTERS/" + modelName 71 | 72 | file = cffFile() 73 | file.filename = modelsFilePath 74 | fstream = file.openFile() 75 | if fstream == undefined then 76 | ( 77 | file.filename = charactersFilePath 78 | fstream = file.openFile() 79 | ) 80 | 81 | if fstream != undefined then 82 | ( 83 | if file.readFile() then 84 | result = file.model 85 | file.closeFile() 86 | ) 87 | 88 | result 89 | ), 90 | fn create = 91 | ( 92 | -- add models 93 | for sceneObject in aniScene.objects do 94 | ( 95 | model = loadModel sceneObject.name 96 | 97 | if model != undefined then 98 | ( 99 | viewer = modelViewer model 100 | 101 | viewer.settings.isTextured = settings.isTextured 102 | viewer.settings.texturesPath = settings.texturesPath 103 | viewer.settings.texFormat = settings.texFormat 104 | viewer.settings.lodIndex = settings.lodIndex 105 | viewer.settings.frameIndex = settings.frameIndex 106 | viewer.settings.to3dsMaxSystem = settings.to3dsMaxSystem 107 | viewer.settings.isClockwizeOrder = settings.isClockwizeOrder 108 | viewer.settings.startFrame = sceneObject.frame 109 | 110 | viewer.createScene redraw:false 111 | ) 112 | ) 113 | 114 | -- add camera 115 | if settings.addCamera then 116 | ( 117 | sceneCamera = max.objects.addCamera name:"Scene camera" 118 | sceneCamera.clipManually = true 119 | sceneCamera.nearclip = 0.004 120 | sceneCamera.farclip = 500 121 | sceneCamera.fov = 65.47 122 | 123 | -- animate camera 124 | if aniScene.header.frameCount > 0 then 125 | ( 126 | if aniScene.header.frameCount > animationRange.end then 127 | max.animation.setLength aniScene.header.frameCount 128 | for frame in aniScene.animations do 129 | setAnimationFrame sceneCamera frame 130 | ) 131 | ) 132 | 133 | 134 | redrawViews() 135 | ) 136 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/cyclone.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "dialogs.ms" 6 | filein "stream.ms" 7 | filein "utils.ms" 8 | filein "cyclone_model.ms" 9 | 10 | struct cffStrings 11 | ( 12 | types = "Cyclone final format (*.cff)|*.cff", 13 | openFileCaption = "Open file", 14 | saveFileCaption = "", 15 | progressString = "Reading LOD model meshes" 16 | ) 17 | 18 | struct clfStrings 19 | ( 20 | types = "Cyclone final format (*.clf)|*.clf", 21 | openFileCaption = "Open file", 22 | saveFileCaption = "", 23 | progressString = "Reading LOD model meshes" 24 | ) 25 | 26 | struct clfFile 27 | ( 28 | strings = clfStrings(), 29 | model = cycloneModel(), 30 | fstream, 31 | filename, 32 | freader, 33 | fn readHeader = 34 | ( 35 | fseek fstream 16 #seek_cur 36 | model.header.lodCount = ReadLong fstream #unsigned 37 | model.header.textureCount = ReadLong fstream #unsigned 38 | fseek fstream 4 #seek_cur 39 | model.header.meshCount = ReadLong fstream #unsigned 40 | fseek fstream 4 #seek_cur 41 | model.header.frameCount = ReadLong fstream #unsigned 42 | fseek fstream 8 #seek_cur 43 | ), 44 | fn readTextureList = 45 | ( 46 | for i = 1 to model.header.textureCount do 47 | ( 48 | textureName = cycloneTextureName() 49 | textureName.name = freader.ReadChars 256 50 | append model.textureList textureName 51 | ) 52 | ), 53 | fn readMesh = 54 | ( 55 | msh = cycloneModelLodMesh() 56 | 57 | -- read header 58 | msh.header.name = freader.ReadChars 32 59 | msh.header.frameCount = ReadLong fstream #unsigned 60 | msh.header.textureIndex = ReadLong fstream #unsigned 61 | msh.header.vertexCount = ReadLong fstream #unsigned 62 | msh.header.faceCount = ReadLong fstream #unsigned 63 | fseek fstream 96 #seek_cur 64 | 65 | 66 | -- read vertexes 67 | for i = 1 to msh.header.vertexCount do 68 | ( 69 | vert = cycloneModelLodMeshVertex() 70 | 71 | vert.coordinates = freader.readVector3F() 72 | fseek fstream 16 #seek_cur 73 | 74 | append msh.vertexes vert 75 | ) 76 | 77 | -- read faces 78 | for i = 1 to msh.header.faceCount do 79 | ( 80 | face = cycloneModelLodMeshFace() 81 | 82 | face.indexes = freader.readVector3UI16() 83 | fseek fstream 2 #seek_cur 84 | 85 | msh.vertexes[face.indexes[1] + 1].uv = freader.readVector2F() 86 | msh.vertexes[face.indexes[2] + 1].uv = freader.readVector2F() 87 | msh.vertexes[face.indexes[3] + 1].uv = freader.readVector2F() 88 | 89 | append msh.faces face 90 | ) 91 | 92 | -- read animations 93 | for i = 1 to msh.header.frameCount do 94 | ( 95 | frame = cycloneModelLodAnimationFrame() 96 | 97 | frame.position = freader.readVector3F() 98 | frame.rotation = freader.readVector3F() 99 | frame.time = ReadFloat fstream 100 | 101 | append msh.animationFrames frame 102 | ) 103 | 104 | result = msh 105 | ), 106 | fn readLods = 107 | ( 108 | modelLod = cycloneModelLod() 109 | 110 | for k = 1 to model.header.lodCount do 111 | ( 112 | progressStart strings.progressString 113 | progress = (100.0/model.header.meshCount as float) 114 | 115 | for i = 1 to model.header.meshCount do 116 | ( 117 | msh = readMesh() 118 | append modelLod.meshes msh 119 | 120 | progressUpdate (progress*i) 121 | 122 | if getProgressCancel() then 123 | ( 124 | setProgressCancel true 125 | exit 126 | ) 127 | ) 128 | 129 | progressEnd() 130 | ) 131 | 132 | append model.modelLods modelLod 133 | ), 134 | fn readFile = 135 | ( 136 | --try 137 | --( 138 | readHeader() 139 | readTextureList() 140 | readLods() 141 | 142 | model.name = fileUtils.getFileName filename 143 | 144 | result = true 145 | --) 146 | --catch 147 | --( 148 | --dialogs.showMessage (formattedprint filename --format:strings.errorReadFile) 149 | --result = false 150 | --) 151 | ), 152 | fn writeHeader = 153 | ( 154 | WriteLong fstream 269554195 155 | WriteLong fstream 2626104 156 | WriteLong fstream 0 157 | WriteLong fstream 0 158 | WriteLong fstream model.header.lodCount #unsigned 159 | WriteLong fstream model.header.textureCount #unsigned 160 | WriteLong fstream 0 161 | WriteLong fstream model.header.meshCount #unsigned 162 | WriteLong fstream 0 163 | WriteLong fstream model.header.frameCount #unsigned 164 | WriteLong fstream 0 165 | WriteLong fstream 0 166 | ), 167 | fn writeTextureList = 168 | ( 169 | for textureFilename in model.textureList do 170 | fwriter.writeString str:msh.header.name length:256 171 | ), 172 | fn writeMesh msh = 173 | ( 174 | -- header 175 | fwriter.writeString msh.header.name length:32 176 | WriteLong fstream msh.header.frameCount #unsigned 177 | WriteLong fstream msh.header.textureIndex #unsigned 178 | WriteLong fstream msh.header.vertexCount #unsigned 179 | WriteLong fstream msh.header.faceCount #unsigned 180 | 181 | -- vertexes 182 | for vert in msh.vertexes do 183 | ( 184 | fwriter.writeVector3F vert.coordinates sign:#unsigned 185 | fwriter.writeVector3F [0, 0, 0] 186 | WriteLong fstream 0 187 | ) 188 | 189 | -- faces 190 | for face in msh.faces do 191 | ( 192 | fwriter.writeVector3UI16 face.indexes 193 | WriteShort fstream 0 194 | fwriter.writeVector2F face.uv1 195 | fwriter.writeVector2F face.uv2 196 | fwriter.writeVector2F face.uv3 197 | ) 198 | 199 | -- animations 200 | for frame in msh.animationFrames do 201 | ( 202 | freader.writeVector3F frame.position 203 | freader.writeVector3F frame.rotation 204 | WriteFloat fstream frame.time 205 | ) 206 | ), 207 | fn writeLods = 208 | ( 209 | for lod in model.modelLods do 210 | for msh in lod do 211 | writeMesh msh 212 | ), 213 | fn writeFile = 214 | ( 215 | writeHeader () 216 | writeTextureList() 217 | writeLods() 218 | ), 219 | fn closeFile = 220 | ( 221 | fclose fstream 222 | ), 223 | fn openStream fstream filename mode:"rb" = 224 | ( 225 | this.fstream = fstream 226 | this.filename = filename 227 | if mode == "rb" then 228 | freader = streamReader(fstream) 229 | else 230 | fwriter = streamWriter(fstream) 231 | ), 232 | fn openFile mode = 233 | ( 234 | dialogs.types = strings.types 235 | if mode == "rb" then 236 | dialogs.caption = strings.openFileCaption 237 | else 238 | dialogs.caption = strings.saveFileCaption 239 | local fname = filename 240 | fstream = dialogs.openFileDialog &fname mode 241 | if fstream != undefined then 242 | ( 243 | filename = fname 244 | freader = rseFormatReader(fstream) 245 | fwriter = rseFormatWriter(fstream) 246 | ) 247 | result = fstream 248 | ) 249 | ) 250 | 251 | -- .cff format 252 | 253 | struct cffFile 254 | ( 255 | strings = cffStrings(), 256 | model = cycloneModel(), 257 | fstream, 258 | filename, 259 | freader, 260 | fn readHeader = 261 | ( 262 | model.header.origin = freader.readVector3F() 263 | model.header.scale = freader.readVector3F() 264 | model.header.textureCount = ReadLong fstream #unsigned 265 | model.header.materialCount = ReadLong fstream #unsigned 266 | model.header.lodCount = ReadLong fstream #unsigned 267 | --model.header.bspSectionOffset = ReadLong fstream 268 | fseek fstream 4 #seek_cur 269 | model.header.occlusionRadius = ReadFloat fstream 270 | ), 271 | fn readTextureList = 272 | ( 273 | for i = 1 to model.header.textureCount do 274 | ( 275 | textureName = cycloneTextureName() 276 | textureName.length = ReadByte fstream #unsigned 277 | textureName.name = freader.ReadChars textureName.length 278 | append model.textureList textureName 279 | ) 280 | ), 281 | fn readMaterials = 282 | ( 283 | for i = 1 to model.header.materialCount do 284 | ( 285 | --material = cycloneMaterial() 286 | fseek fstream 36 #seek_cur 287 | skip = (ReadLong fstream)*20 288 | fseek fstream skip #seek_cur 289 | --append model.textureList textureName 290 | ) 291 | ), 292 | fn readMesh = 293 | ( 294 | msh = cycloneModelLodMesh() 295 | 296 | -- read header 297 | msh.header.origin = freader.readVector3F() 298 | msh.header.uvDelim = ReadFloat fstream 299 | msh.header.occlusionRadius = ReadFloat fstream 300 | msh.header.textureIndex = ReadLong fstream #unsigned 301 | msh.header.vertexCount = ReadLong fstream #unsigned 302 | msh.header.faceCount = ReadLong fstream #unsigned 303 | msh.header.unknown = ReadLong fstream #unsigned 304 | msh.header.frameCount = ReadLong fstream #unsigned 305 | msh.header.name = freader.ReadChars 4 306 | 307 | -- read vertexes 308 | for i = 1 to msh.header.vertexCount do 309 | ( 310 | vert = cycloneModelLodMeshVertex() 311 | 312 | vert.coordinates = freader.readVector3UI16 sign:#signed 313 | uv = freader.readVector2UI16 sign:#signed 314 | vert.uv.x = uv.x 315 | vert.uv.y = uv.y 316 | vert.color = freader.readVector3B() 317 | 318 | append msh.vertexes vert 319 | ) 320 | 321 | -- read faces 322 | for i = 1 to msh.header.faceCount do 323 | ( 324 | face = cycloneModelLodMeshFace() 325 | 326 | if msh.header.vertexCount <= 256 then 327 | face.indexes = freader.readVector3B() 328 | else 329 | face.indexes = freader.readVector3UI16() 330 | 331 | append msh.faces face 332 | ) 333 | 334 | -- read animations 335 | for i = 1 to msh.header.frameCount do 336 | ( 337 | frame = cycloneModelLodAnimationFrame() 338 | 339 | frame.position = freader.readVector3F() 340 | frame.rotation = freader.readVector3F() 341 | frame.time = ReadFloat fstream 342 | 343 | append msh.animationFrames frame 344 | ) 345 | 346 | result = msh 347 | ), 348 | fn readLods = 349 | ( 350 | for k = 1 to model.header.lodCount do 351 | ( 352 | modelLod = cycloneModelLod() 353 | 354 | meshCount = ReadLong fstream #unsigned 355 | fseek fstream 4 #seek_cur 356 | 357 | model.header.meshCount = meshCount 358 | 359 | progressStart strings.progressString 360 | progress = (100.0/meshCount as float) 361 | 362 | for i = 1 to meshCount do 363 | ( 364 | msh = readMesh() 365 | append modelLod.meshes msh 366 | 367 | progressUpdate (progress*i) 368 | 369 | if getProgressCancel() then 370 | ( 371 | setProgressCancel true 372 | exit 373 | ) 374 | ) 375 | 376 | progressEnd() 377 | 378 | append model.modelLods modelLod 379 | ) 380 | ), 381 | fn readFile = 382 | ( 383 | --try 384 | --( 385 | readHeader() 386 | readTextureList() 387 | readMaterials() 388 | readLods() 389 | 390 | model.name = fileUtils.getFileName filename 391 | 392 | result = true 393 | --) 394 | --catch 395 | --( 396 | --dialogs.showMessage (formattedprint filename --format:strings.errorReadFile) 397 | --result = false 398 | --) 399 | ), 400 | fn closeFile = 401 | ( 402 | fclose fstream 403 | ), 404 | fn openStream fstream filename mode:"rb" = 405 | ( 406 | this.fstream = fstream 407 | this.filename = filename 408 | if mode == "rb" then 409 | freader = streamReader(fstream) 410 | else 411 | fwriter = streamWriter(fstream) 412 | ), 413 | fn openFile = 414 | ( 415 | dialogs.types = strings.types 416 | dialogs.caption = strings.openFileCaption 417 | 418 | local fname = filename 419 | fstream = dialogs.openFileDialog &fname "rb" 420 | 421 | if fstream != undefined then 422 | ( 423 | freader = streamReader(fstream) 424 | result = fstream 425 | ) 426 | ) 427 | ) 428 | -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/cyclone_model.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "lib/max.ms" 6 | 7 | struct cyclonModelHeader 8 | ( 9 | origin = (point3 0 0 0), 10 | scale = (point3 0 0 0), 11 | textureCount = 0, 12 | materialCount = 0, 13 | meshCount = 0, 14 | frameCount = 0, 15 | lodCount = 0, 16 | occlusionRadius = 0 17 | ) 18 | 19 | struct cycloneTextureName 20 | ( 21 | length = 0, 22 | name = "" 23 | ) 24 | 25 | struct cycloneMaterialUnknown 26 | ( 27 | Unknown1 = 0, 28 | Unknown2 = 0, 29 | Unknown3 = 0, 30 | Unknown4 = 0, 31 | Unknown5 = 0 32 | ) 33 | 34 | struct cycloneMaterial 35 | ( 36 | Unknown1 = 0, 37 | Unknown2 = 0, 38 | Unknown3 = 0, 39 | Unknown4 = 0, 40 | Unknown5 = 0, 41 | Unknown6 = 0, 42 | Unknown7 = 0, 43 | Unknown8 = 0, 44 | Unknown9 = #() 45 | ) 46 | 47 | struct cycloneModelLodVertex 48 | ( 49 | origin = (point3 0 0 0) 50 | ) 51 | 52 | struct cycloneModelLodHeader 53 | ( 54 | origin = (point3 0 0 0), 55 | uvDelim = 0, 56 | occlusionRadius = 0, 57 | textureIndex = 0, 58 | vertexCount = 0, 59 | faceCount = 0, 60 | unknown = 0, 61 | frameCount = 0, 62 | name = 0 63 | ) 64 | 65 | struct cycloneModelLodMeshVertex 66 | ( 67 | coordinates = (point3 0 0 0), 68 | uv = (point3 0 0 0), 69 | color = (point3 0 0 0) 70 | ) 71 | 72 | struct cycloneModelLodMeshFace 73 | ( 74 | indexes = (point3 0 0 0) 75 | ) 76 | 77 | struct cycloneModelLodAnimationFrame 78 | ( 79 | position = (point3 0 0 0), 80 | rotation = (point3 0 0 0), 81 | time = 0 82 | ) 83 | 84 | struct cycloneModelLodMesh 85 | ( 86 | header = cycloneModelLodHeader(), 87 | vertexes = #(), 88 | faces = #(), 89 | animationFrames = #() 90 | ) 91 | 92 | struct cycloneModelLod 93 | ( 94 | meshes = #() 95 | ) 96 | 97 | struct cycloneModel 98 | ( 99 | name = "", 100 | header = cyclonModelHeader(), 101 | textureList = #(), 102 | materials = #(), 103 | modelLods = #(), 104 | fn addLod objs = 105 | ( 106 | lod = cycloneModelLod() 107 | for obj in objs do 108 | ( 109 | lodMesh = cycloneModelLodMesh() 110 | for i = 1 to obj.numverts do 111 | ( 112 | vertex = cycloneModelLodMeshVertex() 113 | vertex.coordinates = getVert obj i 114 | append lodMesh.vertexes vertex 115 | ) 116 | 117 | for i = 1 to obj.numfaces do 118 | ( 119 | face = cycloneModelLodMeshFace() 120 | indexes = getFace obj i 121 | append lodMesh.faces (indexes - 1) 122 | ) 123 | 124 | for i = 1 to obj.position.controller.keys.count do 125 | ( 126 | frame = cycloneModelLodAnimationFrame() 127 | posKey = getKey obj.position.controller (i) 128 | rotKey = getKey obj.rotation.controller (i) 129 | frame.position = posKey.value 130 | frame.rotation = rotKey.value 131 | frame.time = i - 1 132 | append lodMesh.animationFrames frame 133 | ) 134 | 135 | append lod.meshes lodMesh 136 | ) 137 | append modelLods lod 138 | ) 139 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/cyclone_viewer.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "max.ms" 6 | filein "system.ms" 7 | filein "utils.ms" 8 | filein "math.ms" 9 | 10 | struct cycloneViewerSettings 11 | ( 12 | texturesPath = "", 13 | isTextured = True, 14 | texFormat = "tf", 15 | lodIndex = 1, 16 | frameIndex = 0, 17 | to3dsMaxSystem = True, 18 | isIntermediateFormat = False, 19 | isClockwizeOrder = True, 20 | startFrame = 0 21 | ) 22 | 23 | struct cycloneSceneViewer 24 | ( 25 | materials = #(), 26 | objects = #() 27 | ) 28 | 29 | struct cycloneMeshViewer 30 | ( 31 | isIntermediateFormat = False, 32 | isClockwiseOrder = True, 33 | fn create modelMesh materials: modelPos: modelScale: = 34 | ( 35 | local faceArray = #() 36 | local vertArray = #() 37 | 38 | for vert in modelMesh.vertexes do 39 | ( 40 | if isIntermediateFormat then 41 | append vertArray vert.coordinates 42 | else 43 | ( 44 | local x = modelPos.x + (vert.coordinates.x * modelScale.x) / 32767.0 45 | local y = modelPos.y + (vert.coordinates.y * modelScale.y) / 32767.0 46 | local z = modelPos.z + (vert.coordinates.z * modelScale.z) / 32767.0 47 | 48 | append vertArray [x, y, z] 49 | ) 50 | ) 51 | 52 | for face in modelMesh.faces do 53 | ( 54 | face.indexes.x += 1 55 | if isClockwiseOrder == False then 56 | ( 57 | face.indexes.y += 1 58 | face.indexes.z += 1 59 | ) 60 | else 61 | ( 62 | face.indexes.z += 1 63 | face.indexes.y += 1 64 | ) 65 | 66 | append faceArray face.indexes 67 | ) 68 | 69 | if materials != unsupplied then 70 | ( 71 | tvertArray = #() 72 | 73 | for vert in modelMesh.vertexes do 74 | ( 75 | if isIntermediateFormat then 76 | ( 77 | local uvX = vert.uv.x 78 | local uvY = vert.uv.y 79 | ) 80 | else 81 | ( 82 | local uvX = vert.uv.x/modelMesh.header.uvDelim 83 | local uvY = vert.uv.y/modelMesh.header.uvDelim 84 | ) 85 | 86 | append tvertArray [uvX, -uvY, 0] 87 | ) 88 | 89 | msh = max.createTexturedMesh vertArray faceArray tvertArray \ 90 | name:modelMesh.header.name 91 | 92 | max.material.addMaterialToMesh msh materials[modelMesh.header.textureIndex + 1] 93 | ) 94 | else 95 | msh = max.createMesh vertArray faceArray name:modelMesh.header.name 96 | 97 | result = msh 98 | ) 99 | ) 100 | 101 | struct cycloneAnimationViewer 102 | ( 103 | fn create msh frame startframe:0 transfCoordinates:true = 104 | ( 105 | -- rads to degrees 106 | local angles = radToEuler frame.rotation 107 | 108 | transformMatrix = rotateMatByAngles frame.rotation 109 | 110 | if transfCoordinates then 111 | ( 112 | transMatrix = (matrix3 [1, 0, 0] [0, 0, 1] [0, -1, 0] [0, 0, 0]) 113 | transformMatrix = transformMatrix*transMatrix 114 | ) 115 | 116 | max.controller.addKey msh.position.controller frame.time 117 | max.controller.addKey msh.rotation.controller frame.time 118 | 119 | animate on 120 | ( 121 | at time (frame.time + startFrame) msh.position.controller.value = transformMatrix.translationpart 122 | at time (frame.time + startFrame) msh.rotation.controller.value = transformMatrix.rotationpart 123 | ) 124 | ) 125 | ) 126 | 127 | struct modelViewer 128 | ( 129 | model, 130 | scene = cycloneSceneViewer(), 131 | settings = cycloneViewerSettings(), 132 | meshViewer = cycloneMeshViewer(), 133 | animationViewer = cycloneAnimationViewer(), 134 | fn addMaterial name = 135 | ( 136 | basename = fileUtils.getFileName name 137 | filepath = settings.texturesPath + "/" + basename + "." + settings.texFormat 138 | bitmapMaterial = max.material.createMaterialFromBitmap filepath basename 139 | 140 | if bitmapMaterial == undefined then 141 | ( 142 | standMat = max.material.createStandardMaterial true basename 143 | standMat.diffuseMap = max.material.createTextureMap name 144 | standMat.twoSided = True 145 | result = standMat 146 | ) 147 | else 148 | ( bitmapMaterial.twoSided = True 149 | result = bitmapMaterial 150 | ) 151 | ), 152 | fn addMesh modelMesh mats: = 153 | ( 154 | result = 155 | ( 156 | meshViewer.isIntermediateFormat = settings.isIntermediateFormat 157 | if mats == unsupplied then 158 | meshViewer.create modelMesh modelPos:model.header.origin \ 159 | modelScale:model.header.scale 160 | else 161 | meshViewer.create modelMesh modelPos:model.header.origin \ 162 | modelScale:model.header.scale materials:mats 163 | ) 164 | ), 165 | fn setAnimationFrame msh frame = 166 | ( 167 | animationViewer.create msh frame startFrame:settings.startFrame \ 168 | transfCoordinates:settings.to3dsMaxSystem 169 | ), 170 | fn createScene redraw:true showProgress:true position: rotation: = 171 | ( 172 | -- textures 173 | if settings.isTextured then 174 | ( 175 | max.sme.open() 176 | smeView = max.sme.createView "Materials" 177 | for i = 1 to model.header.textureCount do 178 | ( 179 | mat = addMaterial model.textureList[i].name 180 | max.sme.createNode mat smeView [0, i*100] 181 | append scene.materials mat 182 | ) 183 | max.sme.close() 184 | ) 185 | 186 | if showProgress then progressStart "creating meshes" 187 | 188 | if settings.lodIndex == 0 then 189 | ( 190 | startLodIndex = 1 191 | lodCount = model.header.lodCount 192 | ) 193 | else 194 | ( 195 | if settings.lodIndex <= model.header.lodCount then 196 | ( 197 | startLodIndex = settings.lodIndex 198 | lodCount = settings.lodIndex 199 | ) 200 | else 201 | ( 202 | startLodIndex = 1 203 | lodCount = 1 204 | ) 205 | ) 206 | 207 | -- lods 208 | with undo off 209 | for i = startLodIndex to lodCount do 210 | ( 211 | modelLod = model.modelLods[i] 212 | 213 | progress = (100.0/model.header.meshCount as float) 214 | 215 | meshIndex = 1 216 | 217 | with redraw off 218 | for modelMesh in modelLod.meshes do 219 | ( 220 | if settings.isTextured then 221 | msh = addMesh modelMesh mats:scene.materials 222 | else 223 | msh = addMesh modelMesh 224 | 225 | if showProgress then progressUpdate (progress*meshIndex) 226 | meshIndex += 1 227 | 228 | if showProgress and getProgressCancel() then 229 | ( 230 | setProgressCancel true 231 | exit 232 | ) 233 | 234 | if msh != undefined then 235 | ( 236 | if position == unsupplied and rotation == unsupplied then 237 | ( 238 | rotAngles = mathFunction.radToEuler(rotation) 239 | mat = mathFunction.rotateMatByAngles rotAngles 240 | mat.row4 = position 241 | msh.transform = msh.transform*mat 242 | ) 243 | 244 | append scene.objects msh 245 | -- mesh animations 246 | if modelMesh.header.frameCount > 0 then 247 | ( 248 | if settings.frameIndex == 0 then 249 | ( 250 | for frame in modelMesh.animationFrames do 251 | ( 252 | if frame.time > animationRange.end then 253 | max.animation.setLength frame.time 254 | setAnimationFrame msh frame 255 | ) 256 | ) 257 | else 258 | ( 259 | if settings.frameIndex <= modelMesh.header.frameCount then 260 | setAnimationFrame msh modelMesh.animationFrames[settings.frameIndex] 261 | else 262 | setAnimationFrame msh modelMesh.animationFrames[0] 263 | ) 264 | ) 265 | else 266 | ( 267 | --convert coordinates to 3dsMax ones 268 | if settings.to3dsMaxSystem then 269 | ( 270 | transMatrix = (matrix3 [-1, 0, 0] [0, 0, 1] [0, -1, 0] [0, 0, 0]) 271 | msh.transform = msh.transform*transMatrix 272 | ) 273 | ) 274 | ) 275 | ) 276 | 277 | if showProgress then progressEnd() 278 | ) 279 | 280 | -- group model meshes 281 | max.nodes.createGroup scene.objects model.name opened:true 282 | 283 | if scene.objects.count > 0 and redraw then 284 | ( 285 | select scene.objects[1] 286 | max zoomext sel 287 | redrawViews() 288 | ) 289 | ) 290 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/def.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "dialogs.ms" 6 | filein "stream.ms" 7 | filein "def_model.ms" 8 | 9 | struct defStrings 10 | ( 11 | types = "Sea Dogs 1 defmated scene (*.def)|*.def", 12 | openFileCaption = "Open .def file" 13 | ) 14 | 15 | struct defFile 16 | ( 17 | strings = defStrings(), 18 | scene = defScene(), 19 | fstream, 20 | filename, 21 | freader, 22 | fn readItem = 23 | ( 24 | dfItem = defItem() 25 | dfItem.index = ReadLong fstream #unsigned 26 | dfItem.type = ReadLong fstream #unsigned 27 | dfItem.unknown1 = ReadLong fstream #unsigned 28 | dfItem.filename = freader.ReadChars 256 29 | dfItem.position = freader.readVector3F() 30 | dfItem.rotation = freader.readVector3F() 31 | dfItem.link = ReadLong fstream #signed 32 | 33 | result = dfItem 34 | ), 35 | fn readFile = 36 | ( 37 | itemCount = ReadLong fstream #unsigned 38 | for i = 1 to itemCount do 39 | ( 40 | dfItem = readItem() 41 | -- skip everything except .cff files (3d models) 42 | if dfItem.type == 200 and \ 43 | toLower (fileUtils.getFileExtension (dfItem.filename)) == ".cff" then 44 | append scene.items dfItem 45 | ) 46 | result = True 47 | ), 48 | fn closeFile = 49 | ( 50 | fclose fstream 51 | ), 52 | fn openStream fstream filename = 53 | ( 54 | this.fstream = fstream 55 | this.filename = filename 56 | freader = streamReader(fstream) 57 | ), 58 | fn openFile mode:"rb" = 59 | ( 60 | result = False 61 | 62 | dialogs.types = strings.types 63 | dialogs.caption = strings.openFileCaption 64 | 65 | local fname = filename 66 | fstream = dialogs.openFileDialog &fname mode 67 | if fstream != undefined then 68 | ( 69 | filename = fname 70 | freader = formatReader(fstream) 71 | result = True 72 | ) 73 | ) 74 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/def_model.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct defItem 6 | ( 7 | index = 0, 8 | type = 0, 9 | unknown1 = 0, 10 | filename = "", 11 | position = (point3 0 0 0), 12 | rotation = (point3 0 0 0), 13 | link = -1 14 | ) 15 | 16 | struct defScene 17 | ( 18 | items = #() 19 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/def_viewer.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "lib/max.ms" 6 | filein "lib/cyclone.ms" 7 | filein "lib/cyclone_viewer.ms" 8 | filein "lib/math.ms " 9 | 10 | struct defViewerSettings 11 | ( 12 | showAnimations = True, 13 | modelsFolderPath = "", 14 | texturesPath = "", 15 | isTextured = True, 16 | texFormat = "tf", 17 | lodIndex = 1, 18 | frameIndex = 0, 19 | to3dsMaxSystem = True, 20 | isClockwizeOrder = True, 21 | startFrame = 0, 22 | addCamera = true 23 | ) 24 | 25 | struct defSceneViewer 26 | ( 27 | scene, 28 | settings = defViewerSettings(), 29 | sceneModels = #(), 30 | fn loadModel modelName = 31 | ( 32 | result = undefined 33 | 34 | modelsFilePath = settings.modelsFolderPath + "/" + modelName 35 | charactersFilePath = settings.modelsFolderPath + "/CHARACTERS/" + modelName 36 | 37 | file = cffFile() 38 | file.filename = modelsFilePath 39 | fstream = file.openFile() 40 | if fstream == undefined then 41 | ( 42 | file.filename = charactersFilePath 43 | fstream = file.openFile() 44 | ) 45 | 46 | if fstream != undefined then 47 | ( 48 | if file.readFile() then 49 | result = file.model 50 | file.closeFile() 51 | ) 52 | 53 | result 54 | ), 55 | fn create = 56 | ( 57 | -- load models to scene 58 | for sceneItem in scene.items do 59 | ( 60 | model = loadModel sceneItem.filename 61 | 62 | if model != undefined then 63 | ( 64 | viewer = modelViewer model 65 | 66 | viewer.settings.isTextured = settings.isTextured 67 | viewer.settings.texturesPath = settings.texturesPath 68 | viewer.settings.texFormat = settings.texFormat 69 | viewer.settings.lodIndex = settings.lodIndex 70 | viewer.settings.frameIndex = settings.frameIndex 71 | viewer.settings.to3dsMaxSystem = settings.to3dsMaxSystem 72 | viewer.settings.isClockwizeOrder = settings.isClockwizeOrder 73 | 74 | viewer.createScene redraw:false showProgress:false position:sceneItem.position \ 75 | rotation:sceneItem.rotation 76 | ) 77 | ) 78 | 79 | redrawViews() 80 | ) 81 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/dialogs.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Version: 0.1 4 | Description: 5 | */ 6 | 7 | filein "utils.ms" 8 | 9 | struct dialogs 10 | ( 11 | caption = "", 12 | types = "", 13 | fn isValue txt = 14 | ( 15 | if txt != "" then 16 | ( 17 | try 18 | ( 19 | val = execute txt 20 | result = true 21 | ) 22 | catch 23 | ( 24 | messageBox "ERROR. Not a number: " + txt + "." 25 | result = false 26 | ) 27 | ) 28 | else 29 | result = false 30 | ), 31 | fn isNonNegativeValue txt = 32 | ( 33 | value = converter.stringToInteger txt 34 | if value <= 0 then 35 | ( 36 | messageBox ("Error. Value: " + txt + " must be greater than or equal to zero.") 37 | result = false 38 | ) 39 | else 40 | result = true 41 | ), 42 | fn checkInputValue txt checkType = 43 | ( 44 | result = false 45 | if isValue txt then 46 | result = isnNonNegativeValue txt 47 | ), 48 | fn openFileDialog &filename mode = 49 | ( 50 | if filename == undefined or filename == "" then 51 | filename = 52 | ( 53 | if mode == "rb" then 54 | getOpenFileName caption: caption types: types 55 | else 56 | getSaveFileName caption: caption types: types 57 | ) 58 | if filename != undefined then 59 | filestream = fopen filename mode 60 | ), 61 | fn openFolder caption = 62 | ( 63 | getSavePath caption: caption 64 | ), 65 | fn showMessage caption = 66 | ( 67 | messageBox caption 68 | ) 69 | ) 70 | 71 | dialogs = dialogs() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/ini.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Version: 0.1 4 | Description: 5 | */ 6 | 7 | filein "utils.ms" 8 | 9 | struct iniFile 10 | ( 11 | filename, 12 | fn setValue section key value = 13 | ( 14 | setINISetting filename section key (value as string) 15 | ), 16 | fn getValue section key = 17 | ( 18 | getINISetting filename section key 19 | ), 20 | fn getIntegerValue section key = 21 | ( 22 | strValue = getINISetting filename section key 23 | if strValue != "" then 24 | converter.stringToInteger(strValue) 25 | else 26 | result = -1 27 | ), 28 | fn getBooleanValue section key = 29 | ( 30 | strValue = getINISetting filename section key 31 | if strValue != "" then 32 | converter.stringToBoolean(strValue) 33 | else 34 | result = undefined 35 | ), 36 | fn getFloatValue section key = 37 | ( 38 | strValue = getINISetting filename section key 39 | if strValue != "" then 40 | converter.stringToFloat(strValue) 41 | else 42 | result = -1 43 | ), 44 | fn getArrayValue section key = 45 | ( 46 | strValue = getINISetting filename section key 47 | if strValue != "" then 48 | converter.stringToArray(strValue) 49 | else 50 | result = -1 51 | ), 52 | fn getPoint2Value section key = 53 | ( 54 | strValue = getINISetting filename section key 55 | if strValue != "" then 56 | converter.stringToPoint2 (strValue) 57 | else 58 | result = [0, 0] 59 | ), 60 | fn isKeyExist section key = 61 | ( 62 | hasINISetting filename section key 63 | ) 64 | ) 65 | 66 | ini = iniFile() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/math.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct maxMath 6 | ( 7 | fn radToEuler radians = 8 | ( 9 | const = (180/pi) 10 | result = eulerAngles (radians.x * const) (radians.y * const) (radians.z * const) 11 | ), 12 | fn rotateMatByAngles angles matrix: = 13 | ( 14 | if matrix == unsupplied then 15 | local transformMatrix = matrix3 1 16 | else 17 | local transformMatrix = matrix 18 | 19 | transformMatrix = preRotateY transformMatrix angles.y 20 | transformMatrix = preRotateX transformMatrix angles.x 21 | transformMatrix = preRotateZ transformMatrix angles.z 22 | 23 | result = transformMatrix 24 | ) 25 | ) 26 | 27 | mathFunction = maxMath() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/max.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Description: 3 | 3ds max objects 4 | */ 5 | 6 | filein "dialogs.ms" 7 | 8 | struct maxStrings 9 | ( 10 | lang = "Eng", 11 | errorVertNumber = "Error. Number of vertexes of the mesh is less than %d.", 12 | fn loadFromIni filename = 13 | ( 14 | local strings = settings(this) 15 | strings.loadFromIniFile filename lang 16 | ) 17 | ) 18 | 19 | struct maxAnimation 20 | ( 21 | fn setLength length = 22 | ( 23 | animationRange = interval 0 length 24 | ) 25 | ) 26 | 27 | struct skinModifier 28 | ( 29 | fn create = 30 | ( 31 | result = skin() 32 | ), 33 | fn applyToMesh msh = 34 | ( 35 | skinmod = this.create() 36 | addModifier msh skinmod 37 | setCommandPanelTaskMode #modify 38 | modPanel.setCurrentObject skinmod 39 | result = skinmod 40 | ), 41 | fn setVertexWeight skinMod vertexId boneID vertexWeight = 42 | ( 43 | skinOps.replaceVertexWeights skinMod vertexId boneID vertexWeight 44 | ), 45 | fn addBone skinMod skeletonBone = 46 | ( 47 | skinOps.addBone skinMod skeletonBone 1 48 | ), 49 | fn attachBonesToMesh msh boneArray = 50 | ( 51 | skinmod = this.applyToMesh msh 52 | for skeletonBone in boneArray do 53 | this.addBone skinmod skeletonBone 54 | modPanel.setCurrentObject skinmod 55 | result = skinmod 56 | ) 57 | ) 58 | 59 | struct maxController 60 | ( 61 | fn addKey controller time = 62 | ( 63 | addNewKey controller time 64 | ), 65 | fn deleteAllKeys controller = 66 | ( 67 | deleteKeys controller #allKeys 68 | ), 69 | fn deleteKeysByRange controller startFrame endFrame = 70 | ( 71 | for x in controller.keys.count to 1 by -1 do 72 | ( 73 | if (controller.keys[x].time >= startFrame) and \ 74 | (controller.keys[x].time <= endFrame) do 75 | deleteKey controller x 76 | ) 77 | ) 78 | ) 79 | 80 | struct maxModifier 81 | ( 82 | skin = skinModifier() 83 | ) 84 | 85 | struct maxBones 86 | ( 87 | fn create startPos endPos axis name: = 88 | ( 89 | bone = BoneSys.createBone startPos endPos axis 90 | if name != unsupplied then 91 | bone.name = name 92 | bone.width = 1 93 | bone.height = 1 94 | bone.taper = 100 95 | bone.wirecolor = yellow 96 | bone.showlinks = true 97 | bone.position.controller = linear_position() 98 | bone.rotation.controller = linear_rotation() 99 | result = bone 100 | ) 101 | ) 102 | 103 | struct maxNodeOp 104 | ( 105 | fn addToGroup obj objs = 106 | ( 107 | attachNodesToGroup obj objs 108 | ), 109 | fn createGroup objs name opened:false = 110 | ( 111 | groupNode = Group objs name:name 112 | if opened then 113 | this.openGroup groupNode 114 | result = groupNode 115 | ), 116 | fn openGroup group = 117 | ( 118 | setGroupOpen group true 119 | ), 120 | fn closeGroup group = 121 | ( 122 | setGroupOpen group false 123 | ), 124 | fn getNode name = 125 | ( 126 | result = getnodebyname name exact:true 127 | ) 128 | ) 129 | 130 | struct slateMatEditor 131 | ( 132 | fn open = 133 | ( 134 | sme.Open() 135 | ), 136 | fn close = 137 | ( 138 | sme.Close() 139 | ), 140 | fn createView caption = 141 | ( 142 | local index = sme.GetViewByName caption 143 | if index > 0 then 144 | result = sme.GetView index 145 | else 146 | result = sme.GetView(sme.CreateView caption) 147 | ), 148 | fn createNode material view pos = 149 | ( 150 | result = view.CreateNode material pos 151 | ) 152 | ) 153 | 154 | struct maxMaterial 155 | ( 156 | fn createTextureMap textureName = 157 | ( 158 | bitmapTex = bitmaptexture filename:textureName 159 | result = bitmapTex 160 | ), 161 | fn createStandardMaterial twoSided matName = 162 | ( 163 | standMaterial = standardMaterial twoSided:twoSided showInViewport:true 164 | standMaterial.name = matName 165 | result = standMaterial 166 | ), 167 | fn createMaterialFromBitmap filename matname = 168 | ( 169 | bitmapTexture = this.openBitmapFile fileName 170 | if bitmapTexture != undefined then 171 | ( 172 | mat = this.createBitmapMaterial bitmapTexture 173 | mat.name = matname 174 | result = mat 175 | ) 176 | ), 177 | fn createBitmapBlendMaterial bitmapImageArray = 178 | ( 179 | blendmat = blend 180 | blendmat.map1 = standardMaterial \ 181 | diffuseMap:(bitmaptexture bitmap:bitmapImageArray[1]) showInViewport:true 182 | blendmat.map2 = standardMaterial \ 183 | diffuseMap:(bitmaptexture bitmap:bitmapImageArray[2]) showInViewport:true 184 | blendmat.mask = gradient 185 | result = blendmat 186 | ), 187 | fn createBitmapMultiMaterial bitmapImageArray isTexBlended = 188 | ( 189 | if isTexBlended then 190 | numsubs = bitmapImageArray.count + 1 191 | else 192 | numsubs = bitmapImageArray.count 193 | multimat = multimaterial numsubs:numsubs 194 | for i = 1 to bitmapImageArray.count do 195 | multimat[i] = standardMaterial \ 196 | diffuseMap:(bitmaptexture bitmap:bitmapImageArray[i]) showInViewport:true 197 | if isTexBlended != unsupplied and isTexBlended then 198 | multimat[multimat.count + 1] = createBitmapBlendMaterial bitmapImageArray 199 | result = multimat 200 | ), 201 | fn addMaterialToMesh msh mat = 202 | ( 203 | msh.material = mat 204 | ), 205 | fn openBitmapFile filename = 206 | ( 207 | --try 208 | --( 209 | openBitMap filename 210 | --) 211 | --catch 212 | --( 213 | -- messageBox ("Can't open bitmap file " + filename + ".") 214 | -- result = undefined 215 | --) 216 | ), 217 | fn createBitmapMaterial bitmapImage = 218 | ( 219 | result = standardMaterial diffuseMap:(bitmaptexture bitmap:bitmapImage) \ 220 | showInViewport:true 221 | ), 222 | fn createBitmap imageData imageWidth imageHeight filename = 223 | ( 224 | b = bitmap imageWidth imageHeight color:white 225 | b.filename = filename + ".bmp" 226 | for line = 0 to (imageHeight - 1) do 227 | ( 228 | row = #() 229 | for col = (line*imageWidth + 1) to (line + 1)*imageWidth do 230 | append row imageData[col] 231 | setPixels b [0, line] row 232 | ) 233 | save b 234 | result = b 235 | ), 236 | fn addBitmapToMesh msh bitmapImage = 237 | ( 238 | msh.material = standardMaterial \ 239 | diffuseMap:(bitmaptexture bitmap:bitmapImage) showInViewport:true 240 | ) 241 | ) 242 | 243 | struct maxObjects 244 | ( 245 | fn addCamera camname: = 246 | ( 247 | cam = FreeCamera() 248 | if camname != unsupplied and camname != "" then 249 | cam.name = camname 250 | cam 251 | ) 252 | ) 253 | 254 | struct max3ds 255 | ( 256 | strings, 257 | VisualStyle = #Shaded, 258 | sme, 259 | bones, 260 | nodes, 261 | modifiers, 262 | controller, 263 | animation, 264 | material, 265 | objects, 266 | fn setUnits unitsSystem type = 267 | ( 268 | units.DisplayType = unitsSystem 269 | if unitsSystem == #Metric then 270 | units.MetricType = type 271 | ), 272 | fn getBoundPoints mesh = 273 | ( 274 | boundPoint = #() 275 | append boundPoint mesh.max 276 | append boundPoint mesh.min 277 | boundPoint 278 | ), 279 | fn getMeshDimension msh = 280 | ( 281 | meshDimensions = msh.max - msh.min 282 | ), 283 | fn getMeshVertCount msh = 284 | ( 285 | result = getNumVerts msh 286 | ), 287 | fn getMeshVerts msh = 288 | ( 289 | result = (for i = 1 to msh.numVerts collect (getVert msh i)) 290 | ), 291 | fn getFaceColor mesh = 292 | ( 293 | faceColorArray = #() 294 | for i = 1 to mesh.numVerts do 295 | append vertArray (getVert mesh i) 296 | result = faceColorArray 297 | ), 298 | fn createPlaneMesh size pos name = 299 | ( 300 | vertArray = #([0, 0, 0], [size.x, 0, 0], [0, size.y, 0], [size.x, size.y, 0]) 301 | faceArray = #([1, 2, 3], [2, 4, 3]) 302 | idArray = #(1, 1) 303 | tvertArray = #([0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]) 304 | msh = max.createTexturedMesh vertArray faceArray idArray tvertArray name 305 | if msh != undefined then 306 | ( 307 | msh.pos = pos 308 | result = msh 309 | ) 310 | ), 311 | fn createMesh vertArray faceArray name: = 312 | ( 313 | --try 314 | --( 315 | msh = mesh vertices:vertArray faces:faceArray 316 | if name != unsupplied and name != "" then 317 | msh.name = name 318 | result = msh 319 | --) 320 | --catch 321 | --( 322 | -- messageBox ("ERROR. Can't create mesh.") 323 | --) 324 | ), 325 | fn createTexturedMesh vertArray faceArray tvertArray idArray: name: = 326 | ( 327 | --try 328 | --( 329 | if idArray == unsupplied then 330 | msh = mesh vertices:vertArray faces:faceArray tverts:tvertArray 331 | else 332 | msh = mesh vertices:vertArray faces:faceArray materialIDS:idArray \ 333 | tverts:tvertArray 334 | --) 335 | --catch 336 | --( 337 | --messageBox ("ERROR. Can't create mesh: " + name + ".") 338 | --return undefined 339 | --) 340 | 341 | buildTVFaces msh.mesh 342 | for i = 1 to msh.mesh.numfaces do 343 | (setTVFace msh.mesh i (getFace msh.mesh i)) 344 | if name != unsupplied and name != "" then 345 | msh.name = name 346 | result = msh 347 | ), 348 | fn cloneMesh msh pos nodes = 349 | ( 350 | maxOps.CloneNodes msh offset:pos expandHierarchy:false cloneType:#copy \ 351 | newNodes:&nodes 352 | ), 353 | fn moveMesh msh pos = 354 | ( 355 | move msh pos 356 | ), 357 | fn rotateMesh msh angles = 358 | ( 359 | rotate msh angles 360 | ), 361 | fn copyMesh msh = 362 | ( 363 | mshCopy = copy msh 364 | mshCopy 365 | ), 366 | fn attachMesh srcMesh dstMesh = 367 | ( 368 | meshop.attach srcMesh dstMesh 369 | ), 370 | fn sliceMesh msh planeNormal planePos = 371 | ( 372 | local offset = dot planeNormal (planePos - (msh.pos * inverse msh.transform * msh.objecttransform)) 373 | meshop.slice msh #all planeNormal offset delete:true 374 | update msh 375 | ), 376 | fn createHelperPoint name transformMatrix:(matrix3 1) = 377 | ( 378 | hpoint = point() 379 | hpoint.name = name 380 | hpoint.transform = transformMatrix 381 | result = hpoint 382 | ), 383 | fn init = 384 | ( 385 | if strings == undefined then 386 | strings = maxStrings() 387 | this.sme = slateMatEditor() 388 | this.bones = maxBones() 389 | this.nodes = maxNodeOp() 390 | this.modifiers = maxModifier() 391 | this.controller = maxController() 392 | this.animation = maxAnimation() 393 | this.material = maxMaterial() 394 | this.objects = maxObjects() 395 | -- set viewport mod 396 | VP = NitrousGraphicsManager.GetActiveViewportSetting() 397 | VP.VisualStyleMode = VisualStyle 398 | ), 399 | on create do init() 400 | ) 401 | 402 | max = max3ds() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/ms.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | clearlistener() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/settings.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Version: 0.1 4 | Description: 5 | */ 6 | 7 | filein "utils.ms" 8 | filein "ini.ms" 9 | 10 | struct iniSettings 11 | ( 12 | properties, 13 | iniFile = "settings.ini", 14 | fn saveToIniFile filename iniSectionTitle = 15 | ( 16 | ini.filename = iniFile 17 | if fileUtils.isFileExist filename then 18 | ini.filename = filename 19 | 20 | if fileUtils.isFileExist ini.filename then 21 | ( 22 | local strValue 23 | names = getPropNames properties 24 | for name in names do 25 | ( 26 | strName = name as string 27 | if ini.isKeyExist iniSectionTitle strName then 28 | ( 29 | prop = getProperty properties name 30 | propClass = classof prop 31 | case propClass of 32 | ( 33 | Array: 34 | ( 35 | local str = convertor.arrayValuesToString prop 36 | ini.setValue iniSectionTitle strName str 37 | ) 38 | default: 39 | ini.setValue iniSectionTitle strName (prop as string) 40 | ) 41 | ) 42 | ) 43 | ) 44 | ), 45 | fn loadFromIniFile filename iniSectionTitle = 46 | ( 47 | local intValue = 0 48 | local point = [0, 0] 49 | local strValue = "" 50 | local boolValue = true 51 | 52 | ini.filename = iniFile 53 | if fileUtils.isFileExist filename then 54 | ini.filename = filename 55 | 56 | if fileUtils.isFileExist ini.filename then 57 | ( 58 | local strValue 59 | names = getPropNames properties 60 | for propName in names do 61 | ( 62 | strName = propName as string 63 | if ini.isKeyExist iniSectionTitle strName then 64 | ( 65 | prop = getProperty properties propName 66 | propClass = classof prop 67 | case propClass of 68 | ( 69 | Integer: 70 | ( 71 | intValue = ini.getIntegerValue iniSectionTitle strName 72 | if intValue > 0 then 73 | setProperty properties propName intValue 74 | ) 75 | Array: 76 | ( 77 | strArray = ini.getArrayValue iniSectionTitle strName 78 | if strArray.count > 0 then 79 | setProperty properties propName strArray 80 | ) 81 | Point2: 82 | ( 83 | point = ini.getPoint2Value iniSectionTitle strName 84 | if point.x > 0 then 85 | setProperty properties propName point 86 | ) 87 | BooleanClass: 88 | ( 89 | boolValue = ini.getBooleanValue iniSectionTitle strName 90 | if boolValue != undefined then 91 | setProperty properties propName boolValue 92 | ) 93 | -- String, Value, etc... 94 | default: 95 | ( 96 | strValue = ini.getValue iniSectionTitle strName 97 | if strValue != "" then 98 | setProperty properties propName strValue 99 | ) 100 | ) 101 | ) 102 | ) 103 | ) 104 | ) 105 | ) 106 | -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/sls.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | filein "dialogs.ms" 6 | filein "stream.ms" 7 | filein "utils.ms" 8 | filein "sls_model.ms" 9 | 10 | struct slsStrings 11 | ( 12 | types = "Sea Dogs 1 sailes data (*.sls)|*.sls", 13 | openFileCaption = "Open .sls file" 14 | ) 15 | 16 | struct slsFile 17 | ( 18 | strings = slsStrings(), 19 | model = slsModel(), 20 | fstream, 21 | filename, 22 | freader, 23 | fn readVertex = 24 | ( 25 | modVert = slsModelVertex() 26 | vert.position = freader.readVector3F() 27 | fseek fstream 16 #seek_cur 28 | 29 | result = vertex 30 | ), 31 | fn readFace = 32 | ( 33 | modFace = slsModelFace() 34 | modFace.indexes = freader.readVector3UI16() 35 | fseek fstream 2 #seek_cur 36 | modFace.uv1 = freader.readVector2F() 37 | modFace.uv2 = freader.readVector2F() 38 | modFace.uv3 = freader.readVector2F() 39 | 40 | result = face 41 | ), 42 | fn readYard = 43 | ( 44 | yard = slsYardModel() 45 | yard.filename = fstream.readChars 16 46 | fseek fstream 16 #seek_cur 47 | vertCount = ReadLong fstream #unsigned 48 | faceCount = ReadLong fstream #unsigned 49 | for i = 1 to vertCount do 50 | append yard.vertexes readVertex() 51 | for i = 1 to faceCount do 52 | append yard.faces readFace() 53 | 54 | result = yard 55 | ), 56 | fn readMast = 57 | ( 58 | mast = slsMast() 59 | fseek fstream 8 #seek_cur 60 | mast.mat = fstream.readMatrix() 61 | count = ReadLong fstream #unsigned 62 | for i = 1 to count do 63 | append mast.yards readYard() 64 | 65 | result = mast 66 | ), 67 | fn readFile = 68 | ( 69 | while not eof fstream do 70 | append model.masts readMast() 71 | 72 | result = True 73 | ), 74 | fn closeFile = 75 | ( 76 | fclose fstream 77 | ), 78 | fn openStream fstream filename = 79 | ( 80 | this.fstream = fstream 81 | this.filename = filename 82 | freader = streamReader(fstream) 83 | ), 84 | fn openFile mode:"rb" = 85 | ( 86 | result = False 87 | 88 | dialogs.types = strings.types 89 | dialogs.caption = strings.openFileCaption 90 | 91 | local fname = filename 92 | fstream = dialogs.openFileDialog &fname mode 93 | if fstream != undefined then 94 | ( 95 | filename = fname 96 | freader = formatReader(fstream) 97 | result = True 98 | ) 99 | ) 100 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/sls_model.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct slsModelVertex 6 | ( 7 | position = (point3 0 0 0) 8 | ) 9 | 10 | struct slsModelFace 11 | ( 12 | indexes = (point3 0 0 0), 13 | uv1 = (point2 0 0), 14 | uv2 = (point2 0 0), 15 | uv3 = (point2 0 0) 16 | ) 17 | 18 | struct slsYardModel 19 | ( 20 | filename = "", 21 | vertexes = #(), 22 | faces = #() 23 | ) 24 | 25 | struct slsMast 26 | ( 27 | type = 0, 28 | unknown = 0, 29 | matrix = matrix3 1, 30 | yards = #() 31 | ) 32 | 33 | struct slsModel 34 | ( 35 | masts = #() 36 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/sls_viewer.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct slsViewerStrings 6 | ( 7 | a = "" 8 | ) 9 | 10 | struct slsViewer 11 | ( 12 | strings = slsViewerStrings, 13 | fn create = 14 | ( 15 | 16 | ) 17 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/stream.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct streamReader 6 | ( 7 | fstream, 8 | fn readBool longval:false = 9 | ( 10 | if longval then 11 | result = (if (ReadLong fstream #unsigned) > 0 then true else false) 12 | else 13 | result = (if (ReadByte fstream #unsigned) > 0 then true else false) 14 | ), 15 | fn readName = 16 | ( 17 | fseek fstream 4 #seek_cur 18 | result = ReadString fstream 19 | ), 20 | fn readVector3UI16 sign:#unsigned = 21 | ( 22 | local x = (ReadShort fstream sign) 23 | local y = (ReadShort fstream sign) 24 | local z = (ReadShort fstream sign) 25 | result = (point3 x y z) 26 | ), 27 | fn readVector2UI16 sign:#unsigned = 28 | ( 29 | local x = (ReadShort fstream sign) 30 | local y = (ReadShort fstream sign) 31 | result = (point2 x y) 32 | ), 33 | fn readVector2F = 34 | ( 35 | local x = (ReadFloat fstream) 36 | local y = (ReadFloat fstream) 37 | result = (point2 x y) 38 | ), 39 | fn readVector3F = 40 | ( 41 | local x = (ReadFloat fstream) 42 | local y = (ReadFloat fstream) 43 | local z = (ReadFloat fstream) 44 | result = (point3 x y z) 45 | ), 46 | fn readVector4F = 47 | ( 48 | local x = (ReadFloat fstream) 49 | local y = (ReadFloat fstream) 50 | local z = (ReadFloat fstream) 51 | local w = (ReadFloat fstream) 52 | result = (point4 x y z w) 53 | ), 54 | fn readVector3B = 55 | ( 56 | local x = (ReadByte fstream #unsigned) 57 | local y = (ReadByte fstream #unsigned) 58 | local z = (ReadByte fstream #unsigned) 59 | result = (point3 x y z) 60 | ), 61 | fn readVector3SH = 62 | ( 63 | local x = (ReadShort fstream #unsigned) 64 | local y = (ReadShort fstream #unsigned) 65 | local z = (ReadShort fstream #unsigned ) 66 | result = (point3 x y z) 67 | ), 68 | fn readIndexValues = 69 | ( 70 | values = readVector3UI16() 71 | values.x = values.x + 1 72 | values.y = values.y + 1 73 | values.z = values.z + 1 74 | result = values 75 | ), 76 | fn readColorValues alpha:true normalized:true = 77 | ( 78 | -- color component value is in range 0..1 79 | normalCoeff = 1 80 | if normalized then 81 | normalCoeff = 255 82 | r = (ReadFloat fstream)*normalCoeff 83 | g = (ReadFloat fstream)*normalCoeff 84 | b = (ReadFloat fstream)*normalCoeff 85 | if alpha then 86 | ( 87 | a = (ReadFloat fstream)*normalCoeff 88 | result = (color r g b a) 89 | ) 90 | else 91 | result = (color r g b) 92 | ), 93 | fn readVertexValues = 94 | ( 95 | result = readVector3F() 96 | ), 97 | fn readQuatValues = 98 | ( 99 | local x = (ReadFloat fstream) 100 | local y = (ReadFloat fstream) 101 | local z = (ReadFloat fstream) 102 | local w = (ReadFloat fstream) 103 | result = (quat x y z w) 104 | ), 105 | fn readMatrix = 106 | ( 107 | values1 = readVector3F() 108 | values2 = readVector3F() 109 | values3 = readVector3F() 110 | values4 = readVector3F() 111 | 112 | matrix = matrix3 1 113 | matrix.row1 = [values1.x, values1.y, values1.z] 114 | matrix.row2 = [values2.x, values2.y, values2.z] 115 | matrix.row3 = [values3.x, values3.y, values3.z] 116 | matrix.row4 = [values4.x, values4.y, values4.z] 117 | result = matrix 118 | ), 119 | fn ReadChars length = 120 | ( 121 | local str = "" 122 | for i = 1 to length do 123 | ( 124 | byte = ReadByte fstream #unsigned 125 | if byte == 0 then 126 | ( 127 | fseek fstream (length - i) #seek_cur 128 | exit 129 | ) 130 | str += bit.intAsChar (byte) 131 | ) 132 | return str 133 | ) 134 | ) 135 | 136 | struct streamWriter 137 | ( 138 | fstream, 139 | fn writeBool boolValue = 140 | ( 141 | if boolValue == true then 142 | WriteByte fstream 1 143 | else 144 | WriteByte fstream 0 145 | ), 146 | fn writeString str length: = 147 | ( 148 | if length != unsupplied then 149 | ( 150 | WriteString fstream str 151 | length = length - str.count 152 | for i = 1 to length do 153 | ( 154 | WriteByte fstream 0 155 | ) 156 | ) 157 | else 158 | WriteString fstream str 159 | ), 160 | fn writeName name = 161 | ( 162 | WriteLong fstream (name.count + 1) 163 | WriteString fstream name 164 | ), 165 | fn writeColor colorValues normalized:true = 166 | ( 167 | if normalized then 168 | normalCoeff = 255 169 | ReadFloat fstream colorValues.r*normalCoeff 170 | ReadFloat fstream colorValues.g*normalCoeff 171 | ReadFloat fstream colorValues.b*normalCoeff 172 | ), 173 | fn writeVector3F val = 174 | ( 175 | WriteFloat fstream val.x 176 | WriteFloat fstream val.y 177 | WriteFloat fstream val.z 178 | ), 179 | fn writeVector3UI16 val sign:#unsigned = 180 | ( 181 | WriteShort fstream val.x sign 182 | WriteShort fstream val.y sign 183 | WriteShort fstream val.z sign 184 | ), 185 | fn writeVector2F val sign:#unsigned = 186 | ( 187 | WriteFloat fstream val.x 188 | WriteFloat fstream val.y 189 | ), 190 | fn writeQuatValues quatVar = 191 | ( 192 | WriteFloat fstream quatVar.x 193 | WriteFloat fstream quatVar.y 194 | WriteFloat fstream quatVar.z 195 | WriteFloat fstream quatVar.w 196 | ), 197 | fn writeMatrixValues matrix = 198 | ( 199 | WriteFloat fstream matrix.row1.x 200 | WriteFloat fstream matrix.row1.y 201 | WriteFloat fstream matrix.row1.z 202 | WriteFloat fstream matrix.row2.x 203 | WriteFloat fstream matrix.row2.y 204 | WriteFloat fstream matrix.row2.z 205 | WriteFloat fstream matrix.row3.x 206 | WriteFloat fstream matrix.row3.y 207 | WriteFloat fstream matrix.row3.z 208 | WriteFloat fstream matrix.row4.x 209 | WriteFloat fstream matrix.row4.y 210 | WriteFloat fstream matrix.row4.z 211 | ) 212 | ) -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/system.ms: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | struct systemUtils 6 | ( 7 | fn getDateTimeinSeconds = 8 | ( 9 | epochDateTime = dotnetObject "System.DateTime" 1970 1 1 0 0 0 10 | curDateTime = (dotNetClass "System.DateTime").Now.Subtract(epochDateTime) 11 | result = (curDateTime.TotalSeconds as integer) 12 | ) 13 | ) 14 | 15 | struct maxSystem 16 | ( 17 | currentPath = "", 18 | utils = systemUtils() 19 | ) 20 | 21 | 22 | sys = maxSystem() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/lib/utils.ms: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Description: 4 | */ 5 | 6 | struct converter ( 7 | fn arrayValuesToString valueArray = 8 | ( 9 | if valueArray.count > 1 then 10 | ( 11 | str = valueArray[1] as string 12 | for i = 2 to valueArray.count do 13 | str += "," + (valueArray[i] as string) 14 | result = "(" + str + ")" 15 | ) 16 | else 17 | result = valueArray[1] as string 18 | ), 19 | fn stringToPoint2 str = 20 | ( 21 | elements = filterstring str "[,]" 22 | if elements.count > 0 then 23 | ( 24 | try 25 | ( 26 | first = elements[1] as integer 27 | second = elements[2] as integer 28 | ) 29 | catch 30 | ( 31 | messageBox "Error. Can't convert: " + str + " to Point2 value" 32 | ) 33 | pointTwo = [first, second] 34 | ) 35 | else 36 | ( 37 | --messageBox "Error. Can't convert: " + str + " to Point2 value" 38 | [0, 0] 39 | ) 40 | ), 41 | fn stringToInteger str = 42 | ( 43 | try 44 | ( 45 | str as integer 46 | ) 47 | catch 48 | ( 49 | --messageBox "Error. Can't convert: " + str + " to integer value" 50 | -1 51 | ) 52 | ), 53 | fn stringToFloat str = 54 | ( 55 | try 56 | ( 57 | str as float 58 | ) 59 | catch 60 | ( 61 | --messageBox "Error. Can't convert: " + str + " to float value" 62 | -1 63 | ) 64 | ), 65 | fn stringToBoolean str = 66 | ( 67 | try 68 | ( 69 | str as booleanClass 70 | ) 71 | catch 72 | ( 73 | --messageBox "Error. Can't convert: " + str + " to boolean value" 74 | undefined 75 | ) 76 | ), 77 | fn stringToArray str = 78 | ( 79 | filterstring str "(,)" 80 | ) 81 | ) 82 | 83 | struct fileUtils 84 | ( 85 | fn isFileExist filename = 86 | ( 87 | result = doesFileExist filename 88 | ), 89 | fn getFileExtension filename = 90 | ( 91 | result = getFilenameType filename 92 | ), 93 | fn getCurrentPath filename = 94 | ( 95 | result = getFilenamePath filename 96 | ), 97 | fn getFileName filename ext:false = 98 | ( 99 | if ext then 100 | filenameFromPath filename 101 | else 102 | getFilenameFile filename 103 | ), 104 | fn findFiles directory pattern subfolders:false = 105 | ( 106 | local files = #() 107 | if subfolders then 108 | ( 109 | dir_array = GetDirectories (directory + "/*") 110 | for dir in dirArray do 111 | join dirArray (GetDirectories (dir + "/*")) 112 | for file in dirArray do 113 | join files (getFiles (file + pattern)) 114 | ) 115 | else 116 | files = getFiles (directory + pattern) 117 | result = files 118 | ) 119 | ) 120 | 121 | fileUtils = fileUtils() 122 | converter = converter() -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/mzp.run: -------------------------------------------------------------------------------- 1 | name "Storm 1 Engine tools" 2 | version 0.2 3 | copy raw_export.ms to $scripts\storm_tools 4 | copy raw_import.ms to $scripts\storm_tools 5 | copy icons\*.* to $max\UI_ln\Icons 6 | copy icons\*.* to $max\UI_ln\IconsDark 7 | run storm_panel.mcr 8 | drop storm_panel.mcr 9 | clear temp -------------------------------------------------------------------------------- /plugins/3dsmax/cff_clf/strom_panel.mcr: -------------------------------------------------------------------------------- 1 | /* 2 | Author: AlexKimov 3 | Version: 0.1 4 | Description: Storm 1 Engine tools 5 | Game: Sea Dogs 1 (2000), Age of Sail 2, Privateers Bounty: Age of Sail 2 6 | */ 7 | 8 | macroScript STORM_ENGINE_TOOLS 9 | category: "Game file import/export" 10 | tooltip: "Storm 1 Engine tools" 11 | buttontext: "Storm 1 Engine tools" 12 | icon: #("storm_icon", 1) 13 | autoUndoEnabled:false 14 | ( 15 | struct toolsDialogStrings 16 | ( 17 | buttonImportCyclCaption = "Import Cyclone model", 18 | buttonImportAniCaption = "Import .ani file", 19 | title = "Storm Engine tools", 20 | ) 21 | 22 | struct toolsDialog 23 | ( 24 | strings, 25 | width = 100, 26 | pos = [100, 100], 27 | style = #(#style_titlebar, #style_border, #style_sysmenu), 28 | fn importCyclone = 29 | ( 30 | include "raw_import.ms" 31 | ), 32 | fn importAni = 33 | ( 34 | include "raw_export.ms" 35 | ), 36 | dialog = 37 | ( 38 | rollout dialog strings.title 39 | ( 40 | local owner = if owner != undefined do owner 41 | button button_importCyclone strings.buttonImportCyclCaption 42 | button button_importAni strings.buttonImportAniCaption 43 | on button_importCyclone pressed do owner.importCyclone 44 | on button_importAni pressed do owner.importAni 45 | ) 46 | ), 47 | fn show = createDialog dialog width:width pos:pos style:style, 48 | fn close = try (destroyDialog dialog) catch(), 49 | on create do 50 | ( 51 | dialog.owner = this 52 | strings = toolsDialogStrings() 53 | ) 54 | ) 55 | 56 | stormToolsUI = toolsDialog() 57 | stormToolsUI.show() 58 | ) -------------------------------------------------------------------------------- /plugins/noesis/fmt_aos2_pak.py: -------------------------------------------------------------------------------- 1 | from inc_noesis import * 2 | import os 3 | import noewin 4 | import noewinext 5 | import tempfile 6 | 7 | def registerNoesisTypes(): 8 | handle = noesis.register("Age of Sale 2/Privateer's Bounty resource archive", ".pak") 9 | noesis.setHandlerExtractArc(handle, aosExtractResources) 10 | 11 | handle = noesis.registerTool("Age of Sale 2 resource viewer", aosResViewerToolMethod, \ 12 | "View Age of Sale 2 resource files.") 13 | noesis.setToolFlags(handle, noesis.NTOOLFLAG_CONTEXTITEM) 14 | noesis.setToolVisibleCallback(handle, aosResourceViewerVisible) 15 | 16 | return 1 17 | 18 | 19 | AGE_OF_SAIL_FORMAT = 1001 20 | PRIVATEERS_BOUNTY_FORMAT = 1002 21 | 22 | 23 | class pakDirHeader: 24 | def __init__(self, pos, type, count, offset, dirExist, name): 25 | self.pos = pos 26 | self.type = type 27 | self.count = count 28 | self.offset = offset 29 | self.dirExist = dirExist 30 | self.name = name 31 | self.parent = None 32 | 33 | 34 | class pakFileHeader: 35 | def __init__(self, pos, type, size, offset, name): 36 | self.pos = pos 37 | self.type = type 38 | self.size = size 39 | self.offset = offset 40 | self.name = name 41 | 42 | 43 | class pakFileTableReader: 44 | def __init__(self, filereader): 45 | self.filereader = filereader 46 | self.fileTable = {} 47 | 48 | def readRecHeader(self): 49 | pos = self.filereader.tell() 50 | type = self.filereader.readUByte() 51 | size = self.filereader.readUInt() 52 | offset = self.filereader.readUInt() 53 | dirExist = self.filereader.readUInt() 54 | self.filereader.seek(4, NOESEEK_REL) 55 | name = self.filereader.readString() 56 | 57 | if type == 1: 58 | return pakFileHeader(pos, type, size, offset, name) 59 | else: 60 | return pakDirHeader(pos, type, size, offset, dirExist, name) 61 | 62 | # wtf 63 | def readDirRecord(self, header = None): 64 | recHeader = self.readRecHeader() 65 | 66 | if recHeader.type == 0: 67 | self.readDirRecord(recHeader) 68 | if header != None and header.count > 0: 69 | self.readDirRecord(header) 70 | 71 | if recHeader.type == 1: 72 | self.filereader.seek(recHeader.pos, NOESEEK_ABS) 73 | fileHeaders = [] 74 | 75 | for i in range(header.count): 76 | fileRecHeader = self.readRecHeader() 77 | fileHeaders.append(fileRecHeader) 78 | 79 | self.fileTable.update({header:fileHeaders}) 80 | 81 | self.readDirRecord() 82 | 83 | if recHeader.type == 2 and recHeader.dirExist == 1: 84 | self.readDirRecord() 85 | 86 | def readRecords(self): 87 | self.readDirRecord() 88 | 89 | 90 | class pakDirectoryEntry: 91 | def __init__(self, fileCount = 0, name = ""): 92 | self.fileCount = fileCount 93 | self.name = name 94 | 95 | 96 | class pakFileEntry: 97 | def __init__(self, size = 0, offset = 0, name = ""): 98 | self.size = size 99 | self.offset = offset 100 | self.name = name 101 | 102 | 103 | class pakPBFileTableReader: 104 | def __init__(self, filereader): 105 | self.filereader = filereader 106 | self.fileTable = {} 107 | 108 | def readDirEntry(self): 109 | fileCount = self.filereader.readUInt() 110 | name = self.filereader.readString() 111 | 112 | return pakDirectoryEntry(fileCount, name) 113 | 114 | def readFileEntry(self): 115 | size = self.filereader.readUInt() 116 | offset = self.filereader.readUInt() 117 | self.filereader.seek(4, NOESEEK_REL) 118 | name = self.filereader.readString() 119 | 120 | return pakFileEntry(size, offset, name) 121 | 122 | def readRecords(self): 123 | dirCount = self.filereader.readUInt() 124 | 125 | dirEntries = [] 126 | for i in range(dirCount): 127 | dirEntries.append(self.readDirEntry()) 128 | 129 | for dirEntry in dirEntries: 130 | fileEntries = [] 131 | for i in range(dirEntry.fileCount): 132 | fileEntries.append(self.readFileEntry()) 133 | 134 | self.fileTable.update({dirEntry: fileEntries}) 135 | 136 | return self.fileTable 137 | 138 | 139 | class aosResorceFile: 140 | def __init__(self): 141 | self.fileTable = {} 142 | self.format = AGE_OF_SAIL_FORMAT 143 | 144 | def unpack(self, filepath): 145 | for directory, files in self.fileTable.items(): 146 | for file in files: 147 | try: 148 | filename = "{}\{}\{}".format(filepath, directory.name, file.name) 149 | os.makedirs(os.path.dirname(filename), exist_ok = True) 150 | self.filereader.seek(file.offset, NOESEEK_ABS) 151 | fileData = self.filereader.readBytes(file.size) 152 | with open(filename, "wb") as resFile: 153 | resFile.write(fileData) 154 | except: 155 | return False 156 | 157 | return True 158 | 159 | def getFileData(self, filename): 160 | for directory, files in self.fileTable.items(): 161 | for file in files: 162 | try: 163 | if file.name == filename: 164 | self.filereader.seek(file.offset, NOESEEK_ABS) 165 | return self.filereader.readBytes(file.size) 166 | except: 167 | return None 168 | 169 | def parseHeader(self): 170 | magic = self.filereader.readString() 171 | 172 | if magic != "ENPAK": 173 | return False 174 | 175 | gameType = self.filereader.readByte() 176 | if gameType == 0: # Privateer's Bounty 177 | self.filereader.seek(3, NOESEEK_REL) 178 | self.format = PRIVATEERS_BOUNTY_FORMAT 179 | self.filereader.seek(self.filereader.readUInt(), NOESEEK_ABS) # filetable pos 180 | elif gameType <= 2: # AOS 2 181 | self.filereader.seek(19, NOESEEK_REL) 182 | else: 183 | return False 184 | 185 | return True 186 | 187 | def readFileTable(self): 188 | try: 189 | filetableReader = (pakPBFileTableReader(self.filereader) \ 190 | if self.format == PRIVATEERS_BOUNTY_FORMAT else pakFileTableReader(self.filereader)) 191 | 192 | filetableReader.readRecords() 193 | self.fileTable = filetableReader.fileTable 194 | if self.format == PRIVATEERS_BOUNTY_FORMAT: 195 | self.filereader.seek(30, NOESEEK_ABS) # back pos to files data 196 | except: 197 | return None 198 | 199 | return True 200 | 201 | def open(self, filename): 202 | try: 203 | with open(filename, "rb") as resFile: 204 | self.filename = filename 205 | self.filereader = NoeBitStream(resFile.read()) 206 | 207 | if self.parseHeader(): 208 | self.readFileTable() 209 | else: 210 | return None 211 | except: 212 | return None 213 | 214 | 215 | class resViewerDialogWindow(): 216 | def __init__(self, filename): 217 | self.filename = filename 218 | self.isCanceled = True 219 | self.resourceFile = aosResorceFile() 220 | self.resourceFile.open(self.filename) 221 | 222 | def viewerToolButtonOpen(self, noeWnd, controlId, wParam, lParam): 223 | selestedItem = self.resourceFileView.selected() 224 | if selestedItem != None: 225 | name = self.resourceFileView.getItemText(selestedItem) 226 | 227 | 228 | if name.find(".") != -1: 229 | extension = os.path.splitext(name)[1] 230 | 231 | tempFile = tempfile.NamedTemporaryFile(suffix = extension, \ 232 | delete=False) 233 | data = self.resourceFile.getFileData(name) 234 | if data != None: 235 | tempFile.write(data) 236 | noesis.openAndRemoveTempFile(tempFile.name) 237 | else: 238 | tempFile.close() 239 | 240 | return True 241 | 242 | def viewerToolButtonUnpack(self, noeWnd, controlId, wParam, lParam): 243 | saveDialog = noewinext.NoeUserDialog("Choose path to export", "", "", "") 244 | path = saveDialog.getSaveFileName() 245 | noesis.logPopup() 246 | 247 | if path != None: 248 | if self.resourceFile.unpack(path.rstrip('\n\0')): 249 | noesis.messagePrompt("Files successfully unpacked.") 250 | else: 251 | noesis.doException("Error: Can't unpack.") 252 | 253 | return True 254 | 255 | def viewerToolButtonClose(self, noeWnd, controlId, wParam, lParam): 256 | self.noeWnd.closeWindow() 257 | 258 | return True 259 | 260 | def viewResFile(self): 261 | if self.resourceFile.fileTable != None: 262 | self.resourceFileView.clear() 263 | 264 | for directory, files in self.resourceFile.fileTable.items(): 265 | rootItem = self.resourceFileView.insertItem(directory.name) 266 | for file in files: 267 | self.resourceFileView.insertItem(file.name, rootItem) 268 | 269 | def create(self): 270 | self.noeWnd = noewinext.NoeUserWindowExt( \ 271 | "AOS 2 Resource Viewer", "AOSResourceViewerWindowClass", \ 272 | 385, 495) 273 | noeWindowRect = noewin.getNoesisWindowRect() 274 | 275 | if noeWindowRect: 276 | windowMargin = 100 277 | self.noeWnd.x = noeWindowRect[0] + windowMargin 278 | self.noeWnd.y = noeWindowRect[1] + windowMargin 279 | 280 | if self.noeWnd.createWindow(): 281 | self.noeWnd.setFont("Arial", 12) 282 | 283 | self.noeWnd.createStatic("Resource file:", 5, 2, 110, 20) 284 | 285 | index = self.noeWnd.createTreeView(5, 25, 275, 440) 286 | self.resourceFileView = self.noeWnd.getControlByIndex(index) 287 | 288 | #self.noeWnd.createButton("Open", 290, 25, 80, 30, \ 289 | # self.viewerToolButtonOpen) 290 | #self.noeWnd.createButton("Unpack", 290, 400, 80, 30, \ 291 | # self.viewerToolButtonUnpack) 292 | self.noeWnd.createButton("Close", 290, 435, 80, 30, \ 293 | self.viewerToolButtonClose) 294 | 295 | self.viewResFile() 296 | 297 | self.noeWnd.doModal() 298 | 299 | 300 | def aosResourceViewerVisible(toolIndex, selectedFile): 301 | if selectedFile is None or \ 302 | (os.path.splitext(selectedFile)[1].lower() != ".pak"): 303 | 304 | return 0 305 | 306 | return 1 307 | 308 | 309 | def aosResViewerToolMethod(toolIndex): 310 | srcPath = noesis.getSelectedFile() 311 | 312 | if srcPath is None or os.path.exists(srcPath) is not True: 313 | noesis.messagePrompt( \ 314 | "Selected file isn't readable through the standard filesystem.") 315 | 316 | return 0 317 | 318 | resViewerDialogWindow(srcPath).create() 319 | 320 | return 1 321 | 322 | 323 | def aosExtractResources(fileName, fileLen, justChecking): 324 | if justChecking: #it's valid 325 | return 1 326 | 327 | resourceFile = aosResorceFile() 328 | resourceFile.open(fileName) 329 | 330 | for directory, files in resourceFile.fileTable.items(): 331 | for file in files: 332 | try: 333 | outfilename = "{}\{}".format(directory.name, file.name) 334 | resourceFile.filereader.seek(file.offset, NOESEEK_ABS) 335 | rapi.exportArchiveFile(outfilename, resourceFile.filereader.readBytes(file.size)) 336 | except: 337 | return 0 338 | 339 | return 1 -------------------------------------------------------------------------------- /plugins/noesis/fmt_sd2_tx.py: -------------------------------------------------------------------------------- 1 | from inc_noesis import * 2 | 3 | 4 | def registerNoesisTypes(): 5 | handle = noesis.register("Sea Dogs 2 (Pirates of the Caribbean) Textures", ".tx") 6 | 7 | noesis.setHandlerTypeCheck(handle, sdpcCheckType) 8 | noesis.setHandlerLoadRGBA(handle, sdpcLoadRGBA) 9 | #noesis.setHandlerWriteRGBA(handle, sdpcWriteRGBA) 10 | 11 | return 1 12 | 13 | D3DFORMAT_DXT1 = 827611204 14 | D3DFORMAT_DXT3 = 861165636 15 | D3DFORMAT_DXT5 = 894720068 16 | 17 | class SDPCImage: 18 | def __init__(self, reader): 19 | self.filereader = reader 20 | self.width = 0 21 | self.height = 0 22 | self.type = 0 23 | 24 | def parseHeader(self): 25 | #self.filereader.seek(5, NOESEEK_ABS) 26 | 27 | self.version = self.filereader.readUInt() 28 | self.width = self.filereader.readUInt() 29 | self.height = self.filereader.readUInt() 30 | 31 | self.mapCount = self.filereader.readUInt() 32 | self.type = self.filereader.readUInt() 33 | self.size = self.filereader.readUInt() 34 | 35 | return 0 36 | 37 | def getImageData(self): 38 | d3dFormat = {21:"b8g8r8a8", 22:"b8g8r8a8", 23:"b5g6r5", 24:"b5g5r5a1", \ 39 | 25:"b5g5r5a1", 26:"b4g4r4a4"} 40 | if self.type < D3DFORMAT_DXT1: # RGB 41 | format = d3dFormat[self.type] 42 | if self.type < 23: 43 | imageBuffer = self.filereader.readBytes(self.width * self.height * 4) 44 | else: 45 | imageBuffer = self.filereader.readBytes(self.width * self.height * 2) 46 | self.data = rapi.imageDecodeRaw(imageBuffer, self.width, self.height, \ 47 | format) 48 | else: # DXT 49 | if self.type == D3DFORMAT_DXT1: 50 | self.data = self.filereader.readBytes(int(self.width * self.height / 2)) 51 | else: 52 | self.data = self.filereader.readBytes(self.width * self.height) 53 | 54 | def read(self): 55 | self.getImageData() 56 | 57 | 58 | def sdpcCheckType(data): 59 | sdpcImage = SDPCImage(NoeBitStream(data)) 60 | if sdpcImage.parseHeader() != 0: 61 | return 0 62 | 63 | return 1 64 | 65 | 66 | def sdpcLoadRGBA(data, texList): 67 | sdpcImage = SDPCImage(NoeBitStream(data)) 68 | if sdpcImage.parseHeader() != 0: 69 | return 0 70 | 71 | sdpcImage.read() 72 | 73 | if sdpcImage.type == D3DFORMAT_DXT1: 74 | texList.append(NoeTexture("seadogstex", sdpcImage.width, sdpcImage.height, \ 75 | sdpcImage.data, noesis.NOESISTEX_DXT1)) 76 | elif sdpcImage.type == D3DFORMAT_DXT3: 77 | texList.append(NoeTexture("seadogstex", sdpcImage.width, sdpcImage.height, \ 78 | sdpcImage.data, noesis.NOESISTEX_DXT3)) 79 | elif sdpcImage.type == D3DFORMAT_DXT5: 80 | texList.append(NoeTexture("seadogstex", sdpcImage.width, sdpcImage.height, \ 81 | sdpcImage.data, noesis.NOESISTEX_DXT5)) 82 | else: 83 | texList.append(NoeTexture("seadogstex", sdpcImage.width, sdpcImage.height, \ 84 | sdpcImage.data, noesis.NOESISTEX_RGBA32)) 85 | 86 | return 1 -------------------------------------------------------------------------------- /plugins/noesis/fmt_sd2_zap.py: -------------------------------------------------------------------------------- 1 | from inc_noesis import * 2 | 3 | 4 | def registerNoesisTypes(): 5 | handle = noesis.register("Sea Dogs 2 (Pirates of the Caribbean) mask/foam texture", ".zap") 6 | 7 | noesis.setHandlerTypeCheck(handle, zapCheckType) 8 | noesis.setHandlerLoadRGBA(handle, zapLoadRGBA) 9 | 10 | #noesis.setHandlerWriteRGBA(handle, sdpcWriteRGBA) 11 | 12 | return 1 13 | 14 | 15 | class ZAPImage: 16 | def __init__(self, reader): 17 | self.filereader = reader 18 | self.size = 0 19 | self.blockIndex = [] 20 | self.blockData = [] 21 | 22 | def parseHeader(self): 23 | self.imageSize = self.filereader.readUInt() # image width 24 | self.blocksInRow = self.filereader.readUInt() # number of packed blocks in image line 25 | self.blockSize = self.filereader.readUInt() # size of block in bytes 26 | self.unknown1 = self.filereader.readUInt() # 3 bytes per pixel? 27 | self.unknown2 = self.filereader.readUInt() 28 | if self.blockSize != 8 or self.unknown1 != 3 or self.unknown2 != 7: 29 | return 1 30 | self.blockCount = self.filereader.readUInt() # number of packed blocks 31 | 32 | return 0 33 | 34 | def unpackDataToRGB(self): 35 | # the image splitted into blocks of 8×8 36 | # "blockIndex" contains block indexes, if block index is equel 0xXX80, it 37 | # must be replaced with array of XX values 64 bytes in size, if not data 38 | # must copied from "blockData" using index from "blockIndex" 39 | 40 | unpackedData = bytearray() 41 | col = 0 42 | 43 | unpackedImageLines = bytearray([0] * self.imageSize * self.blockSize) 44 | blockCol = 0 45 | noesis.logPopup() 46 | 47 | # refactor this 48 | for index in self.blockIndex: 49 | if index & 0xFF00 == 32768: 50 | blockData = bytearray([index & 0xFF] * self.blockSize * self.blockSize) 51 | else: 52 | blockData = self.blockData[index] 53 | for i in range(self.blocksInRow): 54 | blockPos = self.blockSize * i 55 | imageLinePos = self.imageSize * i + blockCol * self.blockSize 56 | unpackedImageLines[0 + imageLinePos: self.blockSize + imageLinePos] = \ 57 | blockData[0 + blockPos: self.blockSize + blockPos] 58 | 59 | blockCol += 1 60 | 61 | if blockCol == self.blocksInRow: 62 | unpackedData += unpackedImageLines 63 | unpackedImageLines = bytearray([0] * self.imageSize * self.blockSize) 64 | blockCol = 0 65 | 66 | # from 8bit to rgb24 67 | data = bytearray() 68 | for component in unpackedData: 69 | pixelColorComponent = (component).to_bytes(1, byteorder = 'big') 70 | data += pixelColorComponent + pixelColorComponent + pixelColorComponent 71 | 72 | # it's need to be flipped, but... 73 | 74 | return data 75 | 76 | def getRGBAData(self): 77 | 78 | # read block indexes 79 | count = int((self.imageSize * self.blocksInRow) / self.blockSize) 80 | for i in range(count): 81 | self.blockIndex.append(self.filereader.readUShort()) 82 | 83 | # read blocks 84 | count = self.blockSize*self.blockSize # 64 85 | for i in range(self.blockCount): 86 | self.blockData.append(self.filereader.readBytes(count)) 87 | 88 | # unpack data 89 | return self.unpackDataToRGB() 90 | 91 | def read(self): 92 | self.data = self.getRGBAData() 93 | 94 | 95 | 96 | def zapCheckType(data): 97 | zapImage = ZAPImage(NoeBitStream(data)) 98 | if zapImage.parseHeader() != 0: 99 | return 0 100 | 101 | return 1 102 | 103 | 104 | def zapLoadRGBA(data, texList): 105 | 106 | zapImage = ZAPImage(NoeBitStream(data)) 107 | if zapImage.parseHeader() != 0: 108 | return 0 109 | 110 | zapImage.read() 111 | 112 | texList.append(NoeTexture("seadogstex", zapImage.imageSize, zapImage.imageSize, \ 113 | zapImage.data, noesis.NOESISTEX_RGB24)) 114 | 115 | return 1 -------------------------------------------------------------------------------- /plugins/noesis/fmt_sd_dlt.py: -------------------------------------------------------------------------------- 1 | from inc_noesis import * 2 | 3 | def registerNoesisTypes(): 4 | handle = noesis.register("Sea Dogs (2000) island image", ".dlt") 5 | 6 | noesis.setHandlerTypeCheck(handle, dltCheckType) 7 | noesis.setHandlerLoadRGBA(handle, sdDLTLoadRGBA) 8 | noesis.setHandlerWriteRGBA(handle, sdDLTWriteRGBA) 9 | 10 | return 1 11 | 12 | 13 | class DLTImage: 14 | def __init__(self, reader): 15 | self.filereader = reader 16 | 17 | def parseHeader(self): 18 | self.size = self.filereader.readUInt() 19 | self.width = self.filereader.readUInt() 20 | self.height = self.filereader.readUInt() 21 | self.mapCount = self.filereader.readUInt() 22 | self.filereader.seek(4, NOESEEK_REL) 23 | 24 | return 0 25 | 26 | def getImageData(self): 27 | imageBuffer = self.filereader.readBytes(self.width * self.height * 2) 28 | self.data = rapi.imageDecodeRaw(imageBuffer, self.width, self.height, \ 29 | "b5g6r5") 30 | 31 | def read(self): 32 | self.getImageData() 33 | 34 | 35 | def dltCheckType(data): 36 | dltImage = DLTImage(NoeBitStream(data)) 37 | if dltImage.parseHeader() != 0: 38 | return 0 39 | 40 | return 1 41 | 42 | 43 | def sdDLTLoadRGBA(data, texList): 44 | dltImage = DLTImage(NoeBitStream(data)) 45 | if dltImage.parseHeader() != 0: 46 | return 0 47 | 48 | dltImage.read() 49 | 50 | # 16 bit texture RGB565 51 | texList.append(NoeTexture("seadogsislandimage", dltImage.width, dltImage.height, \ 52 | dltImage.data, noesis.NOESISTEX_RGBA32)) 53 | 54 | return 1 55 | 56 | 57 | class DLTHeader(): 58 | def __init__(self, width, height): 59 | self.width = width 60 | self.height = height 61 | 62 | def toBytes(self): 63 | result = bytearray() 64 | imageSize = 174740 65 | param = 0.9 66 | result += (imageSize).to_bytes(4, byteorder='little') 67 | result += self.width.to_bytes(4, byteorder='little') 68 | result += self.height.to_bytes(4, byteorder='little') 69 | result += (6).to_bytes(4, byteorder='little') 70 | result += bytearray(noePack("f", param)) 71 | 72 | return result 73 | 74 | 75 | def sdDLTWriteRGBA(data, imageWidth, imageHeight, filewriter): 76 | header = DLTHeader(imageWidth, imageHeight) 77 | filewriter.writeBytes(header.toBytes()) 78 | 79 | width = imageWidth 80 | height = imageHeight 81 | 82 | for i in range(6): 83 | imageData = rapi.imageEncodeRaw(data, width, height, "b5g6r5") 84 | filewriter.writeBytes(imageData) 85 | width = int(width / 2) 86 | height = int(height / 2) 87 | 88 | return 1 -------------------------------------------------------------------------------- /plugins/noesis/fmt_sd_tf.py: -------------------------------------------------------------------------------- 1 | from inc_noesis import * 2 | import noewin 3 | 4 | def registerNoesisTypes(): 5 | handle = noesis.register("Sea Dogs (2000) Textures", ".tf") 6 | 7 | noesis.setHandlerTypeCheck(handle, sdCheckType) 8 | noesis.setHandlerLoadRGBA(handle, sdLoadRGBA) 9 | noesis.setHandlerWriteRGBA(handle, sdWriteRGBA) 10 | 11 | return 1 12 | 13 | 14 | class SDImage: 15 | def __init__(self, reader): 16 | self.filereader = reader 17 | self.width = 0 18 | self.height = 0 19 | self.type = 0 20 | 21 | def parseHeader(self): 22 | self.filereader.seek(5, NOESEEK_ABS) 23 | 24 | self.type = self.filereader.readUByte() 25 | self.imageCount = self.filereader.readUByte() 26 | self.palettedCount = self.filereader.readUByte() 27 | 28 | self.width = self.filereader.readUInt() 29 | self.height = self.filereader.readUInt() 30 | 31 | return 0 32 | 33 | def getMipMapsData(self): 34 | # skip mip-maps 35 | width = self.width 36 | height = self.height 37 | 38 | for i in range(self.imageCount - 1): 39 | width = int(width/2) 40 | height = int(height/2) 41 | self.filereader.seek(width * height * 2, NOESEEK_REL) 42 | 43 | def getPalettedImageData(self): 44 | # get palette 45 | 46 | alpha = (255).to_bytes(1, byteorder = "little") 47 | palette = bytearray() 48 | for i in range(256): 49 | palette += self.filereader.readBytes(3) 50 | self.filereader.seek(1, NOESEEK_REL) 51 | palette += alpha 52 | 53 | # get first image 54 | indexes = self.filereader.readBytes(self.width * self.height) 55 | self.maskData = rapi.imageDecodeRawPal(indexes, palette, self.width, \ 56 | self.height, 8, "r8g8b8a8") 57 | 58 | def getImageData(self): 59 | if self.type == 1: 60 | format = "b5g5r5a1" 61 | else: 62 | format = "b5g6r5" 63 | 64 | imageBuffer = self.filereader.readBytes(self.width * self.height * 2) 65 | 66 | self.data = rapi.imageDecodeRaw(imageBuffer, self.width, self.height, \ 67 | format) 68 | 69 | if self.type == 1: 70 | i = 0 71 | size = len(self.data) 72 | for i in range(size): 73 | if not(i & 3): 74 | self.data[i - 1] = 255 75 | 76 | def read(self): 77 | self.getImageData() 78 | self.getMipMapsData() 79 | self.getPalettedImageData() 80 | 81 | 82 | def sdCheckType(data): 83 | sdImage = SDImage(NoeBitStream(data)) 84 | if sdImage.parseHeader() != 0: 85 | return 0 86 | 87 | return 1 88 | 89 | 90 | def sdLoadRGBA(data, texList): 91 | sdImage = SDImage(NoeBitStream(data)) 92 | if sdImage.parseHeader() != 0: 93 | return 0 94 | 95 | sdImage.read() 96 | 97 | # 16 bit texture 98 | texList.append(NoeTexture("seadogstex", sdImage.width, sdImage.height, \ 99 | sdImage.data, noesis.NOESISTEX_RGBA32)) 100 | 101 | # 8 bit texture 102 | #texList.append(NoeTexture("seadogstex", sdImage.width, sdImage.height, \ 103 | # sdImage.maskData, noesis.NOESISTEX_RGBA32)) 104 | return 1 105 | 106 | 107 | class TFHeader(): 108 | def __init__(self, type, mmCount, palCount, width, height): 109 | self.type = type 110 | self.mmCount = mmCount 111 | self.palCount = palCount 112 | self.width = width 113 | self.height = height 114 | 115 | def toBytes(self): 116 | result = bytearray() 117 | result += bytearray(5) # file starts with zeroes 118 | result += self.type.to_bytes(1, byteorder='little') 119 | result += self.mmCount.to_bytes(1, byteorder='little') 120 | result += self.palCount.to_bytes(1, byteorder='little') 121 | result += self.width.to_bytes(4, byteorder='little') 122 | result += self.height.to_bytes(4, byteorder='little') 123 | 124 | return result 125 | 126 | 127 | class exportDialogWindow: 128 | def __init__(self): 129 | self.options = {"type":0, "mmCount":6, "palCount":6} 130 | self.isCanceled = True 131 | 132 | def exportOptionsButtonExport(self, noeWnd, controlId, wParam, lParam): 133 | index = self.typeListBox.getSelectionIndex() 134 | self.options["type"] = index 135 | 136 | index = self.mmcountComboBox.getSelectionIndex() 137 | self.options["mmCount"] = index 138 | 139 | index = self.palcountComboBox.getSelectionIndex() 140 | self.options["palCount"] = index 141 | 142 | self.isCanceled = False 143 | self.noeWnd.closeWindow() 144 | 145 | return True 146 | 147 | def exportOptionsButtonCancel(self, noeWnd, controlId, wParam, lParam): 148 | self.noeWnd.closeWindow() 149 | 150 | return True 151 | 152 | def show(self): 153 | self.noeWnd = noewin.NoeUserWindow("Export options", "HTWindowClass", \ 154 | 300, 155) 155 | noeWindowRect = noewin.getNoesisWindowRect() 156 | 157 | if noeWindowRect: 158 | windowMargin = 64 159 | self.noeWnd.x = noeWindowRect[0] + windowMargin 160 | self.noeWnd.y = noeWindowRect[1] + windowMargin 161 | 162 | if self.noeWnd.createWindow(): 163 | self.noeWnd.setFont("Arial", 12) 164 | 165 | self.noeWnd.createStatic("Choose format:", 5, 5, 160, 20) 166 | # choose game list 167 | index = self.noeWnd.createListBox(5, 25, 184, 47, None, 0) 168 | self.typeListBox = self.noeWnd.getControlByIndex(index) 169 | 170 | typeList = ("Format RGB565", "Format RGBA5551") 171 | 172 | for type in typeList: 173 | self.typeListBox.addString(type) 174 | 175 | self.typeListBox.selectString(typeList[0]) 176 | 177 | self.noeWnd.createStatic("Number of 16 bit images:", 5, 70, 169, 20) 178 | # choose format combobox 179 | index = self.noeWnd.createComboBox(160, 65, 30, 20) 180 | self.mmcountComboBox = self.noeWnd.getControlByIndex(index) 181 | 182 | self.noeWnd.createStatic("Number of paletted images:", 5, 98, 169, 20) 183 | # choose format combobox 184 | index = self.noeWnd.createComboBox(160, 95, 30, 20) 185 | self.palcountComboBox = self.noeWnd.getControlByIndex(index) 186 | 187 | countList = ("6", "5", "4", "3", "2", "1", "0") 188 | 189 | for count in countList: 190 | self.mmcountComboBox.addString(count) 191 | self.palcountComboBox.addString(count) 192 | 193 | self.mmcountComboBox.selectString(countList[0]) 194 | self.palcountComboBox.selectString(countList[0]) 195 | 196 | self.noeWnd.createButton("Export", 210, 25, 80, 30, \ 197 | self.exportOptionsButtonExport) 198 | self.noeWnd.createButton("Cancel", 210, 60, 80, 30, \ 199 | self.exportOptionsButtonCancel) 200 | 201 | self.noeWnd.doModal() 202 | 203 | 204 | def getOptions(): 205 | if not noesis.optWasInvoked("-type"): 206 | exportDialog = exportDialogWindow() 207 | exportDialog.show() 208 | if exportDialog.isCanceled: 209 | return None 210 | options = exportDialog.options 211 | else: 212 | # set export options 213 | options = {"type":0, "mmCount":6, "palCount":6} 214 | 215 | if noesis.optWasInvoked("-type"): 216 | try: 217 | type = int(noesis.optGetArg("-type")) 218 | options["type"] = type 219 | except: 220 | pass 221 | 222 | if noesis.optWasInvoked("-MipMapCount"): 223 | try: 224 | type = int(noesis.optGetArg("-MipMapCount")) 225 | options["mmCount"] = type 226 | except: 227 | pass 228 | 229 | if noesis.optWasInvoked("-PaletteCount"): 230 | try: 231 | type = int(noesis.optGetArg("-PaletteCount")) 232 | options["palCount"] = type 233 | except: 234 | pass 235 | 236 | return options 237 | 238 | 239 | def sdWriteRGBA(data, imageWidth, imageHeight, filewriter): 240 | options = getOptions() 241 | if options == None: 242 | return 0 243 | 244 | type = options["type"] 245 | mmCount = options["mmCount"] 246 | palCount = options["palCount"] 247 | 248 | header = TFHeader(type, mmCount, palCount, imageWidth, imageHeight) 249 | filewriter.writeBytes(header.toBytes()) 250 | 251 | width = imageWidth 252 | height = imageHeight 253 | 254 | if type == 1: 255 | format = "b5g5r5a1" 256 | else: 257 | format = "b5g6r5" 258 | 259 | for i in range(mmCount): 260 | imageData = rapi.imageEncodeRaw(data, width, height, format) 261 | filewriter.writeBytes(imageData) 262 | width = int(width / 2) 263 | height = int(height / 2) 264 | 265 | palette = rapi.imageGetPalette(data, imageWidth, imageHeight, 256, 0, 0) 266 | filewriter.writeBytes(palette) 267 | 268 | width = imageWidth 269 | height = imageHeight 270 | 271 | for i in range(palCount): 272 | indexes = rapi.imageApplyPalette(data, width, height, palette, 256) 273 | filewriter.writeBytes(indexes) 274 | width = int(width / 2) 275 | height = int(height / 2) 276 | 277 | return 1 -------------------------------------------------------------------------------- /scripts/010editor/PackPAK(PB).1sc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexKimov/seadogs-file-formats/e8521eafe6c801398dfea8df72247ed045c3f636/scripts/010editor/PackPAK(PB).1sc -------------------------------------------------------------------------------- /scripts/010editor/PackPAK.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: PackPAK.1sc 5 | // Authors: AE 6 | // Version: 0.1 7 | // Purpose: Pack files to .pak archive 8 | // 9 | // History: 10 | // 11 | // 2018.07 v0.1 12 | //------------------------------------------------ 13 | 14 | local uchar Buffer[10485760]; 15 | local string filetypes = "*.cff;*.clf;*.tf;*.tga;*.tff;*.exe;*.map;*.cffold;*.LOG;*.fls;*.lay;*.psd"; 16 | local string signature = "ENPAK"; 17 | local string PAKDirectory, Name; 18 | local uint index, i, k, z, t, level, size, FileIndex, length, count, pos, fpcount, offset, datasize, fi = 0; 19 | local uint Fpos[10]; 20 | 21 | void WriteFileRecord(uint type, uint count, uint offset, uint size, string name, uint typen) 22 | { 23 | WriteByte(FTell(), type); 24 | FSkip(1); 25 | if (type == 1) // files 26 | { 27 | WriteInt(FTell(), size); // filecount 28 | FSkip(4); 29 | } 30 | else 31 | { 32 | WriteInt(FTell(), count); // filecount 33 | FSkip(4); 34 | }; 35 | WriteInt(FTell(), offset); // offset 36 | FSkip(4); 37 | 38 | WriteInt(FTell(), typen); 39 | FSkip(4); 40 | WriteInt(FTell(), 0); 41 | FSkip(4); 42 | if (name == "") 43 | { 44 | WriteByte(FTell(), 0); 45 | } 46 | else 47 | { 48 | if (type == 1) 49 | name = FileNameGetBase(name); 50 | WriteString(FTell(), name); 51 | FSkip(sizeof(name)); 52 | WriteByte(FTell(), 0); 53 | }; 54 | FSkip(1); 55 | }; 56 | 57 | uint getFileCount(string dir) 58 | { 59 | TFileList fl = FindFiles( dir, filetypes ); 60 | return fl.filecount; 61 | }; 62 | 63 | uint getFileSize(string Filename, uint index) 64 | { 65 | local uint size = 0; 66 | FileOpen(Filename); 67 | size = FileSize(); 68 | FileClose(); 69 | FileSelect(index); 70 | return size; 71 | }; 72 | 73 | int FolderisEnded() 74 | { 75 | FileSelect(fi); 76 | local int endid = ReadInt(FTell()); 77 | if (endid < 0) 78 | FSkip(4); 79 | return endid; 80 | }; 81 | 82 | uint checkifFolder(string Name) { 83 | return Strchr(Name, "."); 84 | } 85 | 86 | string intToStr(int Number) { 87 | local string s; 88 | SPrintf( s, "%d", (int)Number ); 89 | return s; 90 | } 91 | 92 | uint strToInt(char str[]) { 93 | int number, n; 94 | n = SScanf( str, "%d", number ); 95 | Printf("%d ", n); 96 | return number; 97 | }; 98 | 99 | void getFolderData(string Directory) 100 | { 101 | local string dir = Directory; 102 | TFileList fl = FindFiles( dir, filetypes ); 103 | 104 | if (fl.filecount) // files 105 | { 106 | for ( i = 0; i < fl.filecount; ++i ) 107 | { 108 | // File name length 109 | length = Strlen(dir + fl.file[i].filename); 110 | WriteInt(FTell(), length); 111 | FSkip(4); 112 | // File name 113 | pos += 23 + Strlen(fl.file[i].filename); 114 | WriteString(FTell(), dir + fl.file[i].filename); 115 | FSkip(length); 116 | WriteByte(FTell(), 0); 117 | FSkip(1); 118 | // File size 119 | size = getFileSize(dir + fl.file[i].filename, fi); 120 | WriteInt(FTell(), size); 121 | FSkip(4); 122 | }; 123 | }; 124 | for ( i = 0; i < fl.dircount; ++i ) 125 | { 126 | // dir name length 127 | length = Strlen(fl.dir[i].dirname); 128 | WriteInt(FTell(), length); 129 | FSkip(4); 130 | 131 | pos += 23 + length; 132 | // dir name 133 | WriteString(FTell(), fl.dir[i].dirname); 134 | FSkip(length); 135 | WriteByte(FTell(), 0); 136 | FSkip(1); 137 | 138 | // file count in directory 139 | count = geFileCount(dir + fl.dir[i].dirname + "\\"); 140 | WriteInt(FTell(), count); 141 | FSkip(4); 142 | 143 | getFolderData(dir + fl.dir[i].dirname + "\\"); 144 | }; 145 | WriteInt(FTell(), -1); 146 | FSkip(4); 147 | }; 148 | 149 | index = InputRadioButtonBox("Archive name", "Choose .pak file name form list:", 0, "geometry.pak", "images.pak", "imagesl.pak", "texture.pak", "texturel.pak" ); 150 | if (index >= 0) 151 | { 152 | PAKDirectory = InputDirectory("Choose directory with \"Resource\" folder"); 153 | if (PAKDirectory != "") 154 | { 155 | 156 | SetWorkingDirectory(PAKDirectory); 157 | 158 | fi = FileNew("Hex"); 159 | pos = 0; 160 | 161 | length = Strlen("Resource"); 162 | WriteInt(FTell(), length); 163 | FSkip(4); 164 | 165 | pos += 23 + length; 166 | // dir name 167 | WriteString(FTell(), "Resource"); 168 | FSkip(length); 169 | WriteByte(FTell(), 0); 170 | FSkip(1); 171 | 172 | // file count 173 | WriteInt(FTell(), 0); 174 | FSkip(4); 175 | getFolderData(PAKDirectory); 176 | 177 | break; 178 | FileIndex = FileNew("Hex"); 179 | 180 | // write header 181 | WriteString(0, signature); 182 | if (index == 2 || index == 4) 183 | WriteByte(6, 2); 184 | else 185 | WriteByte(6, 1); 186 | WriteByte(7, 0); 187 | WriteByte(8, 1); 188 | local uchar buffer[17] = 0; 189 | WriteBytes(buffer, 9, 17); 190 | FSkip(26); 191 | 192 | 193 | k = 0; 194 | datasize = 0; 195 | i = 0; 196 | offset = pos; 197 | z = 0; 198 | t = 0; 199 | FileSelect(fi); 200 | FSeek(0); 201 | 202 | // write File Table 203 | while ( true ) 204 | { 205 | FileSelect(fi); 206 | if (FEof()) break; 207 | 208 | if (FolderisEnded() < 0) 209 | { 210 | WriteFileRecord(2, 0, offset, 0, "", 0); 211 | continue; 212 | }; 213 | 214 | // name length 215 | length = ReadInt(FTell()); 216 | FSkip(4); 217 | // Name 218 | Name = ReadString(FTell()); 219 | FSkip(length + 1); 220 | // count 221 | count = ReadInt(FTell()); 222 | FSkip(4); 223 | 224 | if ((index == 2 || index == 4) && (FTell() == 16)) 225 | { 226 | FileSelect(FileIndex); 227 | WriteFileRecord(0, 0, offset, 0, Name, 1); 228 | WriteFileRecord(2, 0, offset, 0, "", 1); 229 | continue; 230 | }; 231 | 232 | FileSelect(FileIndex); 233 | WriteFileRecord(0, count, offset, 0, Name, 0); 234 | 235 | if (count > 0) 236 | { 237 | FileSelect(fi); 238 | Fpos[t] = FTell(); 239 | ++t; 240 | }; 241 | for ( k = 0; k < count; ++k ) 242 | { 243 | FileSelect(fi); 244 | // 245 | length = ReadInt(FTell()); 246 | FSkip(4); 247 | // Name 248 | Name = ReadString(FTell()); 249 | FSkip(length + 1); 250 | // 251 | datasize = ReadInt(FTell()); 252 | FSkip(4); 253 | 254 | offset += datasize; 255 | 256 | FileSelect(FileIndex); 257 | WriteFileRecord(1, 0, offset, datasize, FileNameGetBase(Name), 0); 258 | 259 | z += count; 260 | }; 261 | }; 262 | FSeek(0); 263 | fpcount = t; 264 | 265 | // write File Data 266 | for ( k = 0; k < fpcount; ++k ) 267 | { 268 | FileSelect(fi); 269 | FSeek(Fpos[k] - 4); 270 | count = ReadInt(FTell()); 271 | FSkip(4); 272 | for ( i = 0; i < count; ++i ) 273 | { 274 | FileSelect(fi); 275 | // 276 | length = ReadInt(FTell()); 277 | FSkip(4); 278 | // Name 279 | Name = ReadString(FTell()); 280 | FSkip(length + 1); 281 | // FileSize 282 | datasize = ReadInt(FTell()); 283 | FSkip(4); 284 | 285 | FileOpen(Name); 286 | ReadBytes(Buffer, 0, datasize); 287 | FileClose(); 288 | FileSelect(FileIndex); 289 | WriteBytes(Buffer, FTell(), datasize); 290 | FSkip(datasize); 291 | }; 292 | }; 293 | 294 | FileSelect(fi); 295 | //FileClose(); 296 | FileSelect(FileIndex); 297 | switch (index) 298 | { 299 | case (0): Name = "geometry.pak"; break; 300 | case (1): Name = "images.pak"; break; 301 | case (2): Name = "imagesl.pak"; break; 302 | case (3): Name = "texture.pak"; break; 303 | case (4): Name = "texturel.pak"; break; 304 | }; 305 | 306 | FileSave(GetWorkingDirectory() + Name); 307 | 308 | //FileClose(); 309 | }; 310 | }; -------------------------------------------------------------------------------- /scripts/010editor/TFtoTGA.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // History: 10 | //------------------------------------------------ 11 | 12 | local uchar Buffer[10485760]; // file buffer 13 | local uint width, height; 14 | local float size; 15 | local int FileIndex; 16 | local string FileName; 17 | local ubyte MapCount, MaskCount, FileType; 18 | 19 | string FileNameRemoveExt(string FileName) 20 | { 21 | return SubStr(FileName, 0, Strchr(FileName, '.')); 22 | }; 23 | 24 | void CreateBMPFile(string Name, uchar Buffer[], uint type, uint width, uint height) 25 | { 26 | local uchar a, b, RGBA[4], Empty[50], Line[4092]; 27 | local float w, alignment, depth; 28 | local int pos, i; 29 | local float size; 30 | local char bfType[2]; 31 | local WORD bfReserved1, bfReserved2, biPlanes, biBitCount; 32 | local DWORD bfSize, bfOffBits, biSize, biWidth, biHeight, biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant, biRMask, biGMask, biBMask, biAMask; 33 | 34 | FileNew("Hex"); 35 | 36 | depth = 16; 37 | if (type != 3) 38 | { 39 | size = width*height*(depth/8); 40 | w = width*(depth/8); 41 | } 42 | else 43 | { 44 | size = width*height; 45 | w = width; 46 | }; 47 | 48 | if (w % 4 > 0) 49 | alignment = 4 - w % 4; 50 | 51 | // BMP Header 52 | bfType = "BM"; 53 | WriteBytes(bfType, 0, 2); 54 | FSkip(2); 55 | 56 | if (type == 3) 57 | bfSize = size + 1078; 58 | else 59 | if (type >= 4) 60 | bfSize = size + 54; 61 | else 62 | bfSize = size + 70; 63 | 64 | WriteInt(FTell(), bfSize); 65 | FSkip(4); 66 | 67 | bfReserved1 = 0; 68 | WriteShort(FTell(), bfReserved1 ); 69 | FSkip(2); 70 | bfReserved2 = 0; 71 | WriteShort(FTell(), bfReserved2 ); 72 | FSkip(2); 73 | 74 | if (type == 3) 75 | bfOffBits = 1078; 76 | else 77 | if (type >= 4) 78 | bfOffBits = 54; 79 | else 80 | bfOffBits = 70; 81 | WriteInt(FTell(), bfOffBits); 82 | FSkip(4); 83 | 84 | if (type >= 3) 85 | biSize = 40; 86 | else 87 | biSize = 56; 88 | 89 | WriteInt(FTell(), biSize); 90 | FSkip(4); 91 | 92 | biWidth = width; 93 | WriteInt(FTell(), biWidth); 94 | FSkip(4); 95 | biHeight = -height; 96 | WriteInt(FTell(), biHeight); 97 | FSkip(4); 98 | 99 | biPlanes = 1; 100 | WriteShort(FTell(), biPlanes ); 101 | FSkip(2); 102 | 103 | if (type == 3) 104 | biBitCount = 8; 105 | else 106 | biBitCount = depth; 107 | 108 | WriteInt(FTell(), biBitCount); 109 | FSkip(2); 110 | 111 | if (type >= 4) 112 | biCompression = 0; 113 | else 114 | biCompression = 3; 115 | 116 | WriteInt(FTell(), biCompression); 117 | FSkip(4); 118 | biSizeImage = size; 119 | WriteInt(FTell(), biSizeImage); 120 | FSkip(4); 121 | 122 | biXPelsPerMeter = 3780; 123 | WriteInt(FTell(), biXPelsPerMeter ); 124 | FSkip(4); 125 | biYPelsPerMeter = 3780; 126 | WriteInt(FTell(), biYPelsPerMeter); 127 | FSkip(4); 128 | biClrUsed = 0; 129 | WriteInt(FTell(), biClrUsed); 130 | FSkip(4); 131 | biClrImportant = 0; 132 | WriteInt(FTell(), biClrImportant); 133 | FSkip(4); 134 | 135 | if (type == 1) // 565 136 | { 137 | biRMask = 63488; 138 | biGMask = 2016; 139 | biBMask = 31; 140 | biAMask = 0; 141 | } 142 | else // 4444 143 | { 144 | biRMask = 3840; 145 | biGMask = 240; 146 | biBMask = 15; 147 | biAMask = 0; 148 | }; 149 | 150 | if (type < 3) // 8 bit 151 | { 152 | WriteInt(FTell(), biRMask); 153 | FSkip(4); 154 | WriteInt(FTell(), biGMask); 155 | FSkip(4); 156 | WriteInt(FTell(), biBMask); 157 | FSkip(4); 158 | WriteInt(FTell(), biAMask); 159 | FSkip(4); 160 | } 161 | else 162 | if (type == 3) 163 | { 164 | WriteBytes(Palette, FTell(), 1024); 165 | FSkip(1024); 166 | }; 167 | 168 | if (alignment > 0) 169 | for ( i = 0; i < height; ++i) 170 | { 171 | Memcpy(Line, Buffer, w, 0, pos); 172 | WriteBytes(Line, FTell(), w); 173 | FSkip(w); 174 | WriteBytes(Empty, FTell(), alignment); 175 | FSkip(alignment); 176 | pos += w; 177 | } 178 | 179 | WriteBytes(Buffer, FTell(), size); 180 | FileSave(Name + ".bmp"); 181 | FileClose(); 182 | }; 183 | 184 | void ReadTFFile() 185 | { 186 | FSkip(5); 187 | 188 | FileType = ReadByte(); 189 | FSkip(1); 190 | 191 | MapCount = ReadByte(); 192 | FSkip(1); 193 | MaskCount = ReadByte(); 194 | FSkip(1); 195 | 196 | width = ReadInt(); 197 | FSkip(4); 198 | height = ReadInt(); 199 | FSkip(4); 200 | 201 | size = height*width*2; 202 | ReadBytes(Buffer, FTell(), size); 203 | }; 204 | 205 | void TFtoBMP() 206 | { 207 | FileIndex = GetFileNum(); 208 | FileName = GetFileName(); 209 | ReadTFFile(); 210 | if (FileType) 211 | CreateBMPFile(FileNameRemoveExt(FileName), Buffer, 4, width, height); 212 | else 213 | CreateBMPFile(FileNameRemoveExt(FileName), Buffer, 1, width, height); 214 | } 215 | 216 | TFtoBMP(); 217 | -------------------------------------------------------------------------------- /scripts/010editor/UnpackPAK(PB).1sc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexKimov/seadogs-file-formats/e8521eafe6c801398dfea8df72247ed045c3f636/scripts/010editor/UnpackPAK(PB).1sc -------------------------------------------------------------------------------- /scripts/010editor/UnpackPAK.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // History: 10 | //------------------------------------------------ 11 | 12 | local uchar Buffer[10485760]; 13 | local string rootdir = FileNameGetBase(GetFileName()) + "_unpacked"; 14 | local uint type, datasize, length, count, i, level = 0; 15 | local int offset = 0; 16 | local string Name; 17 | local string Path; 18 | local int FileIndex; 19 | local uchar FolderEnd = false; 20 | 21 | FileIndex = GetFileNum(); 22 | Name = GetFileName(); 23 | Path = FileNameGetPath(Name) + rootdir; 24 | MakeDir(Path); // current dir 25 | SetWorkingDirectory(Path); 26 | 27 | FSkip(6); // skip Header 28 | level = ReadShort(FTell()); 29 | FSkip(20); 30 | 31 | void fileTree(uint filecount, string folder) { 32 | local string fp = folder; 33 | for ( i = 0; i < filecount; ++i ) { 34 | type = ReadByte(); 35 | FSkip(1); 36 | if (type == 1) // file 37 | { 38 | datasize = ReadInt(); 39 | FSkip(4); 40 | offset = ReadInt(); 41 | FSkip(12); 42 | Name = ReadString(FTell()); 43 | length = ReadStringLength(FTell()); 44 | FSkip(length); 45 | // create and save file to directory 46 | ReadBytes(Buffer, offset, datasize); 47 | FileNew(); 48 | WriteBytes(Buffer, 0, datasize); 49 | FileSave(fp + "\\" + Name); 50 | FileClose(); 51 | // back to pak file 52 | FileSelect(FileIndex); 53 | } 54 | else if (type == 0) // folder 55 | { 56 | count = ReadInt(); 57 | FSkip(16); 58 | Name = ReadString(FTell()); 59 | length = ReadStringLength(FTell()); 60 | //if (folder == "") 61 | // Path = GetWorkingDirectory() + Name; 62 | //else 63 | Path = fp + "\\" + Name; 64 | MakeDir(Path); 65 | FSkip(length); 66 | FolderEnd = false; 67 | if (count) 68 | fileTree(count, Path); 69 | else 70 | fileTree(1, Path); 71 | } 72 | else if (type == 2) 73 | { 74 | FSkip(8); 75 | if (ReadInt() == 1) 76 | { 77 | if (level == 2) 78 | { 79 | fp = GetWorkingDirectory(); 80 | }; 81 | FSkip(9); 82 | fileTree(1, fp); 83 | }; 84 | FSkip(9); // skip "folder end" 85 | } 86 | }; 87 | }; 88 | 89 | fileTree(1, Path); -------------------------------------------------------------------------------- /scripts/010editor/decodeActionFile.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: decodeActionFile.1sc 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: decode .a files 8 | // 9 | // History: 10 | // 11 | // 2018.07 v0.1 12 | // 13 | //------------------------------------------------ 14 | 15 | local ubyte b, bs, i = 0; 16 | local uint size = 0; 17 | 18 | size = FileSize(); 19 | 20 | while (size > 0) 21 | { 22 | for ( i = 0; i < 8; ++i ) 23 | { 24 | b = ReadByte(); 25 | // ror (b, i) 26 | bs = b << (8 - i); 27 | b >>= i; 28 | b += bs; 29 | WriteByte(FTell(), b); 30 | FSkip(1); 31 | }; 32 | size -= 8; 33 | }; -------------------------------------------------------------------------------- /scripts/010editor/decodeDAT.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: decodeDAT.1sc 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: decode .dat files 8 | // 9 | // History: 10 | // 11 | // 2018.07 v0.1 12 | // 13 | //------------------------------------------------ 14 | 15 | local ubyte b, i = 0; 16 | local uint size; 17 | 18 | size = FileSize(); 19 | 20 | while (i < size) { 21 | b = ReadByte(); 22 | b = b ^ 110 ^ i; // double xor enc 23 | WriteByte(FTell(), b); 24 | FSkip(1); 25 | ++i; 26 | }; -------------------------------------------------------------------------------- /scripts/010editor/encodeActionFile.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Script File 3 | // 4 | // File: PackPAK.1sc 5 | // Authors: AE 6 | // Version: 0.1 7 | // Purpose: Encode .a files 8 | // 9 | // History: 10 | // 11 | // 2018.07 v0.1 12 | // 13 | //------------------------------------------------ 14 | 15 | local ubyte b, bs, i = 0; 16 | local uint size = 0; 17 | 18 | size = FileSize(); 19 | 20 | while (size > 0) 21 | { 22 | for ( i = 0; i < 8; ++i ) 23 | { 24 | b = ReadByte(); 25 | bs = b >> (8 - i); 26 | b <<= i; 27 | b += bs; 28 | WriteByte(FTell(), b); 29 | FSkip(1); 30 | }; 31 | size -= 8; 32 | }; -------------------------------------------------------------------------------- /templates/010Editor/AN.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | UINT FrameCount; 15 | UINT BoneCount; 16 | FLOAT Speed; 17 | 18 | INT BONE_PARENT_ID[BoneCount]; 19 | 20 | struct { 21 | FLOAT X; 22 | FLOAT Y; 23 | FLOAT Z; 24 | } BONE_POSITION[BoneCount]; 25 | 26 | struct { 27 | FLOAT X; 28 | FLOAT Y; 29 | FLOAT Z; 30 | } POSITION[FrameCount]; 31 | 32 | struct { 33 | struct { 34 | FLOAT X; 35 | FLOAT Y; 36 | FLOAT Z; 37 | FLOAT W; 38 | } ROTATION[FrameCount]; 39 | } BONE_ANIMATION[BoneCount]; 40 | -------------------------------------------------------------------------------- /templates/010Editor/ANI.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: ANI.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: Sea Dogs game ANI files 8 | // File Mask: *.ani 9 | // 10 | // History: 11 | // 12 | // 2018.06 v0.1 Initial release 13 | // 14 | //------------------------------------------------ 15 | 16 | struct { 17 | UINT SectionOffset ; 18 | UINT ObjectCount; 19 | UINT SectionoOffset ; 20 | UINT FrameCount; 21 | } FILE_HEADER; 22 | 23 | typedef struct { 24 | UINT type; 25 | UINT StartFrame; 26 | UINT Length; 27 | switch (Length) 28 | { 29 | case 4: 30 | FLOAT Unknown; 31 | break; 32 | case 8: 33 | { 34 | INT Unknown; 35 | UINT Unknown; 36 | } break; 37 | case 36: 38 | { 39 | char ObjectName[Length]; 40 | } break; 41 | case 56: 42 | { 43 | FLOAT Unknown; 44 | FLOAT Unknown; 45 | FLOAT Unknown; 46 | FLOAT Unknown; 47 | FLOAT Unknown; 48 | FLOAT Unknown; 49 | char ObjectName[32]; 50 | } break; 51 | case 296: 52 | { 53 | FLOAT Unknown; 54 | FLOAT Unknown; 55 | FLOAT Unknown; 56 | FLOAT Unknown; 57 | FLOAT Unknown; 58 | FLOAT Unknown; 59 | FLOAT Unknown; 60 | FLOAT Unknown; 61 | FLOAT Unknown; 62 | FLOAT Unknown; 63 | FLOAT Unknown; 64 | UINT Unknown; 65 | UINT Unknown; 66 | FLOAT Unknown; 67 | FLOAT Unknown; 68 | FLOAT Unknown; 69 | FLOAT Unknown; 70 | FLOAT Unknown; 71 | FLOAT Unknown; 72 | UINT Unknown; 73 | FLOAT Unknown; 74 | FLOAT Unknown; 75 | FLOAT Unknown; 76 | FLOAT Unknown; 77 | FLOAT Unknown; 78 | FLOAT Unknown; 79 | char ObjectName1[48]; 80 | char ObjectName2[48]; 81 | char ObjectName3[48]; 82 | char ObjectName4[48]; 83 | } break; 84 | default: char ObjectName[Length]; 85 | }; 86 | } OBJECT ; 87 | 88 | string getName(OBJECT &obj) 89 | { 90 | if (exists(obj.ObjectName)) 91 | return obj.ObjectName; 92 | else 93 | return "Object"; 94 | }; 95 | 96 | typedef struct (uint size) { 97 | OBJECT array[size] ; 98 | } OBJECT_ARRAY; 99 | 100 | OBJECT_ARRAY Array(FILE_HEADER.ObjectCount) ; 101 | 102 | struct { 103 | struct { 104 | FLOAT X; 105 | FLOAT Y; 106 | FLOAT Z; 107 | } POSITION; 108 | struct { 109 | FLOAT X; 110 | FLOAT Y; 111 | FLOAT Z; 112 | } ROTATION; 113 | FLOAT Frame; 114 | } ANIMATIONS[FILE_HEADER.FrameCount]; -------------------------------------------------------------------------------- /templates/010Editor/CFF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: CFF.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.2 7 | // Purpose: Sea Dogs game CFF files 8 | // File Mask: *.cff 9 | // 10 | // History: 11 | // 12 | // 2018.07 v0.2 add computing vertex and texture coordinates, update texture properties section 13 | // 2018.06 v0.1 Initial release 14 | // 15 | //------------------------------------------------ 16 | 17 | local float P_X,P_Y, P_Z, S_X, S_Y, S_Z, UVDel; 18 | local uint i, k, n = 0; 19 | 20 | typedef struct { 21 | UBYTE Length; 22 | char FileName[Length]; 23 | } TEXTURE_FILE ; 24 | 25 | typedef struct (uint size) { 26 | TEXTURE_FILE array[size] ; 27 | } FILE_LIST; 28 | 29 | typedef struct { 30 | UINT Unknown; 31 | UINT Unknown; 32 | UINT Unknown; 33 | UINT Unknown; 34 | UINT Unknown; 35 | UINT Unknown; 36 | UINT Unknown; 37 | UINT Unknown; 38 | UINT Unknown; 39 | UINT Count; 40 | struct { 41 | UINT TextureIndex; 42 | FLOAT Unknown; 43 | UINT Unknown; 44 | UINT Unknown; 45 | UINT Unknown; 46 | } TEXTURE[Count]; 47 | } MATERIALS ; 48 | 49 | typedef struct { 50 | UINT16 X; 51 | UINT16 Y; 52 | UINT16 Z; 53 | UINT16 U; 54 | UINT16 V; 55 | struct { 56 | UBYTE R; 57 | UBYTE G; 58 | UBYTE B; 59 | } COLOR; 60 | 61 | // Computing coordinates 62 | // local float pos_x, pos_y, pos_z, coor_u, coor_v, R, G, B; 63 | // pos_x = P_X + X*S_X/32767.0; 64 | // pos_y = P_Y + Y*S_Y/32767.0; 65 | // pos_z = P_Z + Z*S_Z/32767.0; 66 | // coor_u = U/UVDel; 67 | // coor_v = V/UVDel; 68 | // R = COLOR.R/127; 69 | // G = COLOR.G/127; 70 | // B = COLOR.B/127; 71 | } VERTEX; 72 | 73 | typedef struct { 74 | 75 | struct { 76 | struct { 77 | FLOAT X; 78 | FLOAT Y; 79 | FLOAT Z; 80 | } MESH_ORIGIN; 81 | FLOAT UVDelim; 82 | UVDel = UVDelim; 83 | FLOAT Radius; 84 | UINT TextureIndex; 85 | UINT VertexCount ; 86 | UINT FaceCount ; 87 | UINT Unknown; // always 1 88 | UINT AnimationKeyCount; 89 | char Name[4]; 90 | } HEADER ; 91 | 92 | VERTEX VERTEXES[HEADER.VertexCount]; 93 | 94 | struct { 95 | if (HEADER.VertexCount <= 256) { 96 | UBYTE I1; 97 | UBYTE I2; 98 | UBYTE I3; 99 | } else { 100 | UINT16 I1; 101 | UINT16 I2; 102 | UINT16 I3; 103 | }; 104 | } FACE_INDEXES[HEADER.FaceCount] ; 105 | 106 | struct { 107 | struct { 108 | FLOAT X; 109 | FLOAT Y; 110 | FLOAT Z; 111 | } TRANSLATION; 112 | struct { 113 | FLOAT X; 114 | FLOAT Y; 115 | FLOAT Z; 116 | } ROTATION; 117 | FLOAT Frame; // 118 | } ANIMATIONS[HEADER.AnimationKeyCount]; 119 | 120 | } MESH ; 121 | 122 | 123 | typedef struct (uint size) { 124 | MESH array[size] ; 125 | } MESH_ARRAY; 126 | 127 | struct { 128 | struct { 129 | FLOAT X; 130 | FLOAT Y; 131 | FLOAT Z; 132 | } OBJECT_ORIGIN ; 133 | struct { 134 | FLOAT X; 135 | FLOAT Y; 136 | FLOAT Z; 137 | } OBJECT_SCALE ; 138 | UINT TextureCount ; 139 | UINT MaterialCount ; 140 | UINT LOD ; 141 | UINT SectionOffset ; 142 | FLOAT LODSwitchDistance ; 143 | P_X = OBJECT_ORIGIN.X; 144 | P_Y = OBJECT_ORIGIN.Y; 145 | P_Z = OBJECT_ORIGIN.Z; 146 | S_X = OBJECT_SCALE.X; 147 | S_Y = OBJECT_SCALE.Y; 148 | S_Z = OBJECT_SCALE.Z; 149 | } FILE_HEADER ; 150 | 151 | FILE_LIST Textures(FILE_HEADER.TextureCount) ; 152 | 153 | struct { 154 | MATERIALS TexProperties[FILE_HEADER.MaterialCount] ; 155 | } MATS; 156 | 157 | typedef struct { 158 | UINT MeshCount; 159 | UINT Zero; // not used 160 | MESH_ARRAY Meshes(MeshCount); 161 | } LOD_MODEL; 162 | 163 | LOD_MODEL LODModels[FILE_HEADER.LOD] ; 164 | 165 | if (FILE_HEADER.SectionOffset > 0) { 166 | struct { 167 | struct { 168 | UINT Type; 169 | UINT Count1; 170 | UINT Count2; 171 | UINT Count3; 172 | UINT DataSize; 173 | } HEADER; 174 | if (HEADER.Type == 1) 175 | { 176 | for (i = 0; i < HEADER.Count1 + HEADER.Count2; ++i) 177 | { 178 | struct { 179 | INT Index; 180 | INT Index; 181 | do 182 | { 183 | INT16 Index; 184 | INT16 Index; 185 | } while (Index >= 0); 186 | } NODE; 187 | }; 188 | } 189 | else 190 | { 191 | 192 | }; 193 | } BSP_Tree; 194 | }; 195 | 196 | 197 | string texFileName(TEXTURE_FILE &file) { 198 | return file.FileName; 199 | } 200 | 201 | string meshName(MESH &mesh) { 202 | return mesh.HEADER.Name; 203 | } 204 | 205 | 206 | -------------------------------------------------------------------------------- /templates/010Editor/CLF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: CLF.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: Sea Dogs game CLF files 8 | // File Mask: *.clf 9 | // 10 | // History: 11 | // 12 | // 2018.06 v0.1 Initial release 13 | // 14 | //------------------------------------------------ 15 | 16 | struct { 17 | UINT Unknown ; 18 | UINT Unknown; // 2494616 19 | UINT Unknown; // 0 20 | UINT Unknown; // 0 21 | UINT LodCount; // 1 22 | UINT TextureCount; 23 | // long double 24 | UINT Unknown; 25 | UINT MeshCount; 26 | UINT Unknown; // 0 27 | // 28 | UINT AnimationCount; // 886 29 | UINT Unknown; // 0 30 | UINT Unknown; // 0 31 | } HEADER; 32 | 33 | typedef struct { 34 | char FileName[256]; 35 | } FILENAME ; 36 | 37 | typedef struct (uint size) { 38 | FILENAME array[size]; 39 | } TEXTURES; 40 | 41 | string getfileName(FILENAME &fn) { 42 | return fn.FileName; 43 | }; 44 | 45 | TEXTURES FileNames(HEADER.TextureCount) ; 46 | 47 | typedef struct { 48 | struct { 49 | char Name[32]; 50 | UINT FrameCount; 51 | UINT TextureIndex; 52 | UINT VertexCount; 53 | UINT FaceCount; 54 | UBYTE Empty[96]; 55 | } HEADER ; 56 | struct { 57 | FLOAT X; 58 | FLOAT Y; 59 | FLOAT Z; 60 | FLOAT Unknown; 61 | FLOAT Unknown; 62 | FLOAT Unknown; 63 | INT Unknown; 64 | } VERTEXES[HEADER.VertexCount]; 65 | struct { 66 | UINT16 I1; 67 | UINT16 I2; 68 | UINT16 I3; 69 | UINT16 Zero; 70 | FLOAT U1; 71 | FLOAT V1; 72 | FLOAT U2; 73 | FLOAT V2; 74 | FLOAT U3; 75 | FLOAT V3; 76 | } FACES[HEADER.FaceCount]; 77 | struct { 78 | struct { 79 | FLOAT X; 80 | FLOAT Y; 81 | FLOAT Z; 82 | } POSITION; 83 | struct { 84 | FLOAT X; 85 | FLOAT Y; 86 | FLOAT Z; 87 | } ROTATION; 88 | FLOAT Frame; // 89 | } ANIMATIONS[HEADER.FrameCount]; 90 | } MESH ; 91 | 92 | typedef struct (uint size) { 93 | MESH array[size] ; 94 | } MESHES; 95 | 96 | string getName(MESH &ms) { 97 | return ms.HEADER.Name; 98 | }; 99 | 100 | struct { 101 | MESHES Meshes(HEADER.MeshCount) ; 102 | } LODS[HEADER.LodCount] ; -------------------------------------------------------------------------------- /templates/010Editor/CMP.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | struct { 15 | char AOSCP[6] ; 16 | UINT16 ScenBrfCount; 17 | UINT16 ConnCount ; 18 | UINT16 Unknown; // 0 19 | UINT16 Unknown; // 1 20 | UINT16 Unknown; // 1 21 | UINT Unknown; // 0 22 | UINT16 Unknown; 23 | UINT16 Unknown; 24 | UINT16 Unknown; 25 | UINT16 Unknown; 26 | UINT16 Unknown; 27 | UINT16 Unknown; 28 | UINT16 Unknown; 29 | UINT16 Unknown; 30 | } HEADER ; 31 | 32 | struct { 33 | UINT16 NodeIndex ; 34 | UINT16 Type ; // 2 - scenario, 3 - briefing 35 | UINT16 NextNodeIndex1; 36 | UINT16 NextNodeIndex2; 37 | UINT Unknown; //0 38 | UINT PosX; 39 | UINT PosY; 40 | char ScenarioFileName[260]; 41 | char Name[64]; 42 | } CAMPAIGN_NODES[HEADER.ScenBrfCount] ; 43 | 44 | struct { 45 | UINT16 NodeIndex1; 46 | UINT16 NodeIndex2; 47 | UINT16 Connection1Type; // 102, 101, 103 48 | UINT16 Connection2Type; // 102, 101, 103 49 | UINT Unknown; // 3, 4 50 | struct { 51 | UINT X; 52 | UINT Y; 53 | UINT Z; 54 | } P1; 55 | struct { 56 | UINT X; 57 | UINT Y; 58 | UINT Z; 59 | } P2; 60 | } CONNECTIONS[HEADER.ConnCount] ; 61 | 62 | string CompaignTitle ; 63 | string CompaignDescription ; 64 | 65 | string ScriptFileName ; 66 | -------------------------------------------------------------------------------- /templates/010Editor/DEF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | UINT Count; 15 | 16 | typedef enum { 17 | Model = 200, 18 | Rey = 201, 19 | Sail = 202, 20 | Cannon = 203, 21 | Flag = 204, 22 | Waterline = 205, 23 | Patch = 206, 24 | CannonSet = 207, 25 | AllCannons = 208, 26 | ShipTrace = 209, 27 | U1 = 210, 28 | U2 = 211, 29 | U3 = 212, 30 | } CLASS; 31 | 32 | 33 | typedef struct { 34 | UINT Index; 35 | CLASS Class; 36 | UINT Index; 37 | char FileName[256]; 38 | struct { 39 | FLOAT X; 40 | FLOAT Y; 41 | FLOAT Z; 42 | } POSITION; 43 | struct { 44 | FLOAT X; 45 | FLOAT Y; 46 | FLOAT Z; 47 | } ROTATION; 48 | INT Link; 49 | } ITEM ; 50 | 51 | ITEM Items[Count]; 52 | 53 | string getPartName(ITEM &part) 54 | { 55 | return EnumToString(part.Class) + ": " + part.FileName; 56 | } -------------------------------------------------------------------------------- /templates/010Editor/DLM.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | UBYTE Image[65536]; // -------------------------------------------------------------------------------- /templates/010Editor/DLT.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | struct { 15 | UINT DataSize; 16 | UINT Width; 17 | UINT Heigth; 18 | UINT MapCount; 19 | FLOAT Unknown; 20 | } HEADER; 21 | 22 | UBYTE Image1[131072]; // 16 bit ? 23 | UBYTE Image2[32768]; 24 | UBYTE Image3[8192]; 25 | UBYTE Image4[2048]; 26 | UBYTE Image5[512]; 27 | UBYTE Image6[128]; -------------------------------------------------------------------------------- /templates/010Editor/GM.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | local uint i, k, pos; 15 | local byte bt; 16 | 17 | typedef struct { 18 | string FileName; 19 | } TEXTURE_FILE ; 20 | 21 | typedef struct (uint size) { 22 | TEXTURE_FILE array[size] ; 23 | } NAMES_LIST; 24 | 25 | string texFileName(TEXTURE_FILE &file) { 26 | return file.FileName; 27 | } 28 | 29 | struct { 30 | UINT Magic; 31 | UINT Version; 32 | UINT TexturesSectionSize; 33 | UINT NameCount ; 34 | UINT TextureCount ; 35 | UINT MaterialCount ; 36 | UINT Zero; 37 | UINT LocatorCount ; 38 | UINT MeshCount ; 39 | UINT FaceCount ; 40 | UINT fOne; 41 | 42 | struct { 43 | FLOAT X; 44 | FLOAT Y; 45 | FLOAT Z; 46 | } OBJECT_POSITION ; 47 | struct { 48 | FLOAT X; 49 | FLOAT Y; 50 | FLOAT Z; 51 | FLOAT W; 52 | } OBJECT_ROTATION ; 53 | } HEADER ; 54 | 55 | NAMES_LIST Names(HEADER.NameCount) ; 56 | 57 | UINT Offsets[HEADER.NameCount]; 58 | UINT TextureNameOffsets[HEADER.TextureCount]; 59 | UINT MaterialGroupOffset; 60 | 61 | for ( k = 0; k < HEADER.MaterialCount; ++k ) 62 | struct { 63 | local uint TexNumber; 64 | UINT MaterialNameOffset; 65 | struct { 66 | struct { 67 | BYTE R; 68 | BYTE G; 69 | BYTE B; 70 | BYTE A; 71 | } RGBA; 72 | INT ZERO; 73 | FLOAT vSingle; 74 | INT v3Zero; 75 | 76 | for ( i = 0; i < 4; ++i ) 77 | { 78 | INT Texture; 79 | if (Texture > 0) ++TexNumber; 80 | }; 81 | 82 | for ( i = 0; i < TexNumber; ++i ) 83 | INT TextureNumber; 84 | 85 | INT kMinusOne[4 - TexNumber]; 86 | 87 | if (k < HEADER.MaterialCount - 1) 88 | UINT Unknown; 89 | } PROPERTIES; 90 | } MATERIAL; 91 | 92 | for ( k = 0; k < HEADER.LocatorCount; ++k ) 93 | struct { 94 | UINT LocatorGroupOffset; 95 | UINT LocatorNameOffset; 96 | struct { 97 | // transformation matrix 98 | INT Zero; 99 | struct { 100 | FLOAT X; 101 | FLOAT Y; 102 | FLOAT Z; 103 | } XAxis; 104 | INT Zero; 105 | struct { 106 | FLOAT X; 107 | FLOAT Y; 108 | FLOAT Z; 109 | } YAxis; 110 | INT Zero; 111 | struct { 112 | FLOAT X; 113 | FLOAT Y; 114 | FLOAT Z; 115 | } ZAxis; 116 | INT Zero; 117 | struct { 118 | FLOAT X; 119 | FLOAT Y; 120 | FLOAT Z; 121 | } POSITION; 122 | // 123 | FLOAT s0; 124 | FLOAT s1; 125 | INT Unknown; 126 | INT Unknown; 127 | BYTE Some[20]; 128 | } PROPERTIES; 129 | } LOCATOR; 130 | 131 | for ( k = 0; k < HEADER.MeshCount; ++k ) 132 | struct { 133 | UINT NameOffset; 134 | UINT Offset; 135 | INT Unknown; // 3103 136 | // 137 | struct { 138 | FLOAT X; 139 | FLOAT Y; 140 | FLOAT Z; 141 | FLOAT R; 142 | } BOUNDING_SPHERE; 143 | // 144 | INT Zero; 145 | UINT FaceCount; 146 | UINT startTriangles; 147 | UINT VertCount; 148 | UINT startVert; 149 | UINT MaterialNo; 150 | BYTE r1[8]; 151 | UBYTE B; 152 | if (B == 255) 153 | { 154 | BYTE bC[3]; 155 | BYTE t[20]; 156 | } 157 | else 158 | { 159 | BYTE t[19]; 160 | UINT sMinusOne; 161 | }; 162 | BYTE tt[16]; 163 | if (k < HEADER.MeshCount - 1) 164 | UINT Unknown; 165 | } MESH; 166 | 167 | if (HEADER.MeshCount > 0) 168 | { 169 | bt = ReadByte(FTell()); 170 | if (bt != -1) 171 | { 172 | INT FacesExtra; 173 | struct { 174 | UINT16 I1; 175 | UINT16 I2; 176 | UINT16 I3; 177 | } FACE[HEADER.FaceCount]; 178 | }; 179 | 180 | UINT AB; 181 | UINT Size; 182 | if (AB == 0) 183 | { 184 | UINT E; 185 | UINT EE; 186 | }; 187 | 188 | pos = FTell(); 189 | 190 | struct { 191 | for (i = 0; i < HEADER.MeshCount; ++i) 192 | { 193 | if (AB != 0) 194 | FSeek(pos + MESH[i].startVert*44.0); 195 | else 196 | FSeek(pos + MESH[i].startVert*36.0); 197 | struct { 198 | struct { 199 | struct { 200 | FLOAT X; 201 | FLOAT Y; 202 | FLOAT Z; 203 | } POSITION; 204 | struct { 205 | FLOAT X; 206 | FLOAT Y; 207 | FLOAT Z; 208 | FLOAT W; 209 | } U4; 210 | struct { 211 | FLOAT U; 212 | FLOAT V; 213 | } UV; 214 | if (AB != 0) 215 | { 216 | FLOAT U; 217 | FLOAT V; 218 | }; 219 | } VERTEX[MESH[i].VertCount]; 220 | } MESH_VERTEXES; 221 | }; 222 | } VERTEXES; 223 | 224 | if (AB == 0) 225 | struct { 226 | FLOAT A; 227 | FLOAT A; 228 | FLOAT A; 229 | FLOAT A; 230 | FLOAT A; 231 | FLOAT A; 232 | FLOAT A; 233 | FLOAT A; 234 | FLOAT A; 235 | FLOAT A; 236 | FLOAT A; 237 | } UNKI[EE/44.0]; 238 | 239 | 240 | if (HEADER.Version > 0) 241 | { 242 | UINT CountA; 243 | UINT CountB; 244 | 245 | struct { 246 | UINT A; 247 | FLOAT A; 248 | FLOAT A; 249 | FLOAT A; 250 | FLOAT A; 251 | FLOAT A; 252 | } K1[CountA]; 253 | 254 | UINT E; 255 | struct { 256 | FLOAT A; 257 | FLOAT A; 258 | FLOAT A; 259 | } K2[CountB]; 260 | 261 | struct { 262 | UBYTE I1; 263 | UBYTE I2; 264 | UBYTE I3; 265 | 266 | UBYTE I1; 267 | UBYTE I2; 268 | UBYTE I3; 269 | 270 | UBYTE I1; 271 | UBYTE I2; 272 | UBYTE I3; 273 | } FACES[FacesExtra]; 274 | }; 275 | }; 276 | 277 | -------------------------------------------------------------------------------- /templates/010Editor/IDF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: IDF.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: Sea Dogs IDF files 8 | // File Mask: *.idf 9 | // 10 | // History: 11 | // 12 | // 2018.05 v0.1 Initial release 13 | //------------------------------------------------ 14 | 15 | 16 | struct { 17 | UINT MN ; 18 | UINT Count; 19 | UINT PropertyCount; 20 | } HEADER ; 21 | 22 | typedef struct { 23 | UINT PropertyCount; 24 | typedef struct { 25 | UINT Unknown; 26 | char Name[64]; 27 | char Property[64]; 28 | } PROPERTIES ; 29 | 30 | PROPERTIES Properties[PropertyCount] ; 31 | 32 | } OBJECT ; 33 | 34 | string getName(OBJECT &Obj) { 35 | return Obj.Properties[0].Property; 36 | } 37 | 38 | typedef struct (uint size) { 39 | OBJECT array[size] ; 40 | } OBJECT_TABLE; 41 | 42 | OBJECT_TABLE Object(HEADER.Count) ; -------------------------------------------------------------------------------- /templates/010Editor/PAK(PB).bt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexKimov/seadogs-file-formats/e8521eafe6c801398dfea8df72247ed045c3f636/templates/010Editor/PAK(PB).bt -------------------------------------------------------------------------------- /templates/010Editor/PAK.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: PAK.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: Age of Sale 2 (2001) game PAK files 8 | // File Mask: *.pak 9 | // 10 | // History: 11 | // 12 | // 2018.07 v0.1 Initial release 13 | // 14 | //------------------------------------------------ 15 | 16 | local uint i, count1, coun2 = 0; 17 | 18 | uint checkFolder() { 19 | struct { 20 | BYTE type; // 1 - file, 0 - folder start, 2 - end 21 | } CHECK ; 22 | FSeek(FTell() - 1); 23 | return CHECK.type; 24 | }; 25 | 26 | struct { 27 | char ENPAK[6] ; 28 | BYTE Level; // ? 29 | BYTE Unknown; // 0 30 | BYTE Unknown; // 1 31 | BYTE empty[17]; 32 | } HEADER ; 33 | 34 | typedef struct { 35 | BYTE type; // 1 - file, 0 - folder start, 2 - folder end 36 | 37 | if (type == 0) 38 | UINT FileCount; 39 | else 40 | UINT DataSize; 41 | UINT Offset; 42 | UINT Unknown; // 1 - ?? 43 | UINT Empty; // 0 44 | string Name; 45 | } FILE_HEADER ; 46 | 47 | typedef struct (uint size) { 48 | FILE_HEADER array[size] ; 49 | } FILE_TABLE; 50 | 51 | string fileName(FILE_HEADER &fn) { 52 | switch (fn.type) { 53 | case 1: return "FILE: " + fn.Name; break; 54 | case 0: return "Folder Start: " + fn.Name; break; 55 | case 2: return "Folder End"; break; 56 | } 57 | }; 58 | 59 | // Folders starts first 60 | 61 | FILE_TABLE ResourceFolder(1) ; 62 | 63 | if (checkFolder() == 2) 64 | FILE_TABLE Folder0(1) ; 65 | 66 | FILE_TABLE Folder1(1) ; 67 | 68 | if (checkFolder() == 0) 69 | FILE_TABLE Folder2(1) ; 70 | 71 | // Files 72 | 73 | if (exists(Folder2)) { 74 | FILE_TABLE Files1(Folder2.array.FileCount) ; 75 | FILE_TABLE End(1) ; 76 | FILE_TABLE Files2(Folder1.array.FileCount) ; 77 | } 78 | else 79 | FILE_TABLE Files1(Folder1.array.FileCount) ; 80 | 81 | // folders end 82 | FILE_TABLE End(1) ; 83 | if (!exists(Folder0)) 84 | FILE_TABLE End(1) ; 85 | 86 | typedef struct (uint pos, string name) { 87 | local string n = name; 88 | FSeek(FTell() + pos); 89 | } FILE ; 90 | 91 | string getName(FILE &File) { 92 | return File.n; 93 | }; 94 | 95 | struct { 96 | if (exists(Folder2)) 97 | for (i = 0; i < Folder2.array.FileCount; ++i) { 98 | FILE File(Files1.array[i].DataSize, Files1.array[i].Name); 99 | }; 100 | 101 | for (i = 0; i < Folder1.array.FileCount; ++i) { 102 | FILE File(Files1.array[i].DataSize, Files1.array[i].Name); 103 | }; 104 | } FILES ; -------------------------------------------------------------------------------- /templates/010Editor/SC.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | typedef enum { 15 | Elite, 16 | Veteran, 17 | SeaDog, 18 | Sailor, 19 | Novice, 20 | Rookie, 21 | Lady 22 | } CLASS; 23 | 24 | typedef enum { 25 | Calm = 0, 26 | Light_air = 1, 27 | Light_breeze = 2, 28 | Gentle_breeze = 3, 29 | Moderate_breeze = 4, 30 | Fresh_breeze = 5, 31 | Strong_breeze = 6, 32 | High_wind = 7, 33 | Gail = 8, 34 | Strong_gail = 9, 35 | Storm = 10, 36 | Violent_storm = 11, 37 | Hurricane = 12 38 | } BEAUFORT; 39 | 40 | typedef enum { 41 | Britain = 0, 42 | France = 1, 43 | Spain = 2, 44 | USA = 4, 45 | RUSSIA = 5, 46 | Turkey = 6, 47 | Holland = 7, 48 | Sweden = 8, 49 | Portugal = 9, 50 | Naples = 10, 51 | Danmark = 11, 52 | Privateer1 = 12, 53 | Privateer2 = 13, 54 | Privateer3 = 14, 55 | Slave_trader = 15, 56 | Smuggler1 = 16, 57 | Smuggler2 = 17, 58 | Smuggler3 = 18, 59 | Swargard = 19, 60 | Heritage = 20 61 | } COUNTRY; 62 | 63 | struct { 64 | char AOSS[6]; 65 | UINT16 A; // 0 66 | UINT ShipCount1; 67 | UINT ShipCount2; 68 | UINT B; 69 | } HEADER; 70 | 71 | char EnvironmentName[101]; 72 | char MapFileName[263]; 73 | 74 | struct { 75 | BEAUFORT BeaufortWind; 76 | FLOAT WindDirection; 77 | UINT WindForceChangeProbability; 78 | UINT WindDirectionChangeProbability; 79 | UINT WindForceAmplitude; 80 | UINT WindDirectionAmplitude; 81 | } WIND; 82 | struct { 83 | UINT Hour; 84 | UINT Minute; 85 | } TIME; 86 | UINT Weather; // snow, rain, fog, lightning 87 | UINT Unknown; 88 | UINT TimeLimit; 89 | struct { 90 | COUNTRY Country; 91 | UINT Victory; 92 | UINT Points; 93 | } CountryA; 94 | struct { 95 | COUNTRY Country; 96 | UINT Victory; 97 | UINT Points; 98 | } CountryB; 99 | 100 | UINT Unknown; 101 | 102 | struct { 103 | struct { 104 | FLOAT X; 105 | FLOAT Z; 106 | FLOAT Y; 107 | } POSITION; 108 | struct { 109 | FLOAT A; 110 | FLOAT A; 111 | } ROTATION; 112 | FLOAT Unknown; 113 | } CAMERA1_POSITION; 114 | 115 | struct { 116 | struct { 117 | FLOAT X; 118 | FLOAT Z; 119 | FLOAT Y; 120 | } POSITION; 121 | struct { 122 | FLOAT X; 123 | FLOAT Z; 124 | } ROTATION; 125 | FLOAT Unknown; 126 | } CAMERA2_POSITION; 127 | 128 | UINT A; 129 | struct { 130 | FLOAT X1; 131 | FLOAT X2; 132 | FLOAT Y1; 133 | FLOAT Y2; 134 | } MAP_AREA; 135 | 136 | FLOAT Unknown; 137 | FLOAT Unknown; 138 | FLOAT Unknown; 139 | UINT Unknown; 140 | UINT Unknown; 141 | UINT Unknown; 142 | UINT Year; 143 | UINT Unknown; 144 | UINT Unknown; 145 | UINT Unknown; 146 | UINT Unknown; 147 | 148 | BYTE Empty[40]; 149 | 150 | string Title; 151 | string Briefing; 152 | if (Briefing == "") 153 | UBYTE Empty3[61]; 154 | 155 | typedef struct { 156 | char ShipName[101]; 157 | char ShName[31]; 158 | char ShFileName[32]; 159 | string Name; 160 | struct { 161 | UINT A; 162 | UINT Class; 163 | UINT DisplacementTonnage; 164 | UINT SoldierCount; 165 | UINT Year; 166 | UINT SailorCount; 167 | UINT Mizenmast; 168 | UINT Mainmast; 169 | UINT Foremast; 170 | UINT mast; 171 | UINT Quarterdeck; 172 | UINT Upperdeck; 173 | UINT Forecastle; 174 | UINT GunCalibre; 175 | UINT Calibre; 176 | UINT CarronadeCalibre; 177 | UINT UpperdeckGunCalibre; 178 | UINT MiddleDeck; 179 | UINT MiddleDeckGunCalibre; 180 | UINT LowerDeck; 181 | UINT LowerDeckGunCalibre; 182 | UINT ForecastleGunCalibre; 183 | UINT ForecastleCarronadeCount; 184 | UINT ForecastleCarronadeCalibre; 185 | UINT Speed; 186 | UINT Manoeuvrability; 187 | UINT Height; 188 | UINT Draft; 189 | } PARAMETERS; 190 | UINT A; 191 | UINT A; 192 | UINT A; 193 | UINT A; 194 | UINT A; 195 | UINT A; 196 | UINT A; 197 | UINT A; 198 | UINT A; 199 | UINT A; 200 | FLOAT A; 201 | FLOAT A; 202 | FLOAT A; 203 | FLOAT A; 204 | FLOAT A; 205 | FLOAT A; 206 | FLOAT A; 207 | FLOAT A; 208 | FLOAT A; 209 | FLOAT A; 210 | FLOAT GunsCharge1; 211 | FLOAT GunsCharge2; 212 | FLOAT GunsCharge3; 213 | FLOAT GunsCharge4; 214 | FLOAT Rotation; 215 | FLOAT PositionX; 216 | FLOAT A; 217 | FLOAT PositionY; 218 | FLOAT A; 219 | UINT A; 220 | UINT A; 221 | UINT A; 222 | UINT A; 223 | UINT A; 224 | UINT A; 225 | UINT A; 226 | UINT A; 227 | UINT Owner; // 1 - B side 228 | CLASS Class; // 229 | UINT Team; 230 | UINT Hull; 231 | UINT Sail; 232 | UINT Guns; 233 | UINT A; 234 | UINT A; 235 | UINT A; 236 | UINT A; 237 | UINT A; 238 | } SHIP; 239 | 240 | SHIP Ships1[HEADER.ShipCount1] ; 241 | 242 | SHIP Ships2[HEADER.ShipCount2] ; 243 | 244 | -------------------------------------------------------------------------------- /templates/010Editor/SLS.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | typedef enum { 15 | Square = 0, 16 | Unknown1 = 1, 17 | Unknown2 = 2, 18 | ForeAndAft = 3 19 | } SAIL_TYPE; 20 | 21 | while (!FEof()) { 22 | struct { 23 | UINT Index; 24 | SAIL_TYPE Type; 25 | struct { 26 | struct { 27 | FLOAT X; 28 | FLOAT Y; 29 | FLOAT Z; 30 | } VERTEX1 ; 31 | struct { 32 | FLOAT X; 33 | FLOAT Y; 34 | FLOAT Z; 35 | } VERTEX2 ; 36 | 37 | FLOAT Unknonwn; 38 | 39 | struct { 40 | FLOAT X; 41 | FLOAT Y; 42 | FLOAT Z; 43 | } VERTEX3 ; 44 | struct { 45 | FLOAT X; 46 | FLOAT Y; 47 | FLOAT Z; 48 | } VERTEX4 ; 49 | } SAIL_VERTEX_POSITION; 50 | 51 | 52 | UINT Count ; 53 | 54 | struct { 55 | string FileName ; 56 | BYTE Data[20 - sizeof(FileName)]; 57 | UINT Unknown; 58 | UINT Unknown; 59 | UINT Unknown; 60 | 61 | UINT VertexCount; 62 | UINT CountB; 63 | struct { 64 | FLOAT X; 65 | FLOAT Y; 66 | FLOAT Z; 67 | FLOAT Unknown; 68 | FLOAT Unknown; 69 | FLOAT Unknown; 70 | FLOAT Unknown; 71 | } VERTEXES[VertexCount]; 72 | 73 | struct { 74 | FLOAT Unknown; 75 | FLOAT Unknown; 76 | FLOAT Unknown; 77 | FLOAT Unknown; 78 | 79 | FLOAT Unknown; 80 | FLOAT Unknown; 81 | FLOAT Unknown; 82 | FLOAT Unknown; 83 | } MN2[CountB]; 84 | } YARDS[Count] ; 85 | 86 | } SAIL; 87 | }; 88 | 89 | -------------------------------------------------------------------------------- /templates/010Editor/TF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: TF.bt 5 | // Authors: Alexander Evdokimov 6 | // Version: 0.1 7 | // Purpose: Sea Dogs game TF files 8 | // File Mask: *.tf 9 | // 10 | // History: 11 | // 12 | // 2018.06 v0.1 Initial release 13 | // 14 | //------------------------------------------------ 15 | 16 | local uint i, height, width = 0; 17 | 18 | struct { 19 | UINT Unknown ; // 250698 20 | UBYTE Unknown; 21 | UBYTE Type; // 0 - RGB565, 1 - 22 | UBYTE MipMapCount; 23 | UBYTE MaskCount; 24 | UINT Width; 25 | UINT Height; 26 | } HEADER ; 27 | 28 | BitfieldDisablePadding(); 29 | 30 | typedef struct { 31 | ubyte Red : 5 ; 32 | ubyte Green : 6 ; 33 | ubyte Blue : 5 ; 34 | } RGB565 ; 35 | 36 | typedef struct { 37 | ubyte Red : 5 ; 38 | ubyte Green : 5 ; 39 | ubyte Blue : 5 ; 40 | ubyte Alpha : 1 ; 41 | } RGB5551 ; 42 | 43 | if (HEADER.Type == 1) 44 | RGB565 Pixels[HEADER.Width*HEADER.Height] ; 45 | else 46 | RGB5551 Pixels[HEADER.Width*HEADER.Height] ; 47 | 48 | typedef struct (uint count) { 49 | height = HEADER.Height, width = HEADER.Width; 50 | for (i = 0; i < count; ++i) { 51 | height = height/2; 52 | width = width/2; 53 | struct { 54 | if (HEADER.Type == 1) 55 | RGB565 MipMaps[height*width] ; 56 | else 57 | RGB5551 MipMaps[height*width] ; 58 | } PIXELS; 59 | }; 60 | } MAPS; 61 | 62 | MAPS Maps(HEADER.MipMapCount - 1) ; 63 | 64 | typedef struct { 65 | UBYTE Red ; 66 | UBYTE Green ; 67 | UBYTE Blue ; 68 | UBYTE Alpha ; 69 | } PALETTE ; 70 | 71 | typedef struct { 72 | UBYTE Index; 73 | } COLOR_TABLE; 74 | 75 | struct { 76 | PALETTE P[256] ; 77 | height = HEADER.Height, width = HEADER.Width; 78 | for (i = 0; i < HEADER.MaskCount; ++i) { 79 | struct { 80 | COLOR_TABLE Pixels[height*width] ; 81 | } PIXELS; 82 | height = height/2; 83 | width = width/2; 84 | }; 85 | } PALETTED_IMAGE; -------------------------------------------------------------------------------- /templates/010Editor/TX.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | struct { 15 | local float height, width; 16 | local int DXT = 0; 17 | local int i; 18 | } locals ; 19 | 20 | typedef enum { 21 | DXT1, 22 | DXT3, 23 | DXT5 24 | } DXT_TYPE ; 25 | 26 | typedef enum { 27 | D3DFMT_A8R8G8B8 = 21, 28 | D3DFMT_X8R8G8B8 = 22, 29 | D3DFMT_R5G6B5 = 23, 30 | D3DFMT_X1R5G5B5 = 24, 31 | D3DFMT_A1R5G5B5 = 25, 32 | D3DFMT_A4R4G4B4 = 26 33 | } D3DFORMAT; 34 | 35 | struct { 36 | UINT Version; 37 | UINT Width; 38 | UINT Height; 39 | UINT MapsCount; 40 | union { 41 | DXT_TYPE DXT[4]; 42 | D3DFORMAT D3DFormat; 43 | } IMAGE_TYPE; 44 | 45 | UINT Size ; 46 | } HEADER ; 47 | 48 | BitfieldDisablePadding(); 49 | 50 | typedef struct { 51 | switch (HEADER.IMAGE_TYPE.D3DFormat) 52 | { 53 | case 21: // A8R8G8B8 54 | ubyte Red ; 55 | ubyte Green ; 56 | ubyte Blue ; 57 | ubyte Alpha ; 58 | break; 59 | case 22: // X8R8G8B8 60 | ubyte Red ; 61 | ubyte Green ; 62 | ubyte Blue ; 63 | ubyte X ; 64 | break; 65 | case 23: // R5G6B5 66 | ubyte Red : 5 ; 67 | ubyte Green : 6 ; 68 | ubyte Blue : 5 ; 69 | break; 70 | case 26: 71 | ubyte Red : 4 ; 72 | ubyte Green : 4 ; 73 | ubyte Blue : 4 ; 74 | ubyte Alpha : 4 ; 75 | } 76 | } PIXEL ; 77 | 78 | typedef struct { 79 | if (HEADER.IMAGE_TYPE.DXT != "DXT1") 80 | { 81 | struct { 82 | if (HEADER.IMAGE_TYPE.DXT != "DXT5") { 83 | for (locals.i = 0; locals.i < 16; ++locals.i) { 84 | ubyte AlphaIndex : 4 ; 85 | } 86 | } 87 | else { 88 | ubyte Alpha1; 89 | ubyte Alpha2; 90 | for (locals.i = 0; locals.i < 16; ++locals.i) { 91 | ubyte AlphaIndex : 3 ; 92 | } 93 | } 94 | } AlphaChannel ; 95 | }; 96 | 97 | struct { 98 | struct { 99 | ubyte Red : 5 ; 100 | ubyte Green : 6 ; 101 | ubyte Blue : 5 ; 102 | } Color1; 103 | struct { 104 | ubyte Red : 5 ; 105 | ubyte Green : 6 ; 106 | ubyte Blue : 5 ; 107 | } Color2; 108 | struct { 109 | for (locals.i = 0; locals.i < 16; ++locals.i) 110 | ubyte PixelIndex : 2 ; 111 | } INDEX_TABLE; 112 | } COLOR_DATA ; 113 | } TEXEL ; 114 | 115 | int sizeTEXEL( TEXEL &texel ) 116 | { 117 | if (HEADER.IMAGE_TYPE.DXT != "DXT1") 118 | return 16; 119 | else 120 | return 8; 121 | }; 122 | 123 | int sizePixel( PIXEL &pixel ) 124 | { 125 | if (HEADER.IMAGE_TYPE.D3DFormat == 21 || HEADER.IMAGE_TYPE.D3DFormat == 22) 126 | return 4; 127 | else 128 | return 2; 129 | }; 130 | 131 | typedef struct (int arraySize) { 132 | PIXEL array[arraySize] ; 133 | } PIXEL_ARRAY; 134 | 135 | typedef struct (int arraySize) { 136 | TEXEL array[arraySize] ; 137 | } TEXEL_ARRAY; 138 | 139 | if (HEADER.IMAGE_TYPE.D3DFormat <= 26) 140 | PIXEL_ARRAY Pixels(HEADER.Width*HEADER.Height) ; 141 | else 142 | TEXEL_ARRAY Pixels(HEADER.Width*HEADER.Height/16) ; 143 | 144 | typedef struct { 145 | locals.height = HEADER.Height, locals.width = HEADER.Width; 146 | while (1) 147 | { 148 | locals.height = locals.height/2.0; 149 | locals.width = locals.width/2.0; 150 | if (HEADER.IMAGE_TYPE.D3DFormat == 21) 151 | PIXEL_ARRAY MipMaps(locals.height*locals.width) ; 152 | else 153 | TEXEL_ARRAY MipMaps(locals.height*locals.width) ; 154 | if (locals.height == 1) break; 155 | }; 156 | } MIP_MAPS ; 157 | 158 | if (HEADER.MapsCount > 1) 159 | MIP_MAPS MipMaps; -------------------------------------------------------------------------------- /templates/010Editor/XPS.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | struct { 15 | uchar Magic[8]; 16 | UINT A; 17 | UINT B; 18 | UINT C; 19 | UINT D; 20 | } Header; 21 | 22 | uchar Name[128]; 23 | 24 | typedef struct { 25 | UINT Length; 26 | uchar Name[Length]; 27 | } NAME; 28 | 29 | NAME Name; 30 | 31 | UINT A[4]; 32 | 33 | NAME Name; 34 | 35 | UINT B[2]; 36 | 37 | NAME Name; 38 | 39 | UINT C[2]; 40 | 41 | NAME Name; -------------------------------------------------------------------------------- /templates/010Editor/ZAP.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // File Mask: 10 | // ID Bytes: 11 | // History: 12 | //------------------------------------------------ 13 | 14 | struct { 15 | UINT S; 16 | UINT BlockInRowCount; // 128 17 | UINT BlockSize; // 8 18 | UINT A3; // 3 19 | UINT A4; // 7 20 | UINT BlockCount; 21 | } HEADER; 22 | 23 | struct { 24 | UINT16 BlockNumber; 25 | } TABLE[HEADER.S*HEADER.BlockInRowCount/HEADER.BlockSize] ; 26 | 27 | struct { 28 | UBYTE Block8x8[HEADER.BlockSize*HEADER.BlockSize]; 29 | } BLOCKS[HEADER.BlockCount]; 30 | 31 | --------------------------------------------------------------------------------