Skip to content

Commit

Permalink
Ent export with Rig on body
Browse files Browse the repository at this point in the history
Exports the t0 mesh with the h0 and all the rigs as a multimesh
  • Loading branch information
Simarilius-uk authored Nov 27, 2023
1 parent e11dd68 commit e2ff7aa
Showing 1 changed file with 325 additions and 0 deletions.
325 changes: 325 additions & 0 deletions Scripts/Export_Ent_w_Rig.wscript
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();
}

0 comments on commit e2ff7aa

Please sign in to comment.