Skip to content
Snippets Groups Projects
Commit a06ad515 authored by Amorilia's avatar Amorilia
Browse files

Finished code that creates XNif & XKf files; fixed bug in AttrControllerTarget.

parent 89a1a4cd
No related branches found
No related tags found
No related merge requests found
...@@ -1268,7 +1268,8 @@ public: ...@@ -1268,7 +1268,8 @@ public:
ReadUInt(in); ReadUInt(in);
} }
void WriteAttr( ofstream& out, unsigned int version ) { void WriteAttr( ofstream& out, unsigned int version ) {
WriteUInt( FindTarget()->GetBlockNum(), out ); //WriteUInt( FindTarget()->GetBlockNum(), out );
WriteUInt( FindTarget().get_index(), out ); // we need get_index(), GetBlockNum() chokes on null block references
} }
blk_ref FindTarget() const { blk_ref FindTarget() const {
//Find first ancestor that is controllable //Find first ancestor that is controllable
...@@ -1282,10 +1283,13 @@ public: ...@@ -1282,10 +1283,13 @@ public:
if (par.is_null() == true) if (par.is_null() == true)
return blk_ref(-1); return blk_ref(-1);
// If parent is NiSequenceStreamHelper, return null reference (this is necessary to create consistent XKf files)
if ( par->GetBlockType() == "NiSequenceStreamHelper" )
return blk_ref(-1);
//If parent is controllable, return it //If parent is controllable, return it
if ( par->IsControllable() == true ) { if ( par->IsControllable() == true )
return par; return par;
}
//We didn't find a node this time, set block to par and try again //We didn't find a node this time, set block to par and try again
block = par; block = par;
......
...@@ -498,65 +498,85 @@ void WriteNifTree( string file_name, blk_ref & root_block, unsigned int version ...@@ -498,65 +498,85 @@ void WriteNifTree( string file_name, blk_ref & root_block, unsigned int version
blk_ref txtkey_block = SearchNifTree( root_block, "NiTextKeyExtraData" ); blk_ref txtkey_block = SearchNifTree( root_block, "NiTextKeyExtraData" );
if ( txtkey_block.is_null() == false ) { if ( txtkey_block.is_null() == false ) {
// Create file names for the XKf and XNif files. // Create file names for the XKf and XNif files.
int file_name_dot = file_name.rfind("."); int file_name_slash = file_name.rfind("\\") + 1;
string file_name_base; string file_name_path = file_name.substr(0, file_name_slash);
if ( file_name_dot != string::npos ) string file_name_base = file_name.substr(file_name_slash, file_name.length());
file_name_base = file_name.substr(0, file_name_dot); int file_name_dot = file_name_base.rfind(".");
else file_name_base = file_name_base.substr(0, file_name_dot);
file_name_base = file_name; string xkf_name = file_name_path + "x" + file_name_base + ".kf";
string xkf_name = "x" + file_name + ".kf"; string xnif_name = file_name_path + "x" + file_name_base + ".nif";
string xnif_name = "x" + file_name + ".nif";
// Now construct the XNif file... // Now construct the XNif file...
// Ha, we are lazy. Copy the Nif file. // We are lazy. Copy the Nif file. (TODO: remove keyframe controllers & keyframe data)
WriteRawNifTree( xnif_name, root_block, version ); WriteRawNifTree( xnif_name, root_block, version );
cout << xnif_name << " written" << endl;
// Now the XKf file... // Now the XKf file...
// Create xkf root header. // Create xkf root header.
blk_ref xkf_root = CreateBlock("NiSequenceStreamHelper"); blk_ref xkf_root = CreateBlock("NiSequenceStreamHelper");
// Link the NiTextKeyExtraData block to it. // Add a copy of the NiTextKeyExtraData block to the XKf header.
xkf_root["Extra Data"] = txtkey_block; blk_ref xkf_txtkey_block = CreateBlock("NiTextKeyExtraData");
xkf_root["Extra Data"] = xkf_txtkey_block;
ITextKeyExtraData *itxtkey_block = QueryTextKeyExtraData(txtkey_block);
ITextKeyExtraData *ixkf_txtkey_block = QueryTextKeyExtraData(xkf_txtkey_block);
ixkf_txtkey_block->SetKeys(itxtkey_block->GetKeys());
// Append NiNodes with a NiKeyFrameController as NiStringExtraData blocks. // Append NiNodes with a NiKeyFrameController as NiStringExtraData blocks.
list<blk_ref> nodes = SearchAllNifTree( root_block, "NiNode" ); list<blk_ref> nodes = SearchAllNifTree( root_block, "NiNode" );
for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ) for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ) {
if ( blk_ref( (*it)->GetAttr("Controller") ).is_null() ) if ( (*it)->GetAttr("Controller")->asLink().is_null() || (*it)->GetAttr("Controller")->asLink()->GetBlockType() != "NiKeyframeController" )
it = nodes.erase( it ); it = nodes.erase( it );
else else
++it; it++;
};
blk_ref last_block = txtkey_block; blk_ref last_block = xkf_txtkey_block;
for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ++it ) {
blk_ref nodextra = CreateBlock("NiStringExtraData"); blk_ref nodextra = CreateBlock("NiStringExtraData");
nodextra["String Data"] = string( (*it)["Name"] ); nodextra["String Data"] = (*it)["Name"]->asString();
last_block["Next Extra Data"] = nodextra; last_block["Next Extra Data"] = nodextra;
last_block = nodextra;
}; };
// Add controllers & controller data. // Add controllers & controller data.
last_block = xkf_root; last_block = xkf_root;
list<blk_ref> orig_controllertargets;
for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { for ( list<blk_ref>::iterator it = nodes.begin(); it != nodes.end(); ++it ) {
blk_ref controller = blk_ref( (*it)->GetAttr("Controller") ); blk_ref controller = (*it)->GetAttr("Controller")->asLink();
if ( ! blk_ref( last_block["Next Controller"] ).is_null() ) blk_ref xkf_controller = CreateBlock("NiKeyframeController");
throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one... xkf_controller["Flags"] = controller["Flags"]->asInt();
if ( last_block == xkf_root ) xkf_controller["Frequency"] = controller["Frequency"]->asFloat();
last_block["Controller"] = controller; xkf_controller["Phase"] = controller["Phase"]->asFloat();
else xkf_controller["Start Time"] = controller["Start Time"]->asFloat();
last_block["Next Controller"] = controller; xkf_controller["Stop Time"] = controller["Stop Time"]->asFloat();
orig_controllertargets.push_back(controller["Target Node"]); // save this to restore later
controller["Target Node"] = blk_ref(); // destroy link blk_ref xkf_data = CreateBlock("NiKeyframeData");
last_block = controller; xkf_controller["Data"] = xkf_data;
IKeyframeData *ikfdata = QueryKeyframeData(controller["Data"]->asLink());
IKeyframeData *ixkfdata = QueryKeyframeData(xkf_controller["Data"]->asLink());
ixkfdata->SetRotateType(ikfdata->GetRotateType());
ixkfdata->SetTranslateType(ikfdata->GetTranslateType());
ixkfdata->SetScaleType(ikfdata->GetScaleType());
ixkfdata->SetRotateKeys(ikfdata->GetRotateKeys());
ixkfdata->SetTranslateKeys(ikfdata->GetTranslateKeys());
ixkfdata->SetScaleKeys(ikfdata->GetScaleKeys());
if ( last_block == xkf_root ) {
if ( ! last_block["Controller"]->asLink().is_null() )
throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
last_block["Controller"] = xkf_controller;
} else {
if ( ! last_block["Next Controller"]->asLink().is_null() )
throw runtime_error("Cannot create .kf file for multicontrolled nodes."); // not sure 'bout this one...
last_block["Next Controller"] = xkf_controller;
};
last_block = xkf_controller;
// note: targets are automatically calculated, we don't need to reset them
}; };
// Now write it out... // Now write it out...
WriteRawNifTree( xkf_name, xkf_root, version ); WriteRawNifTree( xkf_name, xkf_root, version );
// Restore the target controllers.
for ( list<blk_ref>::iterator it = nodes.begin(), it2 = orig_controllertargets.begin(); it != nodes.end(); ++it, ++it2 ) {
blk_ref controller = blk_ref( (*it)->GetAttr("Controller") );
controller["Target Node"] = *it2;
};
}; };
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment