Skip to content
Snippets Groups Projects
Commit e67bbcf2 authored by LogicDragon's avatar LogicDragon
Browse files

Fixed EnumerateObjects to write the correct block order

parent cf9927fc
No related branches found
No related tags found
No related merge requests found
...@@ -31,8 +31,7 @@ All rights reserved. Please see niflib.h for license. */ ...@@ -31,8 +31,7 @@ All rights reserved. Please see niflib.h for license. */
#include "../include/obj/NiMultiTargetTransformController.h" #include "../include/obj/NiMultiTargetTransformController.h"
#include "../include/obj/NiStringExtraData.h" #include "../include/obj/NiStringExtraData.h"
#include "../include/obj/NiExtraData.h" #include "../include/obj/NiExtraData.h"
#include "../include/obj/bhkRigidBody.h" #include "../include/obj/bhkConstraint.h"
#include "../include/obj/bhkCollisionObject.h"
#include "../include/gen/Header.h" #include "../include/gen/Header.h"
#include "../include/gen/Footer.h" #include "../include/gen/Footer.h"
...@@ -43,7 +42,8 @@ bool g_objects_registered = false; ...@@ -43,7 +42,8 @@ bool g_objects_registered = false;
void RegisterObjects(); void RegisterObjects();
//Utility Functions //Utility Functions
void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map, bool reverse = false ); bool BlockChildBeforeParent( NiObject * root );
void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map );
NiObjectRef FindRoot( vector<NiObjectRef> const & objects ); NiObjectRef FindRoot( vector<NiObjectRef> const & objects );
NiObjectRef GetObjectByType( NiObject * root, const Type & type ); NiObjectRef GetObjectByType( NiObject * root, const Type & type );
...@@ -577,50 +577,62 @@ void WriteNifTree( ostream & out, NiObject * root, const NifInfo & info ) { ...@@ -577,50 +577,62 @@ void WriteNifTree( ostream & out, NiObject * root, const NifInfo & info ) {
WriteNifTree( out, roots, info ); WriteNifTree( out, roots, info );
} }
void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map, bool reverse ) { // Determine whether block comes before its parent or not, depending on the block type.
//Ensure that this object has not already been visited // return: 'True' if child should come first, 'False' otherwise.
bool BlockChildBeforeParent( NiObject * root ) {
Type *t = (Type*)&(root->GetType());
return (t->IsDerivedType(bhkRefObject::TYPE) && !t->IsDerivedType(bhkConstraint::TYPE));
}
// This is a helper function for write to set up the list of all blocks,
// the block index map, and the block type map.
void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<NiObjectRef, unsigned int> & link_map ) {
// Ensure that this object has not already been visited
if ( link_map.find( root ) != link_map.end() ) { if ( link_map.find( root ) != link_map.end() ) {
//This object has already been visited. Return. //This object has already been visited. Return.
return; return;
} }
//Add this object type to the map if it isn't there already list<NiObjectRef> links = root->GetRefs();
if ( type_map.find( (Type*)&(root->GetType()) ) == type_map.end() ) { Type *t = (Type*)&(root->GetType());
//The type has not yet been registered, so register it
unsigned int n = type_map.size(); // special case: add bhkConstraint entities before bhkConstraint
type_map[ (Type*)&(root->GetType()) ] = n; // (these are actually links, not refs)
if ( t->IsDerivedType(bhkConstraint::TYPE) ) {
vector< bhkEntity * > entities = ((bhkConstraint *)root)->GetEntities();
for ( vector< bhkEntity * >::iterator it = entities.begin(); it != entities.end(); ++it ) {
if ( *it != NULL ) {
EnumerateObjects( (NiObject*)(*it), type_map, link_map );
}
}
} }
// Oblivion has very rigid requirements about object ordering and the bhkRigidBody // Call this function on all links of this object
// must be after its children. Hopefully this can be removed and replaced with // add children that come before the block
// a more generic mechanism in the future. for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
Type *t = (Type*)&(root->GetType()); if ( *it != NULL && BlockChildBeforeParent(*it) ) {
if ( reverse EnumerateObjects( *it, type_map, link_map );
|| t->IsDerivedType(bhkRigidBody::TYPE) }
|| t->IsDerivedType(bhkCollisionObject::TYPE) }
)
{
reverse = true;
}
// If reverse is set then add the link after children otherwise add it before // Add this object type to the map if it isn't there already
if (!reverse) { // TODO: add support for NiDataStreams
unsigned int n = link_map.size(); if ( type_map.find(t) == type_map.end() ) {
link_map[root] = n; //The type has not yet been registered, so register it
} unsigned int n = type_map.size();
type_map[t] = n;
}
//Call this function on all links of this object // add the block
list<NiObjectRef> links = root->GetRefs(); unsigned int n = link_map.size();
for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) { link_map[root] = n;
if ( *it != NULL ) {
EnumerateObjects( *it, type_map, link_map, reverse );
}
}
if (reverse) { // add children that come after the block
unsigned int n = link_map.size(); for ( list<NiObjectRef>::iterator it = links.begin(); it != links.end(); ++it ) {
link_map[root] = n; if ( *it != NULL && !BlockChildBeforeParent(*it) ) {
} EnumerateObjects( *it, type_map, link_map );
}
}
} }
//TODO: Should this be returning an object of a derived type too? //TODO: Should this be returning an object of a derived type too?
......
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