Skip to content

Commit b528988

Browse files
committed
+ v2.2: Enums support, events sorting, correcting animName
1 parent a3ad141 commit b528988

File tree

11 files changed

+420
-191
lines changed

11 files changed

+420
-191
lines changed

source/W3MayaAnimUtil.cpp

Lines changed: 135 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#define upn(val, start, end) for(int val = start; val <= end; ++val)
1010
#define JRef QJsonValueRef
11-
#define VERSION "v2.1.1"
11+
#define VERSION "v2.2"
1212
#define MAU W3MayaAnimUtil
1313

1414
MAU::MAU(QWidget *parent)
@@ -17,7 +17,14 @@ MAU::MAU(QWidget *parent)
1717
{
1818
ui->setupUi(this);
1919
//ui->textLog->setFontPointSize(20);
20-
ui->textLog->setHtml("Welcome to <span style=\"font-weight:700;\">MAU " + QString(VERSION " (" __DATE__ ")") + "</span>!<br>Made by <span style=\"color:#6f00a6;font-weight:700;\">nikich340</span> for better the Witcher 3 modding experiene.<br><br>Click \"Load anim .json\" to start");
20+
ui->textLog->setHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">"
21+
"<html><head><meta name=\"qrichtext\" content=\"1\" /><meta charset=\"utf-8\" /><style type=\"text/css\">"
22+
"p, li { white-space: pre-wrap; }"
23+
"</style></head><body style=\" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;\">"
24+
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Welcome to <span style=\" font-weight:700;\">W3MayaAnimUtil"
25+
+ QString(VERSION " (" __DATE__ ")")
26+
+ "</span>.<br />Made by <span style=\" font-weight:696; color:#6f00a6;\">nikich340</span> for better the Witcher 3 modding experiene.<br /><span style=\" font-style:italic;\"><br /></span>Click &quot;Load anim .json&quot; to start.</p>"
27+
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><img src=\":/icons/motivated_small.png\" /></p></body></html>");
2128
ui->spinSensivity->setMinimum(0.0000000001);
2229
ui->spinSensivity->setSingleStep(0.00001);
2330
ui->spinSensivity->setValue(0.00001);
@@ -28,6 +35,15 @@ MAU::MAU(QWidget *parent)
2835
}
2936
pLabelInfo = new QLabel();
3037

38+
if (QSettings().value("GUIStyle", "windowsvista") == "windowsvista") {
39+
ui->comboGUIStyle->setCurrentText("Windows");
40+
} else if (QSettings().value("GUIStyle", "windowsvista") == "Windows") {
41+
ui->comboGUIStyle->setCurrentText("WindowsXP");
42+
} else {
43+
ui->comboGUIStyle->setCurrentText("Fusion");
44+
}
45+
46+
connect(ui->comboGUIStyle, SIGNAL(currentTextChanged(QString)), this, SLOT(onChanged_GUIStyle(QString)));
3147
connect(ui->buttonLoad, SIGNAL(clicked(bool)), this, SLOT(onClicked_Load()));
3248
connect(ui->buttonSave, SIGNAL(clicked(bool)), this, SLOT(onClicked_Save()));
3349
connect(ui->buttonSaveSplit, SIGNAL(clicked(bool)), this, SLOT(onClicked_SaveSplit()));
@@ -55,6 +71,7 @@ MAU::MAU(QWidget *parent)
5571
/* EVENTS EDIT */
5672
ui->comboEventsType->addItems(m_knownEventTypes);
5773
ui->comboEventsVarType->addItems(m_knownVarTypes);
74+
ui->comboEventsVarType->addItems(m_knownEnumTypes.keys());
5875
ui->stackEventsValue->widget(0)->setProperty("type", QString("Bool"));
5976
ui->stackEventsValue->widget(1)->setProperty("type", QString("Int32"));
6077
ui->stackEventsValue->widget(2)->setProperty("type", QString("Float"));
@@ -86,6 +103,8 @@ MAU::MAU(QWidget *parent)
86103
connect(ui->buttonResetEvents, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsReset()));
87104
connect(ui->buttonApplyEvents, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsApply()));
88105

106+
connect(ui->buttonEventsSort, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsSort()));
107+
connect(ui->buttonEventsFixAnimationName, SIGNAL(clicked(bool)), this, SLOT(onClicked_fixAnimationNames()));
89108
connect(ui->buttonEventsType, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsSetType()));
90109
connect(ui->buttonEventsAdd, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsAdd()));
91110
connect(ui->buttonEventsClone, SIGNAL(clicked(bool)), this, SLOT(onClicked_eventsClone()));
@@ -214,8 +233,8 @@ void MAU::setEventStartTime(QJsonObject& eventObj, double newTime) {
214233
eventObj["Content"] = contentArr;
215234
}
216235
void MAU::onChanged_GUIStyle(QString newStyle) {
217-
if (newStyle == "Windows") {
218-
QSettings().setValue("GUIStyle", "windowsvista");
236+
if (newStyle == "Default") {
237+
QSettings().remove("GUIStyle");
219238
} else if (newStyle == "WindowsXP") {
220239
QSettings().setValue("GUIStyle", "Windows");
221240
} else if (newStyle == "Fusion") {
@@ -357,12 +376,18 @@ void MAU::editRenameAnim(QJsonObject& animObj, QJsonArray& eventsArray, QString
357376
void MAU::editSetCDPRDuration(QJsonObject& animObj) {
358377
QJsonObject animBuff = animObj.value("animBuffer").toObject();
359378
int animFrames = animBuff.value("numFrames").toInt();
379+
double durationCDPR = framesToSec(animFrames - 1);
360380
addLog(QString("\t[EDIT] Set anim and animBuffer duration = %1 s.")
361-
.arg( framesToSec(animFrames - 1) ));
381+
.arg( durationCDPR ));
362382

363-
animBuff["duration"] = framesToSec(animFrames - 1);
383+
animBuff["duration"] = durationCDPR;
364384
animObj["animBuffer"] = animBuff;
365-
animObj["duration"] = framesToSec(animFrames - 1);
385+
animObj["duration"] = durationCDPR;
386+
if ( animObj.contains("motionExtraction") ) {
387+
JSO motionObj = animObj["motionExtraction"].toObject();
388+
motionObj["duration"] = qMin(motionObj["duration"].toDouble(), durationCDPR);
389+
animObj["motionExtraction"] = motionObj;
390+
}
366391
m_animDurations[m_animIndex] = framesToSec(animFrames - 1);
367392
}
368393

@@ -765,6 +790,9 @@ JSO MAU::varToEntry(QString entryName, QVariant val, QString customType) {
765790
if (customType.toUpper() == "CNAME") {
766791
entry["Type"] = "CName";
767792
entry["Value"] = val.toString();
793+
} else if (m_knownEnumTypes.contains(customType)) {
794+
entry["Type"] = customType;
795+
entry["Value"] = val.toString();
768796
} else {
769797
entry["Type"] = "StringAnsi";
770798
entry["val"] = val.toString();
@@ -813,7 +841,7 @@ JSO MAU::varToEntry(QString entryName, QVariant val, QString customType) {
813841
QPair<QString, QString>("cameraAnimOnMissedHit", "CName"),
814842
};
815843
} else {
816-
qDebug() << QString("varToEntry: Unknown type %2 for %1!").arg(entryName).arg(val.typeName());
844+
addLog(QString("[ERROR] varToEntry: unknown type %1 for %2").arg(entryName).arg(val.typeName()), logError);
817845
return JSO();
818846
}
819847
for (QPair<QString, QString> p : mapKeys) {
@@ -829,6 +857,7 @@ JSO MAU::varToEntry(QString entryName, QVariant val, QString customType) {
829857
}
830858
return entry;
831859
}
860+
832861
QVariant MAU::entryToVar(JSO entry) {
833862
if ( !entry.contains("Type") ) {
834863
qDebug() << "entryToVar: entry type not found! Name: " << entry.value("Name").toString();;
@@ -852,6 +881,8 @@ QVariant MAU::entryToVar(JSO entry) {
852881
ret.append( array.at(i).toString() );
853882
}
854883
return ret;
884+
} else if (m_knownEnumTypes.contains(type)) {
885+
return entry.value("Value").toString();
855886
} else if (type == "SEnumVariant" || type == "CPreAttackEventData") {
856887
QHash<QString, QVariant> ret = QHash<QString, QVariant>();
857888
JSA array = entry.value("Content").toArray();
@@ -864,10 +895,11 @@ QVariant MAU::entryToVar(JSO entry) {
864895
}
865896
return ret;
866897
} else {
867-
qDebug() << QString("entryToVar: Unknown type %1!").arg(type);
898+
addLog(QString("[ERROR] entryToVar: unknown type %1 for %2").arg(type).arg(entry["Name"].toString()), logError);
868899
return QVariant();
869900
}
870901
}
902+
871903
void MAU::eventsLoad() {
872904
ui->listEvents->clear();
873905

@@ -878,6 +910,7 @@ void MAU::eventsLoad() {
878910
ui->listEvents->setCurrentRow(0);
879911
}
880912
}
913+
881914
QVariant MAU::getEventParam(QJsonObject eventObj, QString paramName, QVariant defaultValue) {
882915
QJsonArray contentArr = eventObj.value("Content").toArray();
883916
upn(j, 0, contentArr.count() - 1) {
@@ -889,6 +922,7 @@ QVariant MAU::getEventParam(QJsonObject eventObj, QString paramName, QVariant de
889922
qDebug() << QString("Can't find event %1! Type: %2").arg(paramName).arg(eventObj.value("Type").toString());
890923
return defaultValue;
891924
}
925+
892926
void MAU::eventsUpdateLabel(int eventIndex, bool add) {
893927
if (eventIndex < 0)
894928
return;
@@ -912,6 +946,7 @@ void MAU::eventsUpdateLabel(int eventIndex, bool add) {
912946
ui->listEvents->item(eventIndex)->setText( QString("%1 #%2 [%3 s]").arg(type).arg(eventIndex).arg(startTime, 0, 'f', 3) );
913947
}
914948
}
949+
915950
void MAU::eventsUpdateContentLabel(int eventIndex, int index, bool add) {
916951
if (index < 0 || eventIndex < 0)
917952
return;
@@ -933,6 +968,7 @@ void MAU::eventsUpdateContentLabel(int eventIndex, int index, bool add) {
933968
ui->listEventsContent->item(index)->setText( QString("%1 (%2) = %3").arg(entryName).arg(entryType).arg(value.toString()) );
934969
}
935970
}
971+
936972
JSO MAU::defaultEntry(QString name, QString type) {
937973
JSO contentEntry = JSO();
938974
if (type == "Bool") {
@@ -947,6 +983,8 @@ JSO MAU::defaultEntry(QString name, QString type) {
947983
contentEntry = varToEntry(name, "", "CName");
948984
} else if (type == "array:2,0,StringAnsi") {
949985
contentEntry = varToEntry( name, QStringList({""}) );
986+
} else if (m_knownEnumTypes.contains(type)) {
987+
contentEntry = varToEntry(name, m_knownEnumTypes[type].first(), type);
950988
} else if (type == "SEnumVariant") {
951989
QHash<QString, QVariant> map = QHash<QString, QVariant>();
952990
map["enumType"] = QString("ERotationRate");
@@ -958,11 +996,40 @@ JSO MAU::defaultEntry(QString name, QString type) {
958996
map["soundAttackType"] = QString("monster_big_bite");
959997
map["hitReactionType"] = 1;
960998
contentEntry = varToEntry( name, QVariant::fromValue(map), "CPreAttackEventData" );
999+
} else {
1000+
addLog(QString("[ERROR] defaultEntry: unknown type %1 for %2").arg(type).arg(name), logError);
9611001
}
9621002
return contentEntry;
9631003
}
9641004

9651005
// EVENTS slots
1006+
void MAU::onClicked_eventsSort() {
1007+
editSortEvents(m_animEvents);
1008+
eventsLoad();
1009+
addLog(QString("[EVENTS] Sorted event entries: %2.")
1010+
.arg(m_animEvents.count()));
1011+
}
1012+
void MAU::onClicked_fixAnimationNames() {
1013+
int fixed_vars = 0;
1014+
1015+
upn(eventIndex, 0, m_animEvents.count() - 1) {
1016+
JSO eventObj = m_animEvents.at(eventIndex).toObject();
1017+
JSA contentArr = eventObj.value("Content").toArray();
1018+
upn(index, 0, contentArr.count() - 1) {
1019+
JSO contentEntry = contentArr.at(index).toObject();
1020+
if (contentEntry["Name"] == "animationName" && contentEntry["Value"].toString() != m_animNames[m_animIndex]) {
1021+
contentEntry["Value"] = m_animNames[m_animIndex];
1022+
contentArr[index] = contentEntry;
1023+
++fixed_vars;
1024+
}
1025+
}
1026+
eventObj["Content"] = contentArr;
1027+
m_animEvents[eventIndex] = eventObj;
1028+
}
1029+
eventsLoad();
1030+
addLog(QString("[EVENTS] Fixed animationName vars: %1.")
1031+
.arg(fixed_vars));
1032+
}
9661033
void MAU::onChecked_DynamicLabel(bool checked) {
9671034
QCheckBox* box = qobject_cast<QCheckBox*>(sender());
9681035
if (box != nullptr) {
@@ -1014,16 +1081,61 @@ void MAU::onClicked_eventsAdd() {
10141081

10151082
QString type = ui->comboEventsType->currentText();
10161083
// generic CExtAnimEvent
1017-
contentArr.append( varToEntry("eventName", "-", "CName") );
1018-
contentArr.append( varToEntry("startTime", 0.0) );
1084+
contentArr.append( defaultEntry("eventName", "CName") );
1085+
contentArr.append( defaultEntry("startTime", "Float") );
10191086
contentArr.append( varToEntry("animationName", m_animNames[m_animIndex], "CName") );
1020-
if (type.endsWith("DurationEvent")) {
1087+
1088+
if (type.endsWith("DurationEvent") || type == "CEASEnumEvent" || type == "CPreAttackEvent") {
10211089
contentArr.append( varToEntry("duration", qMax(0.01, m_animDurations[m_animIndex] - framesToSec(1))) );
1022-
contentArr.append( varToEntry("alwaysFiresEnd", false) );
1023-
} else if (type.startsWith("CExtAnimEffect")) {
1024-
contentArr.append( varToEntry("effectName", "", "CName") );
1090+
contentArr.append( defaultEntry("alwaysFiresEnd", "Bool") );
1091+
}
1092+
1093+
if (type.startsWith("CExtAnimEffect")) {
1094+
contentArr.append( defaultEntry("effectName", "CName") );
1095+
}
1096+
if (type == "CExtAnimEffectEvent") {
1097+
contentArr.append( defaultEntry("action", "EAnimEffectAction") );
1098+
}
1099+
if (type == "CExtAnimItemEvent") {
1100+
contentArr.append( defaultEntry("category", "CName") );
1101+
contentArr.append( defaultEntry("itemName_optional", "CName") );
1102+
contentArr.append( defaultEntry("ignoreItemsWithTag", "CName") );
1103+
contentArr.append( defaultEntry("action", "EItemAction") );
1104+
}
1105+
if (type == "CExtAnimItemEffectEvent") {
1106+
contentArr.append( defaultEntry("effectName", "CName") );
1107+
contentArr.append( defaultEntry("itemSlot", "CName") );
1108+
contentArr.append( defaultEntry("action", "EItemEffectAction") );
1109+
}
1110+
1111+
if (type.startsWith("CExp")) {
1112+
contentArr.append( defaultEntry("translation", "Bool") );
1113+
contentArr.append( defaultEntry("rotation", "Bool") );
1114+
}
1115+
1116+
if (type == "CExtAnimAttackEvent") {
1117+
contentArr.append( defaultEntry("soundAttackType", "CName") );
1118+
}
1119+
1120+
if (type == "CExtAnimSoundEvent" || type == "CExtAnimFootstepEvent") {
1121+
contentArr.append( defaultEntry("soundEventName", "StringAnsi") );
1122+
contentArr.append( defaultEntry("maxDistance", "Float") );
1123+
contentArr.append( defaultEntry("bone", "CName") );
1124+
contentArr.append( defaultEntry("switchesToUpdate", "array:2,0,StringAnsi") );
1125+
}
1126+
1127+
if (type == "CExtAnimFootstepEvent") {
1128+
contentArr.append( defaultEntry("fx", "Bool") );
1129+
contentArr.append( defaultEntry("customFxName", "CName") );
1130+
}
1131+
1132+
if (type == "CEASEnumEvent") {
1133+
contentArr.append( defaultEntry("enumVariant", "SEnumVariant") );
1134+
}
1135+
1136+
if (type == "CPreAttackEvent") {
1137+
contentArr.append( defaultEntry("data", "CPreAttackEventData") );
10251138
}
1026-
// TODO!!!
10271139

10281140
eventObj["Content"] = contentArr;
10291141
eventObj["Name"] = type;
@@ -1165,6 +1277,11 @@ void MAU::onChanged_eventContentRow(int newRow) {
11651277
} else if (entryType == "array:2,0,StringAnsi") {
11661278
ui->stackEventsValue->setCurrentIndex(4);
11671279
ui->editEventsValueArrayString->setPlainText( value.toStringList().join("\n") );
1280+
} else if (m_knownEnumTypes.contains(entryType)) {
1281+
ui->stackEventsValue->setCurrentIndex(7);
1282+
ui->comboEventsValueEnum->clear();
1283+
ui->comboEventsValueEnum->addItems( m_knownEnumTypes[entryType] );
1284+
ui->comboEventsValueEnum->setCurrentText( value.toString() );
11681285
} else if (entryType == "SEnumVariant") {
11691286
ui->stackEventsValue->setCurrentIndex(5);
11701287
QHash<QString, QVariant> map = value.value< QHash<QString, QVariant> >();
@@ -1304,6 +1421,8 @@ void MAU::onChanged_eventsVarAny() {
13041421
contentEntry = varToEntry( entryName, ui->lineEventsValueString->text(), entryType );
13051422
} else if (entryType == "array:2,0,StringAnsi") {
13061423
contentEntry = varToEntry( entryName, ui->editEventsValueArrayString->toPlainText().split("\n"), entryType );
1424+
} else if (m_knownEnumTypes.contains(entryType)) {
1425+
contentEntry = varToEntry( entryName, ui->comboEventsValueEnum->currentText(), entryType );
13071426
} else if (entryType == "SEnumVariant") {
13081427
ui->stackEventsValue->setCurrentIndex(5);
13091428
QHash<QString, QVariant> map = QHash<QString, QVariant>();

source/W3MayaAnimUtil.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ class W3MayaAnimUtil : public QMainWindow
112112
m_mapControls[ obj->objectName() ] = controller;
113113
}
114114
JSO defaultEntry(QString name, QString type);
115+
const QHash<QString, QStringList> m_knownEnumTypes = {
116+
{ "EItemLatentAction", {"ILA_Draw", "ILA_Holster", "ILA_Switch"} },
117+
{ "EDropAction", {"DA_DropRightHand", "DA_DropLeftHand", "DA_DropAny"} },
118+
{ "EAnimEffectAction", {"EA_Start", "EA_Stop"} },
119+
{ "EItemAction", {"IA_Mount", "IA_MountToHand", "IA_MountToLeftHand", "IA_MountToRightHand", "IA_Unmount"} },
120+
{ "EItemEffectAction", {"IEA_Start", "IEA_Stop"} },
121+
};
115122
const QStringList m_knownVarTypes = { "Bool",
116123
"Int32",
117124
"Float",
@@ -123,8 +130,14 @@ class W3MayaAnimUtil : public QMainWindow
123130
};
124131
QStringList m_knownEventTypes = { "CExtAnimEvent",
125132
"CExtAnimDurationEvent",
133+
"CEASEnumEvent",
134+
"CExtAnimSoundEvent",
135+
"CExtAnimFootstepEvent",
126136
"CExtAnimEffectEvent",
127137
"CExtAnimEffectDurationEvent",
138+
"CExtAnimItemEvent",
139+
"CExtAnimItemEffectEvent",
140+
"CPreAttackEvent",
128141
"CExtAnimAttackEvent",
129142
};
130143
void eventsLoad();
@@ -208,6 +221,8 @@ private slots:
208221
void onChecked_ToggleVar(bool checked);
209222
void onChanged_eventRow(int newRow);
210223
void onChanged_eventContentRow(int newRow);
224+
void onClicked_eventsSort();
225+
void onClicked_fixAnimationNames();
211226
// entries
212227
void onClicked_eventsReset();
213228
void onClicked_eventsApply();

source/W3MayaAnimUtil.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ QT += core gui
33
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
44

55
CONFIG += c++17
6+
RC_ICONS += icons/icon2.ico
67

78
RESOURCES += res.qrc
8-
RC_ICONS = icon.ico
99

1010
# You can make your code fail to compile if it uses deprecated APIs.
1111
# In order to do so, uncomment the following line.

0 commit comments

Comments
 (0)