bool hkbGetWorldFromModelModifier::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    auto writedatafield = [&](const QString & name, const QString & value){
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), value);
    };
    if (writer && !getIsWritten()){
        QString refString = "null";
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        if (getVariableBindingSetData()){
            refString = getVariableBindingSet()->getReferenceString();
        }
        writedatafield("variableBindingSet", refString);
        writedatafield("userData", QString::number(userData));
        writedatafield("name", name);
        writedatafield("enable", getBoolAsString(enable));
        writedatafield("translationOut", translationOut.getValueAsString());
        writedatafield("rotationOut", rotationOut.getValueAsString());
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
        if (getVariableBindingSetData() && !getVariableBindingSet()->write(writer)){
            LogFile::writeToLog(getParentFilename()+": "+getClassname()+": write()!\nUnable to write 'variableBindingSet'!!!");
        }
    }
    return true;
}
QString hkbGetWorldFromModelModifier::evaluateDataValidity(){
    std::lock_guard <std::mutex> guard(mutex);
    QString errors;
    auto isvalid = true;
    auto temp = HkDynamicObject::evaluateDataValidity();
    if (temp != ""){
        errors.append(temp+getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": "+name+": Invalid variable binding set!");
    }
    if (name == ""){
        isvalid = false;
        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": "+name+": Invalid name!");
    }
    setDataValidity(isvalid);
    return errors;
}
Ejemplo n.º 3
0
void Animate::ForwardExec
	(
	Event *ev
	)

{
	int slot = 0;
	float weight = 1.0f;

	if( !edict->tiki )
	{
		ScriptError( "trying to play animation on( entnum: %d, targetname : '%s', classname : '%s' ) which does not have a model",
			entnum,
			targetname.c_str(),
			getClassname()
			);
	}

	if( ev->NumArgs() > 1 )
	{
		slot = ev->GetInteger( 2 );
	}

	if( ev->NumArgs() > 2 )
	{
		weight = ev->GetFloat( 3 );
	}

	NewAnim( ev->GetString( 1 ), slot, weight );
	SetTime( slot );
}
QString hkbCharacterStringData::evaluateDataValidity(){
    std::lock_guard <std::mutex> guard(mutex);
    QString errors;
    auto isvalid = true;
    auto checkstring = [&](const QStringList & list, const QString & fieldname){
        for (auto i = 0; i < list.size(); i++){
            if (list.at(i) == ""){
                isvalid = false;
                errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid "+fieldname+" at "+QString::number(i)+"!");
            }
        }
    };
    checkstring(deformableSkinNames, "deformableSkinNames");
    checkstring(rigidSkinNames, "rigidSkinNames");
    checkstring(animationNames, "animationNames");
    checkstring(animationFilenames, "animationFilenames");
    checkstring(characterPropertyNames, "characterPropertyNames");
    checkstring(retargetingSkeletonMapperFilenames, "retargetingSkeletonMapperFilenames");
    checkstring(lodNames, "lodNames");
    checkstring(mirroredSyncPointSubstringsA, "mirroredSyncPointSubstringsA");
    checkstring(mirroredSyncPointSubstringsB, "mirroredSyncPointSubstringsB");
    checkstring(QStringList(name), "name");
    checkstring(QStringList(rigName), "rigName");
    checkstring(QStringList(ragdollName), "ragdollName");
    checkstring(QStringList(behaviorFilename), "behaviorFilename");
    setDataValidity(isvalid);
    return QString();
}
bool hkbGetWorldFromModelModifier::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    bool ok;
    QByteArray text;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    auto checkvalue = [&](bool value, const QString & fieldname){
        (!value) ? LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'"+fieldname+"' has invalid data!\nObject Reference: "+ref) : NULL;
    };
    for (; index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"; index++){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "variableBindingSet"){
            checkvalue(getVariableBindingSet().readShdPtrReference(index, reader), "variableBindingSet");
        }else if (text == "userData"){
            userData = reader.getElementValueAt(index).toULong(&ok);
            checkvalue(ok, "userData");
        }else if (text == "name"){
            name = reader.getElementValueAt(index);
            checkvalue((name != ""), "name");
        }else if (text == "enable"){
            enable = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "enable");
        }else if (text == "translationOut"){
            translationOut = readVector4(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "translationOut");
        }else if (text == "rotationOut"){
            rotationOut = readVector4(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "rotationOut");
        }
    }
    index--;
    return true;
}
bool hkbProxyModifier::link(){
    std::lock_guard <std::mutex> guard(mutex);
    if (!static_cast<HkDynamicObject *>(this)->linkVar()){
        LogFile::writeToLog(getParentFilename()+": "+getClassname()+": link()!\nFailed to properly link 'variableBindingSet' data field!\nObject Name: "+name);
    }
    return true;
}
void hkbCharacterStringData::addAnimation(const QString & name){
    std::lock_guard <std::mutex> guard(mutex);
    if (!animationNames.contains(name, Qt::CaseInsensitive)){
        animationNames.append(name);
        setIsFileChanged(true);
    }else{
        LogFile::writeToLog(getParentFilename()+": "+getClassname()+": addAnimation()!\nAnimation: "+name+": already exists in the character file!!");
    }
}
bool hkbStateMachineTransitionInfoArray::link(){
    std::lock_guard <std::mutex> guard(mutex);
    HkxSharedPtr *ptr;
    for (auto i = 0; i < transitions.size(); i++){
        ptr = static_cast<BehaviorFile *>(getParentFile())->findHkxObject(transitions.at(i).transition.getShdPtrReference());
        if (ptr){
            if ((*ptr)->getSignature() != HKB_BLENDING_TRANSITION_EFFECT && (*ptr)->getSignature() != HKB_GENERATOR_TRANSITION_EFFECT){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": link()!\n'transition' data field is linked to invalid child!");
            }
            transitions[i].transition = *ptr;
        }
        ptr = static_cast<BehaviorFile *>(getParentFile())->findHkxObject(transitions.at(i).condition.getShdPtrReference());
        if (ptr){
            if ((*ptr)->getSignature() != HKB_EXPRESSION_CONDITION/* && (*ptr)->getSignature() != HKB_STRING_CONDITION*/){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": link()!\n'condition' data field is linked to invalid child!");
            }
            transitions[i].condition = *ptr;
        }
    }
    return true;
}
bool hkbCharacterStringData::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    int numElems;
    bool ok;
    QByteArray text;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    auto checkvalue = [&](bool value, const QString & fieldname){
        (!value) ? LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'"+fieldname+"' has invalid data!\nObject Reference: "+ref) : NULL;
    };
    auto readstrings =[&](QStringList & list, const QString & fieldname){
        numElems = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
        checkvalue(ok, fieldname);
        (numElems > 0) ? index++ : NULL;
        for (auto j = 0; j < numElems && index < reader.getNumElements(); j++, index++){
            list.append(reader.getElementValueAt(index));
            checkvalue((list.last() != ""), fieldname+".at("+QString::number(j)+")");
        }
    };
    for (; index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"; index++){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "deformableSkinNames"){
            readstrings(deformableSkinNames, "deformableSkinNames");
        }else if (text == "rigidSkinNames"){
            readstrings(rigidSkinNames, "rigidSkinNames");
        }else if (text == "animationNames"){
            readstrings(animationNames, "animationNames");
        }else if (text == "characterPropertyNames"){
            readstrings(characterPropertyNames, "characterPropertyNames");
        }else if (text == "retargetingSkeletonMapperFilenames"){
            readstrings(retargetingSkeletonMapperFilenames, "retargetingSkeletonMapperFilenames");
        }else if (text == "lodNames"){
            readstrings(lodNames, "lodNames");
        }else if (text == "mirroredSyncPointSubstringsA"){
            readstrings(mirroredSyncPointSubstringsA, "mirroredSyncPointSubstringsA");
        }else if (text == "mirroredSyncPointSubstringsB"){
            readstrings(mirroredSyncPointSubstringsB, "mirroredSyncPointSubstringsB");
        }else if (text == "name"){
            name = reader.getElementValueAt(index);
            checkvalue((name != ""), "name");
        }else if (text == "rigName"){
            rigName = reader.getElementValueAt(index);
            checkvalue((rigName != ""), "rigName");
        }else if (text == "ragdollName"){
            ragdollName = reader.getElementValueAt(index);
            checkvalue((ragdollName != ""), "ragdollName");
        }else if (text == "behaviorFilename"){
            behaviorFilename = reader.getElementValueAt(index);
            checkvalue((behaviorFilename != ""), "behaviorFilename");
        }
    }
    index--;
    return true;
}
bool hkbBehaviorGraphStringData::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    if (writer && !getIsWritten()){
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        QStringList list3 = {writer->name, writer->numelements};
        QStringList list4 = {"eventNames", QString::number(eventNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < eventNames.size(); i++){
            writer->writeLine(writer->string, QStringList(), QStringList(), eventNames.at(i));
        }
        if (eventNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"attributeNames", QString::number(attributeNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < attributeNames.size(); i++){
            writer->writeLine(writer->string, QStringList(), QStringList(), attributeNames.at(i));
        }
        if (attributeNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"variableNames", QString::number(variableNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < variableNames.size(); i++){
            writer->writeLine(writer->string, QStringList(), QStringList(), variableNames.at(i));
        }
        if (variableNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"characterPropertyNames", QString::number(characterPropertyNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < characterPropertyNames.size(); i++){
            writer->writeLine(writer->string, QStringList(), QStringList(), characterPropertyNames.at(i));
        }
        if (characterPropertyNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
    }
    return true;
}
QString hkbBehaviorGraphStringData::evaluateDataValidity(){
    std::lock_guard <std::mutex> guard(mutex);
    QString errors;
    auto isvalid = true;
    auto checkstring = [&](const QStringList & list, const QString & fieldname){
        for (auto i = 0; i < list.size(); i++){
            if (list.at(i) == ""){
                isvalid = false;
                errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid "+fieldname+" at "+QString::number(i)+"!");
            }
        }
    };
    checkstring(eventNames, "eventNames");
    checkstring(attributeNames, "attributeNames");
    checkstring(variableNames, "variableNames");
    checkstring(characterPropertyNames, "characterPropertyNames");
    setDataValidity(isvalid);
    return errors;
}
bool hkbHandIkDriverInfo::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    auto writedatafield = [&](const QString & name, const QString & value){
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), value);
    };
    if (writer && !getIsWritten()){
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        list1 = {writer->name, writer->numelements};
        list2 = {"hands", QString::number(hands.size())};
        writer->writeLine(writer->parameter, list1, list2, "");
        for (auto i = 0; i < hands.size(); i++){
            writer->writeLine(writer->object, true);
            writedatafield("elbowAxisLS", hands[i].elbowAxisLS.getValueAsString());
            writedatafield("backHandNormalLS", hands[i].backHandNormalLS.getValueAsString());
            writedatafield("handOffsetLS", hands[i].handOffsetLS.getValueAsString());
            writedatafield("handOrienationOffsetLS", hands[i].handOrienationOffsetLS.getValueAsString());
            writedatafield("maxElbowAngleDegrees", QString::number(hands.at(i).maxElbowAngleDegrees, char('f'), 6));
            writedatafield("minElbowAngleDegrees", QString::number(hands.at(i).minElbowAngleDegrees, char('f'), 6));
            writedatafield("shoulderIndex", QString::number(hands.at(i).shoulderIndex));
            writedatafield("shoulderSiblingIndex", QString::number(hands.at(i).shoulderSiblingIndex));
            writedatafield("elbowIndex", QString::number(hands.at(i).elbowIndex));
            writedatafield("elbowSiblingIndex", QString::number(hands.at(i).elbowSiblingIndex));
            writedatafield("wristIndex", QString::number(hands.at(i).wristIndex));
            writedatafield("enforceEndPosition", getBoolAsString(hands.at(i).enforceEndPosition));
            writedatafield("enforceEndRotation", getBoolAsString(hands.at(i).enforceEndRotation));
            writer->writeLine(writer->parameter, QStringList(writer->name), QStringList("localFrameName"), hands.at(i).localFrameName, true);
            writer->writeLine(writer->object, false);
        }
        if (hands.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        writedatafield("fadeInOutCurve", fadeInOutCurve);
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
    }
    return true;
}
QString hkbStateMachineTransitionInfoArray::getTransitionNameAt(int index) const{
    std::lock_guard <std::mutex> guard(mutex);
    hkbStateMachine *stateMachine;
    if (parent){
        if (index > -1 && index < transitions.size()){
            if (parent->getSignature() == HKB_STATE_MACHINE){
                stateMachine = static_cast<hkbStateMachine *>(parent);
            }else if (parent->getSignature() == HKB_STATE_MACHINE_STATE_INFO){
                stateMachine = static_cast<hkbStateMachineStateInfo *>(parent)->getParentStateMachine();
            }
            if (stateMachine){
                if (transitions.at(index).flags.contains("FLAG_TO_NESTED_STATE_ID_IS_VALID")){
                    return "to_"+stateMachine->getNestedStateName(transitions.at(index).toStateId, transitions.at(index).toNestedStateId)+"_Via_"+stateMachine->getStateName(transitions.at(index).toStateId);
                }
                return "to_"+stateMachine->getStateName(transitions.at(index).toStateId);
            }
        }
    }else{
        LogFile::writeToLog(getParentFilename()+": "+getClassname()+": getTransitionNameAt: No parent!!! REF: "+getReferenceString());
    }
    return "";
}
bool hkbProxyModifier::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    auto writedatafield = [&](const QString & name, const QString & value){
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), value);
    };
    if (writer && !getIsWritten()){
        QString refString = "null";
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        if (getVariableBindingSetData()){
            refString = getVariableBindingSet()->getReferenceString();
        }
        writedatafield("variableBindingSet", refString);
        writedatafield("userData", QString::number(userData));
        writedatafield("name", name);
        writedatafield("enable", getBoolAsString(enable));
        writedatafield("proxyInfo", "");
        writer->writeLine(writer->object, true);
        writedatafield("dynamicFriction", QString::number(proxyInfo.dynamicFriction, char('f'), 6));
        writedatafield("staticFriction", QString::number(proxyInfo.staticFriction, char('f'), 6));
        writedatafield("keepContactTolerance", QString::number(proxyInfo.keepContactTolerance));
        writedatafield("up", proxyInfo.up.getValueAsString());
        writedatafield("keepDistance", QString::number(proxyInfo.keepDistance, char('f'), 6));
        writedatafield("contactAngleSensitivity", QString::number(proxyInfo.contactAngleSensitivity, char('f'), 6));
        writedatafield("userPlanes", QString::number(proxyInfo.userPlanes));
        writedatafield("maxCharacterSpeedForSolver", QString::number(proxyInfo.maxCharacterSpeedForSolver, char('f'), 6));
        writedatafield("characterStrength", QString::number(proxyInfo.characterStrength, char('f'), 6));
        writedatafield("characterMass", QString::number(proxyInfo.characterMass, char('f'), 6));
        writedatafield("maxSlope", QString::number(proxyInfo.maxSlope, char('f'), 6));
        writedatafield("penetrationRecoverySpeed", QString::number(proxyInfo.penetrationRecoverySpeed, char('f'), 6));
        writedatafield("maxCastIterations", QString::number(proxyInfo.maxCastIterations));
        writedatafield("id", getBoolAsString(proxyInfo.refreshManifoldInCheckSupport));
        writer->writeLine(writer->object, false);
        writer->writeLine(writer->parameter, false);
        writedatafield("linearVelocity", linearVelocity.getValueAsString());
        writedatafield("horizontalGain", QString::number(horizontalGain, char('f'), 6));
        writedatafield("verticalGain", QString::number(verticalGain, char('f'), 6));
        writedatafield("maxHorizontalSeparation", QString::number(maxHorizontalSeparation, char('f'), 6));
        writedatafield("limitHeadingDegrees", QString::number(limitHeadingDegrees, char('f'), 6));
        writedatafield("maxVerticalSeparation", QString::number(maxVerticalSeparation, char('f'), 6));
        writedatafield("verticalDisplacementError", QString::number(verticalDisplacementError, char('f'), 6));
        writedatafield("verticalDisplacementErrorGain", QString::number(verticalDisplacementErrorGain, char('f'), 6));
        writedatafield("maxVerticalDisplacement", QString::number(maxVerticalDisplacement, char('f'), 6));
        writedatafield("minVerticalDisplacement", QString::number(minVerticalDisplacement, char('f'), 6));
        writedatafield("capsuleHeight", QString::number(capsuleHeight, char('f'), 6));
        writedatafield("capsuleRadius", QString::number(capsuleRadius, char('f'), 6));
        writedatafield("maxSlopeForRotation", QString::number(maxSlopeForRotation, char('f'), 6));
        writedatafield("collisionFilterInfo", QString::number(collisionFilterInfo));
        writedatafield("phantomType", phantomType);
        writedatafield("linearVelocityMode", linearVelocityMode);
        writedatafield("ignoreIncomingRotation", getBoolAsString(ignoreIncomingRotation));
        writedatafield("ignoreCollisionDuringRotation", getBoolAsString(ignoreCollisionDuringRotation));
        writedatafield("ignoreIncomingTranslation", getBoolAsString(ignoreIncomingTranslation));
        writedatafield("includeDownwardMomentum", getBoolAsString(includeDownwardMomentum));
        writedatafield("followWorldFromModel", getBoolAsString(followWorldFromModel));
        writedatafield("isTouchingGround", getBoolAsString(isTouchingGround));
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
        if (getVariableBindingSetData() && !getVariableBindingSet()->write(writer)){
            LogFile::writeToLog(getParentFilename()+": "+getClassname()+": write()!\nUnable to write 'variableBindingSet'!!!");
        }
    }
    return true;
}
bool hkbBehaviorGraphStringData::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    bool ok;
    int numElems = 0;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    QByteArray text;
    while (index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "eventNames"){
            numElems = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            if (!ok){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'eventNames' data!\nObject Reference: "+ref);
                return false;
            }
            index++;
            numElems = numElems + index;
            for (; index < numElems; index++){
                if (reader.getElementNameAt(index) != "hkcstring" || index >= reader.getNumElements()){
                    LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'eventNames' data!\nObject Reference: "+ref);
                    return false;
                }
                eventNames.append(reader.getElementValueAt(index));
            }
            continue;
        }else if (text == "attributeNames"){
            numElems = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            if (!ok){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'attributeNames' data!\nObject Reference: "+ref);
                return false;
            }
            index++;
            numElems = numElems + index;
            for (; index < numElems; index++){
                if (reader.getElementNameAt(index) != "hkcstring" || index >= reader.getNumElements()){
                    LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'attributeNames' data!\nObject Reference: "+ref);
                    return false;
                }
                attributeNames.append(reader.getElementValueAt(index));
            }
            continue;
        }else if (text == "variableNames"){
            numElems = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            if (!ok){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'variableNames' data!\nObject Reference: "+ref);
                return false;
            }
            index++;
            numElems = numElems + index;
            for (; index < numElems; index++){
                if (reader.getElementNameAt(index) != "hkcstring" || index >= reader.getNumElements()){
                    LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'variableNames' data!\nObject Reference: "+ref);
                    return false;
                }
                variableNames.append(reader.getElementValueAt(index));
            }
            continue;
        }else if (text == "characterPropertyNames"){
            numElems = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            if (!ok){
                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'characterPropertyNames' data!\nObject Reference: "+ref);
                return false;
            }
            index++;
            numElems = numElems + index;
            for (; index < numElems; index++){
                if (reader.getElementNameAt(index) != "hkcstring" || index >= reader.getNumElements()){
                    LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\nFailed to properly read 'characterPropertyNames' data!\nObject Reference: "+ref);
                    return false;
                }
                characterPropertyNames.append(reader.getElementValueAt(index));
            }
            continue;
        }
        index++;
    }
    index--;
    return true;
}
bool hkbStateMachineTransitionInfoArray::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    bool ok;
    QByteArray text;
    auto numtrans = 0;
    QStringList list;
    Interval_Type intervalType;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    auto checkvalue = [&](bool value, const QString & fieldname){
        (!value) ? LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'"+fieldname+"' has invalid data!\nObject Reference: "+ref) : NULL;
    };
    for (; index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"; index++){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "transitions"){
            numtrans = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            checkvalue(ok, "transitions");
            (numtrans > 0) ? index++ : NULL;
            for (auto j = 0; j < numtrans; j++, index++){
                transitions.append(HkTransition());
                for (; index < reader.getNumElements(); index++){
                    text = reader.getNthAttributeValueAt(index, 0);
                    if (text == "triggerInterval"){
                        intervalType = TRIGGER;
                    }else if (text == "initiateInterval"){
                        intervalType = INITIATE;
                    }else if (text == "enterEventId"){
                        auto temp = reader.getElementValueAt(index).toInt(&ok);
                        (intervalType == TRIGGER) ? transitions.last().triggerInterval.enterEventId = temp : transitions.last().initiateInterval.enterEventId = temp;
                        checkvalue(ok, "enterEventId");
                    }else if (text == "exitEventId"){
                        auto temp = reader.getElementValueAt(index).toInt(&ok);
                        (intervalType == TRIGGER) ? transitions.last().triggerInterval.exitEventId = temp : transitions.last().initiateInterval.exitEventId = temp;
                        checkvalue(ok, "exitEventId");
                    }else if (text == "enterTime"){
                        auto temp = reader.getElementValueAt(index).toDouble(&ok);
                        (intervalType == TRIGGER) ? transitions.last().triggerInterval.enterTime = temp : transitions.last().initiateInterval.enterTime = temp;
                        checkvalue(ok, "enterTime");
                    }else if (text== "exitTime"){
                        auto temp = reader.getElementValueAt(index).toDouble(&ok);
                        (intervalType == TRIGGER) ? transitions.last().triggerInterval.exitTime = temp : transitions.last().initiateInterval.exitTime = temp;
                        checkvalue(ok, "exitTime");
                    }else if (text == "transition"){
                        checkvalue(transitions.last().transition.readShdPtrReference(index, reader), "transition");
                    }else if (text == "condition"){
                        checkvalue(transitions.last().condition.readShdPtrReference(index, reader), "condition");
                    }else if (text == "eventId"){
                        transitions.last().eventId = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "eventId");
                    }else if (text == "toStateId"){
                        transitions.last().toStateId = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "toStateId");
                    }else if (text == "fromNestedStateId"){
                        transitions.last().fromNestedStateId = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "fromNestedStateId");
                    }else if (text == "toNestedStateId"){
                        transitions.last().toNestedStateId = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "toNestedStateId");
                    }else if (text == "priority"){
                        transitions.last().priority = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "priority");
                    }else if (text == "flags"){
                        transitions.last().flags = reader.getElementValueAt(index);
                        list = transitions.last().flags.split('|');
                        for (auto k = 0; k < list.size(); k++){
                            if (!transitionFlags.contains(list.at(k))){
                                LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'flags' data field contains an invalid string!\nObject Reference: "+ref);
                            }
                        }
                        break;
                    }
                }
            }
            (numtrans > 0) ? index-- : NULL;
        }
    }
    index--;
    return true;
}
void hkbBehaviorGraphStringData::removeVariableNameAt(int index){
    std::lock_guard <std::mutex> guard(mutex);
    (index >= 0 && index < variableNames.size()) ? variableNames.removeAt(index), setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'removeVariableNameAt' failed!");
}
void hkbBehaviorGraphStringData::setEventNameAt(int index, const QString &name){
    std::lock_guard <std::mutex> guard(mutex);
    (eventNames.size() > index && index > -1) ? eventNames.replace(index, name), setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'setEventNameAt' failed!");
}
bool hkbStateMachineTransitionInfoArray::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    auto writedatafield = [&](const QString & name, const QString & value){
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), value);
    };
    auto writeref = [&](const HkxSharedPtr & shdptr, const QString & name){
        QString refString = "null";
        (shdptr.data()) ? refString = shdptr->getReferenceString() : NULL;
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), refString);
    };
    auto writechild = [&](const HkxSharedPtr & shdptr, const QString & datafield){
        if (shdptr.data() && !shdptr->write(writer))
            LogFile::writeToLog(getParentFilename()+": "+getClassname()+": write()!\nUnable to write '"+datafield+"'!!!");
    };
    if (writer && !getIsWritten()){
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        list1 = {writer->name, writer->numelements};
        list2 = {"transitions", QString::number(transitions.size())};
        writer->writeLine(writer->parameter, list1, list2, "");
        for (auto i = 0; i < transitions.size(); i++){
            writer->writeLine(writer->object, true);
            writedatafield("triggerInterval", "");
            writer->writeLine(writer->object, true);
            writedatafield("enterEventId", QString::number(transitions.at(i).triggerInterval.enterEventId));
            writedatafield("exitEventId", QString::number(transitions.at(i).triggerInterval.exitEventId));
            writedatafield("enterTime", QString::number(transitions.at(i).triggerInterval.enterTime, char('f'), 6));
            writedatafield("exitTime", QString::number(transitions.at(i).triggerInterval.exitTime, char('f'), 6));
            writer->writeLine(writer->object, false);
            writer->writeLine(writer->parameter, false);
            writedatafield("initiateInterval", "");
            writer->writeLine(writer->object, true);
            writedatafield("enterEventId", QString::number(transitions.at(i).initiateInterval.enterEventId));
            writedatafield("exitEventId", QString::number(transitions.at(i).initiateInterval.exitEventId));
            writedatafield("enterTime", QString::number(transitions.at(i).initiateInterval.enterTime, char('f'), 6));
            writedatafield("exitTime", QString::number(transitions.at(i).initiateInterval.exitTime, char('f'), 6));
            writer->writeLine(writer->object, false);
            writer->writeLine(writer->parameter, false);
            writeref(transitions.at(i).transition, "transition");
            writeref(transitions.at(i).condition, "condition");
            writedatafield("eventId", QString::number(transitions.at(i).eventId));
            writedatafield("toStateId", QString::number(transitions.at(i).toStateId));
            writedatafield("fromNestedStateId", QString::number(transitions.at(i).fromNestedStateId));
            writedatafield("toNestedStateId", QString::number(transitions.at(i).toNestedStateId));
            writedatafield("priority", QString::number(transitions.at(i).priority));
            writedatafield("flags", transitions.at(i).flags);
            writer->writeLine(writer->object, false);
        }
        if (transitions.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
        for (auto i = 0; i < transitions.size(); i++){
            writechild(transitions.at(i).transition, "transitions.at("+QString::number(i)+").transition");
            writechild(transitions.at(i).condition, "transitions.at("+QString::number(i)+").condition");
        }
    }
    return true;
}
bool hkbCharacterStringData::write(HkxXMLWriter *writer){
    std::lock_guard <std::mutex> guard(mutex);
    auto writedatafield = [&](const QString & name, const QString & value){
        writer->writeLine(writer->parameter, QStringList(writer->name), QStringList(name), value);
    };
    if (writer && !getIsWritten()){
        QStringList list1 = {writer->name, writer->clas, writer->signature};
        QStringList list2 = {getReferenceString(), getClassname(), "0x"+QString::number(getSignature(), 16)};
        writer->writeLine(writer->object, list1, list2, "");
        QStringList list3 = {writer->name, writer->numelements};
        QStringList list4 = {"deformableSkinNames", QString::number(deformableSkinNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < deformableSkinNames.size(); i++){
            writedatafield("", deformableSkinNames.at(i));
        }
        if (deformableSkinNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"rigidSkinNames", QString::number(rigidSkinNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < rigidSkinNames.size(); i++){
            writedatafield("", rigidSkinNames.at(i));
        }
        if (rigidSkinNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"animationNames", QString::number(animationNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < animationNames.size(); i++){
            writedatafield("", QString(animationNames.at(i)).replace("/", "\\"));
        }
        if (animationNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"animationFilenames", QString::number(animationFilenames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < animationFilenames.size(); i++){
            writedatafield("", animationFilenames.at(i));
        }
        if (animationFilenames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"characterPropertyNames", QString::number(characterPropertyNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < characterPropertyNames.size(); i++){
            writedatafield("", characterPropertyNames.at(i));
        }
        if (characterPropertyNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"retargetingSkeletonMapperFilenames", QString::number(retargetingSkeletonMapperFilenames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < retargetingSkeletonMapperFilenames.size(); i++){
            writedatafield("", retargetingSkeletonMapperFilenames.at(i));
        }
        if (retargetingSkeletonMapperFilenames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"lodNames", QString::number(lodNames.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < lodNames.size(); i++){
            writedatafield("", lodNames.at(i));
        }
        if (lodNames.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"mirroredSyncPointSubstringsA", QString::number(mirroredSyncPointSubstringsA.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < mirroredSyncPointSubstringsA.size(); i++){
            writedatafield("", mirroredSyncPointSubstringsA.at(i));
        }
        if (mirroredSyncPointSubstringsA.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        list3 = {writer->name, writer->numelements};
        list4 = {"mirroredSyncPointSubstringsB", QString::number(mirroredSyncPointSubstringsB.size())};
        writer->writeLine(writer->parameter, list3, list4, "");
        for (auto i = 0; i < mirroredSyncPointSubstringsB.size(); i++){
            writedatafield("", mirroredSyncPointSubstringsB.at(i));
        }
        if (mirroredSyncPointSubstringsB.size() > 0){
            writer->writeLine(writer->parameter, false);
        }
        writedatafield("name", name);
        writedatafield("rigName", QString(rigName).replace("/", "\\"));
        writedatafield("ragdollName", QString(ragdollName).replace("/", "\\"));
        writedatafield("behaviorFilename", QString(behaviorFilename).replace("/", "\\"));
        writer->writeLine(writer->object, false);
        setIsWritten();
        writer->writeLine("\n");
    }
    return true;
}
QString hkbStateMachineTransitionInfoArray::evaluateDataValidity(){ //Do not call this outside it's parent state machine or state in a multithreaded context or there will be a potential race condition...
    std::lock_guard <std::mutex> guard(mutex);
    QString errors;
    auto isvalid = true;
    if (!parent){
        isvalid = false;
        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Null parent!");
    }else if (parent->getSignature() != HKB_STATE_MACHINE && parent->getSignature() != HKB_STATE_MACHINE_STATE_INFO){
        isvalid = false;
        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid parent type! Signature: "+QString::number(parent->getSignature(), 16)+"\n");
    }else{
        if (transitions.isEmpty()){
            isvalid = false;
            errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": transitions is empty!");
        }else{
            for (auto i = transitions.size() - 1; i >= 0; i--){
                if (transitions.at(i).condition.data()){
                    if (transitions.at(i).condition->getSignature() != HKB_EXPRESSION_CONDITION){
                        if (transitions.at(i).condition->getSignature() == HKB_STRING_CONDITION){
                            errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid condition type! Fixing: "+QString::number(transitions.at(i).condition->getSignature(), 16)+"\n");
                            transitions[i].condition = HkxSharedPtr();
                        }else{
                            isvalid = false;
                            errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid condition type! Signature: "+QString::number(transitions.at(i).condition->getSignature(), 16)+"\n");
                        }
                    }else if (transitions.at(i).condition->isDataValid() && transitions.at(i).condition->evaluateDataValidity() != ""){
                        isvalid = false;
                        //errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid condition data!");
                    }
                }
                if (transitions.at(i).transition.data()){
                    if (transitions.at(i).transition->getSignature() != HKB_BLENDING_TRANSITION_EFFECT/* || transitions.at(i).condition->getSignature() != HKB_GENERATOR_TRANSITION_EFFECT*/){
                        isvalid = false;
                        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid transition type! Signature: "+QString::number(transitions.at(i).transition->getSignature(), 16)+"\n");
                    }else if (transitions.at(i).transition->isDataValid() && transitions.at(i).transition->evaluateDataValidity() != ""){
                        isvalid = false;
                        //errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": Invalid transition data!");
                    }
                }
                if (transitions.at(i).eventId >= static_cast<BehaviorFile *>(getParentFile())->getNumberOfEvents()){
                    isvalid = false;
                    errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": eventId in transitions at "+QString::number(i)+" out of range! Removing transition!");
                    transitions.removeAt(i);
                    break;
                }
                if (parent->getSignature() == HKB_STATE_MACHINE){
                    if (static_cast<hkbStateMachine *>(parent)->getStateNameNoLock(transitions.at(i).toStateId) == ""){
                        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": toStateId in transitions at "+QString::number(i)+" does not exist! Removing transition!");
                        transitions.removeAt(i);
                        break;
                    }
                    if (transitions.at(i).flags.contains("FLAG_TO_NESTED_STATE_ID_IS_VALID") && static_cast<hkbStateMachine *>(parent)->getNestedStateNameNoLock(transitions.at(i).toStateId, transitions.at(i).toNestedStateId) == ""){
                        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": toNestedStateId in transitions at "+QString::number(i)+" does not exist!");
                    }
                }else if (parent->getSignature() == HKB_STATE_MACHINE_STATE_INFO){
                    if (static_cast<hkbStateMachineStateInfo *>(parent)->getStateNameNoLock(transitions.at(i).toStateId) == ""){
                        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": toStateId in transitions at "+QString::number(i)+" does not exist! Removing transition!");
                        transitions.removeAt(i);
                        break;
                    }
                    if (transitions.at(i).flags.contains("FLAG_TO_NESTED_STATE_ID_IS_VALID") && static_cast<hkbStateMachineStateInfo *>(parent)->getNestedStateNameNoLock(transitions.at(i).toStateId, transitions.at(i).toNestedStateId) == ""){
                        errors.append(getParentFilename()+": "+getClassname()+": Ref: "+getReferenceString()+": toNestedStateId in transitions at "+QString::number(i)+" does not exist!");
                    }
                }
            }
        }
        if (transitions.isEmpty()){
            if (parent->getSignature() == HKB_STATE_MACHINE){
                static_cast<hkbStateMachine *>(parent)->removeWildcardTransitionsNoLock();
            }else if (parent->getSignature() == HKB_STATE_MACHINE_STATE_INFO){
                static_cast<hkbStateMachineStateInfo *>(parent)->removeTransitionsNoLock();
            }
        }
        setDataValidity(isvalid);
    }
    return errors;
}
void hkbStateMachineTransitionInfoArray::removeTransition(int index){
    std::lock_guard <std::mutex> guard(mutex);
    (transitions.size() > index && index > -1) ? transitions.removeAt(index), setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": Transition was not removed!");
}
void hkbStateMachineTransitionInfoArray::removeTransitionToState(ulong stateId){
    std::lock_guard <std::mutex> guard(mutex);
    for (auto i = transitions.size() - 1; i >= 0; i--){
        (transitions.at(i).toStateId == stateId) ? transitions.removeAt(i), setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": Transition was not removed!");
    }
}
void hkbGetWorldFromModelModifier::setName(const QString &newname){
    std::lock_guard <std::mutex> guard(mutex);
    (newname != name && newname != "") ? name = newname, setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'name' was not set!");
}
void hkbGetWorldFromModelModifier::setEnable(bool value){
    std::lock_guard <std::mutex> guard(mutex);
    (value != enable) ? enable = value, setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'enable' was not set!");
}
bool hkbHandIkDriverInfo::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    int numhands;
    bool ok;
    QByteArray text;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    auto checkvalue = [&](bool value, const QString & fieldname){
        (!value) ? LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'"+fieldname+"' has invalid data!\nObject Reference: "+ref) : NULL;
    };
    for (; index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"; index++){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "hands"){
            numhands = reader.getNthAttributeValueAt(index, 1).toInt(&ok);
            checkvalue(ok, "hands");
            (numhands > 0) ? index++ : NULL;
            for (auto j = 0; j < numhands; j++, index++){
                hands.append(hkbHandIkDriverInfoHand());
                for (; index < reader.getNumElements(); index++){
                    text = reader.getNthAttributeValueAt(index, 0);
                    if (text == "elbowAxisLS"){
                        hands.last().elbowAxisLS = readVector4(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").elbowAxisLS");
                    }else if (text == "backHandNormalLS"){
                        hands.last().backHandNormalLS = readVector4(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").backHandNormalLS");
                    }else if (text == "handOffsetLS"){
                        hands.last().handOffsetLS = readVector4(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").handOffsetLS");
                    }else if (text == "handOrienationOffsetLS"){
                        hands.last().handOrienationOffsetLS = readVector4(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").handOrienationOffsetLS");
                    }else if (text == "maxElbowAngleDegrees"){
                        hands.last().maxElbowAngleDegrees = reader.getElementValueAt(index).toDouble(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").maxElbowAngleDegrees");
                    }else if (text == "minElbowAngleDegrees"){
                        hands.last().minElbowAngleDegrees = reader.getElementValueAt(index).toDouble(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").minElbowAngleDegrees");
                    }else if (text == "shoulderIndex"){
                        hands.last().shoulderIndex = reader.getElementValueAt(index).toDouble(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").shoulderIndex");
                    }else if (text == "shoulderSiblingIndex"){
                        hands.last().shoulderSiblingIndex = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").shoulderSiblingIndex");
                    }else if (text == "elbowIndex"){
                        hands.last().elbowIndex = reader.getElementValueAt(index).toDouble(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").elbowIndex");
                    }else if (text == "elbowSiblingIndex"){
                        hands.last().elbowSiblingIndex = reader.getElementValueAt(index).toDouble(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").elbowSiblingIndex");
                    }else if (text == "wristIndex"){
                        hands.last().wristIndex = reader.getElementValueAt(index).toInt(&ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").wristIndex");
                    }else if (text == "enforceEndPosition"){
                        hands.last().enforceEndPosition = toBool(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").enforceEndPosition");
                    }else if (text == "enforceEndRotation"){
                        hands.last().enforceEndRotation = toBool(reader.getElementValueAt(index), &ok);
                        checkvalue(ok, "hands.at("+QString::number(j)+").enforceEndRotation");
                    }else if (text == "localFrameName"){
                        hands.last().localFrameName = reader.getElementValueAt(index);
                        //checkvalue((hands.last().localFrameName != "", "hands.at("+QString::number(j)+").localFrameName");
                        break;
                    }
                }
            }
            (numhands > 0) ? index-- : NULL;
        }else if (text == "fadeInOutCurve"){
            fadeInOutCurve = reader.getElementValueAt(index);
            checkvalue(BlendCurve.contains(fadeInOutCurve), "fadeInOutCurve");
        }
    }
    index--;
    return true;
}
void hkbStateMachineTransitionInfoArray::updateTransitionStateId(int oldid, int newid){
    std::lock_guard <std::mutex> guard(mutex);
    for (auto j = 0; j < transitions.size(); j++){
        (transitions.at(j).toStateId == oldid) ? transitions[j].toStateId = newid, setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": Transition state id was not updated!");
    }
}
void hkbGetWorldFromModelModifier::setRotationOut(const hkQuadVariable &value){
    std::lock_guard <std::mutex> guard(mutex);
    (value != rotationOut) ? rotationOut = value, setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'rotationOut' was not set!");
}
bool hkbProxyModifier::readData(const HkxXmlReader &reader, long & index){
    std::lock_guard <std::mutex> guard(mutex);
    bool ok;
    QByteArray text;
    auto ref = reader.getNthAttributeValueAt(index - 1, 0);
    auto checkvalue = [&](bool value, const QString & fieldname){
        (!value) ? LogFile::writeToLog(getParentFilename()+": "+getClassname()+": readData()!\n'"+fieldname+"' has invalid data!\nObject Reference: "+ref) : NULL;
    };
    for (; index < reader.getNumElements() && reader.getNthAttributeNameAt(index, 1) != "class"; index++){
        text = reader.getNthAttributeValueAt(index, 0);
        if (text == "variableBindingSet"){
            checkvalue(getVariableBindingSet().readShdPtrReference(index, reader), "variableBindingSet");
        }else if (text == "userData"){
            userData = reader.getElementValueAt(index).toULong(&ok);
            checkvalue(ok, "userData");
        }else if (text == "name"){
            name = reader.getElementValueAt(index);
            checkvalue((name != ""), "name");
        }else if (text == "enable"){
            enable = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "enable");
        }else if (text == "dynamicFriction"){
            proxyInfo.dynamicFriction = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "dynamicFriction");
        }else if (text == "staticFriction"){
            proxyInfo.staticFriction = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "staticFriction");
        }else if (text == "keepContactTolerance"){
            proxyInfo.keepContactTolerance = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "keepContactTolerance");
        }else if (text == "up"){
            proxyInfo.up = readVector4(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "up");
        }else if (text == "keepDistance"){
            proxyInfo.keepDistance = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "keepDistance");
        }else if (text == "contactAngleSensitivity"){
            proxyInfo.contactAngleSensitivity = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "contactAngleSensitivity");
        }else if (text == "userPlanes"){
            proxyInfo.userPlanes = reader.getElementValueAt(index).toInt(&ok);
            checkvalue(ok, "userPlanes");
        }else if (text == "maxCharacterSpeedForSolver"){
            proxyInfo.maxCharacterSpeedForSolver = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxCharacterSpeedForSolver");
        }else if (text == "characterStrength"){
            proxyInfo.characterStrength = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "characterStrength");
        }else if (text == "characterMass"){
            proxyInfo.characterMass = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "characterMass");
        }else if (text == "maxSlope"){
            proxyInfo.maxSlope = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxSlope");
        }else if (text == "penetrationRecoverySpeed"){
            proxyInfo.penetrationRecoverySpeed = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "penetrationRecoverySpeed");
        }else if (text == "maxCastIterations"){
            proxyInfo.maxCastIterations = reader.getElementValueAt(index).toInt(&ok);
            checkvalue(ok, "maxCastIterations");
        }else if (text == "refreshManifoldInCheckSupport"){
            proxyInfo.refreshManifoldInCheckSupport = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "refreshManifoldInCheckSupport");
        }else if (text == "linearVelocity"){
            linearVelocity = readVector4(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "linearVelocity");
        }else if (text == "horizontalGain"){
            horizontalGain = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "horizontalGain");
        }else if (text == "verticalGain"){
            verticalGain = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "verticalGain");
        }else if (text == "maxHorizontalSeparation"){
            maxHorizontalSeparation = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxHorizontalSeparation");
        }else if (text == "limitHeadingDegrees"){
            limitHeadingDegrees = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "limitHeadingDegrees");
        }else if (text == "maxVerticalSeparation"){
            maxVerticalSeparation = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxVerticalSeparation");
        }else if (text == "verticalDisplacementError"){
            verticalDisplacementError = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "verticalDisplacementError");
        }else if (text == "verticalDisplacementErrorGain"){
            verticalDisplacementErrorGain = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "verticalDisplacementErrorGain");
        }else if (text == "maxVerticalDisplacement"){
            maxVerticalDisplacement = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxVerticalDisplacement");
        }else if (text == "minVerticalDisplacement"){
            minVerticalDisplacement = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "minVerticalDisplacement");
        }else if (text == "capsuleHeight"){
            capsuleHeight = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "capsuleHeight");
        }else if (text == "capsuleRadius"){
            capsuleRadius = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "capsuleRadius");
        }else if (text == "maxSlopeForRotation"){
            maxSlopeForRotation = reader.getElementValueAt(index).toDouble(&ok);
            checkvalue(ok, "maxSlopeForRotation");
        }else if (text == "collisionFilterInfo"){
            collisionFilterInfo = reader.getElementValueAt(index).toInt(&ok);
            checkvalue(ok, "collisionFilterInfo");
        }else if (text == "phantomType"){
            phantomType = reader.getElementValueAt(index);
            checkvalue(PhantomType.contains(phantomType), "phantomType");
        }else if (text == "linearVelocityMode"){
            linearVelocityMode = reader.getElementValueAt(index);
            checkvalue(LinearVelocityMode.contains(linearVelocityMode), "linearVelocityMode");
        }else if (text == "ignoreIncomingRotation"){
            ignoreIncomingRotation = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "ignoreIncomingRotation");
        }else if (text == "ignoreCollisionDuringRotation"){
            ignoreCollisionDuringRotation = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "ignoreCollisionDuringRotation");
        }else if (text == "ignoreIncomingTranslation"){
            ignoreIncomingTranslation = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "ignoreIncomingTranslation");
        }else if (text == "includeDownwardMomentum"){
            includeDownwardMomentum = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "includeDownwardMomentum");
        }else if (text == "followWorldFromModel"){
            followWorldFromModel = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "followWorldFromModel");
        }else if (text == "isTouchingGround"){
            isTouchingGround = toBool(reader.getElementValueAt(index), &ok);
            checkvalue(ok, "isTouchingGround");
        }
    }
    index--;
    return true;
}
void hkbCharacterStringData::setVariableNameAt(int index, const QString &name){
    std::lock_guard <std::mutex> guard(mutex);
    (characterPropertyNames.size() > index && index > -1) ? characterPropertyNames.replace(index, name), setIsFileChanged(true) : LogFile::writeToLog(getClassname()+": 'setVariableNameAt' failed!");
}