DumpClassListDemo::DumpClassListDemo( hkDemoEnvironment* env) : hkDefaultDemo(env) { hkString filePath("Common/Api/Serialize/Versioning/DumpClassList/"); hkString fileName = hkString(hkVersionUtil::getCurrentVersion()).replace("-","").replace(".","")+"Classes"; const char registryVariableName[] = "CustomStaticRegistry"; // Dump all currently reflected runtime classes // Open a stream to write the cpp header file { hkOstream outfile( hkString(filePath + fileName + ".h").cString() ); HK_ASSERT2( 0x215d080f, outfile.isOk(), "Could not open '" << fileName.cString() << "h' for writing." ); // extern the runtime classes into the header file hkVersionUtil::generateCppExternClassList(outfile, fileName.replace(".","_").asUpperCase().cString(), classes, registryVariableName); } // Open a stream to write the cpp source file { hkOstream outfile( hkString(filePath + fileName + ".cpp").cString() ); HK_ASSERT2( 0x215d0810, outfile.isOk(), "Could not open '" << fileName.cString() << "cpp' for writing." ); // set demos pch file const char* pchfilename = "demos/Demos.h"; // dump the runtime classes into the cpp file hkVersionUtil::generateCppClassList(outfile, classes, pchfilename, registryVariableName); } }
hkString TweakerUtils::clearData(const hkString& memberPath, void* rootData, const hkClass& rootKlass) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); int memberIdx = getMemberIdx(memberName, *klass); if (memberIdx < 0) return classPath; const hkClassMember& member = klass->getMember(memberIdx); void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkString str; switch (member.getType()) { case hkClassMember::TYPE_REAL : { hkReal& value = lookupMember<hkReal>(memberData); value = 0.0f; } break; case hkClassMember::TYPE_INT32 : { hkInt32& value = lookupMember<hkInt32>(memberData); value = 0; } break; case hkClassMember::TYPE_UINT32 : { hkUint32& value = lookupMember<hkUint32>(memberData); value = 0; } break; case hkClassMember::TYPE_BOOL : { bool& value = lookupMember<bool>(memberData); value = static_cast<bool>(0); } break; case hkClassMember::TYPE_ENUM : { const hkClassEnum& e = member.getEnumType(); member.setEnumValue(memberData, e.getItem(0).getValue()); } break; default: break; } return memberPath; }
hkString TweakerUtils::getPrevSiblingPath( const hkString& memberPath, const void* rootData, const class hkClass& rootKlass, HideMemberFunc hideMember ) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); int leftBracketIndex = memberName.indexOf('['); int arrayIndex = -1; if ( leftBracketIndex != -1 ) { int rightBracketIndex = memberName.indexOf(']'); hkString indexString = memberName.substr( leftBracketIndex+1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = memberName.substr( 0, leftBracketIndex ); } int memberIdx = getMemberIdx(memberName, *klass); if ( (memberIdx != -1) && (arrayIndex != -1) ) { const hkClassMember& member = klass->getMember(memberIdx); if ( member.getType() == hkClassMember::TYPE_ARRAY ) { void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkArray<char>* arrayPtr = static_cast<hkArray<char>*>(memberData); int sz = arrayPtr->getSize(); int newIndex = (arrayIndex + sz - 1) % sz; hkString s; s.printf( "%s%s[%d]", classPath.cString(), memberName.cString(), newIndex ); return s; } } if ( memberIdx == -1 ) { memberIdx = 0; } do { memberIdx = ( memberIdx - 1 + klass->getNumMembers()) % klass->getNumMembers(); } while ( hideMember && hideMember(klass->getMember(memberIdx)) ); return classPath + hkString( klass->getMember(memberIdx).getName()); }
hkString TweakerUtils::getParentPath(const hkString& memberPath, const void* rootData, const class hkClass& rootKlass) { if (memberPath.getLength() == 0) return hkString("/"); if ( memberPath[memberPath.getLength()-1] == ']' ) { int leftBracketIndex = memberPath.lastIndexOf('['); return memberPath.substr( 0, leftBracketIndex ); } const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); // Remove trailing / while (classPath.endsWith("/")) classPath = classPath.substr(0, classPath.getLength() -1); return classPath; }
hkgShaderCollection* HardwareSkinningDemo::compileShader() { hkgShaderCollection* ret = HK_NULL; hkgDisplayContext* ctx = m_env->m_window->getContext(); hkgShader* vertexShader = hkgShader::createVertexShader( ctx ); hkgShader* pixelShader = hkgShader::createPixelShader( ctx ); hkString shaderFile("./Resources/Animation/Shaders/SimpleSkinningShader"); shaderFile += hkString(vertexShader->getDefaultFileNameExtension()); vertexShader->realizeCompileFromFile( shaderFile.cString(), "mainVS", HK_NULL, HK_NULL, HK_NULL); pixelShader->realizeCompileFromFile( shaderFile.cString(), "mainPS", HK_NULL, HK_NULL, HK_NULL); ret = hkgShaderCollection::create(); ret->addShaderGrouping(vertexShader, pixelShader); pixelShader->removeReference(); vertexShader->removeReference(); return ret; }
void Gdc2005Demo::handleTweakingInput() { const bool usingGamepad = m_env->m_window->hasGamePads() && !m_env->m_options->m_forceKeyboardGamepad; const hkgKeyboard& keys = m_env->m_window->getKeyboard(); if ( m_env->m_gamePad->wasButtonPressed(HKG_PAD_SELECT) || keys.wasKeyPressed('T') ) { m_tweaking = !m_tweaking; } if (m_tweaking) { // Show help on the keys showKeys(); if (m_selected[0]!='/') m_selected = "/"; extern const hkClass Gdc2005DemoOptionsClass; const hkClass& klass = Gdc2005DemoOptionsClass; hkgPad* pad = m_env->m_gamePad; if (pad->wasButtonPressed(HKG_PAD_DPAD_DOWN)) { m_selected = TweakerUtils::getNextSiblingPath(m_selected, &m_options, klass); } if (pad->wasButtonPressed(HKG_PAD_DPAD_UP)) { m_selected = TweakerUtils::getPrevSiblingPath(m_selected, &m_options, klass); } if (pad->wasButtonPressed(HKG_PAD_DPAD_LEFT)) { m_selected = TweakerUtils::getParentPath(m_selected, &m_options, klass); } if (pad->wasButtonPressed(HKG_PAD_DPAD_RIGHT)) { m_selected = TweakerUtils::getChildPath(m_selected, &m_options, klass); } if (usingGamepad) { if (pad->wasButtonPressed(HKG_PAD_BUTTON_0 )) { TweakerUtils::tweakData(m_selected, &m_options, klass, -0.1f); } if (pad->wasButtonPressed(HKG_PAD_BUTTON_3)) { TweakerUtils::tweakData(m_selected, &m_options, klass, 0.1f); } if (pad->wasButtonPressed(HKG_PAD_BUTTON_2)) { TweakerUtils::clearData(m_selected, &m_options, klass); } } else { if ( keys.wasKeyPressed(HKG_VKEY_SUBTRACT) || keys.wasKeyPressed(HKG_VKEY_SPACE) || keys.wasKeyPressed(HKG_VKEY_OEM_MINUS) || keys.wasKeyPressed(HKG_VKEY_OEM_COMMA) ) { TweakerUtils::tweakData(m_selected, &m_options, klass, -0.1f); } if ( keys.wasKeyPressed(HKG_VKEY_ADD) || keys.wasKeyPressed(HKG_VKEY_OEM_PLUS) || keys.wasKeyPressed(HKG_VKEY_OEM_PERIOD) ) { TweakerUtils::tweakData(m_selected, &m_options, klass, 0.1f); } if ( keys.wasKeyPressed('0') || keys.wasKeyPressed(HKG_VKEY_DELETE) || keys.wasKeyPressed(HKG_VKEY_NUMPAD0) ) { TweakerUtils::clearData(m_selected, &m_options, klass); } } TweakerUtils::displayData(m_selected, &m_options, klass, *m_env->m_textDisplay, 40, 40); m_env->m_textDisplay->outputText( hkString("Tweaking: ") + m_selected, 40, 15, 0xffffffff); // Clean out the pad so the keypresses don't propagate below. hkString::memSet( pad, 0, sizeof(hkgPad)); } }
hkgShaderCollection* HardwareSkinningDemo::loadPrecompiledShader() { const char* filePostfix = hkgSystem::g_RendererType == hkgSystem::HKG_RENDERER_DX8? "_vs11_dx81" : "_vs20_dx9"; const char* filePrefix = ".\\"; hkString shaderFile; hkString pshaderFile; hkString resources("resources\\animation\\shaders\\"); hkString filename; filename = hkString(filePrefix) + resources + "Skinning" + filePostfix; shaderFile = filename + ".vso"; pshaderFile = filename + ".pso"; hkIstream shaderFileStream( shaderFile.cString() ); HK_ASSERT(0x0, shaderFileStream.isOk()); HKG_SHADER_RENDER_STYLE style = HKG_SHADER_RENDER_1LIGHTS; // one spot light hkgShader* shader = hkgShader::create(HKG_VERTEX_SHADER, m_env->m_window->getContext()); shader->setShaderFileName( shaderFile.cString() ); shader->realize(shaderFileStream, style); // add a pixel shader if require (just always use one..) hkgShader* pshader = HK_NULL; if (hkgSystem::g_RendererType == hkgSystem::HKG_RENDERER_DX9S) { // need a precompiled pixel shader.. HK_ASSERT(0x0, "Demo does not make a precompiled pixel shader for d3d9s"); } /* // Vertex Shader // -------------- ----- ---- // mWorldMatrixArray c0 78 // mViewProj c78 4 // lhtDir c82 1 // MaterialAmbient c83 1 // MaterialDiffuse c84 1 */ // table of 26 matrices first for (int i=0; i < 26; ++i) shader->addMatInput(HKG_SHADER_MAT_INPUT_4x4, 12); // add the rest of the actually auto set constants: shader->addMatInput(HKG_SHADER_MAT_INPUT_VP, 16); shader->addNormalInput(HKG_SHADER_INPUT_LIGHT_DIR, 4); shader->addNormalInput(HKG_SHADER_INPUT_AMBIENT_COLOR, 4); shader->addNormalInput(HKG_SHADER_INPUT_DIFFUSE_COLOR, 4); /* // Pixel Shader // -------------- ----- ---- // just the texture in s0 */ // Group the set of shaders together hkgShaderCollection* effect = hkgShaderCollection::create(); effect->addShaderGrouping(shader, pshader); if (shader) shader->release(); if (pshader) pshader->release(); return effect; }
// This function is used to generate the binding. It compares bone names and track names and indicates when they match (returns 0) int HK_CALL bindingCompare( const char* boneName, const char* trackName ) { return ( hkString(trackName).beginsWith( boneName ) ? 0 : 1); }
NativePackfileLoadDemo::NativePackfileLoadDemo( hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Disable warning: 'm_contactRestingVelocity not set, setting it to REAL_MAX, so that the new collision restitution code will be disabled' hkError::getInstance().setEnabled(0xf03243ed, false); hkError::getInstance().setEnabled(0x9fe65234, false); // Setup the camera { hkVector4 from(31, 31, 14); hkVector4 to(2.5f, -2, -.3f); hkVector4 up(0, 0, 1); setupDefaultCameras( env, from, to, up ); } hkString path("Resources/Common/Api/Serialize/SimpleLoad"); hkString fileName; NativePackfileLoadDemo_getBinaryFileName(fileName); hkRootLevelContainer* container = HK_NULL; { // read entire file into local buffer hkArray<char> buf; loadEntireFileIntoBuffer( hkString(path+fileName).cString(), buf ); #if defined(PACKFILE_LOAD_WITH_VERSIONING) updatePackfileDataVersion( buf ); #endif // Now we have native packfile data in the 'buf' variable. // extract only valuable data, stripping out all extras, such as headers and fixups tables // and load it into m_dataBuffer int bufferSize = hkNativePackfileUtils::getRequiredBufferSize( buf.begin(), buf.getSize() ); m_dataBuffer.reserveExactly(bufferSize); // Load the buffer and get the top level object in the file in one step container = static_cast<hkRootLevelContainer*>(hkNativePackfileUtils::load(buf.begin(), buf.getSize(), m_dataBuffer.begin(), m_dataBuffer.getCapacity())); } HK_ASSERT2(0xa6451543, container != HK_NULL, "Could not load root level obejct" ); hkpPhysicsData* physicsData = static_cast<hkpPhysicsData*>( container->findObjectByType( hkpPhysicsDataClass.getName() ) ); HK_ASSERT2(0xa6451544, physicsData != HK_NULL, "Could not find physics data in root level object" ); HK_ASSERT2(0xa6451535, physicsData->getWorldCinfo() != HK_NULL, "No physics cinfo in loaded file - cannot create a hkpWorld" ); // Create a world and add the physics systems to it m_world = new hkpWorld( *physicsData->getWorldCinfo() ); m_world->lock(); // Register all collision agents hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // Add all the physics systems to the world for ( int i = 0; i < physicsData->getPhysicsSystems().getSize(); ++i ) { m_world->addPhysicsSystem( physicsData->getPhysicsSystems()[i] ); } // Setup graphics - this creates graphics objects for all rigid bodies and phantoms in the world setupGraphics(); m_world->unlock(); }
hkString TweakerUtils::tweakData(const hkString& memberPath, void* rootData, const hkClass& rootKlass, float offset, const hkReal threshold, FloatTweakType floatTweakType) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); // deal with arrays int rightBracketIndex = memberName.indexOf( ']' ); int arrayIndex = -1; if ( rightBracketIndex != -1 ) { int leftBracketIndex = memberName.indexOf( '[' ); hkString indexString = memberName.substr( leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = memberName.substr( 0, leftBracketIndex ); } int memberIdx = getMemberIdx(memberName, *klass); if (memberIdx < 0) return classPath; const hkClassMember& member = klass->getMember(memberIdx); void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkString str; switch (member.getType()) { case hkClassMember::TYPE_REAL : { switch(floatTweakType) { case MULTIPLICATIVE: { hkReal& value = lookupMember<hkReal>(memberData); value *= (value > 0) ? 1.0f + offset : 1.0f - offset; // On 0 snap to +ve or -ve if ( value == 0.0f ) { value = (offset > 0) ? threshold : -threshold; } // Snap to 0 exactly if (hkMath::fabs(value) < threshold) { value = 0.0f; } break; } case ADDITIVE: { hkReal& value = lookupMember<hkReal>(memberData); value += offset; } } } break; case hkClassMember::TYPE_INT32 : { hkInt32& value = lookupMember<hkInt32>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value += offsetAsInt; } break; case hkClassMember::TYPE_UINT32 : { hkUint32& value = lookupMember<hkUint32>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value += offsetAsInt; } break; case hkClassMember::TYPE_INT16 : { hkInt16& value = lookupMember<hkInt16>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value = hkInt16( value + offsetAsInt); } break; case hkClassMember::TYPE_UINT16 : { hkUint16& value = lookupMember<hkUint16>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value = hkUint16( value + offsetAsInt); } break; case hkClassMember::TYPE_BOOL : { bool& value = lookupMember<bool>(memberData); value = !value; } break; case hkClassMember::TYPE_ENUM : { const hkClassEnum& e = member.getEnumType(); int value = member.getEnumValue(memberData); // Find item with current value int itemIdx = 0; while ( e.getItem(itemIdx).getValue() != value) itemIdx++; itemIdx += (offset > 0) ? 1 : e.getNumItems() -1; itemIdx = itemIdx % e.getNumItems(); member.setEnumValue(memberData, e.getItem(itemIdx).getValue()); } break; case hkClassMember::TYPE_ARRAY : { switch( member.getSubType() ) { case hkClassMember::TYPE_INT32 : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkInt32>* arrayPtr = static_cast<hkArray<hkInt32>*>( ptrAddr ); (*arrayPtr)[arrayIndex] += (offset > 0) ? 1 : -1; break; } default: { break; } } } break; default: break; } return memberPath; }
hkString TweakerUtils::setReal( const hkString& memberPath, void* rootData, const hkClass& rootKlass, float newValue ) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); // deal with arrays int rightBracketIndex = memberName.indexOf( ']' ); int arrayIndex = -1; if ( rightBracketIndex != -1 ) { int leftBracketIndex = memberName.indexOf( '[' ); hkString indexString = memberName.substr( leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = memberName.substr( 0, leftBracketIndex ); } int memberIdx = getMemberIdx(memberName, *klass); if (memberIdx < 0) return classPath; const hkClassMember& member = klass->getMember(memberIdx); void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkString str; switch (member.getType()) { case hkClassMember::TYPE_REAL : { hkReal& value = lookupMember<hkReal>(memberData); value = newValue; } break; case hkClassMember::TYPE_INT32 : { hkInt32& value = lookupMember<hkInt32>(memberData); value = hkInt32(newValue); } break; case hkClassMember::TYPE_UINT32 : { hkUint32& value = lookupMember<hkUint32>(memberData); value = hkUint32(newValue); } break; case hkClassMember::TYPE_INT16 : { hkInt16& value = lookupMember<hkInt16>(memberData); value = hkInt16(newValue); } break; case hkClassMember::TYPE_UINT16 : { hkUint16& value = lookupMember<hkUint16>(memberData); value = hkUint16(newValue); } break; case hkClassMember::TYPE_BOOL : { bool& value = lookupMember<bool>(memberData); value = (newValue!=0.0f); } break; case hkClassMember::TYPE_ENUM : { // for backward compatibility we clear the data on zero, otherwise do nothing to enums if ( newValue == 0.0f ) { const hkClassEnum& e = member.getEnumType(); member.setEnumValue(memberData, e.getItem(0).getValue()); } } break; case hkClassMember::TYPE_ARRAY: { switch( member.getSubType() ) { case hkClassMember::TYPE_REAL : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkReal>* arrayPtr = static_cast<hkArray<hkReal>*>( ptrAddr ); (*arrayPtr)[arrayIndex] = newValue; } break; case hkClassMember::TYPE_INT32 : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkInt32>* arrayPtr = static_cast<hkArray<hkInt32>*>( ptrAddr ); (*arrayPtr)[arrayIndex] = static_cast<hkInt32>(newValue); } break; default: break; } } break; default: break; } return memberPath; }
hkString TweakerUtils::getClass( const hkString& memberPath, const void* rootData, const class hkClass& rootKlass, void*& data, const hkClass*& klass, HideMemberFunc hideMember ) { hkString path = memberPath; // Strip leading '/' while (path[0] == '/') path = path.substr(1); // Empty string if (path.getLength() == 0) { data = const_cast<void*>(rootData); klass = &rootKlass; return hkString("/"); } // Find next '/' int idx = path.indexOf('/'); if (idx < 0) idx = path.getLength(); // find next '[' int leftBracketIndex = path.indexOf( '[' ); if (leftBracketIndex < 0) leftBracketIndex = path.getLength(); hkBool isArray = ( leftBracketIndex < idx ); hkString memberName; int arrayIndex = -1; hkString memberNameAndIndex; if ( isArray ) { int rightBracketIndex = path.indexOf(']'); hkString indexString = path.substr( leftBracketIndex+1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = path.substr(0, leftBracketIndex ); memberNameAndIndex = path.substr(0, rightBracketIndex+1); path = path.substr(rightBracketIndex+1); } else { memberName = path.substr(0, idx); path = path.substr(idx); // now holds remaining path } // Check the klass has this member int memberIdx = getMemberIdx( memberName, rootKlass); // Member not found so return if (memberIdx == -1) { data = const_cast<void*>(rootData); klass = &rootKlass; return hkString(""); } const hkClassMember& member = rootKlass.getMember( memberIdx ); // Chase pointers to structs / classes if (path.getLength() > 0) { if (member.getType() == hkClassMember::TYPE_STRUCT) { const void* ptrAddr = static_cast<const char*>(rootData) + member.getOffset(); return hkString("/") + memberName + TweakerUtils::getClass(path, ptrAddr, member.getStructClass(), data, klass); } else if (( member.getType() == hkClassMember::TYPE_POINTER) && (member.getSubType() == hkClassMember::TYPE_STRUCT)) { const void* ptrAddr = static_cast<const char*>(rootData) + member.getOffset(); const void* ptrTo = *static_cast<const void*const*>(ptrAddr); const hkClass* instanceClass = getInstanceClass( &member.getStructClass(), ptrTo ); return hkString("/") + memberName + TweakerUtils::getClass(path, ptrTo, *instanceClass, data, klass); } else if (( member.getType() == hkClassMember::TYPE_ARRAY ) && isArray ) { if ( member.getSubType() == hkClassMember::TYPE_STRUCT ) { const void* ptrAddr = static_cast<const char*>(rootData) + member.getOffset(); const hkArray<char>* arrayPtr = static_cast<const hkArray<char>*>( ptrAddr ); int sz = member.getArrayMemberSize(); const void* memberData = arrayPtr->begin() + sz*arrayIndex; return hkString("/") + memberNameAndIndex + TweakerUtils::getClass(path, memberData, member.getStructClass(), data, klass); } else if ( member.getSubType() == hkClassMember::TYPE_POINTER ) { const void* arrayData = static_cast<const void*>(static_cast<const char*>(rootData) + member.getOffset()); const hkArray<void*>* arrayPtr = static_cast<const hkArray<void*>*>( arrayData ); const void* ptrTo = *(arrayPtr->begin() + arrayIndex); const hkClass* instanceClass = getInstanceClass( &member.getStructClass(), ptrTo ); return hkString("/") + memberNameAndIndex + TweakerUtils::getClass(path, ptrTo, *instanceClass, data, klass); } else { return memberPath; } } } // Return this class data = const_cast<void*>(rootData); klass = &rootKlass; return hkString("/"); }
hkString TweakerUtils::getChildPath( const hkString& memberPath, const void* rootData, const class hkClass& rootKlass, HideMemberFunc hideMember ) { if (memberPath.getLength() == 0) return hkString("/"); if ( memberPath.endsWith("]") ) { // getClass only returns the class of the array element type if a slash is at the end hkString path; path = memberPath + hkString("/"); const hkClass* klass = 0; void* data; hkString classPath = TweakerUtils::getClass(path, rootData, rootKlass, data, klass); if ( klass && ( klass->getNumMembers() > 0 ) ) { for( int i = 0; i < klass->getNumMembers(); i++ ) { const hkClassMember& member = klass->getMember(i); if( NOT( hideMember && hideMember(member) ) ) { return classPath + member.getName(); } } // all of the members filtered out so we just return the parent path that was passed in return memberPath; } return memberPath; } hkString path; path = memberPath; const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(path, rootData, rootKlass, data, klass); int memberIdx; { hkString memberName = path; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); memberIdx = getMemberIdx(memberName, *klass); } // Couldn't find the member if (memberIdx == -1) { if (rootKlass.getNumMembers() > 0) { for( int i = 0; i < rootKlass.getNumMembers(); i++ ) { const hkClassMember& member = rootKlass.getMember(i); if( NOT( hideMember && hideMember(member) ) ) { return classPath + member.getName(); } } } } const hkClassMember& member = klass->getMember(memberIdx); if ( member.getType() == hkClassMember::TYPE_STRUCT) { const hkClass& childClass = member.getStructClass(); if (childClass.getNumMembers() > 0) { for( int i = 0; i < childClass.getNumMembers(); i++ ) { const hkClassMember& mem = childClass.getMember(i); if( NOT( hideMember && hideMember(mem) ) ) { return memberPath + "/" + mem.getName(); } } return memberPath; } } else if (( member.getType() == hkClassMember::TYPE_POINTER) && (member.getSubType() == hkClassMember::TYPE_STRUCT)) { const void* ptrAddr = const_cast<const char*> (static_cast<char*>(data) + member.getOffset() ); const void* ptrTo = *static_cast<const void*const*>(ptrAddr); const hkClass& childClass = *getInstanceClass( &member.getStructClass(), ptrTo ); if ( ptrTo && ( childClass.getNumMembers() > 0 ) ) { for( int i = 0; i < childClass.getNumMembers(); i++ ) { const hkClassMember& mem = childClass.getMember(i); if( NOT( hideMember && hideMember(mem) ) ) { return memberPath + "/" + mem.getName(); } } return memberPath; } } else if ( member.getType() == hkClassMember::TYPE_ARRAY ) { // check to see if it is an empty array or not const void* ptrAddr = const_cast<const char*>( static_cast<char*>(data) + member.getOffset() ); const hkArray<char>* arrayPtr = static_cast<const hkArray<char>*>( ptrAddr ); if ( arrayPtr->getSize() ) { return memberPath + "[0]"; // first element } } return memberPath; }
hkDemo::Result TestPlanDemo::stepDemo() { hkString testPlanFilename; if( m_testPlanType == DEMOS_LIST ) { testPlanFilename.printf( "%s.txt", m_testPlanFilename ); } else { testPlanFilename.printf( "%s_%i_%sReport.csv", HAVOK_SDK_VERSION_STRING, HAVOK_BUILD_NUMBER, m_testPlanFilename ); } if( m_step == 0 ) { hkOfstream ostr( testPlanFilename.cString() ); if( m_testPlanType == TEST_PLAN_UNIT_TESTS ) { ostr.printf( "%s,\n", unitTestCols ); } else if( m_testPlanType != DEMOS_LIST ) { ostr.printf( "%s,\n", demoCols ); } // // Get a list of the demos and build a test plan // hkObjectArray<hkString> demoPathItems; const hkObjectArray<hkDemoEntry>& db = hkDemoDatabase::getInstance().getDemos(); for( int i=0; i<db.getSize(); i++ ) { const hkDemoEntry& entry = db[i]; hkString demoName = entry.m_menuPath.replace(","," -"); bool unitTest = entry.m_demoTypeFlags & HK_DEMO_TYPE_TEST && demoName.substr( demoName.indexOf('/')+1, 4 ) == "Test" && demoName.substr( demoName.indexOf('/')+6, 8 ) == "UnitTest"; // Skip demos based on their location in the demos tree. switch (m_testPlanType) { case DEMOS_LIST: // Simply print out the demo name, skipping the path processing after the switch. ostr.printf( "\"%s\"\n", demoName.cString() ); continue; case TEST_PLAN_ALL: // Don't skip any demos. break; case TEST_PLAN_COMMON_DEMOS: if ( demoName.substr(0,6) != hkString("Common") || unitTest ) { continue; } break; case TEST_PLAN_PHYSICS_DEMOS: if ( demoName.substr(0,7) != hkString("Physics") || unitTest ) { continue; } break; case TEST_PLAN_ANIMATION_DEMOS: if ( demoName.substr(0,9) != hkString("Animation") || unitTest ) { continue; } break; case TEST_PLAN_BEHAVIOR_DEMOS: if ( demoName.substr(0,8) != hkString("Behavior") || unitTest ) { continue; } break; case TEST_PLAN_SERIALIZE_DEMOS: if( (entry.m_demoTypeFlags & HK_DEMO_TYPE_SERIALIZE) == 0 ) { continue; } break; case TEST_PLAN_UNIT_TESTS: if( !unitTest ) { continue; } break; case TEST_PLAN_VISUAL_TESTS: if( demoName.substr( demoName.indexOf('/')+1, 4 ) != "Test" || unitTest ) { continue; } break; default: break; } int offset = 0; int depth = 0; while( offset != -1 ) { offset = demoName.indexOf('/'); if( offset == -1 ) { for ( int indent = 0; indent < depth; indent++ ) { ostr.printf( " " ); } ostr.printf( "%s,\n", demoName.cString() ); } else { hkString demoPath = demoName.substr(0, offset+1); if( depth >= demoPathItems.getSize() || demoPathItems[depth] != demoPath ) { for ( int indent = 0; indent < depth; indent++ ) { ostr.printf( " " ); } ostr.printf( "%s,\n", demoPath.cString() ); int itemsToRemove = demoPathItems.getSize() - depth; for( int count = 0; count < itemsToRemove; count++ ) { demoPathItems.popBack(); } demoPathItems.pushBack( demoPath ); } depth++; demoName = demoName.substr(offset+1); } } } m_step++; } if( m_step > 0 ) { m_env->m_textDisplay->outputText(hkString( "Done. Output is in " ) + testPlanFilename, 20, 250, 0xffffffff); } return DEMO_OK; }