mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
Initial Web Menu Implementation (#170)
* initial commit with some nice css * add beginnings of templating. revert to qa model * add most options visually * add parser and full input checks * separate menu code, use ControlModule * add tests for menu rendering locally * wip sliders * add AttackAngle * remove tesla overlay * begin with into_string * add slider.js * don't use in html yet Co-authored-by: jugeeya <jugeeya@llive.com>
This commit is contained in:
parent
049232c420
commit
1a273f7cbf
33 changed files with 867 additions and 2537 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,4 +1 @@
|
|||
|
||||
[submodule "TrainingModpackOverlay/libs/libtesla"]
|
||||
path = TrainingModpackOverlay/libs/libtesla
|
||||
url = https://github.com/WerWolv/libtesla
|
||||
|
|
|
@ -10,10 +10,17 @@ crate-type = ["cdylib"]
|
|||
[dependencies]
|
||||
skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" }
|
||||
skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git" }
|
||||
skyline-web = { git = "https://github.com/skyline-rs/skyline-web.git" }
|
||||
bitflags = "1.2.1"
|
||||
parking_lot = { version = "0.11.0", features = ["nightly"] }
|
||||
lazy_static = "1.4.0"
|
||||
owo-colors = "1.1.3"
|
||||
ramhorns = "0.10.1"
|
||||
paste = "1.0"
|
||||
num = "0.3.0"
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
wsl = "0.1.0"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
---
|
||||
AccessModifierOffset: '-4'
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: 'true'
|
||||
AlignConsecutiveDeclarations: 'true'
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: 'true'
|
||||
AlignTrailingComments: 'true'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'true'
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AllowShortCaseLabelsOnASingleLine: 'false'
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: 'true'
|
||||
AllowShortLoopsOnASingleLine: 'true'
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: 'true'
|
||||
AlwaysBreakTemplateDeclarations: 'false'
|
||||
BinPackArguments: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: 'true'
|
||||
AfterControlStatement: 'true'
|
||||
AfterEnum: 'true'
|
||||
AfterFunction: 'true'
|
||||
AfterNamespace: 'true'
|
||||
AfterStruct: 'true'
|
||||
AfterUnion: 'true'
|
||||
AfterExternBlock: 'true'
|
||||
BeforeCatch: 'true'
|
||||
BeforeElse: 'true'
|
||||
SplitEmptyFunction: 'false'
|
||||
SplitEmptyRecord: 'false'
|
||||
SplitEmptyNamespace: 'false'
|
||||
BreakBeforeTernaryOperators: 'true'
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakStringLiterals: 'false'
|
||||
ColumnLimit: '128'
|
||||
CompactNamespaces: 'false'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
Cpp11BracedListStyle: 'true'
|
||||
FixNamespaceComments: 'true'
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseLabels: 'false'
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'true'
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: '1'
|
||||
PointerAlignment: Left
|
||||
ReflowComments: 'true'
|
||||
SortIncludes: 'false'
|
||||
SortUsingDeclarations: 'false'
|
||||
SpaceAfterCStyleCast: 'false'
|
||||
SpaceAfterTemplateKeyword: 'false'
|
||||
SpaceBeforeAssignmentOperators: 'true'
|
||||
SpaceBeforeParens: Never
|
||||
SpaceInEmptyParentheses: 'false'
|
||||
SpacesInAngles: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInContainerLiterals: 'false'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Cpp11
|
||||
TabWidth: '4'
|
||||
UseTab: ForIndentation
|
||||
|
||||
...
|
5
TrainingModpackOverlay/.github/FUNDING.yml
vendored
5
TrainingModpackOverlay/.github/FUNDING.yml
vendored
|
@ -1,5 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
patreon: werwolv
|
||||
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KP7XRJAND9KWU&source=url
|
||||
github: WerWolv
|
|
@ -1,50 +0,0 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "DKP Aarch64 Windows",
|
||||
"includePath": [
|
||||
"C:/devkitPro/devkitA64/aarch64-none-elf/include/**",
|
||||
"C:/devkitPro/devkitA64/lib/gcc/aarch64-none-elf/10.1.0/include/**",
|
||||
"C:/devkitPro/libnx/include/**",
|
||||
"C:/devkitPro/portlibs/switch/include/**",
|
||||
"C:/devkitPro/portlibs/switch/include/freetype2/**",
|
||||
"${workspaceFolder}/include/**",
|
||||
"${workspaceFolder}/libs/libtesla/include/**"
|
||||
],
|
||||
"defines": [
|
||||
"SWITCH",
|
||||
"__SWITCH__",
|
||||
"__aarch64__",
|
||||
"VERSION=\"\""
|
||||
],
|
||||
"compilerPath": "C:/devkitPro/devkitA64/bin/aarch64-none-elf-g++",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "gcc-x64"
|
||||
},
|
||||
{
|
||||
"name": "DKP Aarch64 Linux",
|
||||
"includePath": [
|
||||
"/opt/devkitpro/devkitA64/aarch64-none-elf/include/**",
|
||||
"/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include/**",
|
||||
"/opt/devkitpro/libnx/include/**",
|
||||
"/opt/devkitpro/portlibs/switch/include/**",
|
||||
"/opt/devkitpro/portlibs/switch/include/**",
|
||||
"/opt/devkitpro/portlibs/switch/include/freetype2/**",
|
||||
"${workspaceFolder}/include/**",
|
||||
"${workspaceFolder}/libs/libtesla/include/**"
|
||||
],
|
||||
"defines": [
|
||||
"SWITCH",
|
||||
"__SWITCH__",
|
||||
"__aarch64__",
|
||||
"VERSION=\"\""
|
||||
],
|
||||
"compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-g++",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
61
TrainingModpackOverlay/.vscode/settings.json
vendored
61
TrainingModpackOverlay/.vscode/settings.json
vendored
|
@ -1,61 +0,0 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"chrono": "cpp",
|
||||
"string_view": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"mutex": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"valarray": "cpp"
|
||||
}
|
||||
}
|
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -1,212 +0,0 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
include $(DEVKITPRO)/libnx/switch_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
|
||||
#
|
||||
# NO_ICON: if set to anything, do not use icon.
|
||||
# NO_NACP: if set to anything, no .nacp file is generated.
|
||||
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
|
||||
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
|
||||
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
|
||||
# ICON is the filename of the icon (.jpg), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.jpg
|
||||
# - icon.jpg
|
||||
# - <libnx folder>/default_icon.jpg
|
||||
#
|
||||
# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.json
|
||||
# - config.json
|
||||
# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead
|
||||
# of a homebrew executable (.nro). This is intended to be used for sysmodules.
|
||||
# NACP building is skipped as well.
|
||||
#---------------------------------------------------------------------------------
|
||||
APP_TITLE := Training Modpack
|
||||
APP_VERSION := 2.6
|
||||
|
||||
TARGET := ovlTrainingModpack
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
DATA := data
|
||||
INCLUDES := include libs/libtesla/include
|
||||
|
||||
ifeq ($(RELEASE),)
|
||||
APP_VERSION := $(APP_VERSION)
|
||||
endif
|
||||
|
||||
NO_ICON := 1
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__ -DVERSION=\"v$(APP_VERSION)\"
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-exceptions -std=c++17
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lnx
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(LIBNX)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
ifeq ($(strip $(CONFIG_JSON)),)
|
||||
jsons := $(wildcard *.json)
|
||||
ifneq (,$(findstring $(TARGET).json,$(jsons)))
|
||||
export APP_JSON := $(TOPDIR)/$(TARGET).json
|
||||
else
|
||||
ifneq (,$(findstring config.json,$(jsons)))
|
||||
export APP_JSON := $(TOPDIR)/config.json
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(ICON)),)
|
||||
icons := $(wildcard *.jpg)
|
||||
ifneq (,$(findstring $(TARGET).jpg,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/$(TARGET).jpg
|
||||
else
|
||||
ifneq (,$(findstring icon.jpg,$(icons)))
|
||||
export APP_ICON := $(TOPDIR)/icon.jpg
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_ICON)),)
|
||||
export NROFLAGS += --icon=$(APP_ICON)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(NO_NACP)),)
|
||||
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
|
||||
endif
|
||||
|
||||
ifneq ($(APP_TITLEID),)
|
||||
export NACPFLAGS += --titleid=$(APP_TITLEID)
|
||||
endif
|
||||
|
||||
ifneq ($(ROMFS),)
|
||||
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@rm -fr $(BUILD) $(TARGET).ovl $(TARGET).nro $(TARGET).nacp $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).ovl
|
||||
|
||||
$(OUTPUT).ovl : $(OUTPUT).elf $(OUTPUT).nacp
|
||||
@elf2nro $< $@ $(NROFLAGS)
|
||||
@echo "built ... $(notdir $(OUTPUT).ovl)"
|
||||
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
|
@ -1,7 +0,0 @@
|
|||
# ovlSysmodule
|
||||
|
||||
A Tesla overlay that allows you to toggle sysmodules on the fly
|
||||
|
||||
## Installation
|
||||
|
||||
Download the latest ovlSysmodules.ovl from the release page and drop it into the /switch/.overlays folder on your Switch's SD card
|
|
@ -1,81 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <tesla.hpp>
|
||||
|
||||
class ClickableListItem : public tsl::elm::ListItem
|
||||
{
|
||||
public:
|
||||
ClickableListItem(std::string text,
|
||||
const std::vector<std::string> values,
|
||||
int* defaultPos,
|
||||
const std::string data,
|
||||
int index,
|
||||
std::string title,
|
||||
std::string help)
|
||||
: tsl::elm::ListItem(text), m_values(values), m_curValue(defaultPos), extdata(data), title(title), help(help)
|
||||
{
|
||||
this->index = index;
|
||||
this->setValue("");
|
||||
}
|
||||
|
||||
~ClickableListItem() {}
|
||||
|
||||
tsl::elm::Element* requestFocus(Element* oldFocus, tsl::FocusDirection direction)
|
||||
{
|
||||
return ListItem::requestFocus(oldFocus, direction);
|
||||
}
|
||||
|
||||
void layout(u16 parentX, u16 parentY, u16 parentWidth, u16 parentHeight)
|
||||
{
|
||||
ListItem::layout(parentX, parentY, parentWidth, parentHeight);
|
||||
}
|
||||
|
||||
bool onClick(u64 keys)
|
||||
{
|
||||
if(keys & KEY_Y)
|
||||
{
|
||||
if(this->m_helpListener != nullptr)
|
||||
{
|
||||
this->m_helpListener(this->title, this->help);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(keys & KEY_A)
|
||||
{
|
||||
if(this->m_clickListener != nullptr)
|
||||
{
|
||||
this->m_clickListener(this->m_values, this->m_curValue, this->extdata, this->index, this->title, this->help);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int getCurValue() { return *(this->m_curValue); }
|
||||
void setCurValue(int value) { *(this->m_curValue) = value; }
|
||||
|
||||
const std::string getExtData() { return this->extdata; }
|
||||
|
||||
const std::vector<std::string> getValues() { return this->m_values; }
|
||||
|
||||
void setClickListener(
|
||||
std::function<void(const std::vector<std::string>, int*, std::string, int index, std::string title, std::string help)>
|
||||
clickListener)
|
||||
{
|
||||
this->m_clickListener = clickListener;
|
||||
}
|
||||
void setHelpListener(std::function<void(std::string, std::string)> helpListener) { this->m_helpListener = helpListener; }
|
||||
|
||||
private:
|
||||
const std::vector<std::string> m_values;
|
||||
int* m_curValue;
|
||||
std::function<void(const std::vector<std::string>, int*, std::string, int, std::string, std::string)> m_clickListener =
|
||||
nullptr;
|
||||
std::function<void(std::string, std::string)> m_helpListener = nullptr;
|
||||
const std::string extdata;
|
||||
const std::string title;
|
||||
const std::string help;
|
||||
int index;
|
||||
};
|
|
@ -1,159 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<class T, typename U = uint32_t> struct BitFlags
|
||||
{
|
||||
using UnderlyingType = U;
|
||||
using Type = T;
|
||||
|
||||
constexpr static const UnderlyingType s_validMask = (UnderlyingType{1u << *Type::Count} - UnderlyingType{1});
|
||||
|
||||
struct NoneType
|
||||
{};
|
||||
struct AllType
|
||||
{};
|
||||
|
||||
UnderlyingType m_bits;
|
||||
|
||||
constexpr static const AllType All{};
|
||||
constexpr static const NoneType None{};
|
||||
|
||||
BitFlags() = default;
|
||||
BitFlags(const BitFlags&) = default;
|
||||
|
||||
constexpr BitFlags(NoneType) : m_bits(0) {}
|
||||
constexpr BitFlags(AllType) : m_bits(s_validMask) {}
|
||||
constexpr explicit BitFlags(UnderlyingType t) : m_bits(s_validMask & t) {}
|
||||
|
||||
BitFlags& operator=(const BitFlags&) = default;
|
||||
~BitFlags() = default;
|
||||
|
||||
constexpr BitFlags(Type t) : m_bits{UnderlyingType{1} << static_cast<std::underlying_type_t<Type>>(t)} {}
|
||||
|
||||
constexpr BitFlags& operator|=(BitFlags rhs)
|
||||
{
|
||||
m_bits |= rhs.m_bits;
|
||||
return *this;
|
||||
}
|
||||
constexpr BitFlags& operator&=(BitFlags rhs)
|
||||
{
|
||||
m_bits &= rhs.m_bits;
|
||||
return *this;
|
||||
}
|
||||
constexpr BitFlags& operator-=(BitFlags rhs)
|
||||
{
|
||||
m_bits &= ~rhs.m_bits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return m_bits != 0; }
|
||||
};
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator|(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
lhs |= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator&(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
lhs &= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator-(BitFlags<T, U> lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
lhs -= rhs;
|
||||
return lhs;
|
||||
}
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator-(BitFlags<T, U> lhs, T rhs)
|
||||
{
|
||||
lhs -= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator-(T lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
rhs -= lhs;
|
||||
return rhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator|(BitFlags<T, U> lhs, T rhs)
|
||||
{
|
||||
lhs |= rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr BitFlags<T, U> operator|(T lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
rhs |= lhs;
|
||||
return rhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr bool operator&(BitFlags<T, U> lhs, T rhs)
|
||||
{
|
||||
lhs &= rhs;
|
||||
return lhs.m_bits != 0;
|
||||
}
|
||||
|
||||
template<typename T, typename U> constexpr bool operator&(T lhs, BitFlags<T, U> rhs)
|
||||
{
|
||||
rhs &= lhs;
|
||||
return rhs.m_bits != 0;
|
||||
}
|
||||
|
||||
template<typename T> struct FlagType;
|
||||
|
||||
template<typename T> using FlagTypeT = typename FlagType<T>::Type;
|
||||
|
||||
template<class T> struct EnumArray;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#define DEFINE_FLAGS_UT(TypeName, UnderlyingType) \
|
||||
using TypeName##s = detail::BitFlags<TypeName, UnderlyingType>; \
|
||||
constexpr TypeName##s operator|(TypeName lhs, TypeName rhs) { return TypeName##s{lhs} | TypeName##s{rhs}; } \
|
||||
namespace detail \
|
||||
{ \
|
||||
template<> struct FlagType<TypeName> \
|
||||
{ \
|
||||
using Type = TypeName##s; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define DEFINE_FLAGS(TypeName) DEFINE_FLAGS_UT(TypeName, uint32_t)
|
||||
#define ENUM_X(type, e, y) e,
|
||||
#define ENUM_QUAL_X(type, e, y) type::e,
|
||||
#define ENUM_NAME_PAIR(type, e, y) {type::e, y},
|
||||
#define CASE_X(type, e, y) \
|
||||
case type::e: \
|
||||
return y;
|
||||
#define DEFINE_ENUM_CLASS_TYPE(Name, Type) \
|
||||
enum class Name : Type \
|
||||
{ \
|
||||
ENUM_CLASS_##Name(Name, ENUM_X) Count \
|
||||
}; \
|
||||
constexpr auto operator*(Name t) { return static_cast<std::underlying_type_t<Name>>(t); } \
|
||||
namespace detail \
|
||||
{ \
|
||||
template<> struct EnumArray<Name> \
|
||||
{ \
|
||||
constexpr static const std::array<std::pair<Name, const char*>, *Name::Count> values{ \
|
||||
{ENUM_CLASS_##Name(Name, ENUM_NAME_PAIR)}}; \
|
||||
}; \
|
||||
} \
|
||||
constexpr const char* toString(Name t) \
|
||||
{ \
|
||||
if(t < Name::Count) \
|
||||
{ \
|
||||
return detail::EnumArray<Name>::values[*t].second; \
|
||||
} \
|
||||
return "UNKNWON"; \
|
||||
} \
|
||||
DEFINE_FLAGS_UT(Name, Type)
|
||||
#define DEFINE_ENUM_CLASS(Name) DEFINE_ENUM_CLASS_TYPE(Name, uint32_t)
|
|
@ -1,38 +0,0 @@
|
|||
#pragma once
|
||||
#include <tesla.hpp>
|
||||
|
||||
static char help_text_global[1024];
|
||||
|
||||
class GuiHelp : public tsl::Gui
|
||||
{
|
||||
public:
|
||||
GuiHelp(std::string title, std::string help) : m_title(std::move(title)), m_help(std::move(help)) {}
|
||||
|
||||
virtual tsl::elm::Element* createUI() override
|
||||
{
|
||||
auto rootFrame = new tsl::elm::OverlayFrame(m_title, "Help");
|
||||
|
||||
snprintf(help_text_global, sizeof help_text_global, "%s", m_help.c_str());
|
||||
|
||||
auto help_text = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||
renderer->drawString(help_text_global, false, 45, 125, 20, renderer->a(0xFFFF));
|
||||
});
|
||||
|
||||
rootFrame->setContent(help_text);
|
||||
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
virtual void update() override {}
|
||||
virtual bool handleInput(u64 keysDown,
|
||||
u64 keysHeld,
|
||||
touchPosition touchInput,
|
||||
JoystickPosition leftJoyStick,
|
||||
JoystickPosition rightJoyStick) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string m_title;
|
||||
std::string m_help;
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <tesla.hpp>
|
||||
#include "value_list_item.hpp"
|
||||
|
||||
class GuiMain : public tsl::Gui
|
||||
{
|
||||
private:
|
||||
FsFileSystem m_fs;
|
||||
tsl::elm::ToggleListItem* toggleItem = nullptr;
|
||||
std::vector<ValueListItem*> valueListItems;
|
||||
|
||||
public:
|
||||
GuiMain();
|
||||
~GuiMain();
|
||||
|
||||
virtual tsl::elm::Element* createUI();
|
||||
virtual void update() override;
|
||||
void applyChanges();
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <tesla.hpp>
|
||||
#include "clickable_list_item.hpp"
|
||||
|
||||
class GuiSublist : public tsl::Gui
|
||||
{
|
||||
private:
|
||||
std::vector<tsl::elm::ListItem*> listItems;
|
||||
std::vector<std::string> menuItems;
|
||||
int* index;
|
||||
std::string extData;
|
||||
std::string title;
|
||||
std::string help;
|
||||
|
||||
public:
|
||||
GuiSublist(std::vector<std::string> menuItems, int* index, std::string extData, std::string title, std::string help);
|
||||
~GuiSublist();
|
||||
|
||||
virtual tsl::elm::Element* createUI();
|
||||
virtual void update() override;
|
||||
void applyChanges();
|
||||
virtual void setClickListener(ClickableListItem* item);
|
||||
};
|
||||
|
||||
class GuiLambda : public tsl::Gui
|
||||
{
|
||||
std::function<tsl::elm::Element*()> m_createUI;
|
||||
tsl::Gui* m_guiMain;
|
||||
|
||||
public:
|
||||
virtual tsl::elm::Element* createUI() override
|
||||
{
|
||||
if(m_createUI) return m_createUI();
|
||||
return nullptr;
|
||||
}
|
||||
virtual void update() override
|
||||
{
|
||||
m_guiMain->update();
|
||||
}
|
||||
GuiLambda(std::function<tsl::elm::Element*()> createUIFunc, tsl::Gui* guiMain) : m_createUI(std::move(createUIFunc)), m_guiMain(guiMain) {}
|
||||
};
|
|
@ -1,61 +0,0 @@
|
|||
#include <tesla.hpp>
|
||||
|
||||
static const char* SYSTEM_SETTINGS_FILE = "/atmosphere/config/system_settings.ini";
|
||||
|
||||
static tsl::hlp::ini::IniData readSettings()
|
||||
{
|
||||
/* Open Sd card filesystem. */
|
||||
FsFileSystem fsSdmc;
|
||||
if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return {};
|
||||
tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); });
|
||||
|
||||
/* Open config file. */
|
||||
FsFile fileConfig;
|
||||
if(R_FAILED(fsFsOpenFile(&fsSdmc, SYSTEM_SETTINGS_FILE, FsOpenMode_Read, &fileConfig))) return {};
|
||||
tsl::hlp::ScopeGuard fileGuard([&] { fsFileClose(&fileConfig); });
|
||||
|
||||
/* Get config file size. */
|
||||
s64 configFileSize;
|
||||
if(R_FAILED(fsFileGetSize(&fileConfig, &configFileSize))) return {};
|
||||
|
||||
/* Read and parse config file. */
|
||||
std::string configFileData(configFileSize, '\0');
|
||||
u64 readSize;
|
||||
Result rc = fsFileRead(&fileConfig, 0, configFileData.data(), configFileSize, FsReadOption_None, &readSize);
|
||||
if(R_FAILED(rc) || readSize != static_cast<u64>(configFileSize)) return {};
|
||||
|
||||
return tsl::hlp::ini::parseIni(configFileData);
|
||||
}
|
||||
|
||||
static void writeSettings(tsl::hlp::ini::IniData const& iniData)
|
||||
{
|
||||
/* Open Sd card filesystem. */
|
||||
FsFileSystem fsSdmc;
|
||||
if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return;
|
||||
tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); });
|
||||
|
||||
std::string iniString = tsl::hlp::ini::unparseIni(iniData);
|
||||
|
||||
fsFsDeleteFile(&fsSdmc, SYSTEM_SETTINGS_FILE);
|
||||
fsFsCreateFile(&fsSdmc, SYSTEM_SETTINGS_FILE, iniString.length(), 0);
|
||||
|
||||
/* Open config file. */
|
||||
FsFile fileConfig;
|
||||
if(R_FAILED(fsFsOpenFile(&fsSdmc, SYSTEM_SETTINGS_FILE, FsOpenMode_Write, &fileConfig))) return;
|
||||
tsl::hlp::ScopeGuard fileGuard([&] { fsFileClose(&fileConfig); });
|
||||
|
||||
fsFileWrite(&fileConfig, 0, iniString.c_str(), iniString.length(), FsWriteOption_Flush);
|
||||
}
|
||||
|
||||
static void updateSettings(tsl::hlp::ini::IniData const& changes)
|
||||
{
|
||||
tsl::hlp::ini::IniData iniData = readSettings();
|
||||
for(auto& section : changes)
|
||||
{
|
||||
for(auto& keyValue : section.second)
|
||||
{
|
||||
iniData[section.first][keyValue.first] = keyValue.second;
|
||||
}
|
||||
}
|
||||
writeSettings(iniData);
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
#include <tesla.hpp>
|
||||
|
||||
class OverflowList : public tsl::elm::List {
|
||||
public:
|
||||
OverflowList() : tsl::elm::List() {}
|
||||
|
||||
virtual tsl::elm::Element* requestFocus(tsl::elm::Element *oldFocus, tsl::FocusDirection direction) override {
|
||||
tsl::elm::Element *newFocus = nullptr;
|
||||
|
||||
if (this->m_clearList || this->m_itemsToAdd.size() > 0)
|
||||
return nullptr;
|
||||
|
||||
if (direction == tsl::FocusDirection::None) {
|
||||
u16 i = 0;
|
||||
|
||||
if (oldFocus == nullptr) {
|
||||
s32 elementHeight = 0;
|
||||
while (elementHeight < this->m_offset && i < this->m_items.size() - 1) {
|
||||
i++;
|
||||
elementHeight += this->m_items[i]->getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < this->m_items.size(); i++) {
|
||||
newFocus = this->m_items[i]->requestFocus(oldFocus, direction);
|
||||
|
||||
if (newFocus != nullptr) {
|
||||
this->m_focusedIndex = i;
|
||||
|
||||
this->updateScrollOffset();
|
||||
return newFocus;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (direction == tsl::FocusDirection::Down) {
|
||||
|
||||
for (u16 i = this->m_focusedIndex + 1; i < this->m_items.size(); i++) {
|
||||
newFocus = this->m_items[i]->requestFocus(oldFocus, direction);
|
||||
|
||||
if (newFocus != nullptr && newFocus != oldFocus) {
|
||||
this->m_focusedIndex = i;
|
||||
|
||||
this->updateScrollOffset();
|
||||
return newFocus;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_focusedIndex == this->m_items.size() - 1) {
|
||||
for (u16 i = 0; i < this->m_items.size(); i++) {
|
||||
newFocus = this->m_items[i]->requestFocus(oldFocus, direction);
|
||||
|
||||
if (newFocus != nullptr && newFocus != oldFocus) {
|
||||
this->m_focusedIndex = i;
|
||||
|
||||
this->updateScrollOffset();
|
||||
return newFocus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return oldFocus;
|
||||
} else if (direction == tsl::FocusDirection::Up) {
|
||||
if (this->m_focusedIndex > 0) {
|
||||
|
||||
for (u16 i = this->m_focusedIndex - 1; i >= 0; i--) {
|
||||
if (i > this->m_items.size() || this->m_items[i] == nullptr)
|
||||
return oldFocus;
|
||||
else
|
||||
newFocus = this->m_items[i]->requestFocus(oldFocus, direction);
|
||||
|
||||
if (newFocus != nullptr && newFocus != oldFocus) {
|
||||
this->m_focusedIndex = i;
|
||||
|
||||
this->updateScrollOffset();
|
||||
return newFocus;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (u16 i = this->m_items.size() - 1; i >= 0; i--) {
|
||||
if (i <= this->m_items.size() && this->m_items[i] != nullptr)
|
||||
newFocus = this->m_items[i]->requestFocus(oldFocus, direction);
|
||||
|
||||
if (newFocus != nullptr && newFocus != oldFocus) {
|
||||
this->m_focusedIndex = i;
|
||||
|
||||
this->updateScrollOffset();
|
||||
return newFocus;
|
||||
}
|
||||
}
|
||||
|
||||
return oldFocus;
|
||||
}
|
||||
}
|
||||
|
||||
return oldFocus;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void updateScrollOffset() {
|
||||
if (this->getInputMode() != tsl::InputMode::Controller)
|
||||
return;
|
||||
|
||||
if (this->m_listHeight <= this->getHeight()) {
|
||||
this->m_nextOffset = 0;
|
||||
this->m_offset = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_nextOffset = 0;
|
||||
for (u16 i = 0; i < this->m_focusedIndex; i++)
|
||||
this->m_nextOffset += this->m_items[i]->getHeight();
|
||||
|
||||
this->m_nextOffset -= this->getHeight() / 3;
|
||||
|
||||
if (this->m_nextOffset < 0)
|
||||
this->m_nextOffset = 0;
|
||||
|
||||
if (this->m_nextOffset > (this->m_listHeight - this->getHeight()) + 50)
|
||||
this->m_nextOffset = (this->m_listHeight - this->getHeight() + 50);
|
||||
}
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
#include <tesla.hpp>
|
||||
|
||||
class OverlayFrameWithHelp : public tsl::elm::OverlayFrame
|
||||
{
|
||||
public:
|
||||
OverlayFrameWithHelp(const std::string& title, const std::string& subtitle) : tsl::elm::OverlayFrame(title, subtitle)
|
||||
{}
|
||||
|
||||
virtual void draw(tsl::gfx::Renderer* renderer) override
|
||||
{
|
||||
renderer->fillScreen(a(tsl::style::color::ColorFrameBackground));
|
||||
renderer->drawRect(tsl::cfg::FramebufferWidth - 1, 0, 1, tsl::cfg::FramebufferHeight, a(0xF222));
|
||||
|
||||
renderer->drawString(this->m_title.c_str(), false, 20, 50, 30, a(tsl::style::color::ColorText));
|
||||
renderer->drawString(this->m_subtitle.c_str(), false, 20, 70, 15, a(tsl::style::color::ColorDescription));
|
||||
|
||||
renderer->drawRect(15, tsl::cfg::FramebufferHeight - 73, tsl::cfg::FramebufferWidth - 30, 1, a(tsl::style::color::ColorText));
|
||||
|
||||
renderer->drawString("\uE0E1 Back \uE0E0 OK \uE0E3 Help", false, 30, 693, 23, a(tsl::style::color::ColorText));
|
||||
|
||||
if (this->m_contentElement != nullptr)
|
||||
this->m_contentElement->frame(renderer);
|
||||
}
|
||||
};
|
|
@ -1,368 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define NONE 0
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "cpp_utils.hpp"
|
||||
|
||||
const std::vector<std::string> on_off{"Off", "On"};
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_OnOffFlag(type,x) \
|
||||
x(type,On,"On")
|
||||
|
||||
// clang-format on
|
||||
DEFINE_ENUM_CLASS(OnOffFlag);
|
||||
|
||||
// Frame Advantage
|
||||
const std::vector<std::string> frame_advantage_items{""};
|
||||
const std::string frame_advantage_help = R""""(
|
||||
Show frame advantage when
|
||||
hitting a CPU's shield.
|
||||
|
||||
This is comparing true frames
|
||||
of actionability between the
|
||||
CPU and player.
|
||||
|
||||
Use this to practice optimal
|
||||
aerial heights and specific
|
||||
safe hitboxes.)"""";
|
||||
|
||||
// Input delay
|
||||
const std::vector<std::string> input_delay_items{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
|
||||
const std::string input_delay_help = R""""(
|
||||
In frames.
|
||||
|
||||
Emulate input delay
|
||||
to practice in a online
|
||||
environment.)"""";
|
||||
|
||||
// Side Taunt
|
||||
|
||||
// DI / Left Stick
|
||||
/*
|
||||
0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398
|
||||
0, pi/4, pi/2, 3pi/4, pi, 5pi/4, 3pi/2, 7pi/4
|
||||
*/
|
||||
|
||||
/* DI */
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_Direction(type,x) \
|
||||
x(type,Out,"Out") \
|
||||
x(type,UpOut,"Up Out") \
|
||||
x(type,Up,"Up") \
|
||||
x(type,UpIn,"Up In") \
|
||||
x(type,In,"In") \
|
||||
x(type,DownIn,"Down In") \
|
||||
x(type,Down,"Down") \
|
||||
x(type,DownOut,"Down Out")\
|
||||
x(type,Nothing,"Neutral")
|
||||
|
||||
DEFINE_ENUM_CLASS(Direction);
|
||||
const std::string di_help = R""""(
|
||||
Specified Direction
|
||||
CPUs DI in the direction specified
|
||||
(relative to the player's facing
|
||||
position).
|
||||
)"""";
|
||||
|
||||
const std::string sdi_help = R""""(
|
||||
Specified Direction
|
||||
CPUs SDI in the direction specified
|
||||
(relative to the player's facing
|
||||
position) every four frames
|
||||
during hitlag.
|
||||
)"""";
|
||||
|
||||
// Left Stick
|
||||
const std::string air_dodge_direction_help = R""""(
|
||||
Air Dodge Direction
|
||||
(relative to the player's facing
|
||||
position).
|
||||
)"""";
|
||||
|
||||
// Ledge Option
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_LedgeFlag(type,x) \
|
||||
x(type,Neutral,"Neutral") \
|
||||
x(type,Roll,"Roll") \
|
||||
x(type,Jump,"Jump") \
|
||||
x(type,Attack,"Attack") \
|
||||
x(type,Wait,"Wait")
|
||||
|
||||
|
||||
// clang-format on
|
||||
|
||||
DEFINE_ENUM_CLASS(LedgeFlag);
|
||||
const std::string ledge_help = R""""(
|
||||
CPUs will perform a ledge option
|
||||
among the selected options.
|
||||
|
||||
CPUs will also perform a defensive
|
||||
option after getting up.
|
||||
)"""";
|
||||
|
||||
const std::string ledge_delay_help = R""""(
|
||||
Frames to delay ledge option.)"""";
|
||||
|
||||
// Tech Option
|
||||
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_TechFlag(type,x) \
|
||||
x(type,Miss,"Miss Tech") \
|
||||
x(type,RollF,"RollF") \
|
||||
x(type,RollB,"RollB") \
|
||||
x(type,InPlace,"In Place")
|
||||
|
||||
// clang-format on
|
||||
DEFINE_ENUM_CLASS(TechFlag);
|
||||
|
||||
constexpr const char* const tech_help = R""""(
|
||||
CPUs will perform a random
|
||||
tech option among the selected
|
||||
options.
|
||||
|
||||
CPUs will also perform a defensive
|
||||
option after getting up.
|
||||
|
||||
For wall tech jumps set it to RollF
|
||||
)"""";
|
||||
|
||||
// Missed Tech Option
|
||||
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_MissTechFlag(type,x) \
|
||||
x(type,Getup,"Normal Getup") \
|
||||
x(type,Attack,"Getup Attack") \
|
||||
x(type,RollF,"RollF") \
|
||||
x(type,RollB,"RollB")
|
||||
|
||||
// clang-format on
|
||||
DEFINE_ENUM_CLASS(MissTechFlag);
|
||||
|
||||
constexpr const char* const miss_tech_help = R""""(
|
||||
CPUs will perform a random
|
||||
option after missing a tech
|
||||
among the selected options.
|
||||
|
||||
CPUs will also perform a defensive
|
||||
option after getting up.)"""";
|
||||
|
||||
// Defensive States
|
||||
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_DefensiveFlag(type,x) \
|
||||
x(type,SpotDodge,"Spotdodge") \
|
||||
x(type,RollF,"RollF") \
|
||||
x(type,RollB,"RollB") \
|
||||
x(type,Jab,"Jab")\
|
||||
x(type,Shield,"Shield")
|
||||
|
||||
// clang-format on
|
||||
DEFINE_ENUM_CLASS(DefensiveFlag);
|
||||
|
||||
const std::string defensive_help = R""""(
|
||||
Choose the defensive option a CPU
|
||||
will perform after teching or
|
||||
getting up from the ledge.
|
||||
|
||||
The option will be random
|
||||
among the selected options.
|
||||
)"""";
|
||||
|
||||
// Mash States
|
||||
const std::string mash_help = R""""(
|
||||
Use this toggle along with the Shield
|
||||
Options toggle to practice moves on
|
||||
shield.
|
||||
|
||||
The option will be random
|
||||
among the selected options.
|
||||
|
||||
CPUs will mash on the first frame out
|
||||
of hitstun or out of specific states.
|
||||
)"""";
|
||||
|
||||
// Action items (Follow Up only atm)
|
||||
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_ActionFlag(type,x) \
|
||||
x(type,Airdodge,"Airdodge") x(type,Jump,"Jump") x(type,Shield,"Shield") x(type,Spotdodge,"Spotdodge") x(type,RollF,"Roll F") x(type,RollB,"Roll B") \
|
||||
x(type,Nair,"Neutral Air") x(type,Fair,"Forward Air") x(type,Bair,"Back Air") x(type,Uair,"Up Air") x(type,Dair,"Down Air") \
|
||||
x(type,NeutralB,"Neutral B") x(type,SideB,"Side B") x(type,UpB,"Up B") x(type,DownB,"Down B") \
|
||||
x(type,FSmash,"Forward Smash") x(type,USmash,"Up Smash") x(type,DSmash,"Down Smash") \
|
||||
x(type,Jab,"Jab") x(type,FTilt,"Ftilt") x(type,UTilt,"Utilt") x(type,Dtilt,"Dtilt") \
|
||||
x(type,Grab,"Grab") x(type,Dash,"Dash") x(type,DashAttack,"Dash Attack")
|
||||
|
||||
// clang-format on
|
||||
DEFINE_ENUM_CLASS(ActionFlag);
|
||||
|
||||
const std::string follow_up_help = R""""(
|
||||
The selected action will be
|
||||
buffered after the specified
|
||||
mash option.
|
||||
|
||||
The option will be random
|
||||
among the selected options.
|
||||
)"""";
|
||||
|
||||
// Hitbox visualization
|
||||
const std::string hitbox_help = R""""(
|
||||
Currently, hitboxes and
|
||||
grabboxes are supported.
|
||||
|
||||
Original move effects are
|
||||
paused during normal attacks
|
||||
and specials when hitbox
|
||||
visualization is active.)"""";
|
||||
|
||||
// Stage Hazards
|
||||
const std::string hazards_help = R""""(
|
||||
Toggle state hazards on/off for
|
||||
Training Mode.
|
||||
|
||||
Only works outside of a match.
|
||||
Make sure to turn them on/off
|
||||
before leaving the Character
|
||||
Select Screen.
|
||||
|
||||
If you change this while in training,
|
||||
make sure to restart training mode.
|
||||
)"""";
|
||||
|
||||
// Save states
|
||||
const std::vector<std::string> empty_items{""};
|
||||
const std::string save_states_help = R""""(
|
||||
Press Grab + Down Taunt at any
|
||||
time to save the state of the
|
||||
training mode for you and the
|
||||
CPU.
|
||||
|
||||
Press Grab + Up Taunt at any
|
||||
time to revert to a
|
||||
previously saved state.
|
||||
|
||||
The following attributes
|
||||
are saved:
|
||||
- Percent
|
||||
- Position
|
||||
- Facing direction)"""";
|
||||
|
||||
const std::string reset_menu_help = R""""(
|
||||
Reset menu to default
|
||||
configuration. Please also
|
||||
use on the first boot after
|
||||
upgrading Training Modpack
|
||||
versions.)"""";
|
||||
|
||||
// Shield States
|
||||
#define SHIELD_INFINITE 1
|
||||
#define SHIELD_HOLD 2
|
||||
const std::vector<std::string> shield_items{"None", "Infinite", "Hold", "Constant"};
|
||||
const std::string shield_help = R""""(
|
||||
Use these toggles in conjunction
|
||||
with Mash toggles to practice
|
||||
moves on shield.
|
||||
|
||||
Infinite
|
||||
CPUs will hold a shield that does
|
||||
not deteriorate over time or
|
||||
by damage.
|
||||
|
||||
Hold
|
||||
CPUs will hold a normal shield.
|
||||
This shield will not deteriorate
|
||||
until hit once.)
|
||||
|
||||
Constant
|
||||
Shield will take damage but not deteriorate
|
||||
|
||||
)"""";
|
||||
|
||||
// OOS
|
||||
const std::string oos_help = R""""(
|
||||
Option to delay oos options
|
||||
until a certain number of hits
|
||||
have connected.
|
||||
|
||||
Consecutive hits that keep the
|
||||
CPU locked in shield stun
|
||||
between hits will count
|
||||
as a single hit.)"""";
|
||||
|
||||
const std::string reaction_time_help = R""""(
|
||||
Additional reaction time
|
||||
in frames.
|
||||
|
||||
Used to delay OOS Options.)"""";
|
||||
|
||||
const std::string shield_tilt_help = R""""(
|
||||
Shield Tilt Direction
|
||||
)"""";
|
||||
|
||||
// Mash in neutral
|
||||
const std::string mash_neutral_help = R""""(
|
||||
Force mash options to
|
||||
always occur, not just
|
||||
out of specific states.)"""";
|
||||
|
||||
// clang-format off
|
||||
#define ENUM_CLASS_DelayFlag(type,x) \
|
||||
x(type,D0,"0") \
|
||||
x(type,D1,"1") x(type,D2,"2") x(type,D3,"3") x(type,D4,"4") x(type,D5,"5") \
|
||||
x(type,D6,"6") x(type,D7,"7") x(type,D8,"8") x(type,D9,"9") x(type,D10,"10") \
|
||||
x(type,D11,"11") x(type,D12,"12") x(type,D13,"13") x(type,D14,"14") x(type,D15,"15") \
|
||||
x(type,D16,"16") x(type,D17,"17") x(type,D18,"18") x(type,D19,"19") x(type,D20,"20") \
|
||||
x(type,D21,"21") x(type,D22,"22") x(type,D23,"23") x(type,D24,"24") x(type,D25,"25") \
|
||||
x(type,D26,"26") x(type,D27,"27") x(type,D28,"28") x(type,D29,"29") x(type,D30,"30") \
|
||||
// clang-format on
|
||||
|
||||
DEFINE_ENUM_CLASS(DelayFlag);
|
||||
|
||||
#define ENUM_CLASS_BoolFlag(type,x) \
|
||||
x(type,True,"True") x(type,False,"False")
|
||||
|
||||
DEFINE_ENUM_CLASS(BoolFlag);
|
||||
|
||||
const std::string fast_fall_help = R""""(
|
||||
CPUs will fast fall
|
||||
out of jumps and aerial
|
||||
attacks as soon as possible.)"""";
|
||||
|
||||
const std::string fast_fall_delay_help = R""""(
|
||||
Frames to delay CPU
|
||||
fast fall.)"""";
|
||||
|
||||
const std::string falling_aerials_help = R""""(
|
||||
CPUs will only begin
|
||||
aerials at the apex of
|
||||
their jump.)"""";
|
||||
|
||||
const std::string aerial_delay_help = R""""(
|
||||
Frames to delay CPU Aerial.)"""";
|
||||
|
||||
const std::string full_hop_help = R""""(
|
||||
CPUs will full hop
|
||||
rather than short hop
|
||||
aerials.)"""";
|
||||
|
||||
#define ENUM_CLASS_AttackAngleFlag(type,x) \
|
||||
x(type,Neutral,"Neutral") x(type,Up,"Up") x(type,Down,"Down")
|
||||
DEFINE_ENUM_CLASS(AttackAngleFlag);
|
||||
|
||||
const std::string attack_angle_help = R""""(
|
||||
Set angleable tilt and smash attacks.)"""";
|
||||
|
||||
const std::string save_damage_help = R""""(
|
||||
Set if save states should apply to damage.)"""";
|
||||
|
||||
#define NORMAL 0
|
||||
const std::vector<std::string> strength_items{ "Normal", "Medium", "High"};
|
||||
const std::string sdi_strength_help = R""""(
|
||||
How many frames between each SDI input
|
||||
|
||||
Normal 8
|
||||
Medium 6
|
||||
High 4
|
||||
|
||||
)"""";
|
|
@ -1,185 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <cstdint>
|
||||
#include <tesla.hpp>
|
||||
#include "gui_help.hpp"
|
||||
#include "gui_sublist.hpp"
|
||||
#include "cpp_utils.hpp"
|
||||
|
||||
class ValueListItem : public tsl::elm::ListItem
|
||||
{
|
||||
public:
|
||||
ValueListItem(std::string text,
|
||||
const std::vector<std::string> values,
|
||||
int* defaultPos,
|
||||
const std::string data,
|
||||
const std::string help)
|
||||
: tsl::elm::ListItem(text), m_values(values), m_curValue(defaultPos), extdata(data), help(help)
|
||||
{
|
||||
this->setValue(m_values[*m_curValue]);
|
||||
|
||||
this->initEventListener();
|
||||
}
|
||||
|
||||
~ValueListItem() {}
|
||||
|
||||
void applyChanges()
|
||||
{
|
||||
int value = this->getCurValue();
|
||||
this->setValue(this->getValues()[value]);
|
||||
this->setCurValue(value);
|
||||
}
|
||||
|
||||
tsl::elm::Element* requestFocus(Element* oldFocus, tsl::FocusDirection direction)
|
||||
{
|
||||
return ListItem::requestFocus(oldFocus, direction);
|
||||
}
|
||||
|
||||
void layout(u16 parentX, u16 parentY, u16 parentWidth, u16 parentHeight)
|
||||
{
|
||||
ListItem::layout(parentX, parentY, parentWidth, parentHeight);
|
||||
}
|
||||
|
||||
bool onClick(u64 keys)
|
||||
{
|
||||
if(keys & KEY_A)
|
||||
{
|
||||
if(this->m_valueChangeListener != nullptr)
|
||||
{
|
||||
this->m_valueChangeListener(this->m_values, this->m_curValue, this->extdata, this->getText(), this->help);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int getCurValue() { return *(this->m_curValue); }
|
||||
void setCurValue(int value) { *(this->m_curValue) = value; }
|
||||
|
||||
const std::string getExtData() { return this->extdata; }
|
||||
|
||||
const std::vector<std::string> getValues() { return this->m_values; }
|
||||
|
||||
void setStateChangedListener(
|
||||
std::function<void(const std::vector<std::string>, int*, std::string, std::string, std::string)> valueChangeListener)
|
||||
{
|
||||
this->m_valueChangeListener = valueChangeListener;
|
||||
}
|
||||
|
||||
protected:
|
||||
void initEventListener()
|
||||
{
|
||||
this->setStateChangedListener(
|
||||
[](std::vector<std::string> menuItems, int* val, std::string data, std::string title, std::string helpTxt) {
|
||||
tsl::changeTo<GuiSublist>(menuItems, val, data, title, helpTxt);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<std::string> m_values;
|
||||
int* m_curValue;
|
||||
std::function<void(const std::vector<std::string>, int*, std::string, std::string, std::string)> m_valueChangeListener =
|
||||
nullptr;
|
||||
const std::string extdata;
|
||||
const std::string help;
|
||||
};
|
||||
|
||||
template<typename T> class BitFlagToggleListItem : public tsl::elm::ToggleListItem
|
||||
{
|
||||
public:
|
||||
using FlagType = detail::FlagTypeT<T>;
|
||||
|
||||
private:
|
||||
T m_mask;
|
||||
FlagType* m_value;
|
||||
std::string m_name;
|
||||
std::string m_help;
|
||||
|
||||
public:
|
||||
BitFlagToggleListItem(const std::string& text, T mask, FlagType* value, std::string name = "", std::string help = "")
|
||||
: tsl::elm::ToggleListItem(text, (mask & *value) != 0, "\uE14B", "\uE14C"), m_mask(mask), m_value(value), m_name(name), m_help(help)
|
||||
{
|
||||
setStateChangedListener([this](bool v) {
|
||||
if(v)
|
||||
{
|
||||
*m_value = *m_value | m_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_value = *m_value - m_mask;
|
||||
}
|
||||
});
|
||||
}
|
||||
virtual bool onClick(u64 keys) override
|
||||
{
|
||||
// temp band-aid for issues with ToggleListItem
|
||||
if(keys & KEY_A)
|
||||
{
|
||||
setState(!m_state);
|
||||
return ListItem::onClick(keys);
|
||||
}
|
||||
else if(keys & KEY_Y)
|
||||
{
|
||||
if (m_help != "") {
|
||||
tsl::changeTo<GuiHelp>(m_name, m_help);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual void setState(bool state) override
|
||||
{
|
||||
// temp band-aid for issues with ToggleListItem
|
||||
bool stateChanged = state != this->m_state;
|
||||
ToggleListItem::setState(state);
|
||||
if(stateChanged && m_stateChangedListener)
|
||||
{
|
||||
m_stateChangedListener(state);
|
||||
}
|
||||
}
|
||||
virtual ~BitFlagToggleListItem() = default;
|
||||
};
|
||||
|
||||
class SetToggleListItem : public tsl::elm::ListItem
|
||||
{
|
||||
std::vector<tsl::elm::ToggleListItem*> m_itemsOn;
|
||||
std::vector<tsl::elm::ToggleListItem*> m_itemsOff;
|
||||
std::string m_name;
|
||||
std::string m_help;
|
||||
|
||||
public:
|
||||
SetToggleListItem(std::vector<tsl::elm::ToggleListItem*> itemsOn,
|
||||
std::vector<tsl::elm::ToggleListItem*> itemsOff,
|
||||
const std::string& text,
|
||||
const std::string name = "",
|
||||
const std::string help = "",
|
||||
const std::string& value = "")
|
||||
: tsl::elm::ListItem(text, value), m_itemsOn(std::move(itemsOn)), m_itemsOff(std::move(itemsOff)), m_name(name), m_help(help)
|
||||
{
|
||||
setClickListener([this](u64 keys) -> bool {
|
||||
if(keys & KEY_A)
|
||||
{
|
||||
for(auto it : m_itemsOn)
|
||||
{
|
||||
it->setState(true);
|
||||
}
|
||||
for(auto it : m_itemsOff)
|
||||
{
|
||||
it->setState(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(keys & KEY_Y)
|
||||
{
|
||||
if (m_help != "") {
|
||||
tsl::changeTo<GuiHelp>(m_name, m_help);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
virtual ~SetToggleListItem() = default;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
Subproject commit a68af19eda8e2b1d51008a2e1a1b71649460f901
|
|
@ -1,539 +0,0 @@
|
|||
#include <tesla.hpp>
|
||||
#include "gui_main.hpp"
|
||||
#include "gui_help.hpp"
|
||||
#include "overflow_list.hpp"
|
||||
#include "overlay_frame_with_help.hpp"
|
||||
#include "value_list_item.hpp"
|
||||
#include "clickable_list_item.hpp"
|
||||
#include "ini_settings.hpp"
|
||||
#include "taunt_toggles.hpp"
|
||||
|
||||
static struct TrainingModpackMenu
|
||||
{
|
||||
OnOffFlags HITBOX_VIS = OnOffFlag::On;
|
||||
OnOffFlags STAGE_HAZARDS = OnOffFlags::None;
|
||||
Directions DI_STATE = Directions::None;
|
||||
Directions SDI_STATE = Directions::None;
|
||||
int SDI_STRENGTH = NORMAL;
|
||||
Directions AIR_DODGE_DIR = Directions::None;
|
||||
ActionFlags MASH_STATE = ActionFlags::None;
|
||||
ActionFlags FOLLOW_UP = ActionFlags::None;
|
||||
AttackAngleFlags ATTACK_ANGLE = AttackAngleFlags::None;
|
||||
LedgeFlags LEDGE_STATE = LedgeFlags::All;
|
||||
DelayFlags LEDGE_DELAY = DelayFlags::All;
|
||||
TechFlags TECH_STATE = TechFlags::All;
|
||||
MissTechFlags MISS_TECH_STATE = MissTechFlags::All;
|
||||
int SHIELD_STATE = NONE;
|
||||
DefensiveFlags DEFENSIVE_STATE = DefensiveFlags::All;
|
||||
DelayFlags OOS_OFFSET = DelayFlags::None;
|
||||
DelayFlags REACTION_TIME = DelayFlags::None;
|
||||
Directions SHIELD_TILT = Directions::None;
|
||||
OnOffFlags MASH_IN_NEUTRAL = OnOffFlags::None;
|
||||
BoolFlags FAST_FALL = BoolFlags::None;
|
||||
DelayFlags FAST_FALL_DELAY = DelayFlags::None;
|
||||
BoolFlags FALLING_AERIALS = BoolFlags::None;
|
||||
DelayFlags AERIAL_DELAY = DelayFlags::None;
|
||||
BoolFlags FULL_HOP = BoolFlags::None;
|
||||
int INPUT_DELAY = 0;
|
||||
OnOffFlags SAVE_DAMAGE = OnOffFlag::On;
|
||||
} menu;
|
||||
|
||||
static struct TrainingModpackMenu defaultMenu = menu;
|
||||
|
||||
static int FRAME_ADVANTAGE = 0;
|
||||
|
||||
u64 pidSmash = 0;
|
||||
static const char* TRAINING_MOD_LOG = "/TrainingModpack/training_modpack.log";
|
||||
static const char* TRAINING_MOD_FRAME_ADV_LOG = "/TrainingModpack/training_modpack_frame_adv.log";
|
||||
static const char* TRAINING_MOD_CONF = "/TrainingModpack/training_modpack_menu.conf";
|
||||
|
||||
GuiMain::GuiMain()
|
||||
{
|
||||
smInitialize();
|
||||
pminfoInitialize();
|
||||
pmbmInitialize();
|
||||
smExit();
|
||||
|
||||
pmdmntGetProcessId(&pidSmash, 0x01006A800016E000);
|
||||
|
||||
Result rc = fsOpenSdCardFileSystem(&this->m_fs);
|
||||
if(R_FAILED(rc)) return;
|
||||
|
||||
FsFile menuFile;
|
||||
rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_CONF, FsOpenMode_Read, &menuFile);
|
||||
if(R_FAILED(rc)) return;
|
||||
|
||||
u64 bytesRead;
|
||||
rc = fsFileRead(&menuFile, 0, static_cast<void*>(&menu), sizeof(menu), FsReadOption_None, &bytesRead);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
fsFileWrite(&menuFile, 0, static_cast<void*>(&menu), sizeof(menu), FsOpenMode_Write);
|
||||
}
|
||||
|
||||
fsFileClose(&menuFile);
|
||||
}
|
||||
|
||||
GuiMain::~GuiMain()
|
||||
{
|
||||
// apply changes on exit
|
||||
applyChanges();
|
||||
|
||||
smInitialize();
|
||||
pminfoExit();
|
||||
pmbmExit();
|
||||
smExit();
|
||||
}
|
||||
|
||||
static char FrameAdvantage[672];
|
||||
|
||||
class FrameAdvantageOverlayFrame : public tsl::elm::OverlayFrame
|
||||
{
|
||||
public:
|
||||
FrameAdvantageOverlayFrame(const std::string& title, const std::string& subtitle) : tsl::elm::OverlayFrame(title, subtitle)
|
||||
{}
|
||||
|
||||
virtual void draw(tsl::gfx::Renderer* renderer) override
|
||||
{
|
||||
renderer->clearScreen();
|
||||
|
||||
renderer->drawRect(0, 0, tsl::cfg::FramebufferWidth, 85, a(tsl::style::color::ColorFrameBackground));
|
||||
|
||||
renderer->drawString(this->m_title.c_str(), false, 20, 50, 30, a(tsl::style::color::ColorText));
|
||||
renderer->drawString(this->m_subtitle.c_str(), false, 20, 70, 15, a(tsl::style::color::ColorDescription));
|
||||
|
||||
if(this->m_contentElement != nullptr) this->m_contentElement->frame(renderer);
|
||||
}
|
||||
};
|
||||
|
||||
class GuiFrameAdvantage : public tsl::Gui
|
||||
{
|
||||
public:
|
||||
GuiFrameAdvantage()
|
||||
{
|
||||
tsl::hlp::requestForeground(false);
|
||||
smInitialize();
|
||||
pminfoInitialize();
|
||||
pmbmInitialize();
|
||||
smExit();
|
||||
|
||||
pmdmntGetProcessId(&pidSmash, 0x01006A800016E000);
|
||||
|
||||
Result rc = fsOpenSdCardFileSystem(&this->m_fs);
|
||||
if(R_FAILED(rc)) return;
|
||||
}
|
||||
|
||||
~GuiFrameAdvantage()
|
||||
{
|
||||
smInitialize();
|
||||
pminfoExit();
|
||||
pmbmExit();
|
||||
smExit();
|
||||
}
|
||||
|
||||
virtual tsl::elm::Element* createUI() override
|
||||
{
|
||||
snprintf(FrameAdvantage, 256, "Frame Advantage: %d", FRAME_ADVANTAGE);
|
||||
auto rootFrame = new FrameAdvantageOverlayFrame(FrameAdvantage, "\uE0A2 + \uE07B Back");
|
||||
|
||||
this->rootFrame = rootFrame;
|
||||
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
virtual void update() override
|
||||
{
|
||||
static u32 counter = 0;
|
||||
|
||||
if(counter++ % 10 != 0) return;
|
||||
|
||||
Result rc;
|
||||
Handle debug;
|
||||
|
||||
if(pidSmash != 0)
|
||||
{
|
||||
rc = svcDebugActiveProcess(&debug, pidSmash);
|
||||
if(R_SUCCEEDED(rc))
|
||||
{
|
||||
u64 frame_adv_addr = 0;
|
||||
FsFile menuAddrFile;
|
||||
rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_FRAME_ADV_LOG, FsOpenMode_Read, &menuAddrFile);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
snprintf(FrameAdvantage, sizeof FrameAdvantage, "Failed to open file with error %d", rc);
|
||||
rootFrame->setTitle(FrameAdvantage);
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[100];
|
||||
u64 bytesRead;
|
||||
rc = fsFileRead(&menuAddrFile, 0, buffer, 100, FsReadOption_None, &bytesRead);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
snprintf(FrameAdvantage, sizeof FrameAdvantage, "Failed to read file with error %d", rc);
|
||||
rootFrame->setTitle(FrameAdvantage);
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
|
||||
fsFileClose(&menuAddrFile);
|
||||
buffer[bytesRead] = '\0';
|
||||
frame_adv_addr = strtoul(buffer, NULL, 16);
|
||||
|
||||
if(frame_adv_addr != 0)
|
||||
{
|
||||
rc = svcReadDebugProcessMemory(&FRAME_ADVANTAGE, debug, frame_adv_addr, sizeof(int));
|
||||
snprintf(FrameAdvantage, sizeof FrameAdvantage, "Frame Advantage: %d", FRAME_ADVANTAGE);
|
||||
rootFrame->setTitle(FrameAdvantage);
|
||||
}
|
||||
|
||||
svcCloseHandle(debug);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(FrameAdvantage, sizeof FrameAdvantage, "Smash is not running.");
|
||||
rootFrame->setTitle(FrameAdvantage);
|
||||
}
|
||||
}
|
||||
virtual bool handleInput(u64 keysDown,
|
||||
u64 keysHeld,
|
||||
touchPosition touchInput,
|
||||
JoystickPosition leftJoyStick,
|
||||
JoystickPosition rightJoyStick) override
|
||||
{
|
||||
if(keysHeld & KEY_DLEFT)
|
||||
{
|
||||
if(keysHeld & KEY_X)
|
||||
{
|
||||
tsl::goBack();
|
||||
tsl::hlp::requestForeground(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// intercept B inputs
|
||||
if(keysDown & KEY_B)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FrameAdvantageOverlayFrame* rootFrame;
|
||||
FsFileSystem m_fs;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
tsl::elm::ListItem* createBitFlagOption(T* option, const std::string& name, const std::string& help, GuiMain* guiMain)
|
||||
{
|
||||
using FlagType = typename T::Type;
|
||||
|
||||
auto item = new tsl::elm::ListItem(name);
|
||||
item->setClickListener([name, help, option, guiMain](u64 keys) -> bool {
|
||||
if(keys & KEY_A)
|
||||
{
|
||||
tsl::changeTo<GuiLambda>(
|
||||
[option, name, help]() -> tsl::elm::Element* {
|
||||
auto toggleList = new OverflowList();
|
||||
std::vector<tsl::elm::ToggleListItem*> items;
|
||||
for(auto& [flag, str] : detail::EnumArray<FlagType>::values)
|
||||
{
|
||||
items.emplace_back(new BitFlagToggleListItem<FlagType>(str, flag, option, name, help));
|
||||
}
|
||||
|
||||
auto allOff = new SetToggleListItem({}, items, "None", name, help);
|
||||
auto allOn = new SetToggleListItem(items, {}, "All", name, help);
|
||||
|
||||
toggleList->addItem(allOn);
|
||||
toggleList->addItem(allOff);
|
||||
|
||||
for(auto it : items)
|
||||
{
|
||||
toggleList->addItem(it);
|
||||
}
|
||||
|
||||
auto frame = new OverlayFrameWithHelp(name, "Press \uE0E3 for help with these options.");
|
||||
frame->setContent(toggleList);
|
||||
return frame;
|
||||
},
|
||||
guiMain);
|
||||
return true;
|
||||
}
|
||||
if(keys & KEY_Y)
|
||||
{
|
||||
tsl::changeTo<GuiHelp>(name, help);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return item;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
tsl::elm::Element* GuiMain::createUI()
|
||||
{
|
||||
char buffer[256];
|
||||
snprintf(buffer, 256, "Version %s", VERSION);
|
||||
OverlayFrameWithHelp* rootFrame = new OverlayFrameWithHelp("Training Modpack", buffer);
|
||||
|
||||
auto list = new OverflowList();
|
||||
|
||||
Result rc;
|
||||
Handle debug;
|
||||
|
||||
tsl::hlp::ini::IniData iniData = readSettings();
|
||||
bool ease_nro_restriction = false;
|
||||
for(auto& section : iniData)
|
||||
{
|
||||
for(auto& keyValue : section.second)
|
||||
{
|
||||
if(section.first == "ro")
|
||||
{
|
||||
if(keyValue.first == "ease_nro_restriction")
|
||||
{
|
||||
ease_nro_restriction = (readSettings()["ro"]["ease_nro_restriction"] == "u8!0x1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!ease_nro_restriction)
|
||||
{
|
||||
tsl::elm::Element* iniShow = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||
renderer->drawString(
|
||||
"Your config file did not have the \nproper configuration to run the \nTraining Modpack.\n\n\nIt has been automatically \nupdated.\n- atmosphere\n---- config\n-------- system_settings.ini\n\n(enable ease_nro_restriction)\n\n\nPlease reboot your Switch.",
|
||||
false,
|
||||
50,
|
||||
225,
|
||||
20,
|
||||
tsl::Color(255, 255, 255, 255));
|
||||
});
|
||||
|
||||
updateSettings({{"ro", {{"ease_nro_restriction", "u8!0x1"}}}});
|
||||
|
||||
rootFrame->setContent(iniShow);
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
if(pidSmash != 0)
|
||||
{
|
||||
rc = svcDebugActiveProcess(&debug, pidSmash);
|
||||
if(R_SUCCEEDED(rc))
|
||||
{
|
||||
svcCloseHandle(debug);
|
||||
|
||||
// Remove because it breaks scrolling up to the bottom of the
|
||||
// menu, because CategoryHeaders can't requestFocus?
|
||||
// list->addItem(new tsl::elm::CategoryHeader("Mash", true));
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.MASH_STATE, "Mash Toggles", mash_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.FOLLOW_UP, "Followup Toggles", follow_up_help, this));
|
||||
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
|
||||
"Mash In Neutral", OnOffFlag::On, &menu.MASH_IN_NEUTRAL, "Mash In Neutral", mash_neutral_help));
|
||||
list->addItem(createBitFlagOption(&menu.ATTACK_ANGLE, "Attack Angle", attack_angle_help, this));
|
||||
|
||||
list->addItem(new tsl::elm::CategoryHeader("Left Stick", true));
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.DI_STATE, "Set DI", di_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.SDI_STATE, "Set SDI", sdi_help, this));
|
||||
|
||||
ValueListItem* sdiItem =
|
||||
new ValueListItem("SDI Strength", strength_items, &menu.SDI_STRENGTH, "SDI Strength", sdi_strength_help);
|
||||
list->addItem(sdiItem);
|
||||
valueListItems.push_back(sdiItem);
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.AIR_DODGE_DIR, "Airdodge Direction", air_dodge_direction_help, this));
|
||||
|
||||
list->addItem(new tsl::elm::CategoryHeader("Shield", true));
|
||||
|
||||
ValueListItem* shieldItem =
|
||||
new ValueListItem("Shield Options", shield_items, &menu.SHIELD_STATE, "shield", shield_help);
|
||||
list->addItem(shieldItem);
|
||||
valueListItems.push_back(shieldItem);
|
||||
|
||||
ClickableListItem* frameAdvantageItem = new ClickableListItem("Frame Advantage",
|
||||
frame_advantage_items,
|
||||
nullptr,
|
||||
"frameAdvantage",
|
||||
0,
|
||||
"Frame Advantage",
|
||||
frame_advantage_help);
|
||||
frameAdvantageItem->setClickListener([](std::vector<std::string> values,
|
||||
int* curValue,
|
||||
std::string extdata,
|
||||
int index,
|
||||
std::string title,
|
||||
std::string help) { tsl::changeTo<GuiFrameAdvantage>(); });
|
||||
frameAdvantageItem->setHelpListener(
|
||||
[](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
|
||||
list->addItem(frameAdvantageItem);
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.OOS_OFFSET, "OOS Offset", oos_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.REACTION_TIME, "Reaction Time", reaction_time_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.SHIELD_TILT, "Shield Tilt", shield_tilt_help, this));
|
||||
|
||||
list->addItem(new tsl::elm::CategoryHeader("Chase", true));
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.LEDGE_STATE, "Ledge Options", ledge_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.LEDGE_DELAY, "Ledge Delay", ledge_delay_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.TECH_STATE, "Tech Options", tech_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.MISS_TECH_STATE, "Missed Tech Options", miss_tech_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.DEFENSIVE_STATE, "Defensive Options", defensive_help, this));
|
||||
|
||||
list->addItem(new tsl::elm::CategoryHeader("Aerials", true));
|
||||
|
||||
list->addItem(createBitFlagOption(&menu.FAST_FALL, "Fast Fall", fast_fall_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.FAST_FALL_DELAY, "Fast Fall Delay", fast_fall_delay_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.FALLING_AERIALS, "Falling Aerials", falling_aerials_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.AERIAL_DELAY, "Aerial Delay", aerial_delay_help, this));
|
||||
list->addItem(createBitFlagOption(&menu.FULL_HOP, "Full Hop", full_hop_help, this));
|
||||
|
||||
list->addItem(new tsl::elm::CategoryHeader("Miscellaneous", true));
|
||||
|
||||
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
|
||||
"Hitbox Visualization", OnOffFlag::On, &menu.HITBOX_VIS, "Hitbox Visualization", hitbox_help));
|
||||
|
||||
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
|
||||
"Stage Hazards", OnOffFlag::On, &menu.STAGE_HAZARDS, "Stage Hazards", hazards_help));
|
||||
|
||||
ClickableListItem* saveStateItem =
|
||||
new ClickableListItem("Save States", empty_items, nullptr, "saveStates", 0, "Save States", save_states_help);
|
||||
saveStateItem->setClickListener([](std::vector<std::string> values,
|
||||
int* curValue,
|
||||
std::string extdata,
|
||||
int index,
|
||||
std::string title,
|
||||
std::string help) { tsl::changeTo<GuiHelp>(title, help); });
|
||||
saveStateItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
|
||||
list->addItem(saveStateItem);
|
||||
|
||||
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
|
||||
"Save Damage", OnOffFlag::On, &menu.SAVE_DAMAGE, "Save Damage", save_damage_help));
|
||||
|
||||
ValueListItem* inputDelayItem =
|
||||
new ValueListItem("Input Delay", input_delay_items, &menu.INPUT_DELAY, "inputDelay", input_delay_help);
|
||||
list->addItem(inputDelayItem);
|
||||
valueListItems.push_back(inputDelayItem);
|
||||
|
||||
ClickableListItem* resetMenuItem =
|
||||
new ClickableListItem("Reset Menu", empty_items, nullptr, "resetMenu", 0, "Reset Menu", reset_menu_help);
|
||||
resetMenuItem->setClickListener([](std::vector<std::string> values,
|
||||
int* curValue,
|
||||
std::string extdata,
|
||||
int index,
|
||||
std::string title,
|
||||
std::string help) {
|
||||
menu = defaultMenu;
|
||||
|
||||
/* Open Sd card filesystem. */
|
||||
FsFileSystem fsSdmc;
|
||||
if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return;
|
||||
tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); });
|
||||
|
||||
fsFsDeleteFile(&fsSdmc, TRAINING_MOD_CONF);
|
||||
|
||||
tsl::goBack();
|
||||
});
|
||||
resetMenuItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
|
||||
list->addItem(resetMenuItem);
|
||||
|
||||
rootFrame->setContent(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
tsl::elm::Element* warning =
|
||||
new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||
renderer->drawString("\uE150", false, 180, 250, 90, tsl::Color(255, 255, 255, 255));
|
||||
renderer->drawString("Could not debug process memory", false, 110, 340, 25, tsl::Color(255, 255, 255, 255));
|
||||
});
|
||||
|
||||
rootFrame->setContent(warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tsl::elm::Element* warning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||
renderer->drawString("\uE150", false, 180, 250, 90, tsl::Color(255, 255, 255, 255));
|
||||
renderer->drawString("Smash not running.", false, 110, 340, 25, tsl::Color(255, 255, 255, 255));
|
||||
});
|
||||
|
||||
rootFrame->setContent(warning);
|
||||
}
|
||||
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
void GuiMain::update()
|
||||
{
|
||||
static u32 counter = 0;
|
||||
|
||||
if(counter++ % 15 != 0) return;
|
||||
|
||||
applyChanges();
|
||||
}
|
||||
|
||||
void GuiMain::applyChanges()
|
||||
{
|
||||
for(ValueListItem* item : valueListItems)
|
||||
{
|
||||
item->applyChanges();
|
||||
}
|
||||
Result rc;
|
||||
Handle debug;
|
||||
|
||||
if(pidSmash != 0)
|
||||
{
|
||||
rc = svcDebugActiveProcess(&debug, pidSmash);
|
||||
if(R_SUCCEEDED(rc))
|
||||
{
|
||||
u64 menu_addr = 0;
|
||||
FsFile menuAddrFile;
|
||||
rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_LOG, FsOpenMode_Read, &menuAddrFile);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[100];
|
||||
u64 bytesRead;
|
||||
rc = fsFileRead(&menuAddrFile, 0, buffer, 100, FsReadOption_None, &bytesRead);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
|
||||
fsFileClose(&menuAddrFile);
|
||||
buffer[bytesRead] = '\0';
|
||||
menu_addr = strtoul(buffer, NULL, 16);
|
||||
|
||||
if(menu_addr != 0)
|
||||
{
|
||||
rc = svcWriteDebugProcessMemory(debug, &menu, (u64)menu_addr, sizeof(menu));
|
||||
}
|
||||
svcCloseHandle(debug);
|
||||
}
|
||||
}
|
||||
|
||||
FsFile menuFile;
|
||||
fsFsCreateFile(&this->m_fs, TRAINING_MOD_CONF, sizeof(menu), 0);
|
||||
|
||||
rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_CONF, FsOpenMode_Write, &menuFile);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
fsFileClose(&menuFile);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = fsFileWrite(&menuFile, 0, static_cast<void*>(&menu), sizeof(menu), FsOpenMode_Write);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
fsFileClose(&menuFile);
|
||||
return;
|
||||
}
|
||||
|
||||
fsFileClose(&menuFile);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
#include "gui_sublist.hpp"
|
||||
#include "overflow_list.hpp"
|
||||
#include "overlay_frame_with_help.hpp"
|
||||
#include "gui_help.hpp"
|
||||
#include "clickable_list_item.hpp"
|
||||
#include "taunt_toggles.hpp"
|
||||
|
||||
GuiSublist::GuiSublist(std::vector<std::string> menuItems, int* index, std::string extData, std::string title, std::string help)
|
||||
{
|
||||
this->menuItems = menuItems;
|
||||
this->index = index;
|
||||
this->extData = extData;
|
||||
this->title = title;
|
||||
this->help = help;
|
||||
}
|
||||
|
||||
GuiSublist::~GuiSublist() {}
|
||||
|
||||
tsl::elm::Element* GuiSublist::createUI()
|
||||
{
|
||||
tsl::elm::OverlayFrame* rootFrame = new OverlayFrameWithHelp(title, "Press \uE0E3 for help with these options.");
|
||||
|
||||
auto list = new OverflowList();
|
||||
|
||||
for(size_t i = 0; i < menuItems.size(); i++)
|
||||
{
|
||||
auto item = new ClickableListItem(menuItems[i], menuItems, this->index, "", i, title, help);
|
||||
setClickListener(item);
|
||||
item->setHelpListener([](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
|
||||
list->addItem(item);
|
||||
listItems.push_back(item);
|
||||
}
|
||||
|
||||
list->setFocusedIndex(*index);
|
||||
|
||||
rootFrame->setContent(list);
|
||||
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
void GuiSublist::setClickListener(ClickableListItem* item)
|
||||
{
|
||||
item->setClickListener([](std::vector<std::string> values,
|
||||
int* curValue,
|
||||
std::string extdata,
|
||||
int index,
|
||||
std::string title,
|
||||
std::string help) {
|
||||
*curValue = index;
|
||||
tsl::goBack();
|
||||
});
|
||||
}
|
||||
|
||||
void GuiSublist::update()
|
||||
{
|
||||
static u32 counter = 0;
|
||||
|
||||
if(counter++ % 15 != 0) return;
|
||||
|
||||
applyChanges();
|
||||
}
|
||||
|
||||
void GuiSublist::applyChanges() {}
|
|
@ -1,20 +0,0 @@
|
|||
#define TESLA_INIT_IMPL
|
||||
#include "gui_main.hpp"
|
||||
|
||||
class TrainingModpackOverlay : public tsl::Overlay
|
||||
{
|
||||
public:
|
||||
TrainingModpackOverlay() {}
|
||||
~TrainingModpackOverlay() {}
|
||||
|
||||
void initServices() override { pmshellInitialize(); }
|
||||
|
||||
void exitServices() override { pmshellExit(); }
|
||||
|
||||
std::unique_ptr<tsl::Gui> loadInitialGui() override { return std::make_unique<GuiMain>(); }
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return tsl::loop<TrainingModpackOverlay>(argc, argv);
|
||||
}
|
|
@ -3,8 +3,15 @@ use core::f64::consts::PI;
|
|||
use smash::lib::lua_const::*;
|
||||
|
||||
// bitflag helper function macro
|
||||
macro_rules! to_vec_impl {
|
||||
macro_rules! extra_bitflag_impls {
|
||||
($e:ty) => {
|
||||
impl core::fmt::Display for $e {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
core::fmt::Debug::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl $e {
|
||||
pub fn to_vec(&self) -> Vec::<$e> {
|
||||
let mut vec = Vec::<$e>::new();
|
||||
let mut field = <$e>::from_bits_truncate(self.bits);
|
||||
|
@ -15,11 +22,7 @@ macro_rules! to_vec_impl {
|
|||
}
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_index_impl {
|
||||
($e:ty) => {
|
||||
pub fn to_index(&self) -> u32 {
|
||||
if self.bits == 0 {
|
||||
return 0;
|
||||
|
@ -27,15 +30,7 @@ macro_rules! to_index_impl {
|
|||
|
||||
return self.bits.trailing_zeros();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn random_option<T>(arg: &[T]) -> &T {
|
||||
&arg[get_random_int(arg.len() as i32) as usize]
|
||||
}
|
||||
|
||||
macro_rules! get_random_impl {
|
||||
($e:ty) => {
|
||||
pub fn get_random(&self) -> $e {
|
||||
let options = self.to_vec();
|
||||
match options.len() {
|
||||
|
@ -50,7 +45,22 @@ macro_rules! get_random_impl {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn to_toggle_strs() -> Vec<String> {
|
||||
let all_options = <$e>::all().to_vec();
|
||||
all_options.iter().map(|i| i.into_string()).collect()
|
||||
}
|
||||
|
||||
pub fn to_toggle_vals() -> Vec<usize> {
|
||||
let all_options = <$e>::all().to_vec();
|
||||
all_options.iter().map(|i| i.bits() as usize).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_option<T>(arg: &[T]) -> &T {
|
||||
&arg[get_random_int(arg.len() as i32) as usize]
|
||||
}
|
||||
|
||||
// DI
|
||||
|
@ -98,9 +108,23 @@ impl Direction {
|
|||
_ => 0,
|
||||
}
|
||||
}
|
||||
to_vec_impl! {Direction}
|
||||
get_random_impl! {Direction}
|
||||
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
Direction::OUT => "Away",
|
||||
Direction::UP_OUT => "Up and Away",
|
||||
Direction::UP => "Up",
|
||||
Direction::UP_IN => "Up and In",
|
||||
Direction::IN => "In",
|
||||
Direction::DOWN_IN => "Down and In",
|
||||
Direction::DOWN => "Down",
|
||||
Direction::DOWN_OUT => "Down and Away",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {Direction}
|
||||
|
||||
// Ledge Option
|
||||
bitflags! {
|
||||
|
@ -125,9 +149,20 @@ impl LedgeOption {
|
|||
_ => return None,
|
||||
})
|
||||
}
|
||||
to_vec_impl! {LedgeOption}
|
||||
get_random_impl! {LedgeOption}
|
||||
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
LedgeOption::NEUTRAL => "Neutral Getup",
|
||||
LedgeOption::ROLL => "Roll",
|
||||
LedgeOption::JUMP => "Jump",
|
||||
LedgeOption::ATTACK => "Getup Attack",
|
||||
LedgeOption::WAIT => "Wait",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {LedgeOption}
|
||||
|
||||
// Tech options
|
||||
bitflags! {
|
||||
|
@ -140,9 +175,18 @@ bitflags! {
|
|||
}
|
||||
|
||||
impl TechFlags {
|
||||
to_vec_impl! {TechFlags}
|
||||
get_random_impl! {TechFlags}
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
TechFlags::NO_TECH => "No Tech",
|
||||
TechFlags::ROLL_F => "Roll Forwards",
|
||||
TechFlags::ROLL_B => "Roll Backwards",
|
||||
TechFlags::IN_PLACE => "Tech In Place",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {TechFlags}
|
||||
|
||||
// Missed Tech Options
|
||||
bitflags! {
|
||||
|
@ -155,13 +199,22 @@ bitflags! {
|
|||
}
|
||||
|
||||
impl MissTechFlags {
|
||||
to_vec_impl! {MissTechFlags}
|
||||
get_random_impl! {MissTechFlags}
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
MissTechFlags::GETUP => "Neutral Getup",
|
||||
MissTechFlags::ATTACK => "Getup Attack",
|
||||
MissTechFlags::ROLL_F => "Roll Forwards",
|
||||
MissTechFlags::ROLL_B => "Roll Backwards",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {MissTechFlags}
|
||||
|
||||
/// Shield States
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, FromPrimitive)]
|
||||
pub enum Shield {
|
||||
None = 0,
|
||||
Infinite = 1,
|
||||
|
@ -169,6 +222,18 @@ pub enum Shield {
|
|||
Constant = 3,
|
||||
}
|
||||
|
||||
impl Shield {
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
Shield::None => "None",
|
||||
Shield::Infinite => "Infinite",
|
||||
Shield::Hold => "Hold",
|
||||
Shield::Constant => "Constant",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
// Defensive States
|
||||
bitflags! {
|
||||
pub struct Defensive : u32 {
|
||||
|
@ -181,9 +246,19 @@ bitflags! {
|
|||
}
|
||||
|
||||
impl Defensive {
|
||||
to_vec_impl! {Defensive}
|
||||
get_random_impl! {Defensive}
|
||||
fn into_string(self) -> String {
|
||||
match self {
|
||||
Defensive::SPOT_DODGE => "Spotdodge",
|
||||
Defensive::ROLL_F => "Roll Forwards",
|
||||
Defensive::ROLL_B => "Roll Backwards",
|
||||
Defensive::JAB => "Jab",
|
||||
Defensive::SHIELD => "Shield",
|
||||
_ => "",
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {Defensive}
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -192,6 +267,24 @@ pub enum OnOff {
|
|||
On = 1,
|
||||
}
|
||||
|
||||
impl OnOff {
|
||||
pub fn from_val(val: u32) -> Option<Self> {
|
||||
match val {
|
||||
1 => Some(OnOff::On),
|
||||
0 => Some(OnOff::Off),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> String {
|
||||
match self {
|
||||
OnOff::Off => "Off",
|
||||
OnOff::On => "On",
|
||||
_ => ""
|
||||
}.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct Action : u32 {
|
||||
const AIR_DODGE = 0x1;
|
||||
|
@ -234,9 +327,14 @@ impl Action {
|
|||
_ => return None,
|
||||
})
|
||||
}
|
||||
to_vec_impl! {Action}
|
||||
get_random_impl! {Action}
|
||||
|
||||
pub fn into_string(self) -> String {
|
||||
// TODO: add
|
||||
return self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {Action}
|
||||
|
||||
bitflags! {
|
||||
pub struct AttackAngle : u32 {
|
||||
|
@ -247,9 +345,13 @@ bitflags! {
|
|||
}
|
||||
|
||||
impl AttackAngle {
|
||||
to_vec_impl! {AttackAngle}
|
||||
get_random_impl! {AttackAngle}
|
||||
pub fn into_string(self) -> String {
|
||||
// TODO: add
|
||||
return self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {AttackAngle}
|
||||
|
||||
|
||||
bitflags! {
|
||||
|
@ -289,10 +391,13 @@ bitflags! {
|
|||
}
|
||||
|
||||
impl Delay {
|
||||
to_vec_impl! {Delay}
|
||||
get_random_impl! {Delay}
|
||||
to_index_impl! {Delay}
|
||||
pub fn into_string(self) -> String {
|
||||
// TODO: add
|
||||
return self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {Delay}
|
||||
|
||||
bitflags! {
|
||||
pub struct BoolFlag : u32 {
|
||||
|
@ -301,16 +406,20 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl BoolFlag {
|
||||
to_vec_impl! {BoolFlag}
|
||||
get_random_impl! {BoolFlag}
|
||||
extra_bitflag_impls! {BoolFlag}
|
||||
|
||||
impl BoolFlag {
|
||||
pub fn into_bool(self) -> bool {
|
||||
match self {
|
||||
BoolFlag::TRUE => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> String {
|
||||
// TODO: add
|
||||
return self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -343,6 +452,50 @@ pub struct TrainingModpackMenu {
|
|||
pub save_damage: OnOff,
|
||||
}
|
||||
|
||||
macro_rules! set_by_str {
|
||||
($obj:ident, $s:ident, $(($field:ident = $rhs:expr))*) => {
|
||||
$(
|
||||
if $s == stringify!($field) {
|
||||
$obj.$field = $rhs.unwrap();
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl TrainingModpackMenu {
|
||||
pub fn set(&mut self, s: &str, val: u32) {
|
||||
set_by_str!(self, s,
|
||||
(di_state = Direction::from_bits(val))
|
||||
(sdi_state = Direction::from_bits(val))
|
||||
(air_dodge_dir = Direction::from_bits(val))
|
||||
|
||||
(mash_state = Action::from_bits(val))
|
||||
(follow_up = Action::from_bits(val))
|
||||
|
||||
(ledge_state = LedgeOption::from_bits(val))
|
||||
(ledge_delay = Delay::from_bits(val))
|
||||
(tech_state = TechFlags::from_bits(val))
|
||||
(miss_tech_state = MissTechFlags::from_bits(val))
|
||||
|
||||
(shield_state = num::FromPrimitive::from_u32(val))
|
||||
(defensive_state = Defensive::from_bits(val))
|
||||
(oos_offset = Delay::from_bits(val))
|
||||
(reaction_time = Delay::from_bits(val))
|
||||
|
||||
(fast_fall = BoolFlag::from_bits(val))
|
||||
(fast_fall_delay = Delay::from_bits(val))
|
||||
(falling_aerials = BoolFlag::from_bits(val))
|
||||
(aerial_delay = Delay::from_bits(val))
|
||||
(full_hop = BoolFlag::from_bits(val))
|
||||
|
||||
(hitbox_vis = OnOff::from_val(val))
|
||||
(stage_hazards = OnOff::from_val(val))
|
||||
|
||||
(input_delay = Some(val as i32))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fighter Ids
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -368,4 +521,9 @@ impl SdiStrength {
|
|||
SdiStrength::High => 4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_string(self) -> String {
|
||||
// TODO: add
|
||||
return "".to_string()
|
||||
}
|
||||
}
|
291
src/common/menu.rs
Normal file
291
src/common/menu.rs
Normal file
|
@ -0,0 +1,291 @@
|
|||
|
||||
|
||||
use crate::common::*;
|
||||
use skyline::nn::hid::NpadHandheldState;
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
use skyline_web::{Background, BootDisplay, Webpage};
|
||||
use ramhorns::{Template, Content};
|
||||
|
||||
#[derive(Content)]
|
||||
struct Slider {
|
||||
min: usize,
|
||||
max: usize,
|
||||
index: usize,
|
||||
value: usize
|
||||
}
|
||||
|
||||
#[derive(Content)]
|
||||
struct Toggle<'a> {
|
||||
title: &'a str,
|
||||
checked: &'a str,
|
||||
index: usize,
|
||||
value: usize,
|
||||
}
|
||||
|
||||
impl<'a> Toggle<'a> {
|
||||
pub fn new(title: &'a str, checked: bool, value: usize) -> Toggle<'a> {
|
||||
Toggle{
|
||||
title: title,
|
||||
checked: if checked { "is-appear "} else { "is-hidden" },
|
||||
index: 0,
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Content)]
|
||||
struct SubMenu<'a> {
|
||||
title: &'a str,
|
||||
id: &'a str,
|
||||
toggles: Vec<Toggle<'a>>,
|
||||
sliders: Vec<Slider>,
|
||||
index: usize,
|
||||
check_against: usize
|
||||
}
|
||||
|
||||
impl<'a> SubMenu<'a> {
|
||||
pub fn max_idx(&self) -> usize {
|
||||
self.toggles
|
||||
.iter()
|
||||
.max_by(|t1,t2| t1.index.cmp(&t2.index))
|
||||
.map(|t| t.index)
|
||||
.unwrap_or(self.index)
|
||||
}
|
||||
|
||||
pub fn add_toggle(&mut self, title: &'a str, checked: bool, value: usize) {
|
||||
self.toggles.push(Toggle{
|
||||
title: title,
|
||||
checked: if checked { "is-appear "} else { "is-hidden" },
|
||||
index: self.max_idx() + 1,
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
pub fn add_slider(&mut self, min: usize, max: usize, value: usize) {
|
||||
self.sliders.push(Slider{
|
||||
min,
|
||||
max,
|
||||
index: self.max_idx() + 1,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Content)]
|
||||
struct Menu<'a> {
|
||||
sub_menus: Vec<SubMenu<'a>>
|
||||
}
|
||||
|
||||
impl<'a> Menu<'a> {
|
||||
pub fn max_idx(&self) -> usize {
|
||||
self.sub_menus
|
||||
.iter()
|
||||
.max_by(|x, y| x.max_idx().cmp(&y.max_idx()))
|
||||
.map(|sub_menu| sub_menu.max_idx())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn add_sub_menu(&mut self, title: &'a str, id: &'a str, check_against: usize, toggles: Vec<(&'a str, usize)>, sliders: Vec<(usize,usize,usize)>) {
|
||||
let mut sub_menu = SubMenu {
|
||||
title: title,
|
||||
id: id,
|
||||
toggles: Vec::new(),
|
||||
sliders: Vec::new(),
|
||||
index: self.max_idx() + 1,
|
||||
check_against: check_against
|
||||
};
|
||||
|
||||
for toggle in toggles {
|
||||
sub_menu.add_toggle(toggle.0, (check_against & toggle.1) != 0, toggle.1)
|
||||
}
|
||||
|
||||
for slider in sliders {
|
||||
sub_menu.add_slider(slider.0, slider.1, slider.2);
|
||||
}
|
||||
|
||||
self.sub_menus.push(sub_menu);
|
||||
}
|
||||
|
||||
pub fn add_sub_menu_sep(&mut self, title: &'a str, id: &'a str, check_against: usize, strs: Vec<&'a str>, vals: Vec<usize>) {
|
||||
let mut sub_menu = SubMenu {
|
||||
title: title,
|
||||
id: id,
|
||||
toggles: Vec::new(),
|
||||
sliders: Vec::new(),
|
||||
index: self.max_idx() + 1,
|
||||
check_against: check_against
|
||||
};
|
||||
|
||||
for i in 0..strs.len() {
|
||||
sub_menu.add_toggle(strs[i], (check_against & vals[i]) != 0, vals[i])
|
||||
}
|
||||
|
||||
// TODO: add sliders?
|
||||
|
||||
self.sub_menus.push(sub_menu);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! add_bitflag_submenu {
|
||||
($menu:ident, $title:literal, $id:ident, $e:ty) => {
|
||||
paste::paste!{
|
||||
let [<$id _strs>] = <$e>::to_toggle_strs();
|
||||
let [<$id _vals>] = <$e>::to_toggle_vals();
|
||||
|
||||
$menu.add_sub_menu_sep(
|
||||
$title,
|
||||
stringify!($id),
|
||||
MENU_STRUCT.$id.bits() as usize,
|
||||
[<$id _strs>].iter().map(|i| i.as_str()).collect(),
|
||||
[<$id _vals>]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_menu_from_url(s: &str) {
|
||||
let base_url_len = "http://localhost/".len();
|
||||
let total_len = s.len();
|
||||
|
||||
let ss: String = s.chars().skip(base_url_len).take(total_len - base_url_len).collect();
|
||||
|
||||
for toggle_values in ss.split("&") {
|
||||
let toggle_value_split = toggle_values.split("?").collect::<Vec<&str>>();
|
||||
let toggle = toggle_value_split[0];
|
||||
if toggle == "" { continue; }
|
||||
|
||||
let toggle_vals = toggle_value_split[1];
|
||||
|
||||
let mut bits = 0;
|
||||
for toggle_val in toggle_vals.split(",") {
|
||||
if toggle_val == "" { continue; }
|
||||
|
||||
let mut val = toggle_val.parse::<u32>().unwrap();
|
||||
bits = bits | val;
|
||||
}
|
||||
|
||||
|
||||
unsafe {
|
||||
MENU_STRUCT.set(toggle, bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn menu_condition(module_accessor: &mut smash::app::BattleObjectModuleAccessor) -> bool {
|
||||
ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_SPECIAL) &&
|
||||
ControlModule::check_button_on_trriger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI)
|
||||
}
|
||||
|
||||
pub unsafe fn render_menu() -> String {
|
||||
let tpl = Template::new(include_str!("../templates/menu.html")).unwrap();
|
||||
|
||||
let mut overall_menu = Menu {
|
||||
sub_menus: Vec::new()
|
||||
};
|
||||
|
||||
// Toggle/bitflag menus
|
||||
add_bitflag_submenu!(overall_menu, "Mash Toggles", mash_state, Action);
|
||||
add_bitflag_submenu!(overall_menu, "Followup Toggles", follow_up, Action);
|
||||
add_bitflag_submenu!(overall_menu, "Attack Angle", attack_angle, AttackAngle);
|
||||
|
||||
add_bitflag_submenu!(overall_menu, "Ledge Options", ledge_state, LedgeOption);
|
||||
add_bitflag_submenu!(overall_menu, "Ledge Delay", ledge_delay, Delay);
|
||||
add_bitflag_submenu!(overall_menu, "Tech Options", tech_state, TechFlags);
|
||||
add_bitflag_submenu!(overall_menu, "Miss Tech Options", miss_tech_state, MissTechFlags);
|
||||
add_bitflag_submenu!(overall_menu, "Defensive Options", defensive_state, Defensive);
|
||||
|
||||
add_bitflag_submenu!(overall_menu, "OoS Offset", oos_offset, Delay);
|
||||
add_bitflag_submenu!(overall_menu, "Reaction Time", reaction_time, Delay);
|
||||
|
||||
add_bitflag_submenu!(overall_menu, "Fast Fall", fast_fall, BoolFlag);
|
||||
add_bitflag_submenu!(overall_menu, "Fast Fall Delay", fast_fall_delay, Delay);
|
||||
add_bitflag_submenu!(overall_menu, "Falling Aerials", falling_aerials, BoolFlag);
|
||||
add_bitflag_submenu!(overall_menu, "Full Hop", full_hop, BoolFlag);
|
||||
|
||||
add_bitflag_submenu!(overall_menu, "Shield Tilt", shield_tilt, Direction);
|
||||
|
||||
add_bitflag_submenu!(overall_menu, "DI", di_state, Direction);
|
||||
add_bitflag_submenu!(overall_menu, "SDI", sdi_state, Direction);
|
||||
add_bitflag_submenu!(overall_menu, "Airdodge Direction", air_dodge_dir, Direction);
|
||||
|
||||
overall_menu.add_sub_menu(
|
||||
"Shield Toggles",
|
||||
"shield_state",
|
||||
MENU_STRUCT.shield_state as usize,
|
||||
[
|
||||
("None", Shield::None as usize),
|
||||
("Hold", Shield::Hold as usize),
|
||||
("Infinite", Shield::Infinite as usize),
|
||||
].to_vec(),
|
||||
[].to_vec()
|
||||
);
|
||||
|
||||
// Slider menus
|
||||
overall_menu.add_sub_menu(
|
||||
"Input Delay",
|
||||
"input_delay",
|
||||
// unnecessary for slider?
|
||||
MENU_STRUCT.input_delay as usize,
|
||||
[].to_vec(),
|
||||
[
|
||||
(0, 10, MENU_STRUCT.input_delay as usize)
|
||||
].to_vec()
|
||||
);
|
||||
|
||||
// SDI strength
|
||||
|
||||
|
||||
// TODO: OnOff flags... need a different sort of submenu.
|
||||
overall_menu.add_sub_menu(
|
||||
"Hitbox Visualization",
|
||||
"hitbox_vis",
|
||||
MENU_STRUCT.hitbox_vis as usize,
|
||||
[
|
||||
("Off", OnOff::Off as usize),
|
||||
("On", OnOff::On as usize),
|
||||
].to_vec(),
|
||||
[].to_vec()
|
||||
);
|
||||
overall_menu.add_sub_menu(
|
||||
"Stage Hazards",
|
||||
"stage_hazards",
|
||||
MENU_STRUCT.stage_hazards as usize,
|
||||
[
|
||||
("Off", OnOff::Off as usize),
|
||||
("On", OnOff::On as usize),
|
||||
].to_vec(),
|
||||
[].to_vec()
|
||||
);
|
||||
overall_menu.add_sub_menu(
|
||||
"Mash In Neutral",
|
||||
"mash_in_neutral",
|
||||
MENU_STRUCT.mash_in_neutral as usize,
|
||||
[
|
||||
("Off", OnOff::Off as usize),
|
||||
("On", OnOff::On as usize),
|
||||
].to_vec(),
|
||||
[].to_vec()
|
||||
);
|
||||
|
||||
|
||||
|
||||
tpl.render(&overall_menu)
|
||||
}
|
||||
|
||||
pub unsafe fn spawn_menu() {
|
||||
let data = render_menu();
|
||||
|
||||
let response = Webpage::new()
|
||||
.background(Background::BlurredScreenshot)
|
||||
.file("index.html", &data)
|
||||
.htdocs_dir("contents")
|
||||
.boot_display(BootDisplay::BlurredScreenshot)
|
||||
.boot_icon(true)
|
||||
.open()
|
||||
.unwrap();
|
||||
|
||||
let last_url = response.get_last_url().unwrap();
|
||||
|
||||
set_menu_from_url(last_url);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod consts;
|
||||
pub mod menu;
|
||||
|
||||
use crate::common::consts::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
|
|
|
@ -2,14 +2,20 @@
|
|||
#![feature(with_options)]
|
||||
#![feature(const_mut_refs)]
|
||||
|
||||
mod common;
|
||||
pub mod common;
|
||||
mod hazard_manager;
|
||||
mod hitbox_visualizer;
|
||||
mod training;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
use crate::common::*;
|
||||
use training::combo::FRAME_ADVANTAGE;
|
||||
|
||||
|
@ -39,6 +45,7 @@ macro_rules! c_str {
|
|||
};
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[skyline::main(name = "training_modpack")]
|
||||
pub fn main() {
|
||||
macro_rules! log {
|
||||
|
|
8
src/templates/check.svg
Normal file
8
src/templates/check.svg
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="レイヤー_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" viewBox="-15 -10 80 80" enable-background="new 0 0 80 80" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M 6,36 18,48 48,6" style="stroke:#FFFFFF; stroke-width:6; fill:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 447 B |
BIN
src/templates/frame_adv.webp
Normal file
BIN
src/templates/frame_adv.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
221
src/templates/menu.html
Normal file
221
src/templates/menu.html
Normal file
|
@ -0,0 +1,221 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="./help/css/common.css" />
|
||||
<link rel="stylesheet" href="./help/css/qa.css" />
|
||||
<link id="font-stylesheet" rel="stylesheet" href="./help/css/font.css">
|
||||
<link rel="stylesheet" href="./help/css/keyword.css">
|
||||
<link href="./nouislider.min.css" rel="stylesheet">
|
||||
<style>
|
||||
@-moz-document url-prefix() {
|
||||
@font-face {
|
||||
font-family: '-webkit-standard';
|
||||
src: url('nintendo_udsg-r_std_003.ttf');
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* Overwrite padding from keyword stuff. */
|
||||
.l-main-content {
|
||||
padding: 0px 0px 0px;
|
||||
}
|
||||
|
||||
/* Somehow isn't getting passed through from default css. */
|
||||
.ret-icon-shadow {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 3px;
|
||||
left: 2px;
|
||||
display: inline-block;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="./help/js/jquery-3.3.1.min.js"></script>
|
||||
<script src="./help/common/js/wsnd.min.js"></script>
|
||||
<script src="./help/common/js/keyhelp.js"></script>
|
||||
<script src="./help/js/common.js"></script>
|
||||
<script src="./help/js/qa.js"></script>
|
||||
<script src="./nouislider.min.js"></script>
|
||||
|
||||
<div class="l-header">
|
||||
<div class="l-header-title">
|
||||
<div class="header-title f-u-bold"><span data-msgcom="true" data-msgid="textbox_id-10020">Ultimate Training
|
||||
Modpack Menu</span></div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<a id="ret-button" tabindex="-1" class="header-decoration" href="javascript:goBackHook();"
|
||||
nx-se-disabled="">
|
||||
<div class="ret-icon-wrapper">
|
||||
<img class="ret-icon-shadow is-appear" ref="./help/img/icon/m_retnormal.svg"
|
||||
src="./help/img/icon/m_retnormal.svg">
|
||||
<img class="ret-icon is-appear" ref="./help/img/icon/m_retnormal.svg"
|
||||
src="./help/img/icon/m_retnormal.svg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<!--
|
||||
Script the part below via templating. Overall structure is perhaps
|
||||
[
|
||||
l-qa qa [id=qa-{{menuName}} tabindex="{{index}}"] {
|
||||
// make question for {{menuName}}
|
||||
// make answer with l-grid : l-item list for options
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
|
||||
Remember to set make max keyword size greater than 23!
|
||||
-->
|
||||
{{#sub_menus}}
|
||||
<div class="l-qa">
|
||||
<a id="qa-{{id}}" class="qa" tabindex="{{index}}" href="javascript:void(0);" onfocus="focusQA(this)"
|
||||
onblur="defocusQA(this)" onclick="openAnswer(this)" nx-se-disabled="">
|
||||
<div class="question-outer">
|
||||
<div class="question-border">
|
||||
<div id="question-{{id}}" class="question scuffle-thema">
|
||||
<img class="question-icon" ref="./{{id}}.svg" />
|
||||
<p class="question-message f-u-bold"><span data-msgid="textbox_id-7">{{title}}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="answer-border-{{id}}" class="answer-border-outer is-hidden">
|
||||
<div class="l-main">
|
||||
<ul class="l-grid" id="{{id}}">
|
||||
{{#toggles}}
|
||||
<li class="l-item" val="{{value}}">
|
||||
<div class="keyword-button-outer"> <a tabindex="{{index}}"
|
||||
class="flex-button keyword-button scuffle-thema" href="javascript:void(0)" onclick="clickToggle(this);" nx-se-disabled="">
|
||||
<div class="button-icon-wrapper"> <img class="button-icon {{checked}}"
|
||||
ref="./check.svg" src="./check.svg">
|
||||
</div>
|
||||
<div class="button-msg-wrapper">
|
||||
<div class="keyword-message f-u-bold">{{title}}</div>
|
||||
</div>
|
||||
</a> </div>
|
||||
</li>
|
||||
{{/toggles}}
|
||||
{{#sliders}}
|
||||
<li class="l-item" val="{{value}}">
|
||||
<div class="keyword-button-outer"> <a tabindex="{{index}}"
|
||||
class="flex-button keyword-button scuffle-thema" href="javascript:void(0)" onclick="clickToggle(this);" nx-se-disabled="">
|
||||
<div class="button-icon-wrapper"> <img class="button-icon {{checked}}"
|
||||
ref="./check.svg" src="./check.svg">
|
||||
</div>
|
||||
<div class="button-msg-wrapper">
|
||||
<div class="keyword-message f-u-bold">
|
||||
<div name='range_slider' oninput="this.nextElementSibling.value = this.value">
|
||||
</div>
|
||||
<output>{{value}}</output>
|
||||
</div>
|
||||
</div>
|
||||
</a> </div>
|
||||
</li>
|
||||
{{/sliders}}
|
||||
{{#range_sliders}}
|
||||
<li class="l-item" val="{{value}}">
|
||||
<div class="keyword-button-outer"> <a tabindex="{{index}}"
|
||||
class="flex-button keyword-button scuffle-thema" href="javascript:void(0)" onclick="clickToggle(this);" nx-se-disabled="">
|
||||
<div class="button-icon-wrapper"> <img class="button-icon {{checked}}"
|
||||
ref="./check.svg" src="./check.svg">
|
||||
</div>
|
||||
<div class="button-msg-wrapper">
|
||||
<div class="keyword-message f-u-bold">
|
||||
<div name="{{id}}">
|
||||
</div>
|
||||
</div>
|
||||
</a> </div>
|
||||
</li>
|
||||
{{/range_sliders}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{{/sub_menus}}
|
||||
{{#sub_menus}}
|
||||
{{#sliders}}
|
||||
<script>
|
||||
// todo: loop through
|
||||
noUiSlider.create(document.getElementsByName('range_slider')[0], {
|
||||
start: {{value}},
|
||||
range: {
|
||||
'min': {{min}},
|
||||
'max': {{max}}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{/sliders}}
|
||||
{{/sub_menus}}
|
||||
<script>
|
||||
if (isNx) {
|
||||
window.nx.footer.setAssign('B', '', goBackHook, {
|
||||
se: ''
|
||||
})
|
||||
}
|
||||
function goBackHook() {
|
||||
// Use this function to check menu settings on exit, return through localhost
|
||||
|
||||
$('.is-focused').addClass('is-pause-anim')
|
||||
$('#ret-button').addClass('is-focus')
|
||||
|
||||
disabledOtherLink()
|
||||
|
||||
playSound('cancel')
|
||||
|
||||
fadeOutPage(function () {
|
||||
window.history.back()
|
||||
})
|
||||
|
||||
|
||||
var url = "http://localhost/"
|
||||
|
||||
$(".l-grid").each(function() {
|
||||
var section = this.id;
|
||||
|
||||
url += section + "?"
|
||||
|
||||
var children = this.children;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
if (child.innerHTML.includes("is-appear")) {
|
||||
url += child.getAttribute("val") + ",";
|
||||
}
|
||||
}
|
||||
|
||||
url += "&"
|
||||
});
|
||||
|
||||
location.href = url;
|
||||
}
|
||||
|
||||
function clickToggle(e) {
|
||||
var toggleImage = e.children[0];
|
||||
if (toggleImage.innerHTML.includes("is-appear")) {
|
||||
toggleImage.innerHTML = toggleImage.innerHTML.replace("is-appear", "is-hidden");
|
||||
} else {
|
||||
toggleImage.innerHTML = toggleImage.innerHTML.replace("is-hidden", "is-appear");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
77
src/templates/slider.js
Normal file
77
src/templates/slider.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
var slider = document.getElementById('slider');
|
||||
const STEP = 5
|
||||
|
||||
function checkGamepad(index, gamepad) {
|
||||
// Gets the current value of the sliders
|
||||
var current_value = slider.noUiSlider.get();
|
||||
|
||||
// Displays it on the HTML page
|
||||
document.getElementById("input").innerHTML = current_value;
|
||||
|
||||
|
||||
// Checks to see if the L-button is pressed
|
||||
if(gamepad.buttons[4].pressed){
|
||||
// If the right-side of the slider is focused on, subtract STEP from the current value
|
||||
if(document.activeElement.classList.contains("noUi-handle-upper")){
|
||||
slider.noUiSlider.set(
|
||||
[
|
||||
null,
|
||||
parseInt(current_value[1]) - STEP
|
||||
]);
|
||||
}
|
||||
// If the left-side of the slider is focused on, subtract STEP from the current value
|
||||
else if(document.activeElement.classList.contains("noUi-handle-lower")){
|
||||
slider.noUiSlider.set(
|
||||
[
|
||||
parseInt(current_value[0]) - STEP,
|
||||
null
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Checks to see if the R-button is pressed
|
||||
else if(gamepad.buttons[5].pressed){
|
||||
// If the right-side of the slider is focused on, add STEP to the current value
|
||||
if(document.activeElement.classList.contains("noUi-handle-upper")){
|
||||
slider.noUiSlider.set(
|
||||
[
|
||||
null,
|
||||
parseInt(current_value[1]) + STEP
|
||||
]);
|
||||
}
|
||||
// If the left-side of the slider is focused on, add STEP to the current value
|
||||
else if(document.activeElement.classList.contains("noUi-handle-lower")){
|
||||
slider.noUiSlider.set(
|
||||
[
|
||||
parseInt(current_value[0]) + STEP,
|
||||
null
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
// Creates the slider
|
||||
noUiSlider.create(slider, {
|
||||
start: [20, 80],
|
||||
connect: true,
|
||||
range: {
|
||||
'min': 0,
|
||||
'max': 100
|
||||
}
|
||||
});
|
||||
|
||||
// Listens to see if the gamepad is connected
|
||||
window.addEventListener("gamepadconnected", function (e) {
|
||||
document.getElementById("input").innerHTML = "Gamepad Connected!";
|
||||
});
|
||||
|
||||
// Sets an interval and runs a function every 100 seconds to check the gamepads
|
||||
setInterval(function () {
|
||||
var gpl = navigator.getGamepads();
|
||||
if (gpl.length > 0) {
|
||||
for (var i = 0; i < gpl.length; i++) {
|
||||
checkGamepad(i, gpl[i]);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
30
src/test.rs
Normal file
30
src/test.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
/// Recommended to run with the following command:
|
||||
/// `RUSTFLAGS=-Awarnings cargo test --target=x86_64-unknown-linux-gnu`
|
||||
/// But you can replace the target with your PC's target.
|
||||
|
||||
/// This will run and render the default menu in your default HTML opening program, ideally Chrome.
|
||||
#[test]
|
||||
fn render_menu() {
|
||||
unsafe {
|
||||
use std::process::Command;
|
||||
use crate::common::menu::render_menu;
|
||||
|
||||
let folder_path = "../contents.htdocs";
|
||||
let path = "../contents.htdocs/index.html";
|
||||
|
||||
assert!(std::path::Path::new(folder_path).exists(), "Needs required folder: ../contents.htdocs!");
|
||||
|
||||
std::fs::write(path, render_menu()).unwrap();
|
||||
|
||||
let (cmd, args) = if wsl::is_wsl() || cfg!(target_os = "windows") {
|
||||
("cmd.exe", ["/C", "start", path])
|
||||
} else {
|
||||
("sh", ["-c", "open", path])
|
||||
};
|
||||
|
||||
Command::new(cmd)
|
||||
.args(&args)
|
||||
.output()
|
||||
.expect("failed to open rendered HTML file");
|
||||
}
|
||||
}
|
|
@ -98,6 +98,10 @@ fn once_per_frame_per_fighter(
|
|||
}
|
||||
|
||||
unsafe {
|
||||
if crate::common::menu::menu_condition(module_accessor) {
|
||||
crate::common::menu::spawn_menu();
|
||||
}
|
||||
|
||||
input_record::get_command_flag_cat(module_accessor);
|
||||
combo::get_command_flag_cat(module_accessor);
|
||||
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
||||
|
|
Loading…
Reference in a new issue