-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exports the t0 mesh with the h0 and all the rigs as a multimesh
- Loading branch information
1 parent
e11dd68
commit e2ff7aa
Showing
1 changed file
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
// Entity export script for characters with Rigs | ||
// @author Simarilius, DZK & Seberoth | ||
// @version 0.2 | ||
// Exports ent files and all referenced files (recursively) | ||
import * as Logger from 'Logger.wscript'; | ||
import * as TypeHelper from 'TypeHelper.wscript'; | ||
|
||
const fileTemplate = '{"Header":{"WKitJsonVersion":"0.0.7","DataType":"CR2W"},"Data":{"Version":195,"BuildVersion":0,"RootChunk":{},"EmbeddedFiles":[]}}'; | ||
const jsonExtensions = [".app", ".ent", ".mesh", ".rig",".phys"]; | ||
const exportExtensions = [".anims", ".mesh"]; | ||
const exportEmbeddedExtensions = [".mesh", ".xbm", ".mlmask"]; | ||
|
||
// Rather than a manual list does it for all ents in the project. | ||
var ents = []; | ||
|
||
// if you dont want to process any entities already in the project set this to false | ||
var add_from_project = true; | ||
|
||
// sets of files that are parsed for processing | ||
const parsedFiles = new Set(); | ||
const projectSet = new Set(); | ||
const exportSet = new Set(); | ||
const jsonSet = new Set(); | ||
const rigs = new Map(); | ||
const mergemeshes = new Set(); | ||
const bodymesh = new Set(); | ||
|
||
if (add_from_project) { | ||
for (var filename of wkit.GetProjectFiles('archive')) { | ||
//Logger.Info(filename) | ||
var ext = filename.split('.').pop(); | ||
if (ext === "ent") { | ||
ents.push(filename); | ||
} | ||
if (ext === "anims") { | ||
exportSet.add(filename); | ||
} | ||
} | ||
} | ||
|
||
// Set these to true if you want proxys/shadow meshes | ||
var include_proxys = false; | ||
var include_shadows = false; | ||
var include_fx = false; | ||
|
||
// loop over every entity in `ents` and find rigs | ||
for (var ent in ents) { | ||
Logger.Info('Finding rigs in ' + ents[ent]); | ||
FindEntRigs(ents[ent]); | ||
// FindEntAnims(ents[ent]); //uncomment if you want the anims | ||
Logger.Info(''); | ||
for (const [key, value] of rigs) { | ||
Logger.Info(`${key} = ${value}`); | ||
if (!value.includes("base_rig")) { | ||
projectSet.add(value); | ||
jsonSet.add(value); | ||
} | ||
} | ||
Logger.Info(''); | ||
} | ||
|
||
// now find the mesh files | ||
for (var ent in ents) { | ||
Logger.Info(ents[ent]); | ||
ParseFile(ents[ent], null); | ||
} | ||
|
||
// save all our files to the project and export JSONs | ||
for (const fileName of projectSet) { | ||
// skip shadows if the variable is set | ||
if ((include_shadows == false) && (fileName.includes("shadow"))) { | ||
continue; | ||
} | ||
// skip proxies if the variable is set | ||
if ((include_proxys == false) && (fileName.includes("proxy"))) { | ||
continue; | ||
} | ||
// skip fx bodies if the variable is set | ||
if ((include_fx == false) && (fileName.includes("fx"))) { | ||
continue; | ||
} | ||
// Load project vesion if it exists, otherwise add to the project | ||
if (wkit.FileExistsInProject(fileName)) { | ||
var file = wkit.GetFileFromProject(fileName, OpenAs.GameFile); | ||
} | ||
else { | ||
var file = wkit.GetFileFromBase(fileName); | ||
wkit.SaveToProject(fileName, file); | ||
} | ||
|
||
if (jsonSet.has(fileName)) { | ||
var path = ""; | ||
if (file.Extension === ".ent") { | ||
path = wkit.ChangeExtension(file.Name, ".ent.json"); | ||
} | ||
if (file.Extension === ".app") { | ||
path = wkit.ChangeExtension(file.Name, ".app.json"); | ||
} | ||
if (file.Extension === ".rig") { | ||
path = wkit.ChangeExtension(file.Name, ".rig.json"); | ||
} | ||
if (file.Extension === ".mesh") { | ||
path = wkit.ChangeExtension(file.Name, ".mesh.json"); | ||
} | ||
if (file.Extension === ".phys") { | ||
path = wkit.ChangeExtension(file.Name, ".phys.json"); | ||
} | ||
if (path.length > 0) { | ||
var json = wkit.GameFileToJson(file); | ||
wkit.SaveToRaw(path, json); | ||
} | ||
} | ||
} | ||
|
||
|
||
var defmeshSettings = { | ||
"Mesh": { | ||
"MeshExporter": "Default", | ||
"meshExportType": "MeshOnly", // Or "ExportType": ... | ||
"LodFilter": true, | ||
"isGLBinary": true, // Or "Binary": ... | ||
"withMaterials": true, // Or "WithMaterials": ... | ||
"ExportGarmentSupport": true, | ||
"MultiMeshMeshes": [], | ||
"MultiMeshRigs" :[], | ||
"Rig": [], | ||
"MaterialUncookExtension": "png" // Or "ImageType": ... | ||
} | ||
} | ||
|
||
// export all of our files with the default export settings | ||
wkit.ExportFiles([...exportSet],defmeshSettings); | ||
|
||
var meshSettings = { | ||
"Mesh": { | ||
"MeshExporter": "Default", | ||
"meshExportType": "Multimesh", // Or "ExportType": ... | ||
"LodFilter": true, | ||
"isGLBinary": true, // Or "Binary": ... | ||
"withMaterials": true, // Or "WithMaterials": ... | ||
"ExportGarmentSupport": true, | ||
"MultiMeshMeshes": Array.from(mergemeshes), | ||
"MultiMeshRigs" :Array.from(rigs.values()), | ||
"Rig": [], | ||
"MaterialUncookExtension": "png" // Or "ImageType": ... | ||
} | ||
} | ||
wkit.ExportFiles([...bodymesh], meshSettings); | ||
|
||
|
||
|
||
// begin helper functions | ||
function* GetPaths(jsonData) { | ||
for (let [key, value] of Object.entries(jsonData || {})) { | ||
if (value instanceof TypeHelper.ResourcePath && !value.isEmpty()) { | ||
yield value.value; | ||
} | ||
|
||
if (typeof value === "object") { | ||
yield* GetPaths(value); | ||
} | ||
} | ||
} | ||
|
||
function convertEmbedded(embeddedFile) { | ||
let data = TypeHelper.JsonParse(fileTemplate); | ||
data["Data"]["RootChunk"] = embeddedFile["Content"]; | ||
let jsonString = TypeHelper.JsonStringify(data); | ||
|
||
let cr2w = wkit.JsonToCR2W(jsonString); | ||
wkit.SaveToProject(embeddedFile["FileName"], cr2w); | ||
} | ||
|
||
// Parse a CR2W file | ||
function ParseFile(fileName, parentFile) { | ||
// check if we've already worked with this file and that it's actually a string | ||
if (parsedFiles.has(fileName)) { | ||
return; | ||
} | ||
parsedFiles.add(fileName); | ||
|
||
let extension = 'unkown'; | ||
if (typeof (fileName) === 'string') { | ||
extension = "." + fileName.split('.').pop(); | ||
} | ||
//Logger.Info('Extension ' + extension); | ||
if (extension !== 'unkown') { | ||
if (!(jsonExtensions.includes(extension) || exportExtensions.includes(extension))) { | ||
return; | ||
} | ||
|
||
if (parentFile != null && parentFile["Data"]["EmbeddedFiles"].length > 0) { | ||
for (let embeddedFile of parentFile["Data"]["EmbeddedFiles"]) { | ||
if (embeddedFile["FileName"] === fileName) { | ||
convertEmbedded(embeddedFile); | ||
|
||
if (jsonExtensions.includes(extension)) { | ||
jsonSet.add(fileName); | ||
} | ||
|
||
if (exportEmbeddedExtensions.includes(extension)) { | ||
exportSet.add(fileName); | ||
} | ||
|
||
return; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (fileName.split('\\').pop().split('/').pop().includes('h0_')){ | ||
mergemeshes.add(fileName) | ||
} | ||
if (fileName.split('\\').pop().split('/').pop().includes('t0_') && !fileName.includes('_dec_')){ | ||
bodymesh.add(fileName) | ||
} | ||
|
||
if (typeof (fileName) === 'bigint') { | ||
fileName = fileName.toString(); | ||
} | ||
|
||
if (typeof (fileName) !== 'string') { | ||
Logger.Error('Unknown path type'); | ||
return; | ||
} | ||
|
||
// Load project vesion if it exists, otherwise get the basegamefile | ||
if (wkit.FileExistsInProject(fileName)) { | ||
var file = wkit.GetFileFromProject(fileName, OpenAs.GameFile); | ||
} | ||
else { | ||
var file = wkit.GetFileFromBase(fileName); | ||
} | ||
|
||
if (file === null) { | ||
Logger.Error(fileName + " could not be found"); | ||
return; | ||
} | ||
|
||
extension = file.Extension; | ||
|
||
if (!(jsonExtensions.includes(extension) || exportExtensions.includes(extension))) { | ||
return; | ||
} | ||
|
||
|
||
|
||
if (jsonExtensions.includes(extension)) { | ||
projectSet.add(fileName); | ||
jsonSet.add(fileName); | ||
} | ||
|
||
if (exportExtensions.includes(extension)) { | ||
projectSet.add(fileName); | ||
exportSet.add(fileName); | ||
} | ||
|
||
if (extension === ".app" || extension === ".ent" || extension === ".mesh" || extension === ".anims") { | ||
var json = TypeHelper.JsonParse(wkit.GameFileToJson(file)); | ||
for (let path of GetPaths(json["Data"]["RootChunk"])) { | ||
ParseFile(path, json); | ||
} | ||
} | ||
} | ||
|
||
// Parse a ent file for rigs | ||
function FindEntRigs(fileName) { | ||
Logger.Info(fileName) | ||
if (wkit.FileExistsInProject(fileName)) { | ||
Logger.Info("Opening project Ent") | ||
var file = wkit.GetFileFromProject(fileName, OpenAs.GameFile); | ||
} | ||
else { | ||
Logger.Info("Opening basegame Ent") | ||
var file = wkit.GetFileFromBase(fileName); | ||
} | ||
var json = TypeHelper.JsonParse(wkit.GameFileToJson(file)); | ||
//find the rigs in the base ent components (normally root and deformations) | ||
for (let comp of json["Data"]["RootChunk"]["components"]) { | ||
if (!("rig" in comp) == 0) { | ||
Logger.Info(comp["name"]); | ||
Logger.Info(comp["rig"]["DepotPath"]); | ||
rigs.set(comp["name"].toString(), comp["rig"]["DepotPath"].toString()); | ||
projectSet.add(comp["rig"]["DepotPath"].toString()); | ||
} | ||
} | ||
// find any rigs referenced in the appearances (head and dangle) | ||
for (let app of json["Data"]["RootChunk"]["appearances"]) { | ||
var appfileName = app["appearanceResource"]["DepotPath"]; | ||
//Logger.Info(appfileName); | ||
var appfile = wkit.GetFileFromBase(appfileName.toString()); | ||
var appjson = TypeHelper.JsonParse(wkit.GameFileToJson(appfile)); | ||
for (let appApp of appjson["Data"]["RootChunk"]["appearances"]) { | ||
for (let appcomp of appApp["Data"]["components"]) { | ||
if (!("rig" in appcomp) == 0) { | ||
Logger.Info(appcomp["name"]); | ||
Logger.Info(appcomp["rig"]["DepotPath"]); | ||
rigs.set(appcomp["name"].toString(), appcomp["rig"]["DepotPath"].toString()); | ||
projectSet.add(appcomp["rig"]["DepotPath"].toString()); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Parse a ent file for rigs | ||
function FindEntAnims(fileName) { | ||
if (wkit.FileExistsInProject(fileName)) { | ||
var file = wkit.GetFileFromProject(fileName, OpenAs.GameFile); | ||
} | ||
else { | ||
var file = wkit.GetFileFromBase(fileName); | ||
} | ||
var json = TypeHelper.JsonParse(wkit.GameFileToJson(file)); | ||
//find the anims in the ent resolved dependencies | ||
for (let dep of json["Data"]["RootChunk"]["resolvedDependencies"]) { | ||
Logger.Info(dep["DepotPath"].toString()); | ||
projectSet.add(dep["DepotPath"].toString()); | ||
// exportSet.add(dep["DepotPath"].toString()); | ||
} | ||
} | ||
|
||
function get_filename(str) { | ||
return str.split('\\').pop().split('/').pop(); | ||
} |