From c0521d8d8cf46582231379272528734ee4768a5a Mon Sep 17 00:00:00 2001 From: AXIS5hacker Date: Sun, 16 Jun 2024 02:54:38 +0800 Subject: [PATCH 1/3] update a new feature: Note Count --- CMakeLists.txt | 2 +- Dynamix_chart_width_control/chart_store.cpp | 46 +- Dynamix_chart_width_control/chart_store.h | 25 +- Dynamix_chart_width_control/main.cpp | 22 +- .../DNX_widthGUI_en_en.qm | Bin 2791 -> 2998 bytes .../DNX_widthGUI_en_en.ts | 195 ++-- .../DNX_widthGUI_zh_CN.qm | Bin 3596 -> 3825 bytes .../DNX_widthGUI_zh_CN.ts | 195 ++-- .../chart_store.cpp | 46 +- Dynamix_chart_width_control_GUI/chart_store.h | 25 +- Dynamix_chart_width_control_GUI/maingui.cpp | 23 +- Dynamix_chart_width_control_GUI/maingui.ui | 999 ++++++++++++------ version.h | 2 +- 13 files changed, 1035 insertions(+), 545 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71340b5..1eace8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -#Compile all +#Compile all cmake_minimum_required(VERSION 3.5) project(Dynamix_note_width_changer) diff --git a/Dynamix_chart_width_control/chart_store.cpp b/Dynamix_chart_width_control/chart_store.cpp index 9658fde..da81a9a 100644 --- a/Dynamix_chart_width_control/chart_store.cpp +++ b/Dynamix_chart_width_control/chart_store.cpp @@ -1,6 +1,7 @@ /** * Creator:AXIS5 * This is the realization of class chart_store +* Note: this file must be the same in both CLI application and GUI application */ #include "chart_store.h" #include"defs.h" @@ -9,7 +10,7 @@ using namespace std; //functions used bool numcheck_int(string s) { for (auto& p : s) { - if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t'&&p!='-'&&p!='+') { + if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t' && p != '-' && p != '+') { return false; } } @@ -20,7 +21,7 @@ bool numcheck_decimal(string s) { bool decimal_point_exists = false; for (auto& p : s) { if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t' && p != '-' && p != '+') { - if (p == '.'&& (!decimal_point_exists)) { + if (p == '.' && (!decimal_point_exists)) { decimal_point_exists = true; } else { @@ -101,6 +102,11 @@ void chart_store::clear() { ltype = sides::UNKNOWN; rtype = sides::UNKNOWN; lines = 1;//beginning + + //erase note count + tap_count = 0; + chain_count = 0; + hold_count = 0; } int chart_store::readfile(string fn) { @@ -207,6 +213,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "middle")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_mid.erase(it.second); @@ -225,6 +232,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "left")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_left.erase(it.second); @@ -243,6 +251,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "right")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_right.erase(it.second); @@ -365,7 +374,7 @@ void chart_store::parse_elem() { char lln[64]; snprintf(lln, sizeof(lln), "%d.", tag_line); string errmsg = ex.what(); - throw std::logic_error(errmsg+" Tag begins at line " + string(lln)); + throw std::logic_error(errmsg + " Tag begins at line " + string(lln)); return; } if (text != "") { @@ -749,18 +758,25 @@ void chart_store::parse_elem() { } //note info is complete switch (modes) { - case 1: + case 1://middle //scan for duplicated note id if (m_notes.find(temp_id) == m_notes.end()) { m_notes.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_mid.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_mid.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -770,18 +786,25 @@ void chart_store::parse_elem() { throw std::logic_error("Error: Duplicated note id: " + string(id_string) + ".\nThe note begins at line " + string(lln) + " in the XML."); } break; - case 2: + case 2://left //scan for duplicated note id if (m_left.find(temp_id) == m_left.end()) { m_left.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_left.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_left.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -791,18 +814,25 @@ void chart_store::parse_elem() { throw std::logic_error("Error: Duplicated note id: " + string(id_string) + ".\nThe note begins at line " + string(lln) + " in the XML."); } break; - case 3: + case 3://right //scan for duplicated note id if (m_right.find(temp_id) == m_right.end()) { m_right.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_right.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_right.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -897,10 +927,10 @@ void chart_store::parse_elem() { } catch (exception& ex) { char lln[64]; - snprintf(lln, sizeof(lln), "%d.",tag_line); + snprintf(lln, sizeof(lln), "%d.", tag_line); string errmsg = ex.what(); - throw std::logic_error(errmsg+" The xml tag begins at line "+string(lln)); + throw std::logic_error(errmsg + " The xml tag begins at line " + string(lln)); return; } } diff --git a/Dynamix_chart_width_control/chart_store.h b/Dynamix_chart_width_control/chart_store.h index 56db6f8..8c0f491 100644 --- a/Dynamix_chart_width_control/chart_store.h +++ b/Dynamix_chart_width_control/chart_store.h @@ -1,6 +1,7 @@ /** * Creator:AXIS5 * This is the definition of class chart_store +* Note: this file must be the same in both CLI application and GUI application */ #ifndef CHART_STORE_H #define CHART_STORE_H @@ -19,7 +20,7 @@ using std::map; using std::set; //added default note type: NULLTP -enum types { NORMAL = 1, CHAIN, HOLD, SUB , NULLTP}; +enum types { NORMAL = 1, CHAIN, HOLD, SUB, NULLTP }; //added default sides type: UNKNOWN enum sides { PAD, MIXER, MULTI, UNKNOWN }; struct note { @@ -30,11 +31,11 @@ struct note { double width; int subid; //constructor - note() :id(-1), - notetype(types::NULLTP), - time(-1e8), - position(-1e8), - width(-1e8), + note() :id(-1), + notetype(types::NULLTP), + time(-1e8), + position(-1e8), + width(-1e8), subid(INT_MIN) {} }; class chart_store @@ -58,6 +59,13 @@ class chart_store void set_lside(sides x) { ltype = x; } void set_rside(sides x) { rtype = x; } + //fetch note count + int get_mid_count() { return m_notes.size(); } + int get_left_count() { return m_left.size(); } + int get_right_count() { return m_right.size(); } + int get_tap_count() { return tap_count; } + int get_chain_count() { return chain_count; } + int get_hold_count() { return hold_count; } private: string name;//song name @@ -85,7 +93,10 @@ class chart_store string parse_elem_text();//parsing element text string parse_elem_attr_key();//parsing element attribute name string parse_elem_attr_val();//parsing element attribute value - + //note counter + int tap_count; + int chain_count; + int hold_count; }; diff --git a/Dynamix_chart_width_control/main.cpp b/Dynamix_chart_width_control/main.cpp index 5e896a3..b297bf0 100644 --- a/Dynamix_chart_width_control/main.cpp +++ b/Dynamix_chart_width_control/main.cpp @@ -42,6 +42,7 @@ int main(int argc, char* argv[]) bool next_width = false; bool next_filename = false;//if specifying filename bool default_filename = true;//if filename not specified + bool show_notecount = false;//if showing note count bool def_stimestamp = true;//using default start time bool def_etimestamp = true;//using default end time @@ -153,7 +154,10 @@ int main(int argc, char* argv[]) else if (arglist[i] == "-rnd2") { random_trigger = 2; } - else if (argc == 1 || argc > 14) {//not specified arguments or too many arguments + else if (arglist[i] == "-c") { + show_notecount = true; + } + else if (argc == 1 || argc > 15) {//not specified arguments or too many arguments false_usage = true; } else if (i > 1) {//wrong argument detected @@ -162,7 +166,7 @@ int main(int argc, char* argv[]) } if (help_only) { cout << "usage:" << endl; - cout << "filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r]" << endl << endl; + cout << "filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r] [-c]" << endl << endl; cout << "-w width_multiplier\tchange the width of a chart, width_multiplier is a decimal number" << endl; cout << "-o output_filename\tspecify the filename of the changed chart" << endl; cout << "-s start_time(bar)\tspecify the start time of the time range you want to change, in the unit of bar." << endl; @@ -175,6 +179,7 @@ int main(int argc, char* argv[]) cout << "-rnd2\tchange the note width randomly, using random mode 2(will ignore the \"-w\" argument)" << endl; cout << "-?\thelp" << endl; cout << "-h\thelp, same as -?" << endl; + cout << "-c\tshow the detailed note quantity of this chart" << endl; } else if (next_width) { cout << "please specify a width multiplier" << endl; @@ -182,7 +187,7 @@ int main(int argc, char* argv[]) else if (false_usage) { cout << "invalid arguments" << endl; cout << "usage:" << endl; - cout << "filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r]" << endl << endl; + cout << "filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r] [-c]" << endl << endl; cout << "-w width_multiplier\tchange the width of a chart, width_multiplier is a decimal number" << endl; cout << "-o output_filename\tspecify the filename of the changed chart" << endl; cout << "-s start_time(bar)\tspecify the start time of the time range you want to change, in the unit of bar." << endl; @@ -195,6 +200,7 @@ int main(int argc, char* argv[]) cout << "-rnd2\tchange the note width randomly, using random mode 2(will ignore the \"-w\" argument)" << endl; cout << "-?\thelp" << endl; cout << "-h\thelp, same as -?" << endl; + cout << "-c\tshow the detailed note quantity of this chart" << endl; } else { filename = arglist[1]; @@ -356,6 +362,16 @@ int main(int argc, char* argv[]) cout << "Cannot save changed chart file." << endl;//invalid output chart name } else { + //show note count + if (show_notecount) { + cout << "Note Count" << endl; + cout << "===============================" << endl; + cout << "Middle:\t" << cs.get_mid_count() << "\tTap:\t" << cs.get_tap_count() << endl; + cout << "Left:\t" << cs.get_left_count() << "\tChain:\t" << cs.get_chain_count() << endl; + cout << "Right:\t" << cs.get_right_count() << "\tHold:\t" << cs.get_hold_count() << endl; + cout << "===============================" << endl; + } + //side change info output cout << "Changed sides: "; if (side_mask & MID_CHANGE) { cout << "middle "; diff --git a/Dynamix_chart_width_control_GUI/DNX_widthGUI_en_en.qm b/Dynamix_chart_width_control_GUI/DNX_widthGUI_en_en.qm index ae60c8793fa8f872f4abfb469504222aae66af50..79434faa6b1831aa57caa07e8ee6d54a00dd2fcd 100644 GIT binary patch delta 540 zcmaDZx=nn79OnuKhNuPx2KJJP^5XT03@jf)7#Nrp7+Aik0BHvXR_!Yc3@kPbtYu3X z7}&fRST~q5FmR|aND8wuFfceUcs~CJr0+6B{Qbhfz`B?r^4DRYx~B{k{1QO^5k_W~ zO$-c-9~l?#asuj`%lPxmSD^f4rc5(KApazgHUiS$nH}$yGBDJ0xG?u?STQg#U1ph? zHx+2`ZkFx-Gl6_{me>5w3=EueSQ!{qfd=eml~3LW6kow=zZ%GAHDL`>4gxy#0c$b; zNuat2)(eF|hqH#U{`k8QXihI1N3J5!muzf4cb@>o`Pf+n^MU4MvFF->9A3+Qp!yX< zJp)rCN0?+PP~aU$vEn+Q#(x}De;R=yk-+iI!VhS`WX^om4xo4jXMMvipm-lwcoZ-s zSX#NJ?)(V!Ne*|V@ll|UdwKi}ZU7zlmnZRbC{W!Mo>K`4K=FgTQamSs>SK5pEiD9! z|KjUvssftp!Oy(^xggNx2l*H6dkLgfGl9h8$x9etv#~m7BxdGKHe{8a+|TrR@)qXp z0{pJI1tpaVX_+~xd5O8HdSJF*XC&sOPyWa*v$>qJfDr&7b&)9m delta 459 zcmdlc{#Wc zs{h9L^UPPEyfIUz8PGlsB_M6Yz);T-z}&B41ys0`WoF(~pn1C|N{3n6(8(A+D0v*UI!}{azMxg#)HjZ3Hp!#KO zK6im0VY$N2Dwq%CbFm+&eg!ml5=WS1Do}kNN3r5MhI$5uyBt-28i77l>SytsN=N{TFW{BpIRVtC#Jgx|AyE7PUsqEV&>=7QnfE_uVBnPEU$pNfC(s9V znLwV+ - + Dynamix note width changer GUI - + Load Chart - + Edit queue: - + SAVE - + Input File - - + + + Width change + + + + + - - + + Width multiplier - + - + 0.01 - + - + 5.00 - + - + Limited multiplier - + - + Time - + - + Start time(bar): - + - + End time(bar): - + - + Set Start Time - + - + Set End Time - + - + EXIT - + - + Sides - + + - + + Middle - + + - + + Left - + + - + + Right - + - + Browse - + - + APPLY CHANGE - + - + Dynamix Note Width Changer Dynamix Note width changer - + - + Mode Select - + - + Width randomizer 1 - + - + Width randomizer 2 - + + + Note count + + + + + + Tap + + + + + + Hold + + + + + + Chain + + + + - + languages - - + + - - + + English - - + + - - + + 中文 @@ -220,54 +256,60 @@ + - + Current Chart File: - + + Empty filename. + + + + Barpm fix - + Illegal Barpm! Please enter a valid Barpm: - + Barpm is set to %1 - - + + Left side fix Left side Fix - + Left side type is not specified! Please enter a valid side type Left side type is not specified! - - + + Invalid side type! Please enter again! - - + + Right side fix Right side Fix - + Right side type is not specified! Please enter a valid side type Right side type is not specified! Please enter a valid side type. @@ -290,33 +332,28 @@ For more info, see %1 for details. - - Current Chart File: %1 - - - - + Start time must be less than end time! Start time must be lesser than end time! - + Hold-Sub mismatch! - + Width change applied! - + Save chart to - + XML Chart files (*.xml) diff --git a/Dynamix_chart_width_control_GUI/DNX_widthGUI_zh_CN.qm b/Dynamix_chart_width_control_GUI/DNX_widthGUI_zh_CN.qm index cfbb0b11974227b5142d0902828dc89b7e888d83..7914bac35a338119b14c4bb4767d22ab3d2057fd 100644 GIT binary patch delta 628 zcmYk2Ur19?9LIm>-g9>E?(Xff(n_s4$w?6mE0XZR{*1yPR*dD!AU5XB4cs5wl$@|@ z5fv4b$WR|5T3SL7*?kBFO^~2W$cKUmRy`C_14*(`(V|~3!-vC{@9+H1=X`&^>zkH0 z-?W*>09yM1%pd!!H|Q>)-@E|S3A9j)>H)U>H2}K@ta}tdYytLYH-Iz`73&xP?1RIL ze*uUUP83%Fgan-YJ&Uj^IHztzKSX%?7=RljcP9@3STyo${s(f#xp2b{^tVuVqQ2qx zzwZLjr4|0h)prDYevW=l$&PlSHm|vQA%(%RD*trR3ZU?6cKQoW zpoGylj1f{!%4j;9af)9 w)VM9`+**1uw+g^}193yKaKt8NoTsMrZCX?5rR)p0B}4XLC=hKoiWZgo2X%v(_5c6? delta 499 zcmew;+aohUuD*eR+0c*y1ehBQfTRKg%bF)ZP6`9dhY$t^76}Gc?JEontT_yKmw zfa+H;{yg&)DDTdcX$G{9>j989VqmD}mSFDJumW1RlVxV!RG@*cS+@Jn1oC-UUh_LM zF!0E-GBBzFHCD6QuLja=TUdjXgMhRTYcc;x1_thhtQQJ_4rIH<`s43Lp#J4-9Jz`> z^>^5O?gBl+*2c~%m=ENOupg*?1vIyVBTOjM3=E7Pc>D}* z01f`ilXyB5sQv-Zse}ZeIwM{wo)bWQ6L=RbEd - + Dynamix note width changer GUI Dynamix自制谱键宽缩放器 - + Load Chart 加载谱面 - + Edit queue: 编辑队列: - + SAVE 保存谱面 - + Input File 输入谱面 - - + + + Width change + 键宽缩放 + + + + - - + + Width multiplier 键宽倍率缩放 - + - + 0.01 - + - + 5.00 - + - + Limited multiplier 限制缩放倍率 - + - + Time 时间控制 - + - + Start time(bar): 开始时间(小节): - + - + End time(bar): 结束时间(小节): - + - + Set Start Time 指定开始时间 @@ -117,114 +123,144 @@ 指定结束时间 - + - + Set End Time 指定结束时间 - + - + EXIT 退出 - + - + Sides 指定下落面 - + + - + + Middle 正面 - + + - + + Left 左面 - + + - + + Right 右面 - + - + Browse 浏览 - + - + APPLY CHANGE 应用键宽更改 - + - + Dynamix Note Width Changer Dynamix Note width changer Dynamix自制谱键宽缩放器 - + - + Mode Select 模式选择 - + - + Width randomizer 1 随机键宽1 - + - + Width randomizer 2 随机键宽2 - + + + Note count + 音符数统计 + + + + + Tap + 蓝键 + + + + + Hold + 长键 + + + + + Chain + 红键 + + + - + languages 语言 - - + + - - + + English - - + + - - + + 中文 @@ -239,55 +275,61 @@ XML 谱面文件 (*.xml);;所有文件 (*.*) + - + Current Chart File: 当前谱面文件: - + + Empty filename. + 文件名为空。 + + + Barpm fix Barpm Fix Barpm修复 - + Illegal Barpm! Please enter a valid Barpm: 无效的Barpm! 请输入合法的Barpm数值: - + Barpm is set to %1 Barpm已设置为%1 - - + + Left side fix Left side Fix 左侧面类型修复 - + Left side type is not specified! Please enter a valid side type Left side type is not specified! 未指定左侧面类型! 请输入合法的左侧面类型 - - + + Invalid side type! Please enter again! 侧面类型无效! 请重新输入! - - + + Right side fix Right side Fix 右侧面类型修复 - + Right side type is not specified! Please enter a valid side type Right side type is not specified! Please enter a valid side type. 未指定右侧面类型! 请输入合法的右侧面类型 @@ -311,33 +353,28 @@ For more info, see %1 for details. 谱面自动修复完成,您可以点击保存修改按钮将其保存,或者用键宽缩放选项作更多修改。 - - Current Chart File: %1 - 当前谱面文件: %1 - - - + Start time must be less than end time! Start time must be lesser than end time! 开始时间必须小于结束时间! - + Hold-Sub mismatch! - + Width change applied! 键宽缩放已应用! - + Save chart to 保存谱面到 - + XML Chart files (*.xml) XML谱面文件 (*.xml) diff --git a/Dynamix_chart_width_control_GUI/chart_store.cpp b/Dynamix_chart_width_control_GUI/chart_store.cpp index 9658fde..da81a9a 100644 --- a/Dynamix_chart_width_control_GUI/chart_store.cpp +++ b/Dynamix_chart_width_control_GUI/chart_store.cpp @@ -1,6 +1,7 @@ /** * Creator:AXIS5 * This is the realization of class chart_store +* Note: this file must be the same in both CLI application and GUI application */ #include "chart_store.h" #include"defs.h" @@ -9,7 +10,7 @@ using namespace std; //functions used bool numcheck_int(string s) { for (auto& p : s) { - if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t'&&p!='-'&&p!='+') { + if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t' && p != '-' && p != '+') { return false; } } @@ -20,7 +21,7 @@ bool numcheck_decimal(string s) { bool decimal_point_exists = false; for (auto& p : s) { if ((p < '0' || p > '9') && p != '\n' && p != ' ' && p != '\t' && p != '-' && p != '+') { - if (p == '.'&& (!decimal_point_exists)) { + if (p == '.' && (!decimal_point_exists)) { decimal_point_exists = true; } else { @@ -101,6 +102,11 @@ void chart_store::clear() { ltype = sides::UNKNOWN; rtype = sides::UNKNOWN; lines = 1;//beginning + + //erase note count + tap_count = 0; + chain_count = 0; + hold_count = 0; } int chart_store::readfile(string fn) { @@ -207,6 +213,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "middle")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_mid.erase(it.second); @@ -225,6 +232,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "left")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_left.erase(it.second); @@ -243,6 +251,7 @@ int chart_store::readfile(string fn) { //store mismatch hold mismatched_notes.push_back(make_pair(it.first, "right")); mismatch = true; + hold_count--;//hold count - 1 } else { sub_right.erase(it.second); @@ -365,7 +374,7 @@ void chart_store::parse_elem() { char lln[64]; snprintf(lln, sizeof(lln), "%d.", tag_line); string errmsg = ex.what(); - throw std::logic_error(errmsg+" Tag begins at line " + string(lln)); + throw std::logic_error(errmsg + " Tag begins at line " + string(lln)); return; } if (text != "") { @@ -749,18 +758,25 @@ void chart_store::parse_elem() { } //note info is complete switch (modes) { - case 1: + case 1://middle //scan for duplicated note id if (m_notes.find(temp_id) == m_notes.end()) { m_notes.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_mid.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_mid.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -770,18 +786,25 @@ void chart_store::parse_elem() { throw std::logic_error("Error: Duplicated note id: " + string(id_string) + ".\nThe note begins at line " + string(lln) + " in the XML."); } break; - case 2: + case 2://left //scan for duplicated note id if (m_left.find(temp_id) == m_left.end()) { m_left.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_left.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_left.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -791,18 +814,25 @@ void chart_store::parse_elem() { throw std::logic_error("Error: Duplicated note id: " + string(id_string) + ".\nThe note begins at line " + string(lln) + " in the XML."); } break; - case 3: + case 3://right //scan for duplicated note id if (m_right.find(temp_id) == m_right.end()) { m_right.insert(make_pair(temp_id, *tempnote)); //store hold for hold-sub checking if (tempnote->notetype == types::HOLD) { hold_right.insert(make_pair(temp_id, tempnote->subid)); + hold_count++; } //store sub for hold-sub checking else if (tempnote->notetype == types::SUB) { sub_right.insert(temp_id); } + else if (tempnote->notetype == types::NORMAL) { + tap_count++; + } + else if (tempnote->notetype == types::CHAIN) { + chain_count++; + } } //duplicated else { @@ -897,10 +927,10 @@ void chart_store::parse_elem() { } catch (exception& ex) { char lln[64]; - snprintf(lln, sizeof(lln), "%d.",tag_line); + snprintf(lln, sizeof(lln), "%d.", tag_line); string errmsg = ex.what(); - throw std::logic_error(errmsg+" The xml tag begins at line "+string(lln)); + throw std::logic_error(errmsg + " The xml tag begins at line " + string(lln)); return; } } diff --git a/Dynamix_chart_width_control_GUI/chart_store.h b/Dynamix_chart_width_control_GUI/chart_store.h index 56db6f8..8c0f491 100644 --- a/Dynamix_chart_width_control_GUI/chart_store.h +++ b/Dynamix_chart_width_control_GUI/chart_store.h @@ -1,6 +1,7 @@ /** * Creator:AXIS5 * This is the definition of class chart_store +* Note: this file must be the same in both CLI application and GUI application */ #ifndef CHART_STORE_H #define CHART_STORE_H @@ -19,7 +20,7 @@ using std::map; using std::set; //added default note type: NULLTP -enum types { NORMAL = 1, CHAIN, HOLD, SUB , NULLTP}; +enum types { NORMAL = 1, CHAIN, HOLD, SUB, NULLTP }; //added default sides type: UNKNOWN enum sides { PAD, MIXER, MULTI, UNKNOWN }; struct note { @@ -30,11 +31,11 @@ struct note { double width; int subid; //constructor - note() :id(-1), - notetype(types::NULLTP), - time(-1e8), - position(-1e8), - width(-1e8), + note() :id(-1), + notetype(types::NULLTP), + time(-1e8), + position(-1e8), + width(-1e8), subid(INT_MIN) {} }; class chart_store @@ -58,6 +59,13 @@ class chart_store void set_lside(sides x) { ltype = x; } void set_rside(sides x) { rtype = x; } + //fetch note count + int get_mid_count() { return m_notes.size(); } + int get_left_count() { return m_left.size(); } + int get_right_count() { return m_right.size(); } + int get_tap_count() { return tap_count; } + int get_chain_count() { return chain_count; } + int get_hold_count() { return hold_count; } private: string name;//song name @@ -85,7 +93,10 @@ class chart_store string parse_elem_text();//parsing element text string parse_elem_attr_key();//parsing element attribute name string parse_elem_attr_val();//parsing element attribute value - + //note counter + int tap_count; + int chain_count; + int hold_count; }; diff --git a/Dynamix_chart_width_control_GUI/maingui.cpp b/Dynamix_chart_width_control_GUI/maingui.cpp index 818a7b3..5c907a0 100644 --- a/Dynamix_chart_width_control_GUI/maingui.cpp +++ b/Dynamix_chart_width_control_GUI/maingui.cpp @@ -120,7 +120,14 @@ void MainGUI::on_loadFile_clicked() { ui->widthSpinBox->setEnabled(false); ui->widthMultiply->setEnabled(false); ui->modeSelect->setEnabled(false); - QMessageBox::critical(this, "Error", "Empty filename."); + //reset note count + ui->middleCount->setText(""); + ui->leftCount->setText(""); + ui->rightCount->setText(""); + ui->tapCount->setText(""); + ui->chainCount->setText(""); + ui->holdCount->setText(""); + QMessageBox::critical(this, "Error", tr("Empty filename.")); return; } try { @@ -289,6 +296,13 @@ void MainGUI::on_loadFile_clicked() { throw std::logic_error("Unknown error"); } ui->loaded_file->setText(tr("Current Chart File: ") + str2qstr_utf8(cs.chart_filename)); + //show note count + ui->middleCount->setText(QString::number(cs.get_mid_count())); + ui->leftCount->setText(QString::number(cs.get_left_count())); + ui->rightCount->setText(QString::number(cs.get_right_count())); + ui->tapCount->setText(QString::number(cs.get_tap_count())); + ui->chainCount->setText(QString::number(cs.get_chain_count())); + ui->holdCount->setText(QString::number(cs.get_hold_count())); } catch (exception& ex) { ui->loaded_file->setText(""); @@ -301,6 +315,13 @@ void MainGUI::on_loadFile_clicked() { ui->widthSpinBox->setEnabled(false); ui->widthMultiply->setEnabled(false); ui->modeSelect->setEnabled(false); + //reset note count + ui->middleCount->setText(""); + ui->leftCount->setText(""); + ui->rightCount->setText(""); + ui->tapCount->setText(""); + ui->chainCount->setText(""); + ui->holdCount->setText(""); QMessageBox::critical(this, "Error", ex.what()); return; } diff --git a/Dynamix_chart_width_control_GUI/maingui.ui b/Dynamix_chart_width_control_GUI/maingui.ui index 1a571ff..aad9356 100644 --- a/Dynamix_chart_width_control_GUI/maingui.ui +++ b/Dynamix_chart_width_control_GUI/maingui.ui @@ -132,244 +132,6 @@ Input File - - - false - - - - 400 - 250 - 611 - 101 - - - - Width multiplier - - - - false - - - - 50 - 60 - 501 - 21 - - - - 1 - - - 500 - - - 100 - - - Qt::Horizontal - - - QSlider::TicksBothSides - - - 25 - - - - - false - - - - 60 - 30 - 121 - 21 - - - - 0.010000000000000 - - - 30.000000000000000 - - - 0.010000000000000 - - - 1.000000000000000 - - - - - - 20 - 60 - 31 - 21 - - - - 0.01 - - - - - - 560 - 60 - 31 - 21 - - - - 5.00 - - - - - - 300 - 30 - 171 - 20 - - - - Limited multiplier - - - true - - - - - - false - - - - 710 - 360 - 301 - 151 - - - - Time - - - - - 20 - 60 - 111 - 21 - - - - Start time(bar): - - - - - - 20 - 120 - 111 - 21 - - - - End time(bar): - - - - - false - - - - 140 - 60 - 121 - 21 - - - - 6 - - - -999.000000000000000 - - - 9999.989999999999782 - - - 0.010000000000000 - - - - - false - - - - 140 - 120 - 121 - 21 - - - - 6 - - - -999.000000000000000 - - - 9999.989999999999782 - - - 0.010000000000000 - - - - - - 20 - 30 - 131 - 20 - - - - Qt::LeftToRight - - - Set Start Time - - - - - - 20 - 90 - 131 - 20 - - - - Qt::LeftToRight - - - Set End Time - - - @@ -425,70 +187,6 @@ EXIT - - - false - - - - 580 - 360 - 121 - 151 - - - - Sides - - - - - 20 - 30 - 79 - 20 - - - - Middle - - - true - - - - - - 20 - 60 - 79 - 20 - - - - Left - - - true - - - - - - 20 - 90 - 79 - 20 - - - - Right - - - true - - - @@ -743,62 +441,661 @@ - - - false - + 400 - 360 - 161 - 151 + 230 + 641 + 301 - - Mode Select + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + - - - - 10 - 30 - 121 - 21 - - - - Width multiplier - - - true - - - - - - 10 - 60 - 141 - 21 - - - - Width randomizer 1 - + + false + + + QTabWidget:pane {border:0px solid #f0f0f0;background: transparent; } + + + QTabWidget::Rounded + + + 0 + + + + Width change + + + + false + + + + 10 + 0 + 611 + 101 + + + + Width multiplier + + + + false + + + + 50 + 60 + 501 + 21 + + + + 1 + + + 500 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksBothSides + + + 25 + + + + + false + + + + 60 + 30 + 121 + 21 + + + + 0.010000000000000 + + + 30.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + 20 + 60 + 31 + 21 + + + + 0.01 + + + + + + 560 + 60 + 31 + 21 + + + + 5.00 + + + + + + 300 + 30 + 171 + 20 + + + + Limited multiplier + + + true + + + + + + false + + + + 320 + 110 + 301 + 151 + + + + Time + + + + + 20 + 60 + 111 + 21 + + + + Start time(bar): + + + + + + 20 + 120 + 111 + 21 + + + + End time(bar): + + + + + false + + + + 140 + 60 + 121 + 21 + + + + 6 + + + -999.000000000000000 + + + 9999.989999999999782 + + + 0.010000000000000 + + + + + false + + + + 140 + 120 + 121 + 21 + + + + 6 + + + -999.000000000000000 + + + 9999.989999999999782 + + + 0.010000000000000 + + + + + + 20 + 30 + 131 + 20 + + + + Qt::LeftToRight + + + Set Start Time + + + + + + 20 + 90 + 131 + 20 + + + + Qt::LeftToRight + + + Set End Time + + + + + + false + + + + 190 + 110 + 121 + 151 + + + + Sides + + + + + 20 + 30 + 79 + 20 + + + + Middle + + + true + + + + + + 20 + 60 + 79 + 20 + + + + Left + + + true + + + + + + 20 + 90 + 79 + 20 + + + + Right + + + true + + + + + + false + + + + 10 + 110 + 161 + 151 + + + + Mode Select + + + + + 10 + 30 + 121 + 21 + + + + Width multiplier + + + true + + + + + + 10 + 60 + 141 + 21 + + + + Width randomizer 1 + + + + + + 10 + 90 + 141 + 21 + + + + Width randomizer 2 + + + - - - - 10 - 90 - 141 - 21 - - - - Width randomizer 2 - + + + Note count + + + + + 100 + 30 + 113 + 20 + + + + true + + + + + + 20 + 30 + 61 + 16 + + + + Left + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 20 + 70 + 61 + 16 + + + + Right + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 20 + 110 + 61 + 16 + + + + Middle + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 100 + 70 + 113 + 20 + + + + true + + + + + + 100 + 110 + 113 + 20 + + + + true + + + + + + 340 + 110 + 113 + 20 + + + + true + + + + + + 340 + 70 + 113 + 20 + + + + true + + + + + + 260 + 30 + 61 + 16 + + + + Tap + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 260 + 110 + 61 + 16 + + + + Hold + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 340 + 30 + 113 + 20 + + + + true + + + + + + 260 + 70 + 61 + 16 + + + + Chain + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + diff --git a/version.h b/version.h index 0ca881a..d5cb7c3 100644 --- a/version.h +++ b/version.h @@ -3,6 +3,6 @@ * The header that specifies the program version. * * */ -#define VERSION_H "v1.2.33" +#define VERSION_H "v1.3.0" #endif \ No newline at end of file From 0635cf7f8dd382cd67b28e4f7d9eed3ed02601b4 Mon Sep 17 00:00:00 2001 From: AXIS5hacker Date: Sun, 16 Jun 2024 03:02:51 +0800 Subject: [PATCH 2/3] update readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6896b2d..fa18d0d 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Then you can proceed with CMake: # Arguments (for console application) -filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r] +filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(bar)] [-e end_time(bar)] [-?|-h] [-m] [-l] [-r] [-c] -w width_multiplier change the width of a chart, width_multiplier is a decimal number @@ -115,6 +115,8 @@ filename [-w width_multiplier|-rnd1|-rnd2] [-o output_filename] [-s start_time(b -h help, same as -? +-c show the detailed note quantity of this chart (v1.3.x and newer) + # About the random width modes The program is now integrated with my width randomizer, and the randomizer has 2 modes. From 418b9f615c7e18907aeab4a9db778cd7f8d55621 Mon Sep 17 00:00:00 2001 From: AXIS5hacker Date: Sun, 16 Jun 2024 14:08:35 +0800 Subject: [PATCH 3/3] added support for charts with varied Barpm --- Dynamix_chart_width_control/chart_store.cpp | 196 +++++++++++++++++- Dynamix_chart_width_control/chart_store.h | 18 +- .../chart_store.cpp | 196 +++++++++++++++++- Dynamix_chart_width_control_GUI/chart_store.h | 18 +- version.h | 2 +- 5 files changed, 419 insertions(+), 11 deletions(-) diff --git a/Dynamix_chart_width_control/chart_store.cpp b/Dynamix_chart_width_control/chart_store.cpp index da81a9a..f15e433 100644 --- a/Dynamix_chart_width_control/chart_store.cpp +++ b/Dynamix_chart_width_control/chart_store.cpp @@ -91,6 +91,8 @@ void chart_store::clear() { sub_mid.clear(); sub_left.clear(); sub_right.clear(); + //init bpm list + bpm_list.clear(); //init mismatched note list mismatched_notes.clear(); @@ -122,11 +124,15 @@ int chart_store::readfile(string fn) { ifstream fin; bool mismatch = false;//check if hold-sub mismatch - modes = 0;//0->none 1->middle 2->left 3->right + modes = 0;//0->none 1->middle 2->left 3->right 4->bpmchange tempnote = NULL; + temp_bpm = NULL; note_trigger = false; note_reading = false;//if reading a note + bpm_mode = false;//if reading bpm section + bpm_reading = false;//if reading bpm + int chart_flags = 0; fin.open(fn);//open file @@ -365,6 +371,55 @@ void chart_store::parse_elem() { return; } } + else if (tag == "m_argument") {//barpm change argument + if (modes == 0)modes = 4; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax Error when reading BPM change info. Occured at line " + string(lln)); + return; + } + } + else if (tag == "m_bpmchange") {//barpm change + if (modes == 4) bpm_mode = true; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax Error when reading BPM change info. Occured at line " + string(lln)); + return; + } + } + else if (tag == "CBpmchange") { //head of a bpm change info + if (bpm_mode) { + if (!bpm_reading) { + bpm_reading = true; + temp_bpm = new bpmchange; + } + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: asset error, triggered at line " + + string(lln)); + return; + } + } + else {//not bpm change mode + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Unexpected BPM change info detected outside the BPM lists, triggered at line " + + string(lln)); + return; + } + } + //read text string text = ""; try { @@ -504,7 +559,7 @@ void chart_store::parse_elem() { return; } } - else if (tag == "m_time" && note_trigger == true) {//note time + else if (tag == "m_time" && note_trigger) {//note time if (note_reading) { bool valid = numcheck_decimal(text); if (!valid) { @@ -628,6 +683,66 @@ void chart_store::parse_elem() { } } + else if (tag == "m_time" && bpm_mode) {//bpm change time + if (bpm_reading) { + bool valid = numcheck_decimal(text); + if (!valid) { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: time is not a valid decimal expression. Occured at line " + string(lln)); + return; + } + extr.str(text); + if (temp_bpm != NULL) { + extr >> temp_bpm->time;//read current bpm change time + extr.clear(); + } + else { + throw std::logic_error("Read bpmchange error: Unable to create object \"bpmchange\""); + return; + } + } + else {//not in + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: BPM change info detected outside . Occured at line " + string(lln)); + return; + } + } + else if (tag == "m_value") {//bpm change value + if (bpm_reading) { + bool valid = numcheck_decimal(text); + if (!valid) { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: barpm value is not a valid decimal expression. Occured at line " + string(lln)); + return; + } + extr.str(text); + if (temp_bpm != NULL) { + extr >> temp_bpm->bpm;//read current barpm + extr.clear(); + } + else { + throw std::logic_error("Read bpmchange error: Unable to create object \"bpmchange\""); + return; + } + } + else {//not in + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: BPM change info detected outside . Occured at line " + string(lln)); + return; + } + } //ignore all other tags } } @@ -888,7 +1003,59 @@ void chart_store::parse_elem() { return; } } + else if (tag == "m_argument") {//m_argument end + if (modes == 4)modes = 0; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } + else if (tag == "m_bpmchange") {//m_bpmchange end + if (bpm_mode)bpm_mode = false;//stop reading bpm change list + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } + else if (tag == "CBpmchange") {//end of a bpm change info + if (bpm_reading) { + //checking bpm change info integrity + //time + if (temp_bpm->time < -1e7) { + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", tag_line); + throw std::logic_error("Read bpmchange error: bpm change info missing time.\nThe bpm change info begins at line " + string(lln)); + } + //bpm value + if (temp_bpm->bpm < -1e7) { + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", tag_line); + throw std::logic_error("Read bpmchange error: bpm change info missing bpm value.\nThe bpm change info begins at line " + string(lln)); + } + //bpm change info is complete + bpm_list.push_back(*temp_bpm);//add the info to bpm change list + delete temp_bpm; + temp_bpm = NULL; + bpm_reading = false; + } + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } //finish parsing element break; } @@ -1120,7 +1287,23 @@ void chart_store::side_out(const map& v, ofstream& of) {//output each of << "" << endl; } } - +void chart_store::bpm_out(const vector& v, ofstream& of) { + of << fixed << setprecision(6); + if (v.empty()) { + of << "" << endl; + return; + } + else { + of << "" << endl; + for (const bpmchange& item : v) { + of << "" << endl; + of << "" << item.time << "" << endl; + of << "" << item.bpm << "" << endl; + of << "" << endl; + } + of << "" << endl; + } +} bool chart_store::to_file(string f) { ofstream fout; fout.open(f); @@ -1161,7 +1344,6 @@ bool chart_store::to_file(string f) { //notes middle fout << "" << endl; fout << "" << endl; - side_out(m_notes, fout); fout << "" << endl; fout << "" << endl; @@ -1177,6 +1359,12 @@ bool chart_store::to_file(string f) { side_out(m_right, fout); fout << "" << endl; fout << "" << endl; + //bpm list + fout << "" << endl; + + bpm_out(bpm_list, fout); + + fout << "" << endl; //end fout << "" << endl; fout.close(); diff --git a/Dynamix_chart_width_control/chart_store.h b/Dynamix_chart_width_control/chart_store.h index 8c0f491..df885c6 100644 --- a/Dynamix_chart_width_control/chart_store.h +++ b/Dynamix_chart_width_control/chart_store.h @@ -23,6 +23,7 @@ using std::set; enum types { NORMAL = 1, CHAIN, HOLD, SUB, NULLTP }; //added default sides type: UNKNOWN enum sides { PAD, MIXER, MULTI, UNKNOWN }; +//note struct note { int id; types notetype; @@ -38,6 +39,14 @@ struct note { width(-1e8), subid(INT_MIN) {} }; +//bpmchange +struct bpmchange { + double time; + double bpm; + //constructor + bpmchange() :time(-1e8), bpm(-1e8) {} +}; +//chart class chart_store { public: @@ -51,6 +60,8 @@ class chart_store set sub_mid, sub_left, sub_right; //mismatch note list(used for hold-sub autofix) vector > mismatched_notes; + //bpmchange list + vector bpm_list; bool to_file(string f);//print to XML int readfile(string fn);//read XML @@ -74,17 +85,22 @@ class chart_store double barpm;//Bar per minute sides ltype, rtype;//left type and right type void side_out(const map& v, ofstream& of);//output each side + void bpm_out(const vector& v, ofstream& of);//output bpm change list void clear(); //xml parser members string t_buf;//the string buffer int buf_index;//the current index in the string buffer - int modes;//0->none 1->middle 2->left 3->right + int modes;//0->none 1->middle 2->left 3->right 4->bpmchange note* tempnote; + bpmchange* temp_bpm; bool note_trigger; bool note_reading;//if reading a note int lines;//at which line in xml + bool bpm_mode = false;//if reading bpm section + bool bpm_reading = false;//if reading bpm + void skip_space();//skip the space when parsing bool parse_decl();//if declaration bool parse_comment();//if parsing comment diff --git a/Dynamix_chart_width_control_GUI/chart_store.cpp b/Dynamix_chart_width_control_GUI/chart_store.cpp index da81a9a..f15e433 100644 --- a/Dynamix_chart_width_control_GUI/chart_store.cpp +++ b/Dynamix_chart_width_control_GUI/chart_store.cpp @@ -91,6 +91,8 @@ void chart_store::clear() { sub_mid.clear(); sub_left.clear(); sub_right.clear(); + //init bpm list + bpm_list.clear(); //init mismatched note list mismatched_notes.clear(); @@ -122,11 +124,15 @@ int chart_store::readfile(string fn) { ifstream fin; bool mismatch = false;//check if hold-sub mismatch - modes = 0;//0->none 1->middle 2->left 3->right + modes = 0;//0->none 1->middle 2->left 3->right 4->bpmchange tempnote = NULL; + temp_bpm = NULL; note_trigger = false; note_reading = false;//if reading a note + bpm_mode = false;//if reading bpm section + bpm_reading = false;//if reading bpm + int chart_flags = 0; fin.open(fn);//open file @@ -365,6 +371,55 @@ void chart_store::parse_elem() { return; } } + else if (tag == "m_argument") {//barpm change argument + if (modes == 0)modes = 4; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax Error when reading BPM change info. Occured at line " + string(lln)); + return; + } + } + else if (tag == "m_bpmchange") {//barpm change + if (modes == 4) bpm_mode = true; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax Error when reading BPM change info. Occured at line " + string(lln)); + return; + } + } + else if (tag == "CBpmchange") { //head of a bpm change info + if (bpm_mode) { + if (!bpm_reading) { + bpm_reading = true; + temp_bpm = new bpmchange; + } + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: asset error, triggered at line " + + string(lln)); + return; + } + } + else {//not bpm change mode + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Unexpected BPM change info detected outside the BPM lists, triggered at line " + + string(lln)); + return; + } + } + //read text string text = ""; try { @@ -504,7 +559,7 @@ void chart_store::parse_elem() { return; } } - else if (tag == "m_time" && note_trigger == true) {//note time + else if (tag == "m_time" && note_trigger) {//note time if (note_reading) { bool valid = numcheck_decimal(text); if (!valid) { @@ -628,6 +683,66 @@ void chart_store::parse_elem() { } } + else if (tag == "m_time" && bpm_mode) {//bpm change time + if (bpm_reading) { + bool valid = numcheck_decimal(text); + if (!valid) { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: time is not a valid decimal expression. Occured at line " + string(lln)); + return; + } + extr.str(text); + if (temp_bpm != NULL) { + extr >> temp_bpm->time;//read current bpm change time + extr.clear(); + } + else { + throw std::logic_error("Read bpmchange error: Unable to create object \"bpmchange\""); + return; + } + } + else {//not in + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: BPM change info detected outside . Occured at line " + string(lln)); + return; + } + } + else if (tag == "m_value") {//bpm change value + if (bpm_reading) { + bool valid = numcheck_decimal(text); + if (!valid) { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: barpm value is not a valid decimal expression. Occured at line " + string(lln)); + return; + } + extr.str(text); + if (temp_bpm != NULL) { + extr >> temp_bpm->bpm;//read current barpm + extr.clear(); + } + else { + throw std::logic_error("Read bpmchange error: Unable to create object \"bpmchange\""); + return; + } + } + else {//not in + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: BPM change info detected outside . Occured at line " + string(lln)); + return; + } + } //ignore all other tags } } @@ -888,7 +1003,59 @@ void chart_store::parse_elem() { return; } } + else if (tag == "m_argument") {//m_argument end + if (modes == 4)modes = 0; + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } + else if (tag == "m_bpmchange") {//m_bpmchange end + if (bpm_mode)bpm_mode = false;//stop reading bpm change list + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } + else if (tag == "CBpmchange") {//end of a bpm change info + if (bpm_reading) { + //checking bpm change info integrity + //time + if (temp_bpm->time < -1e7) { + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", tag_line); + throw std::logic_error("Read bpmchange error: bpm change info missing time.\nThe bpm change info begins at line " + string(lln)); + } + //bpm value + if (temp_bpm->bpm < -1e7) { + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", tag_line); + throw std::logic_error("Read bpmchange error: bpm change info missing bpm value.\nThe bpm change info begins at line " + string(lln)); + } + //bpm change info is complete + bpm_list.push_back(*temp_bpm);//add the info to bpm change list + delete temp_bpm; + temp_bpm = NULL; + bpm_reading = false; + } + else { + //get error position + char lln[64]; + snprintf(lln, sizeof(lln), "%d.", lines); + + throw std::logic_error("Read bpmchange error: Syntax error when stop reading bpm change info.\nOccured at line " + string(lln)); + return; + } + } //finish parsing element break; } @@ -1120,7 +1287,23 @@ void chart_store::side_out(const map& v, ofstream& of) {//output each of << "" << endl; } } - +void chart_store::bpm_out(const vector& v, ofstream& of) { + of << fixed << setprecision(6); + if (v.empty()) { + of << "" << endl; + return; + } + else { + of << "" << endl; + for (const bpmchange& item : v) { + of << "" << endl; + of << "" << item.time << "" << endl; + of << "" << item.bpm << "" << endl; + of << "" << endl; + } + of << "" << endl; + } +} bool chart_store::to_file(string f) { ofstream fout; fout.open(f); @@ -1161,7 +1344,6 @@ bool chart_store::to_file(string f) { //notes middle fout << "" << endl; fout << "" << endl; - side_out(m_notes, fout); fout << "" << endl; fout << "" << endl; @@ -1177,6 +1359,12 @@ bool chart_store::to_file(string f) { side_out(m_right, fout); fout << "" << endl; fout << "" << endl; + //bpm list + fout << "" << endl; + + bpm_out(bpm_list, fout); + + fout << "" << endl; //end fout << "" << endl; fout.close(); diff --git a/Dynamix_chart_width_control_GUI/chart_store.h b/Dynamix_chart_width_control_GUI/chart_store.h index 8c0f491..df885c6 100644 --- a/Dynamix_chart_width_control_GUI/chart_store.h +++ b/Dynamix_chart_width_control_GUI/chart_store.h @@ -23,6 +23,7 @@ using std::set; enum types { NORMAL = 1, CHAIN, HOLD, SUB, NULLTP }; //added default sides type: UNKNOWN enum sides { PAD, MIXER, MULTI, UNKNOWN }; +//note struct note { int id; types notetype; @@ -38,6 +39,14 @@ struct note { width(-1e8), subid(INT_MIN) {} }; +//bpmchange +struct bpmchange { + double time; + double bpm; + //constructor + bpmchange() :time(-1e8), bpm(-1e8) {} +}; +//chart class chart_store { public: @@ -51,6 +60,8 @@ class chart_store set sub_mid, sub_left, sub_right; //mismatch note list(used for hold-sub autofix) vector > mismatched_notes; + //bpmchange list + vector bpm_list; bool to_file(string f);//print to XML int readfile(string fn);//read XML @@ -74,17 +85,22 @@ class chart_store double barpm;//Bar per minute sides ltype, rtype;//left type and right type void side_out(const map& v, ofstream& of);//output each side + void bpm_out(const vector& v, ofstream& of);//output bpm change list void clear(); //xml parser members string t_buf;//the string buffer int buf_index;//the current index in the string buffer - int modes;//0->none 1->middle 2->left 3->right + int modes;//0->none 1->middle 2->left 3->right 4->bpmchange note* tempnote; + bpmchange* temp_bpm; bool note_trigger; bool note_reading;//if reading a note int lines;//at which line in xml + bool bpm_mode = false;//if reading bpm section + bool bpm_reading = false;//if reading bpm + void skip_space();//skip the space when parsing bool parse_decl();//if declaration bool parse_comment();//if parsing comment diff --git a/version.h b/version.h index d5cb7c3..10ce100 100644 --- a/version.h +++ b/version.h @@ -3,6 +3,6 @@ * The header that specifies the program version. * * */ -#define VERSION_H "v1.3.0" +#define VERSION_H "v1.3.2" #endif \ No newline at end of file