@@ -243,7 +243,12 @@ void W3MayaAnimUtil::applyEdits() {
243243 hasChanges = true ;
244244 }
245245 if (ui->checkEditAddRootMotion ->isChecked ()) {
246-
246+ QJsonObject animBuff = animObj.value (" animBuffer" ).toObject ();
247+ QJsonArray animBones = animBuff.value (" bones" ).toArray ();
248+ editAddEmptyBoneFrames (animBones, " RootMotion" );
249+ animBuff[" bones" ] = animBones;
250+ animObj[" animBuffer" ] = animBuff;
251+ hasChanges = true ;
247252 }
248253 if (ui->groupEditBake ->isChecked ()) {
249254 editBakeBones (animObj, ui->checkEditBakePos ->isChecked (), ui->checkEditBakeRot ->isChecked (), ui->checkEditBakeScale ->isChecked ());
@@ -258,6 +263,11 @@ void W3MayaAnimUtil::applyEdits() {
258263 hasChanges = true ;
259264 }
260265
266+ if (ui->groupEditOptimize ->isChecked ()) {
267+ int boneOptimized = editOptimizeBones (animObj, ui->checkEditOptimizePos ->isChecked (), ui->checkEditOptimizeRot ->isChecked (), ui->checkEditOptimizeScale ->isChecked ());
268+ hasChanges = hasChanges || (boneOptimized > 0 );
269+ }
270+
261271 if (ui->checkEditSortEvents ->isChecked ()) {
262272 editSortEvents (eventsArray);
263273 hasChanges = true ;
@@ -397,7 +407,7 @@ void W3MayaAnimUtil::editCropAnim(QJsonObject& animObj, QJsonArray& eventsArray,
397407 .arg ( framesToSec (durationFrames - 1 ) ));
398408}
399409
400- void W3MayaAnimUtil::editAddEmptyBone (QJsonArray& bonesArr, QString boneName) {
410+ void W3MayaAnimUtil::editAddEmptyBoneFrames (QJsonArray& bonesArr, QString boneName, int numFrames ) {
401411 int last_index = 0 ;
402412 if (!bonesArr.isEmpty ()) {
403413 last_index = bonesArr.last ().toObject ().value (" index" ).toInt ();
@@ -411,14 +421,16 @@ void W3MayaAnimUtil::editAddEmptyBone(QJsonArray& bonesArr, QString boneName) {
411421 double dt = 0.033333333 ;
412422 QString attrNames[3 ] = { " position" , " rotation" , " scale" };
413423 upn (j, 0 , 2 ) {
414- newBoneObj.insert (QString (" %1_numFrames" ).arg (attrNames[j]), 1 );
424+ newBoneObj.insert (QString (" %1_numFrames" ).arg (attrNames[j]), numFrames );
415425 QJsonArray attrArray = QJsonArray ();
416- if (attrNames[j] == " rotation" )
417- attrArray.append (objXYZW (0 ,0 ,0 ,1 ));
418- else if (attrNames[j] == " position" )
419- attrArray.append (objXYZ (0 ,0 ,0 ));
420- else
421- attrArray.append (objXYZ (1 ,1 ,1 ));
426+ upn (jj, 1 , numFrames) {
427+ if (attrNames[j] == " rotation" )
428+ attrArray.append (objXYZW (0 ,0 ,0 ,1 ));
429+ else if (attrNames[j] == " position" )
430+ attrArray.append (objXYZ (0 ,0 ,0 ));
431+ else
432+ attrArray.append (objXYZ (1 ,1 ,1 ));
433+ }
422434 newBoneObj.insert (QString (" %1Frames" ).arg (attrNames[j]), attrArray);
423435 newBoneObj.insert (QString (" %1_dt" ).arg (attrNames[j]), dt);
424436 }
@@ -471,6 +483,94 @@ void W3MayaAnimUtil::editBakeBones(QJsonObject& animObj, bool bakePos, bool bake
471483 animBuff[" bones" ] = animBones;
472484 animObj[" animBuffer" ] = animBuff;
473485}
486+
487+ bool W3MayaAnimUtil::editOptimizeBone (QJsonObject& boneObj, bool optimizePos, bool optimizeRot, bool optimizeScale) {
488+ int posNum = boneObj[" position_numFrames" ].toInt ();
489+ int rotNum = boneObj[" rotation_numFrames" ].toInt ();
490+ int scaleNum = boneObj[" scale_numFrames" ].toInt ();
491+
492+ optimizePos = posNum > 1 ;
493+ optimizeRot = rotNum > 1 ;
494+ optimizeScale = scaleNum > 1 ;
495+ QJsonArray posArray = boneObj[" positionFrames" ].toArray ();
496+ QJsonArray rotArray = boneObj[" rotationFrames" ].toArray ();
497+ QJsonArray scaleArray = boneObj[" scaleFrames" ].toArray ();
498+
499+ upn (frame, 1 , posNum - 1 ) {
500+ double diffX = posArray[frame].toObject ().value (" x" ).toDouble () - posArray[frame - 1 ].toObject ().value (" x" ).toDouble ();
501+ double diffY = posArray[frame].toObject ().value (" y" ).toDouble () - posArray[frame - 1 ].toObject ().value (" y" ).toDouble ();
502+ double diffZ = posArray[frame].toObject ().value (" z" ).toDouble () - posArray[frame - 1 ].toObject ().value (" z" ).toDouble ();
503+ double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ);
504+ if (diffTotal > mReductionSensitivity ()) {
505+ optimizePos = false ;
506+ break ;
507+ }
508+ }
509+ upn (frame, 1 , rotNum - 1 ) {
510+ double diffX = rotArray[frame].toObject ().value (" X" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" X" ).toDouble ();
511+ double diffY = rotArray[frame].toObject ().value (" Y" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" Y" ).toDouble ();
512+ double diffZ = rotArray[frame].toObject ().value (" Z" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" Z" ).toDouble ();
513+ double diffW = rotArray[frame].toObject ().value (" W" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" W" ).toDouble ();
514+ double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ) + qAbs (diffW);
515+ if (diffTotal > mReductionSensitivity ()) {
516+ optimizeRot = false ;
517+ break ;
518+ }
519+ }
520+ upn (frame, 1 , scaleNum - 1 ) {
521+ double diffX = scaleArray[frame].toObject ().value (" x" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" x" ).toDouble ();
522+ double diffY = scaleArray[frame].toObject ().value (" y" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" y" ).toDouble ();
523+ double diffZ = scaleArray[frame].toObject ().value (" z" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" z" ).toDouble ();
524+ double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ);
525+ if (diffTotal > mReductionSensitivity ()) {
526+ optimizeScale = false ;
527+ break ;
528+ }
529+ }
530+ if (optimizePos) {
531+ QJsonArray newPosArray;
532+ newPosArray.append ( posArray.first () );
533+ boneObj[" positionFrames" ] = newPosArray;
534+ boneObj[" position_numFrames" ] = 1 ;
535+ }
536+ if (optimizeRot) {
537+ QJsonArray newRotArray;
538+ newRotArray.append ( rotArray.first () );
539+ boneObj[" rotationFrames" ] = newRotArray;
540+ boneObj[" rotation_numFrames" ] = 1 ;
541+ }
542+ if (optimizeScale) {
543+ QJsonArray newScaleArray;
544+ newScaleArray.append ( scaleArray.first () );
545+ boneObj[" scaleFrames" ] = newScaleArray;
546+ boneObj[" scale_numFrames" ] = 1 ;
547+ }
548+ return (optimizePos || optimizeRot || optimizeScale);
549+ }
550+
551+ int W3MayaAnimUtil::editOptimizeBones (QJsonObject& animObj, bool optimizePos, bool optimizeRot, bool optimizeScale) {
552+ QJsonObject bufferObj = animObj[" animBuffer" ].toObject ();
553+ QJsonArray bonesArray = bufferObj[" bones" ].toArray ();
554+ int optimized = 0 ;
555+ int numBones = bonesArray.count ();
556+
557+ upn (i, 0 , numBones - 1 ) {
558+ QJsonObject boneObj = bonesArray.at (i).toObject ();
559+ bool boneOptimized = editOptimizeBone (boneObj, optimizePos, optimizeRot, optimizeScale);
560+ if (boneOptimized) {
561+ optimized += 1 ;
562+ bonesArray[i] = boneObj;
563+ }
564+ }
565+
566+ if (optimized > 0 ) {
567+ bufferObj[" bones" ] = bonesArray;
568+ animObj[" animBuffer" ] = bufferObj;
569+ }
570+ addLog (QString (" \t [EDIT] Optimized %1 bones of %2." ).arg (optimized).arg (numBones));
571+ return optimized;
572+ }
573+
474574void W3MayaAnimUtil::onChecked_EditCut (bool checked) {
475575 if (checked) {
476576 if (!ui->groupEditBake ->isChecked ())
@@ -483,6 +583,13 @@ void W3MayaAnimUtil::onChecked_EditCut(bool checked) {
483583 ui->groupEditBake ->setEnabled (true );
484584 }
485585}
586+ void W3MayaAnimUtil::onClicked_EditGroupOptimize (bool checked) {
587+ if (checked) {
588+ ui->checkEditOptimizePos ->setChecked (true );
589+ ui->checkEditOptimizeRot ->setChecked (true );
590+ ui->checkEditOptimizeScale ->setChecked (true );
591+ }
592+ }
486593void W3MayaAnimUtil::onClicked_EditApply () {
487594 applyEdits ();
488595}
@@ -1320,6 +1427,11 @@ bool W3MayaAnimUtil::extractMotionFromBone(QJsonValueRef ref) {
13201427 m_animNames.push_back (animName);
13211428 m_animDurations.push_back (animDuration);
13221429
1430+ int bonesOptimized = 0 ;
1431+ if ( ui->checkOptimizeEqual ->isChecked () ) {
1432+ bonesOptimized = editOptimizeBones (animObj, true , true , true );
1433+ }
1434+
13231435 QJsonObject bufferObj = animObj[" animBuffer" ].toObject ();
13241436 QJsonArray bonesArray = bufferObj[" bones" ].toArray ();
13251437 if ( bonesArray.isEmpty () ) {
@@ -1330,133 +1442,66 @@ bool W3MayaAnimUtil::extractMotionFromBone(QJsonValueRef ref) {
13301442 int animFrames = bufferObj[" numFrames" ].toInt ();
13311443 int mBoneIdx = -1 ;
13321444 QStringList brokenBones;
1333- int bonesOptimized = 0 ;
1334- int bonesBaked = 0 ;
1445+
13351446
13361447 upn (i, 0 , bonesArray.size () - 1 ) {
1337- QJsonObject tempObj = bonesArray[i].toObject ();
1338- QString boneName = tempObj .value (" BoneName" ).toString ();
1448+ QJsonObject boneObj = bonesArray[i].toObject ();
1449+ QString boneName = boneObj .value (" BoneName" ).toString ();
13391450
13401451 if (boneName == mBoneName ) {
13411452 mBoneIdx = i;
13421453 }
1343- int posNum = tempObj[" position_numFrames" ].toInt ();
1344- int rotNum = tempObj[" rotation_numFrames" ].toInt ();
1345- int scaleNum = tempObj[" scale_numFrames" ].toInt ();
1346-
1347- if ( ui->checkOptimizeEqual ->isChecked () ) {
1348- bool optimizeTranslation = posNum > 1 ;
1349- bool optimizeRotation = rotNum > 1 ;
1350- bool optimizeScale = scaleNum > 1 ;
1351- QJsonArray posArray = tempObj[" positionFrames" ].toArray ();
1352- QJsonArray rotArray = tempObj[" rotationFrames" ].toArray ();
1353- QJsonArray scaleArray = tempObj[" scaleFrames" ].toArray ();
1354-
1355- upn (frame, 1 , posNum - 1 ) {
1356- double diffX = posArray[frame].toObject ().value (" x" ).toDouble () - posArray[frame - 1 ].toObject ().value (" x" ).toDouble ();
1357- double diffY = posArray[frame].toObject ().value (" y" ).toDouble () - posArray[frame - 1 ].toObject ().value (" y" ).toDouble ();
1358- double diffZ = posArray[frame].toObject ().value (" z" ).toDouble () - posArray[frame - 1 ].toObject ().value (" z" ).toDouble ();
1359- double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ);
1360- if (diffTotal > mReductionSensitivity ()) {
1361- optimizeTranslation = false ;
1362- break ;
1363- }
1364- }
1365- upn (frame, 1 , rotNum - 1 ) {
1366- double diffX = rotArray[frame].toObject ().value (" X" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" X" ).toDouble ();
1367- double diffY = rotArray[frame].toObject ().value (" Y" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" Y" ).toDouble ();
1368- double diffZ = rotArray[frame].toObject ().value (" Z" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" Z" ).toDouble ();
1369- double diffW = rotArray[frame].toObject ().value (" W" ).toDouble () - rotArray[frame - 1 ].toObject ().value (" W" ).toDouble ();
1370- double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ) + qAbs (diffW);
1371- if (diffTotal > mReductionSensitivity ()) {
1372- optimizeRotation = false ;
1373- break ;
1374- }
1375- }
1376- upn (frame, 1 , scaleNum - 1 ) {
1377- double diffX = scaleArray[frame].toObject ().value (" x" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" x" ).toDouble ();
1378- double diffY = scaleArray[frame].toObject ().value (" y" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" y" ).toDouble ();
1379- double diffZ = scaleArray[frame].toObject ().value (" z" ).toDouble () - scaleArray[frame - 1 ].toObject ().value (" z" ).toDouble ();
1380- double diffTotal = qAbs (diffX) + qAbs (diffY) + qAbs (diffZ);
1381- if (diffTotal > mReductionSensitivity ()) {
1382- optimizeScale = false ;
1383- break ;
1384- }
1385- }
1386- if (optimizeTranslation) {
1387- QJsonArray nposArray;
1388- nposArray.append ( posArray.first () );
1389- tempObj[" positionFrames" ] = nposArray;
1390- tempObj[" position_numFrames" ] = 1 ;
1391- posNum = 1 ;
1392- }
1393- if (optimizeRotation) {
1394- QJsonArray nrotArray;
1395- nrotArray.append ( rotArray.first () );
1396- tempObj[" rotationFrames" ] = nrotArray;
1397- tempObj[" rotation_numFrames" ] = 1 ;
1398- rotNum = 1 ;
1399- }
1400- if (optimizeScale) {
1401- QJsonArray nscaleArray;
1402- nscaleArray.append ( scaleArray.first () );
1403- tempObj[" scaleFrames" ] = nscaleArray;
1404- tempObj[" scale_numFrames" ] = 1 ;
1405- scaleNum = 1 ;
1406- }
1407- if (optimizeTranslation || optimizeRotation || optimizeScale) {
1408- bonesArray[i] = tempObj;
1409- bonesOptimized += 1 ;
1410- }
1411- }
1454+ /* int posNum = boneObj["position_numFrames"].toInt();
1455+ int rotNum = boneObj["rotation_numFrames"].toInt();
1456+ int scaleNum = boneObj["scale_numFrames"].toInt();
14121457
14131458 QString error;
14141459 if (posNum != animFrames && posNum != 1) {
14151460 if (ui->checkAutoBakeIncomplete->isChecked()) {
1416- QJsonArray posArray = tempObj [" positionFrames" ].toArray ();
1461+ QJsonArray posArray = boneObj ["positionFrames"].toArray();
14171462 while (posArray.count() != animFrames) {
14181463 posArray.append( posArray.last() );
14191464 }
1420- tempObj [" positionFrames" ] = posArray;
1421- tempObj [" position_numFrames" ] = animFrames;
1465+ boneObj ["positionFrames"] = posArray;
1466+ boneObj ["position_numFrames"] = animFrames;
14221467 }
14231468 error += QString(" [translation = %1];").arg(posNum);
14241469 }
14251470
14261471 if (rotNum != animFrames && rotNum != 1) {
14271472 if (ui->checkAutoBakeIncomplete->isChecked()) {
1428- QJsonArray rotArray = tempObj [" rotationFrames" ].toArray ();
1473+ QJsonArray rotArray = boneObj ["rotationFrames"].toArray();
14291474 while (rotArray.count() != animFrames) {
14301475 rotArray.append( rotArray.last() );
14311476 }
1432- tempObj [" rotationFrames" ] = rotArray;
1433- tempObj [" rotation_numFrames" ] = animFrames;
1477+ boneObj ["rotationFrames"] = rotArray;
1478+ boneObj ["rotation_numFrames"] = animFrames;
14341479 }
14351480 error += QString(" [rotation = %1];").arg(rotNum);
14361481 }
14371482
14381483 if (scaleNum != animFrames && scaleNum != 1) {
14391484 if (ui->checkAutoBakeIncomplete->isChecked()) {
1440- QJsonArray scaleArray = tempObj [" scaleFrames" ].toArray ();
1485+ QJsonArray scaleArray = boneObj ["scaleFrames"].toArray();
14411486 while (scaleArray.count() != animFrames) {
14421487 scaleArray.append( scaleArray.last() );
14431488 }
1444- tempObj [" scaleFrames" ] = scaleArray;
1445- tempObj [" scale_numFrames" ] = animFrames;
1489+ boneObj ["scaleFrames"] = scaleArray;
1490+ boneObj ["scale_numFrames"] = animFrames;
14461491 }
14471492 error += QString(" [scale = %1];").arg(scaleNum);
14481493 }
14491494
14501495 if (!error.isEmpty()) {
14511496 if (ui->checkAutoBakeIncomplete->isChecked()) {
1452- bonesArray[i] = tempObj ;
1497+ bonesArray[i] = boneObj ;
14531498 ++bonesBaked;
14541499 }
14551500 if (boneName.endsWith("_roll") || boneName.startsWith("IK_"))
14561501 brokenBones.append( boneName + ":" + error );
14571502 else
14581503 brokenBones.append( "!!! " + boneName + ":" + error );
1459- }
1504+ }*/
14601505 }
14611506
14621507 bool isAdditive = isAdditiveAnim (animObj);
@@ -1515,7 +1560,7 @@ bool W3MayaAnimUtil::extractMotionFromBone(QJsonValueRef ref) {
15151560 QMessageBox::information (this , " Warning!" , QString (" Detected bones with incorrect numFrames in anim [%1] (numFrames = %2)\n It may break the game!\n Bones: %3" ).arg (animName).arg (animFrames).arg (brokenBones.join (" \n " )));
15161561 }
15171562 if (mBoneIdx == -1 ) {
1518- if (bonesOptimized || bonesBaked ) {
1563+ if (bonesOptimized) {
15191564 bufferObj[" bones" ] = bonesArray;
15201565 animObj[" animBuffer" ] = bufferObj;
15211566 }
@@ -2521,11 +2566,11 @@ void W3MayaAnimUtil::onClicked_MergeProcess() {
25212566 boneByNameF[boneNameF] = animBonesF[i].toObject ();
25222567 }
25232568 if (!boneByNameF.contains (" RootMotion" )) {
2524- editAddEmptyBone (animBonesF, " RootMotion" );
2569+ editAddEmptyBoneFrames (animBonesF, " RootMotion" , framesF );
25252570 boneByNameF[" RootMotion" ] = animBonesF.last ().toObject ();
25262571 }
25272572 if (!boneByNameS.contains (" RootMotion" )) {
2528- editAddEmptyBone (animBonesS, " RootMotion" );
2573+ editAddEmptyBoneFrames (animBonesS, " RootMotion" , framesS );
25292574 boneByNameS[" RootMotion" ] = animBonesS.last ().toObject ();
25302575 }
25312576
@@ -2540,8 +2585,6 @@ void W3MayaAnimUtil::onClicked_MergeProcess() {
25402585 // for every bone
25412586 for (int j = 0 ; j < animBonesF.count (); j += 1 ) {
25422587 QString boneNameF = animBonesF[j].toObject ().value (" BoneName" ).toString ();
2543- if ( !isBlend && boneNameF == " RootMotion" )
2544- continue ;
25452588
25462589 QJsonObject boneF = animBonesF[j].toObject ();
25472590 QJsonObject boneS = boneByNameS[boneNameF];
@@ -2651,7 +2694,7 @@ void W3MayaAnimUtil::onClicked_MergeProcess() {
26512694 rotArrF[frame - 1 ] = objXYZW (sumQ.x (), sumQ.y (), sumQ.z (), sumQ.scalar ());
26522695 }
26532696 if (ui->checkMergeCropToSecond ->isChecked ()) {
2654- addLog (QString (" \t [MERGE] Cropping anim from %1 to %2 frames." ).arg (posArrF.count ()).arg (framesS));
2697+ addLog (QString (" \t [MERGE] Cropping bone %1 from %2 to %3 frames." ). arg (boneNameF ).arg (posArrF.count ()).arg (framesS));
26552698 while (posArrF.count () > framesS) {
26562699 posArrF.pop_back ();
26572700 }
@@ -2751,6 +2794,11 @@ void W3MayaAnimUtil::onClicked_MergeProcess() {
27512794 animObjF[" duration" ] = framesToSec (framesTotal - 1 );
27522795 animObjF[" animBuffer" ] = animBuffF;
27532796
2797+ /* optimize */
2798+ if (ui->checkMergeOptimize ->isChecked ()) {
2799+ editOptimizeBones (animObjF, true , true , true );
2800+ }
2801+
27542802 QJsonObject mergedJsonRoot = QJsonObject ();
27552803 mergedJsonRoot.insert (" animation" , animObjF);
27562804 mergedJsonRoot.insert (" entries" , eventsArrayF);
0 commit comments